public void Emit(OpcodeEncoder opcode, Operand symbolOperand, int symbolOffset) { int pos = (int)codeStream.Position + symbolOffset; Emit(opcode); if (symbolOperand.IsLabel) { linker.Link(LinkType.AbsoluteAddress, PatchType.I4, MethodName, SectionKind.Text, pos, 0, symbolOperand.Name, SectionKind.ROData, 0); } else if (symbolOperand.IsField) { var section = symbolOperand.Field.Data != null ? SectionKind.ROData : SectionKind.BSS; linker.Link(LinkType.AbsoluteAddress, PatchType.I4, MethodName, SectionKind.Text, pos, 0, symbolOperand.Field.FullName, section, (int)symbolOperand.Displacement); } else if (symbolOperand.IsSymbol) { var section = symbolOperand.Method != null ? SectionKind.Text : SectionKind.ROData; var symbol = linker.GetSymbol(symbolOperand.Name, section); if (symbol == null) { symbol = linker.FindSymbol(symbolOperand.Name); } linker.Link(LinkType.AbsoluteAddress, PatchType.I4, MethodName, SectionKind.Text, pos, 0, symbol, 0); } }
private static void CmpXchg(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsRegister); Debug.Assert(node.Operand1.IsRegister); Debug.Assert(node.Operand2.IsRegister); Debug.Assert(node.GetOperand(3).IsRegister); Debug.Assert(node.Result.Register == GeneralPurposeRegister.EAX); Debug.Assert(node.Operand1.Register == GeneralPurposeRegister.EAX); Debug.Assert(node.ResultCount == 1); var linkreference = node.Operand2.IsLabel || node.Operand2.IsField || node.Operand2.IsSymbol; // Compare EAX with r/m32. If equal, ZF is set and r32 is loaded into r/m32. // Else, clear ZF and load r/m32 into EAX. // memory, register 0000 1111 : 1011 000w : mod reg r/m var opcode = new OpcodeEncoder() .AppendConditionalPrefix(0x66, node.Size == InstructionSize.Size16) // 8:prefix: 16bit .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b1011) // 4:opcode .Append3Bits(Bits.b000) // 3:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width .ModRegRMSIBDisplacement(node.GetOperand(3), node.Operand2, node.Operand3) // Mod-Reg-RM-?SIB-?Displacement .AppendConditionalIntegerValue(0, linkreference); // 32:memory if (linkreference) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
private static void MovImmediateToFixedMemory(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand1.IsConstant); Debug.Assert(node.Operand2.IsConstantZero); Debug.Assert(node.Operand3.IsConstant); Debug.Assert(node.ResultCount == 0); var linkreference = node.Operand3.IsLabel || node.Operand3.IsField || node.Operand3.IsSymbol; // immediate to memory 1100 011w: mod 000 r/m : immediate data var opcode = new OpcodeEncoder() .AppendConditionalPrefix(0x66, node.Size == InstructionSize.Size16) // 8:prefix: 16bit .AppendNibble(Bits.b1100) // 4:opcode .Append3Bits(Bits.b011) // 3:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width .AppendMod(Bits.b00) // 2:mod (000) .Append3Bits(Bits.b000) // 3:source (000) .AppendRM(node.Operand1) // 3:r/m (destination) .AppendConditionalDisplacement(node.Operand1, !linkreference) // 32:displacement value .AppendConditionalIntegerValue(0, linkreference) // 32:memory .AppendInteger(node.Operand3, node.Size); // 8/16/32:immediate if (linkreference) emitter.Emit(opcode, node.Operand1, (opcode.Size - (int)node.Size) / 8); else emitter.Emit(opcode); }
protected override void Emit(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsRegister); Debug.Assert(node.Operand1.IsRegister); Debug.Assert(node.Operand2.IsConstant); // reg from xmmreg, imm8 // 0110 0110:0000 1111:0011 1010: 0001 0110:11 xmmreg reg: imm8 var opcode = new OpcodeEncoder() .AppendNibble(Bits.b0110) // 4:opcode .AppendNibble(Bits.b0110) // 4:opcode .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b0011) // 4:opcode .AppendNibble(Bits.b1010) // 4:opcode .AppendNibble(Bits.b0001) // 4:opcode .AppendNibble(Bits.b0110) // 4:opcode .Append2Bits(Bits.b11) // 2:opcode .AppendRM(node.Operand1) // 3:r/m (source) .AppendRegister(node.Result.Register) // 3:register (destination) .AppendByteValue((byte)node.Operand2.ConstantUnsignedInteger); // 8:memory emitter.Emit(opcode); }
private static void MovsdRegToMemory(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand3.IsCPURegister); Debug.Assert(node.ResultCount == 0); Debug.Assert(!node.Operand3.IsConstant); // xmmreg1 to mem 1111 0010:0000 1111:0001 0001: mod xmmreg r/m var opcode = new OpcodeEncoder() .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b0010) // 4:opcode .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b0001) // 4:opcode .AppendNibble(Bits.b0001) // 4:opcode // This opcode has a directionality bit, and it is set to 0 // This means we must swap around operand1 and operand3, and set offsetDestination to false .ModRegRMSIBDisplacement(false, node.Operand3, node.Operand1, node.Operand2) // Mod-Reg-RM-?SIB-?Displacement .AppendConditionalIntegerValue(node.Operand1.IsLinkerResolved, 0); // 32:memory if (node.Operand1.IsLinkerResolved) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
private static void LeaAddress(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsCPURegister); // LEA – Load Effective Address 1000 1101 : modA reg r/m var opcode = new OpcodeEncoder() .AppendConditionalPrefix(node.Size == InstructionSize.Size16, 0x66) // 8:prefix: 16bit .AppendNibble(Bits.b1000) // 4:opcode .AppendNibble(Bits.b1101) // 3:opcode .ModRegRMSIBDisplacement(false, node.Result, node.Operand1, node.Operand2) // Mod-Reg-RM-?SIB-?Displacement .AppendConditionalIntegerValue(node.Operand1.IsLinkerResolved, 0); // 32:memory if (node.Operand1.IsLinkerResolved) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
private static void MovsxRegToReg(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsRegister); Debug.Assert(node.Operand1.IsRegister); // register2 to register1 0000 1111 : 1011 111w : 11 reg1 reg2 var opcode = new OpcodeEncoder() .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b1011) // 4:opcode .Append3Bits(Bits.b111) // 4:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width .AppendMod(Bits.b11) // 2:mod .AppendRegister(node.Result) // 3:register (destination) .AppendRM(node.Operand1); // 3:r/m (source) emitter.Emit(opcode); }
private static void MovsxMemoryToReg(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsCPURegister); // memory to reg 0000 1111 : 1011 111w : mod reg r/m var opcode = new OpcodeEncoder() .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b1011) // 4:opcode .Append3Bits(Bits.b111) // 4:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width .ModRegRMSIBDisplacement(false, node.Result, node.Operand1, node.Operand2) // Mod-Reg-RM-?SIB-?Displacement .AppendConditionalIntegerValue(node.Operand1.IsLinkerResolved, 0); // 32:memory if (node.Operand1.IsLinkerResolved) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
private static void MovMemoryToReg(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsRegister); var linkreference = node.Operand1.IsLabel || node.Operand1.IsField || node.Operand1.IsSymbol; // memory to reg 1000 101w: mod reg r/m var opcode = new OpcodeEncoder() .AppendConditionalPrefix(0x66, node.Size == InstructionSize.Size16) // 8:prefix: 16bit .AppendNibble(Bits.b1000) // 4:opcode .Append3Bits(Bits.b101) // 3:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width .ModRegRMSIBDisplacement(node.Result, node.Operand1, node.Operand2) // Mod-Reg-RM-?SIB-?Displacement .AppendConditionalIntegerValue(0, linkreference); // 32:memory if (linkreference) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
private static void InvlpgMemory(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand1.IsConstant); // INVLPG – Invalidate TLB Entry 0000 1111 : 0000 0001 : mod 111 r/m var opcode = new OpcodeEncoder() .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b0001) // 4:opcode .Append2Bits(Bits.b00) // 2:mod (must not be b11) .Append3Bits(Bits.b010) // 3:reg .AppendRM(node.Operand1) // 3:r/m (source, always b101) .AppendConditionalDisplacement(!node.Operand1.IsConstantZero, node.Operand1) // 32:displacement value .AppendConditionalIntegerValue(node.Operand1.IsLinkerResolved, 0); // 32:memory if (node.Operand1.IsLinkerResolved) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
private static void MovFixedMemoryToReg(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsCPURegister); Debug.Assert(node.Operand1.IsLinkerResolved); // memory to reg 1000 101w: mod reg r/m var opcode = new OpcodeEncoder() .AppendConditionalPrefix(node.Size == InstructionSize.Size16, 0x66) // 8:prefix: 16bit .AppendNibble(Bits.b1000) // 4:opcode .Append3Bits(Bits.b101) // 3:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width .AppendMod(Bits.b00) // 2:mod .AppendRegister(node.Result.Register) // 3:register (destination) .AppendRM(Bits.b101) // 3:r/m (source) .AppendConditionalIntegerValue(node.Operand1.IsLinkerResolved, 0); // 32:memory if (node.Operand1.IsLinkerResolved) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8, node.Operand2.ConstantSignedInteger); else emitter.Emit(opcode); }
private static void LgdtMemoryConstant(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand1.IsConstant); // LGDT – Load Global Descriptor Table Register 0000 1111 : 0000 0001 : modA 010 r / m var opcode = new OpcodeEncoder() .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b0001) // 4:opcode .Append2Bits(Bits.b00) // 2:mod (must not be b11) .Append3Bits(Bits.b010) // 3:reg .AppendRM(node.Operand1) // 3:r/m (source, always b101) .AppendConditionalDisplacement(!node.Operand1.IsConstantZero, node.Operand1) // 32:displacement value .AppendConditionalIntegerValue(node.Operand1.IsLinkerResolved, 0); // 32:memory if (node.Operand1.IsLinkerResolved) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
private static void MovapsMemoryToReg(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsRegister); var linkreference = node.Operand1.IsLabel || node.Operand1.IsField || node.Operand1.IsSymbol; // mem to xmmreg 1111 0011:0000 1111:0101 1101: mod xmmreg r/m var opcode = new OpcodeEncoder() .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b0011) // 4:opcode .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b0101) // 4:opcode .AppendNibble(Bits.b1101) // 4:opcode .ModRegRMSIBDisplacement(node.Result, node.Operand1, node.Operand2) // Mod-Reg-RM-?SIB-?Displacement .AppendConditionalIntegerValue(0, linkreference); // 32:memory if (linkreference) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
public void Emit(OpcodeEncoder opcode, Operand symbolOperand, int patchOffset, int referenceOffset = 0) { int pos = (int)codeStream.Position + patchOffset; Emit(opcode); if (symbolOperand.IsLabel) { linker.Link(LinkType.AbsoluteAddress, PatchType.I4, SectionKind.Text, MethodName, pos, SectionKind.ROData, symbolOperand.Name, referenceOffset); } else if (symbolOperand.IsStaticField) { var section = symbolOperand.Field.Data != null ? SectionKind.ROData : SectionKind.BSS; linker.Link(LinkType.AbsoluteAddress, PatchType.I4, SectionKind.Text, MethodName, pos, section, symbolOperand.Field.FullName, referenceOffset); } else if (symbolOperand.IsSymbol) { var section = symbolOperand.Method != null ? SectionKind.Text : SectionKind.ROData; // First try finding the symbol in the expected section var symbol = linker.FindSymbol(symbolOperand.Name, section); // If no symbol found, look in all sections if (symbol == null) { symbol = linker.FindSymbol(symbolOperand.Name); } // Otherwise create the symbol in the expected section if (symbol == null) { symbol = linker.GetSymbol(symbolOperand.Name, section); } linker.Link(LinkType.AbsoluteAddress, PatchType.I4, SectionKind.Text, MethodName, pos, symbol, referenceOffset); } }
private static void MovupsMemoryToReg(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsRegister); var linkreference = node.Operand1.IsLabel || node.Operand1.IsField || node.Operand1.IsSymbol; // mem to xmmreg1 0000 1111:0001 0000: mod xmmreg r/m var opcode = new OpcodeEncoder() .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b0001) // 4:opcode .AppendNibble(Bits.b0000) // 4:opcode .AppendMod(true, node.Operand2) // 2:mod .AppendRegister(node.Result.Register) // 3:register (destination) .AppendRM(node.Operand1) // 3:r/m (source) .AppendConditionalDisplacement(node.Operand2, !node.Operand2.IsConstantZero) // 8/32:displacement value .AppendConditionalIntegerValue(0, linkreference); // 32:memory if (linkreference) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
private static void LidtMemoryConstant(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand1.IsConstant); var linkreference = node.Operand1.IsLabel || node.Operand1.IsField || node.Operand1.IsSymbol; // LIDT – Load Interrupt Descriptor Table Register 0000 1111 : 0000 0001 : modA 011 r/m var opcode = new OpcodeEncoder() .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b0001) // 4:opcode .Append2Bits(Bits.b00) // 2:mod (must not be b11) .Append3Bits(Bits.b011) // 3:reg .AppendRM(node.Operand1) // 3:r/m (source, always b101) .AppendConditionalDisplacement(node.Operand1, !node.Operand1.IsConstantZero) // 32:displacement value .AppendConditionalIntegerValue(0, linkreference); // 32:memory if (linkreference) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
protected override void Emit(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Result.IsCPURegister); Debug.Assert(node.Operand1.IsCPURegister); // reg from mmxreg // 0000 1111:0111 1110: 11 mmxreg reg var opcode = new OpcodeEncoder() .AppendNibble(Bits.b0110) // 4:opcode .AppendNibble(Bits.b0110) // 4:opcode .AppendNibble(Bits.b0000) // 4:opcode .AppendNibble(Bits.b1111) // 4:opcode .Append3Bits(Bits.b011) // 3:opcode .AppendBit(node.Result.Register.Width != 128) // 1:direction .AppendNibble(Bits.b1110) // 4:opcode .Append2Bits(Bits.b11) // 2:opcode .AppendRM(node.Operand1) // 3:r/m (source) .AppendRegister(node.Result.Register); // 3:register (destination) emitter.Emit(opcode); }
private static void MovImmediateToMemory(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand3.IsConstant); // immediate to memory 1100 011w: mod 000 r/m : immediate data var opcode = new OpcodeEncoder() .AppendConditionalPrefix(node.Size == InstructionSize.Size16, 0x66) // 8:prefix: 16bit .AppendNibble(Bits.b1100) // 4:opcode .Append3Bits(Bits.b011) // 3:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width .ModRegRMSIBDisplacement(true, node.Operand1, node.Operand3, node.Operand2) // Mod-Reg-RM-?SIB-?Displacement .AppendInteger(node.Operand3, node.Size) // 8/16/32:immediate .AppendConditionalIntegerValue(node.Operand3.IsLinkerResolved, 0); // 32:memory if (node.Operand3.IsLinkerResolved) emitter.Emit(opcode, node.Operand3, 24 / 8, node.Operand2.ConstantSignedInteger); else emitter.Emit(opcode); }
private static void MovRegToFixedMemory(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand3.IsCPURegister); Debug.Assert(!node.Operand3.IsConstant); Debug.Assert(node.Operand1.IsConstant); // reg to memory 1000 100w: mod reg r/m var opcode = new OpcodeEncoder() .AppendConditionalPrefix(node.Size == InstructionSize.Size16, 0x66) // 8:prefix: 16bit .AppendNibble(Bits.b1000) // 4:opcode .Append3Bits(Bits.b100) // 3:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width .AppendMod(Bits.b00) // 2:mod (00) .AppendRegister(node.Operand3) // 3:source .AppendRegister(Bits.b101) // 3:r/m (101=Fixed Displacement) .AppendConditionalIntegerValue(node.Operand1.IsLinkerResolved, 0) // 32:memory .AppendConditionalIntegerValue(!node.Operand1.IsLinkerResolved, node.Operand1.ConstantUnsignedInteger); // 32:memory if (node.Operand1.IsLinkerResolved) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8, node.Operand2.ConstantSignedInteger); else emitter.Emit(opcode); }
private static void MovRegToMemory(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand3.IsCPURegister); Debug.Assert(!node.Operand3.IsConstant); // reg to memory 1000 100w: mod reg r/m var opcode = new OpcodeEncoder() .AppendConditionalPrefix(node.Size == InstructionSize.Size16, 0x66) // 8:prefix: 16bit .AppendNibble(Bits.b1000) // 4:opcode .Append3Bits(Bits.b100) // 3:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width // This opcode has a directionality bit, and it is set to 0 // This means we must swap around operand1 and operand3, and set offsetDestination to false .ModRegRMSIBDisplacement(false, node.Operand3, node.Operand1, node.Operand2) // Mod-Reg-RM-?SIB-?Displacement .AppendConditionalIntegerValue(node.Operand1.IsLinkerResolved, 0); // 32:displacement if (node.Operand1.IsLinkerResolved) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }
private static void MovImmediateToFixedMemory(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand1.IsConstant); Debug.Assert(node.Operand2.IsResolvedConstant); Debug.Assert(node.Operand3.IsConstant); // immediate to memory 1100 011w: mod 000 r/m : immediate data var opcode = new OpcodeEncoder() .AppendConditionalPrefix(node.Size == InstructionSize.Size16, 0x66) // 8:prefix: 16bit .AppendNibble(Bits.b1100) // 4:opcode .Append3Bits(Bits.b011) // 3:opcode .AppendWidthBit(node.Size != InstructionSize.Size8) // 1:width .AppendMod(Bits.b00) // 2:mod (00) .Append3Bits(Bits.b000) // 3:source (000) .AppendRM(node.Operand1) // 3:r/m (destination) .AppendConditionalDisplacement(!node.Operand1.IsLinkerResolved, node.Operand1) // 32:displacement value .AppendConditionalIntegerValue(node.Operand1.IsLinkerResolved, 0) // 32:memory .AppendInteger(node.Operand3, node.Size); // 8/16/32:immediate if (node.Operand1.IsLinkerResolved && !node.Operand3.IsLinkerResolved) emitter.Emit(opcode, node.Operand1, 2, node.Operand2.ConstantSignedInteger); else if (node.Operand1.IsLinkerResolved && node.Operand3.IsLinkerResolved) { // fixme: trouble! throw new NotImplementCompilerException("not here"); } else emitter.Emit(opcode); }
/// <summary> /// Emits the specified opcode. /// </summary> /// <param name="opcode">The opcode.</param> public void Emit(OpcodeEncoder opcode) { opcode.WriteTo(codeStream); }
private static void MovRegToMemory(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand3.IsRegister); Debug.Assert(node.ResultCount == 0); Debug.Assert(!node.Operand3.IsConstant); var size = BaseMethodCompilerStage.GetInstructionSize(node.Size, node.Operand1.Type); var linkreference = node.Operand1.IsLabel || node.Operand1.IsField || node.Operand1.IsSymbol; // reg to memory 1000 100w: mod reg r/m var opcode = new OpcodeEncoder() .AppendConditionalPrefix(0x66, size == InstructionSize.Size16) // 8:prefix: 16bit .AppendNibble(Bits.b1000) // 4:opcode .Append3Bits(Bits.b100) // 3:opcode .AppendWidthBit(size != InstructionSize.Size8) // 1:width .ModRegRMSIBDisplacement(node.Operand3, node.Operand1, node.Operand2) // Mod-Reg-RM-?SIB-?Displacement .AppendConditionalIntegerValue(0, linkreference); // 32:memory if (linkreference) emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); else emitter.Emit(opcode); }