1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Diagnostics; 7 8 namespace ILCompiler.DependencyAnalysis.X86 9 { 10 public struct X86Emitter 11 { X86EmitterILCompiler.DependencyAnalysis.X86.X86Emitter12 public X86Emitter(NodeFactory factory, bool relocsOnly) 13 { 14 Builder = new ObjectDataBuilder(factory, relocsOnly); 15 TargetRegister = new TargetRegisterMap(factory.Target.OperatingSystem); 16 } 17 18 public ObjectDataBuilder Builder; 19 public TargetRegisterMap TargetRegister; 20 EmitADDILCompiler.DependencyAnalysis.X86.X86Emitter21 public void EmitADD(ref AddrMode addrMode, sbyte immediate) 22 { 23 if (addrMode.Size == AddrModeSize.Int16) 24 Builder.EmitByte(0x66); 25 EmitIndirInstruction((byte)((addrMode.Size != AddrModeSize.Int8) ? 0x83 : 0x80), (byte)0, ref addrMode); 26 Builder.EmitByte((byte)immediate); 27 } 28 EmitJMPILCompiler.DependencyAnalysis.X86.X86Emitter29 public void EmitJMP(ISymbolNode symbol) 30 { 31 if (symbol.RepresentsIndirectionCell) 32 { 33 Builder.EmitByte(0xff); 34 Builder.EmitByte(0x25); 35 Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); 36 } 37 else 38 { 39 Builder.EmitByte(0xE9); 40 Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); 41 } 42 } 43 EmitINT3ILCompiler.DependencyAnalysis.X86.X86Emitter44 public void EmitINT3() 45 { 46 Builder.EmitByte(0xCC); 47 } 48 InSignedByteRangeILCompiler.DependencyAnalysis.X86.X86Emitter49 private bool InSignedByteRange(int i) 50 { 51 return i == (int)(sbyte)i; 52 } 53 EmitImmediateILCompiler.DependencyAnalysis.X86.X86Emitter54 private void EmitImmediate(int immediate, int size) 55 { 56 switch (size) 57 { 58 case 0: 59 break; 60 case 1: 61 Builder.EmitByte((byte)immediate); 62 break; 63 case 2: 64 Builder.EmitShort((short)immediate); 65 break; 66 case 4: 67 Builder.EmitInt(immediate); 68 break; 69 default: 70 throw new NotImplementedException(); 71 } 72 } 73 EmitModRMILCompiler.DependencyAnalysis.X86.X86Emitter74 private void EmitModRM(byte subOpcode, ref AddrMode addrMode) 75 { 76 byte modRM = (byte)((subOpcode & 0x07) << 3); 77 if (addrMode.BaseReg > Register.None) 78 { 79 Debug.Assert(addrMode.BaseReg >= Register.RegDirect); 80 81 Register reg = (Register)(addrMode.BaseReg - Register.RegDirect); 82 Builder.EmitByte((byte)(0xC0 | modRM | ((int)reg & 0x07))); 83 } 84 else 85 { 86 byte lowOrderBitsOfBaseReg = (byte)((int)addrMode.BaseReg & 0x07); 87 modRM |= lowOrderBitsOfBaseReg; 88 int offsetSize = 0; 89 90 if (addrMode.Offset == 0 && (lowOrderBitsOfBaseReg != (byte)Register.EBP)) 91 { 92 offsetSize = 0; 93 } 94 else if (InSignedByteRange(addrMode.Offset)) 95 { 96 offsetSize = 1; 97 modRM |= 0x40; 98 } 99 else 100 { 101 offsetSize = 4; 102 modRM |= 0x80; 103 } 104 105 bool emitSibByte = false; 106 Register sibByteBaseRegister = addrMode.BaseReg; 107 108 if (addrMode.BaseReg == Register.None) 109 { 110 emitSibByte = (addrMode.IndexReg != Register.NoIndex); 111 modRM &= 0x38; // set Mod bits to 00 and clear out base reg 112 offsetSize = 4; // this forces 32-bit displacement 113 114 if (emitSibByte) 115 { 116 // EBP in SIB byte means no base 117 // ModRM base register forced to ESP in SIB code below 118 sibByteBaseRegister = Register.EBP; 119 } 120 else 121 { 122 // EBP in ModRM means no base 123 modRM |= (byte)(Register.EBP); 124 } 125 } 126 else if (lowOrderBitsOfBaseReg == (byte)Register.ESP || addrMode.IndexReg.HasValue) 127 { 128 emitSibByte = true; 129 } 130 131 if (!emitSibByte) 132 { 133 Builder.EmitByte(modRM); 134 } 135 else 136 { 137 modRM = (byte)((modRM & 0xF8) | (int)Register.ESP); 138 Builder.EmitByte(modRM); 139 int indexRegAsInt = (int)(addrMode.IndexReg.HasValue ? addrMode.IndexReg.Value : Register.ESP); 140 Builder.EmitByte((byte)((addrMode.Scale << 6) + ((indexRegAsInt & 0x07) << 3) + ((int)sibByteBaseRegister & 0x07))); 141 } 142 EmitImmediate(addrMode.Offset, offsetSize); 143 } 144 } 145 EmitExtendedOpcodeILCompiler.DependencyAnalysis.X86.X86Emitter146 private void EmitExtendedOpcode(int opcode) 147 { 148 if ((opcode >> 16) != 0) 149 { 150 if ((opcode >> 24) != 0) 151 { 152 Builder.EmitByte((byte)(opcode >> 24)); 153 } 154 Builder.EmitByte((byte)(opcode >> 16)); 155 } 156 Builder.EmitByte((byte)(opcode >> 8)); 157 } 158 EmitIndirInstructionILCompiler.DependencyAnalysis.X86.X86Emitter159 private void EmitIndirInstruction(int opcode, byte subOpcode, ref AddrMode addrMode) 160 { 161 if ((opcode >> 8) != 0) 162 { 163 EmitExtendedOpcode(opcode); 164 } 165 Builder.EmitByte((byte)opcode); 166 EmitModRM(subOpcode, ref addrMode); 167 } 168 } 169 } 170