// // Copyright (c) Microsoft Corporation. All rights reserved. // using System; using System.Collections; using System.IO; using Bartok.DebugInfo; namespace Bartok.MSIL { public class Instruction { // Constructor Methods internal static Instruction[] getInstructions(MetaDataLoader mdLoader, Stream fileStream, int codeOffset, int[] lines, int[] columns, int[] offsets, String srcFileName, int lineCount, out EHClause[] ehTable, out int[] bbTable, out int maxStack, out Signature.Type[] locals, out bool initLocals) { fileStream.Seek(codeOffset, SeekOrigin.Begin); BinaryReader reader = new BinaryReader(fileStream); byte headerByte = reader.ReadByte(); byte formatMask = (byte) (headerByte & 0x7); int codeSize; byte[] codeBytes; ehTable = sharedEmptyTable; switch ((MethodFormats) formatMask) { case MethodFormats.Tiny: case MethodFormats.Tiny1: { initLocals = false; maxStack = 8; codeSize = headerByte >> 2; locals = null; codeBytes = new byte[codeSize]; int count = reader.Read(codeBytes, 0, codeSize); if (count != codeSize) { throw new IllegalInstructionStreamException("Only got "+count+" out of "+codeSize+" code bytes"); } break; } case MethodFormats.Fat: { // for Fat format, check for CorILMethod_InitLocals // Section 24.4.4 of ECMA spec, partition II initLocals = ((headerByte & 0x10) != 0); byte headerByte2 = reader.ReadByte(); int size = headerByte2 >> 4; if (size != 3) { throw new IllegalInstructionStreamException("Unexpected FAT size: "+size); } maxStack = reader.ReadUInt16(); codeSize = reader.ReadInt32(); int localVarSignatureToken = reader.ReadInt32(); if (localVarSignatureToken == 0) { locals = null; } else { MetaDataStandAloneSig standAloneSig = (MetaDataStandAloneSig) mdLoader.getObjectFromToken(localVarSignatureToken); Signature unresolvedSignature = standAloneSig.Signature; SignatureLocalVar localVarSignature = (SignatureLocalVar) unresolvedSignature.resolve(mdLoader); locals = localVarSignature.Locals; } codeBytes = new byte[codeSize]; int count = reader.Read(codeBytes, 0, codeSize); if (count != codeSize) { throw new IllegalInstructionStreamException("Only got "+count+" out of "+codeSize+" code bytes"); } break; } default: { throw new IllegalInstructionStreamException("Unknown format: "+formatMask.ToString("x")); } } int pcLimit = codeBytes.Length; int[] byteToInstrMapping = new int[pcLimit+1]; int instructionCount = 0; int instructionLength, operandLength; for (int pc = 0; pc < pcLimit; pc += instructionLength + operandLength) { byteToInstrMapping[pc] = instructionCount; instructionCount++; Opcode opcode = (Opcode) codeBytes[pc]; switch (opcode) { case Opcode.PREFIX1: instructionLength = 2; opcode = (Opcode) (codeBytes[pc+1] + 256); if (opcode < 0 || (Opcode) opcode >= Opcode.COUNT) { throw new IllegalInstructionStreamException("Saw prefixed opcode of "+opcode); } break; case Opcode.PREFIXREF: case Opcode.PREFIX2: case Opcode.PREFIX3: case Opcode.PREFIX4: case Opcode.PREFIX5: case Opcode.PREFIX6: case Opcode.PREFIX7: throw new IllegalInstructionStreamException("Saw unexpected prefix opcode "+opcode); default: instructionLength = 1; break; } OpcodeInfo opcodeInfo = opcodeInfoTable[(int) opcode]; operandLength = opcodeInfo.operandSize; if (operandLength == 0xFF) { int operandOffset = pc + instructionLength; switch (opcodeInfo.operandFormat) { case OperandFormat.Switch: { int caseCount = intFromCodeBytes(codeBytes, operandOffset); operandLength = 4 + 4 * caseCount; break; } case OperandFormat.InlinePhi: { int caseCount = codeBytes[operandOffset]; operandLength = 1 + 2 * caseCount; break; } case OperandFormat.BranchTarget: { int byteCount = intFromCodeBytes(codeBytes, operandOffset); operandLength = 4 + byteCount; break; } case OperandFormat.ShortBranchTarget: { int byteCount = codeBytes[operandOffset]; operandLength = 1 + byteCount; break; } default: throw new IllegalInstructionStreamException("Unexpected operand format "+opcodeInfo.operandFormat); } } } byteToInstrMapping[pcLimit] = instructionCount; BitArray bbStarts = new BitArray(instructionCount+1); // Check whether or not there is an EH section if (formatMask == (byte) MethodFormats.Fat && (headerByte & 0x08) != 0) { int sectionPadding = (codeOffset + codeSize) % 4; if (sectionPadding != 0) { while (sectionPadding < 4) { sectionPadding++; byte padding = reader.ReadByte(); } } byte sectionKind = reader.ReadByte(); if ((sectionKind & 0x80) != 0) { throw new IllegalInstructionStreamException("More than one section after the code"); } if ((sectionKind & 0x3f) != (int) SectionKind.EHTable) { throw new IllegalInstructionStreamException("Expected EH table section, got "+sectionKind.ToString("x")); } int dataSize; if ((sectionKind & 0x40) == 0) { // Small section int ehByteCount = reader.ReadByte(); dataSize = (ehByteCount) / 12; int headerSize = (ehByteCount % 12); if ((headerSize != 0) && (headerSize != 4)) { throw new IllegalInstructionStreamException("Unexpected byte count for small EH table: "+ehByteCount); } int sectSmallReserved = reader.ReadInt16(); ehTable = new EHClause[dataSize]; for (int i = 0; i < dataSize; i++) { int flags = reader.ReadUInt16(); int tryOffset = reader.ReadUInt16(); int tryLength = reader.ReadByte(); int handlerOffset = reader.ReadUInt16(); int handlerLength = reader.ReadByte(); int tokenOrOffset = (i+1==dataSize && headerSize==0 && flags != (int) EHClause.ExceptionFlag.None) ? 0 : // The VC++ compiler did not output a 0 here! reader.ReadInt32(); int tryInstrOffset = byteToInstrMapping[tryOffset]; bbStarts[tryInstrOffset] =true; int tryInstrEnd = byteToInstrMapping[tryOffset + tryLength]; int handlerInstrOffset = byteToInstrMapping[handlerOffset]; bbStarts[handlerInstrOffset] = true; int handlerInstrEnd = byteToInstrMapping[handlerOffset + handlerLength]; bbStarts[handlerInstrEnd] = true; MetaDataObject classObject = null; if ((flags & (int) EHClause.ExceptionFlag.Filter) != 0) { tokenOrOffset = byteToInstrMapping[tokenOrOffset]; bbStarts[tokenOrOffset] = true; } else if (flags == (int) EHClause.ExceptionFlag.None) { classObject = mdLoader.getObjectFromToken(tokenOrOffset); tokenOrOffset = 0; } else { // The VC++ compiler is known to get the ehByteCount // wrong and generate spurious data for tokenOrOffset if (headerSize != 0 && tokenOrOffset != 0) { Console.WriteLine("Unknown token or offset "+tokenOrOffset.ToString("x8")); } } ehTable[i] = new EHClause(flags, tryInstrOffset, tryInstrEnd - tryInstrOffset, handlerInstrOffset, handlerInstrEnd - handlerInstrOffset, tokenOrOffset, classObject); } } else { // Fat section int ehByteCount; ehByteCount = reader.ReadByte(); ehByteCount |= reader.ReadByte() << 8; ehByteCount |= reader.ReadByte() << 16; dataSize = ehByteCount / 24; int headerSize = (ehByteCount % 12); if ((headerSize != 0) && (headerSize != 4)) { throw new IllegalInstructionStreamException("Unexpected byte count for fat EH table: "+ehByteCount); } ehTable = new EHClause[dataSize]; for (int i = 0; i < dataSize; i++) { int flags = reader.ReadInt32(); int tryOffset = reader.ReadInt32(); int tryLength = reader.ReadInt32(); int handlerOffset = reader.ReadInt32(); int handlerLength = reader.ReadInt32(); int tokenOrOffset = reader.ReadInt32(); int tryInstrOffset = byteToInstrMapping[tryOffset]; bbStarts[tryInstrOffset] = true; int tryInstrEnd = byteToInstrMapping[tryOffset + tryLength]; int handlerInstrOffset = byteToInstrMapping[handlerOffset]; bbStarts[handlerInstrOffset] = true; int handlerInstrEnd = byteToInstrMapping[handlerOffset + handlerLength]; bbStarts[handlerInstrEnd] = true; MetaDataObject classObject = null; if ((flags & (int) EHClause.ExceptionFlag.Filter) != 0) { tokenOrOffset = byteToInstrMapping[tokenOrOffset]; bbStarts[tokenOrOffset] = true; } else if (flags == (int) EHClause.ExceptionFlag.None) { classObject = mdLoader.getObjectFromToken(tokenOrOffset); tokenOrOffset = 0; } else { // The VC++ compiler is known to get the ehByteCount // wrong and generate spurious data for tokenOrOffset if (headerSize != 0 && tokenOrOffset != 0) { Console.WriteLine("Unknown token or offset "+tokenOrOffset.ToString("x8")); } } ehTable[i] = new EHClause(flags, tryInstrOffset, tryInstrEnd - tryInstrOffset, handlerInstrOffset, handlerInstrEnd - handlerInstrOffset, tokenOrOffset, classObject); } } } Instruction[] instructionTable = new Instruction[instructionCount]; int instructionCounter = 0; int currLineIndex = 0; int prevLineNumber = 0; DebugLineNumber lineInfo = null; for (int pc = 0; pc < pcLimit;) { if (pc > 0 && byteToInstrMapping[pc] == 0) { throw new IllegalInstructionStreamException("Out of sync at "+pc.ToString("x")); } // read in the line number information. int lineNumber = 0; int column = 0; if (lineCount != 0) { if (currLineIndex == lineCount - 1) { // last line. lineNumber = lines[currLineIndex]; } else { int nextOffset = offsets[currLineIndex+1]; if (pc < nextOffset) { lineNumber = lines[currLineIndex]; column = columns[currLineIndex]; } else if (pc == nextOffset) { // advance to next line record currLineIndex++; lineNumber = lines[currLineIndex]; column = columns[currLineIndex]; } else { Console.WriteLine("Error! Reading lineNumber"); } } } Opcode opcode = (Opcode) codeBytes[pc]; pc++; if (opcode == Opcode.PREFIX1) { opcode = (Opcode) (codeBytes[pc] + 256); pc++; } OpcodeInfo opcodeInfo = opcodeInfoTable[(int) opcode]; Operand operand; switch (opcodeInfo.operandFormat) { case OperandFormat.None: if (opcode == Opcode.RET || opcode == Opcode.THROW || opcode == Opcode.RETHROW || opcode == Opcode.ENDFINALLY || opcode == Opcode.ENDFILTER) { // mark the instruction after a throw, return, or // endfinally as the beginning of a basic block. // // If we have dead code, then there may be no branch to // it. if (pc < pcLimit) { bbStarts[byteToInstrMapping[pc]] = true; } } operand = null; break; case OperandFormat.Var: operand = new OperandInt(shortFromCodeBytes(codeBytes, pc)); pc += 2; break; case OperandFormat.Int: case OperandFormat.RVA: operand = new OperandInt(intFromCodeBytes(codeBytes, pc)); pc += 4; break; case OperandFormat.Float: operand = new OperandDouble(doubleFromCodeBytes(codeBytes, pc)); pc += 8; break; case OperandFormat.BranchTarget: { int target = intFromCodeBytes(codeBytes, pc); pc += 4; if (opcodeInfo.operandSize == 0xFF) { // Random data inserted into instruction stream byte[] dataBuffer = new byte[target]; Array.Copy(codeBytes, pc, dataBuffer, 0, target); pc += target; operand = new OperandByteArray(dataBuffer); } else { // A real branch target int instrTarget = byteToInstrMapping[pc+target]; bbStarts[instrTarget] = true; // Fall through branch should be marked too bbStarts[instructionCounter+1] = true; operand = new OperandTarget(instrTarget); } break; } case OperandFormat.Int8: operand = new OperandLong(longFromCodeBytes(codeBytes, pc)); pc += 8; break; case OperandFormat.Method: { int token = intFromCodeBytes(codeBytes, pc); pc += 4; MetaDataObject mdMethod = mdLoader.getObjectFromToken(token); operand = new OperandObject(mdMethod); break; } case OperandFormat.Field: { int token = intFromCodeBytes(codeBytes, pc); pc += 4; int index = token & 0x00FFFFFF; MetaDataObject mdField = mdLoader.getObjectFromToken(token); operand = new OperandObject(mdField); break; } case OperandFormat.Type: { int token = intFromCodeBytes(codeBytes, pc); pc += 4; MetaDataObject type = mdLoader.getObjectFromToken(token); operand = new OperandObject(type); break; } case OperandFormat.Token: { int token = intFromCodeBytes(codeBytes, pc); pc += 4; MetaDataObject mdToken = mdLoader.getObjectFromToken(token); operand = new OperandObject(mdToken); break; } case OperandFormat.String: { int token = intFromCodeBytes(codeBytes, pc); pc += 4; if (((uint) token & 0xFF000000) != (uint) MetaDataLoader.TokenType.String) { throw new IllegalInstructionStreamException("Unexpected string token "+token.ToString("x")); } int index = token & 0x00FFFFFF; operand = new OperandString(mdLoader.getUserString(index)); break; } case OperandFormat.Sig: { int token = intFromCodeBytes(codeBytes, pc); pc += 4; MetaDataObject calleeDescr = mdLoader.getObjectFromToken(token); operand = new OperandObject(calleeDescr); break; } case OperandFormat.Switch: { int caseCount = intFromCodeBytes(codeBytes, pc); pc += 4; int[] branchArray = new int[caseCount]; int nextPC = pc + 4 * caseCount; for (int j = 0; j < caseCount; j++) { int target = intFromCodeBytes(codeBytes, pc); pc += 4; int instrTarget = byteToInstrMapping[nextPC+target]; bbStarts[instrTarget] = true; branchArray[j] = instrTarget; } bbStarts[instructionCounter+1] = true; // Fall through operand = new OperandTargetArray(branchArray); break; } case OperandFormat.InlinePhi: { int caseCount = codeBytes[pc]; pc++; byte[] varArray = new byte[caseCount]; for (int j = 0; j < caseCount; j++) { varArray[j] = codeBytes[pc]; pc++; } operand = new OperandByteArray(varArray); break; } case OperandFormat.ShortVar: operand = new OperandInt(codeBytes[pc]); pc++; break; case OperandFormat.ShortInt: { int value = codeBytes[pc]; pc++; if (value > 127) { value = -(256-value); } operand = new OperandInt(value); break; } case OperandFormat.ShortFloat: operand = new OperandSingle(singleFromCodeBytes(codeBytes, pc)); pc += 4; break; case OperandFormat.ShortBranchTarget: { int offset = codeBytes[pc]; pc++; if (offset > 127) { offset = -(256-offset); } int instrTarget = byteToInstrMapping[pc+offset]; bbStarts[instrTarget] = true; // Fall through branch should be marked too bbStarts[instructionCounter+1] = true; operand = new OperandTarget(instrTarget); break; } default: throw new IllegalInstructionStreamException("Unknown operand type "+opcodeInfo.operandFormat); } if (lineNumber != prevLineNumber && srcFileName != null) { lineInfo = new CVLineNumber(lineNumber, column, srcFileName); prevLineNumber = lineNumber; } instructionTable[instructionCounter] = new Instruction(opcode, operand, lineInfo); instructionCounter++; } int bbCount = 1; for (int i = 1; i < instructionCount; i++) { if (bbStarts[i]) { bbCount++; } } bbTable = new int[bbCount]; bbCount = 1; for (int i = 1; i < instructionCount; i++) { if (bbStarts[i]) { bbTable[bbCount] = i; bbCount++; } } return instructionTable; } private Instruction(Opcode opcode, Operand operand, DebugLineNumber lineNumber) { this.opcode = opcode; this.operand = operand; this.lineNumber = lineNumber; } // Access Methods public Opcode Operator { get { return this.opcode; } } public Operand Argument { get { return this.operand; } } public DebugLineNumber LineNumber { get { return this.lineNumber; } } public bool isControl() { return opcodeInfoTable[(int) this.opcode].isControl; } // Helper Methods private static int intFromCodeBytes(byte[] codeBytes, int offset) { return ((codeBytes[offset]) | (codeBytes[offset+1] << 8) | (codeBytes[offset+2] << 16) | (codeBytes[offset+3] << 24)); } private static short shortFromCodeBytes(byte[] codeBytes, int offset) { return (short) ((codeBytes[offset]) | (codeBytes[offset+1] << 8)); } private static long longFromCodeBytes(byte[] codeBytes, int offset) { return (((long) ((uint) (codeBytes[offset]) | (uint) (codeBytes[offset+1] << 8) | (uint) (codeBytes[offset+2] << 16) | (uint) (codeBytes[offset+3] << 24))) | (((long) ((uint) (codeBytes[offset+4]) | (uint) (codeBytes[offset+5] << 8) | (uint) (codeBytes[offset+6] << 16) | (uint) (codeBytes[offset+7] << 24))) << 32)); } private static float singleFromCodeBytes(byte[] codeBytes, int offset) { MemoryStream memoryStream = new MemoryStream(codeBytes, offset, 4); BinaryReader binaryReader = new BinaryReader(memoryStream); return binaryReader.ReadSingle(); } private static double doubleFromCodeBytes(byte[] codeBytes, int offset) { MemoryStream memoryStream = new MemoryStream(codeBytes, offset, 8); BinaryReader binaryReader = new BinaryReader(memoryStream); return binaryReader.ReadDouble(); } // Debug Methods public override String ToString() { if (lineNumber != null) { return (opcodeInfoTable[(int) this.opcode].name + lineNumber.ToString()); } else { return (opcodeInfoTable[(int) this.opcode].name); } } internal static void dumpToConsole(Instruction[] instructions) { int count = instructions.Length; for (int i = 0; i < count; i++) { Console.WriteLine("IL_"+i.ToString("x4")+": "+instructions[i]); } } // State private readonly Opcode opcode; private readonly Operand operand; private readonly DebugLineNumber lineNumber; // Internal Types private enum MethodFormats: byte { Tiny = 2, Fat = 3, Tiny1 = 6 } private enum SectionKind: byte { Reserved = 0, EHTable = 1, OptILTable = 2 } public enum Opcode: short { NOP, BREAK, LDARG_0, LDARG_1, LDARG_2, LDARG_3, LDLOC_0, LDLOC_1, LDLOC_2, LDLOC_3, STLOC_0, STLOC_1, STLOC_2, STLOC_3, LDARG_S, LDARGA_S, STARG_S, LDLOC_S, LDLOCA_S, STLOC_S, LDNULL, LDC_I4_M1, LDC_I4_0, LDC_I4_1, LDC_I4_2, LDC_I4_3, LDC_I4_4, LDC_I4_5, LDC_I4_6, LDC_I4_7, LDC_I4_8, LDC_I4_S, LDC_I4, LDC_I8, LDC_R4, LDC_R8, UNUSED49, DUP, POP, JMP, CALL, CALLI, RET, BR_S, BRFALSE_S, BRTRUE_S, BEQ_S, BGE_S, BGT_S, BLE_S, BLT_S, BNE_UN_S, BGE_UN_S, BGT_UN_S, BLE_UN_S, BLT_UN_S, BR, BRFALSE, BRTRUE, BEQ, BGE, BGT, BLE, BLT, BNE_UN, BGE_UN, BGT_UN, BLE_UN, BLT_UN, SWITCH, LDIND_I1, LDIND_U1, LDIND_I2, LDIND_U2, LDIND_I4, LDIND_U4, LDIND_I8, LDIND_I, LDIND_R4, LDIND_R8, LDIND_REF, STIND_REF, STIND_I1, STIND_I2, STIND_I4, STIND_I8, STIND_R4, STIND_R8, ADD, SUB, MUL, DIV, DIV_UN, REM, REM_UN, AND, OR, XOR, SHL, SHR, SHR_UN, NEG, NOT, CONV_I1, CONV_I2, CONV_I4, CONV_I8, CONV_R4, CONV_R8, CONV_U4, CONV_U8, CALLVIRT, CPOBJ, LDOBJ, LDSTR, NEWOBJ, CASTCLASS, ISINST, CONV_R_UN, ANN_DATA_S, UNUSED1, UNBOX, THROW, LDFLD, LDFLDA, STFLD, LDSFLD, LDSFLDA, STSFLD, STOBJ, CONV_OVF_I1_UN, CONV_OVF_I2_UN, CONV_OVF_I4_UN, CONV_OVF_I8_UN, CONV_OVF_U1_UN, CONV_OVF_U2_UN, CONV_OVF_U4_UN, CONV_OVF_U8_UN, CONV_OVF_I_UN, CONV_OVF_U_UN, BOX, NEWARR, LDLEN, LDELEMA, LDELEM_I1, LDELEM_U1, LDELEM_I2, LDELEM_U2, LDELEM_I4, LDELEM_U4, LDELEM_I8, LDELEM_I, LDELEM_R4, LDELEM_R8, LDELEM_REF, STELEM_I, STELEM_I1, STELEM_I2, STELEM_I4, STELEM_I8, STELEM_R4, STELEM_R8, STELEM_REF, LDELEM, STELEM, UNBOX_ANY, UNUSED5, UNUSED6, UNUSED7, UNUSED8, UNUSED9, UNUSED10, UNUSED11, UNUSED12, UNUSED13, UNUSED14, UNUSED15, UNUSED16, UNUSED17, CONV_OVF_I1, CONV_OVF_U1, CONV_OVF_I2, CONV_OVF_U2, CONV_OVF_I4, CONV_OVF_U4, CONV_OVF_I8, CONV_OVF_U8, UNUSED50, UNUSED18, UNUSED19, UNUSED20, UNUSED21, UNUSED22, UNUSED23, REFANYVAL, CKFINITE, UNUSED24, UNUSED25, MKREFANY, ANN_CALL, ANN_CATCH, ANN_DEAD, ANN_HOISTED, ANN_HOISTED_CALL, ANN_LAB, ANN_DEF, ANN_REF_S, ANN_PHI, LDTOKEN, CONV_U2, CONV_U1, CONV_I, CONV_OVF_I, CONV_OVF_U, ADD_OVF, ADD_OVF_UN, MUL_OVF, MUL_OVF_UN, SUB_OVF, SUB_OVF_UN, ENDFINALLY, LEAVE, LEAVE_S, STIND_I, CONV_U, UNUSED26, UNUSED27, UNUSED28, UNUSED29, UNUSED30, UNUSED31, UNUSED32, UNUSED33, UNUSED34, UNUSED35, UNUSED36, UNUSED37, UNUSED38, UNUSED39, UNUSED40, UNUSED41, UNUSED42, UNUSED43, UNUSED44, UNUSED45, UNUSED46, UNUSED47, UNUSED48, PREFIX7, PREFIX6, PREFIX5, PREFIX4, PREFIX3, PREFIX2, PREFIX1, PREFIXREF, ARGLIST, CEQ, CGT, CGT_UN, CLT, CLT_UN, LDFTN, LDVIRTFTN, UNUSED56, LDARG, LDARGA, STARG, LDLOC, LDLOCA, STLOC, LOCALLOC, UNUSED57, ENDFILTER, UNALIGNED, VOLATILE, TAILCALL, INITOBJ, ANN_LIVE, CPBLK, INITBLK, ANN_REF, RETHROW, UNUSED51, SIZEOF, REFANYTYPE, UNUSED52, UNUSED53, UNUSED54, UNUSED55, ANN_DATA, ILLEGAL, MACRO_END, COUNT } private enum OperandFormat: byte { None = 0, Var = 1, Int = 2, Float = 3, BranchTarget = 4, Int8 = 5, Method = 6, Field = 7, Type = 8, String = 9, Sig = 10, RVA = 11, Token = 12, Switch = 13, InlinePhi = 14, PrimaryMask = (ShortOperand-1), ShortOperand = 16, Opcode = (ShortOperand + None), ShortVar = (ShortOperand + Var), ShortInt = (ShortOperand + Int), ShortFloat = (ShortOperand + Float), ShortBranchTarget = (ShortOperand + BranchTarget), Illegal = 0Xff } private static readonly EHClause[] sharedEmptyTable = new EHClause[0]; private static readonly OpcodeInfo[] opcodeInfoTable = new OpcodeInfo[(int) Opcode.COUNT] { new OpcodeInfo("nop",Opcode.NOP,OperandFormat.None,0,false), new OpcodeInfo("break",Opcode.BREAK,OperandFormat.None,0,false), new OpcodeInfo("ldarg.0",Opcode.LDARG_0,OperandFormat.None,0,false), new OpcodeInfo("ldarg.1",Opcode.LDARG_1,OperandFormat.None,0,false), new OpcodeInfo("ldarg.2",Opcode.LDARG_2,OperandFormat.None,0,false), new OpcodeInfo("ldarg.3",Opcode.LDARG_3,OperandFormat.None,0,false), new OpcodeInfo("ldloc.0",Opcode.LDLOC_0,OperandFormat.None,0,false), new OpcodeInfo("ldloc.1",Opcode.LDLOC_1,OperandFormat.None,0,false), new OpcodeInfo("ldloc.2",Opcode.LDLOC_2,OperandFormat.None,0,false), new OpcodeInfo("ldloc.3",Opcode.LDLOC_3,OperandFormat.None,0,false), new OpcodeInfo("stloc.0",Opcode.STLOC_0,OperandFormat.None,0,false), new OpcodeInfo("stloc.1",Opcode.STLOC_1,OperandFormat.None,0,false), new OpcodeInfo("stloc.2",Opcode.STLOC_2,OperandFormat.None,0,false), new OpcodeInfo("stloc.3",Opcode.STLOC_3,OperandFormat.None,0,false), new OpcodeInfo("ldarg.s",Opcode.LDARG_S,OperandFormat.ShortVar,1,false), new OpcodeInfo("ldarga.s",Opcode.LDARGA_S,OperandFormat.ShortVar,1,false), new OpcodeInfo("starg.s",Opcode.STARG_S,OperandFormat.ShortVar,1,false), new OpcodeInfo("ldloc.s",Opcode.LDLOC_S,OperandFormat.ShortVar,1,false), new OpcodeInfo("ldloca.s",Opcode.LDLOCA_S,OperandFormat.ShortVar,1,false), new OpcodeInfo("stloc.s",Opcode.STLOC_S,OperandFormat.ShortVar,1,false), new OpcodeInfo("ldnull",Opcode.LDNULL,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.m1",Opcode.LDC_I4_M1,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.0",Opcode.LDC_I4_0,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.1",Opcode.LDC_I4_1,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.2",Opcode.LDC_I4_2,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.3",Opcode.LDC_I4_3,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.4",Opcode.LDC_I4_4,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.5",Opcode.LDC_I4_5,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.6",Opcode.LDC_I4_6,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.7",Opcode.LDC_I4_7,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.8",Opcode.LDC_I4_8,OperandFormat.None,0,false), new OpcodeInfo("ldc.i4.s",Opcode.LDC_I4_S,OperandFormat.ShortInt,1,false), new OpcodeInfo("ldc.i4",Opcode.LDC_I4,OperandFormat.Int,4,false), new OpcodeInfo("ldc.i8",Opcode.LDC_I8,OperandFormat.Int8,8,false), new OpcodeInfo("ldc.r4",Opcode.LDC_R4,OperandFormat.ShortFloat,4,false), new OpcodeInfo("ldc.r8",Opcode.LDC_R8,OperandFormat.Float,8,false), new OpcodeInfo("unused",Opcode.UNUSED49,OperandFormat.Illegal,0,false), new OpcodeInfo("dup",Opcode.DUP,OperandFormat.None,0,false), new OpcodeInfo("pop",Opcode.POP,OperandFormat.None,0,false), new OpcodeInfo("jmp",Opcode.JMP,OperandFormat.Method,4,true), new OpcodeInfo("call",Opcode.CALL,OperandFormat.Method,4,false), new OpcodeInfo("calli",Opcode.CALLI,OperandFormat.Sig,4,false), new OpcodeInfo("ret",Opcode.RET,OperandFormat.None,0,true), new OpcodeInfo("br.s",Opcode.BR_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("brfalse.s",Opcode.BRFALSE_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("brtrue.s",Opcode.BRTRUE_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("beq.s",Opcode.BEQ_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("bge.s",Opcode.BGE_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("bgt.s",Opcode.BGT_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("ble.s",Opcode.BLE_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("blt.s",Opcode.BLT_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("bne.un.s",Opcode.BNE_UN_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("bge.un.s",Opcode.BGE_UN_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("bgt.un.s",Opcode.BGT_UN_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("ble.un.s",Opcode.BLE_UN_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("blt.un.s",Opcode.BLT_UN_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("br",Opcode.BR,OperandFormat.BranchTarget,4,true), new OpcodeInfo("brfalse",Opcode.BRFALSE,OperandFormat.BranchTarget,4,true), new OpcodeInfo("brtrue",Opcode.BRTRUE,OperandFormat.BranchTarget,4,true), new OpcodeInfo("beq",Opcode.BEQ,OperandFormat.BranchTarget,4,true), new OpcodeInfo("bge",Opcode.BGE,OperandFormat.BranchTarget,4,true), new OpcodeInfo("bgt",Opcode.BGT,OperandFormat.BranchTarget,4,true), new OpcodeInfo("ble",Opcode.BLE,OperandFormat.BranchTarget,4,true), new OpcodeInfo("blt",Opcode.BLT,OperandFormat.BranchTarget,4,true), new OpcodeInfo("bne.un",Opcode.BNE_UN,OperandFormat.BranchTarget,4,true), new OpcodeInfo("bge.un",Opcode.BGE_UN,OperandFormat.BranchTarget,4,true), new OpcodeInfo("bgt.un",Opcode.BGT_UN,OperandFormat.BranchTarget,4,true), new OpcodeInfo("ble.un",Opcode.BLE_UN,OperandFormat.BranchTarget,4,true), new OpcodeInfo("blt.un",Opcode.BLT_UN,OperandFormat.BranchTarget,4,true), new OpcodeInfo("switch",Opcode.SWITCH,OperandFormat.Switch,0xFF,true), new OpcodeInfo("ldind.i1",Opcode.LDIND_I1,OperandFormat.None,0,false), new OpcodeInfo("ldind.u1",Opcode.LDIND_U1,OperandFormat.None,0,false), new OpcodeInfo("ldind.i2",Opcode.LDIND_I2,OperandFormat.None,0,false), new OpcodeInfo("ldind.u2",Opcode.LDIND_U2,OperandFormat.None,0,false), new OpcodeInfo("ldind.i4",Opcode.LDIND_I4,OperandFormat.None,0,false), new OpcodeInfo("ldind.u4",Opcode.LDIND_U4,OperandFormat.None,0,false), new OpcodeInfo("ldind.i8",Opcode.LDIND_I8,OperandFormat.None,0,false), new OpcodeInfo("ldind.i",Opcode.LDIND_I,OperandFormat.None,0,false), new OpcodeInfo("ldind.r4",Opcode.LDIND_R4,OperandFormat.None,0,false), new OpcodeInfo("ldind.r8",Opcode.LDIND_R8,OperandFormat.None,0,false), new OpcodeInfo("ldind.ref",Opcode.LDIND_REF,OperandFormat.None,0,false), new OpcodeInfo("stind.ref",Opcode.STIND_REF,OperandFormat.None,0,false), new OpcodeInfo("stind.i1",Opcode.STIND_I1,OperandFormat.None,0,false), new OpcodeInfo("stind.i2",Opcode.STIND_I2,OperandFormat.None,0,false), new OpcodeInfo("stind.i4",Opcode.STIND_I4,OperandFormat.None,0,false), new OpcodeInfo("stind.i8",Opcode.STIND_I8,OperandFormat.None,0,false), new OpcodeInfo("stind.r4",Opcode.STIND_R4,OperandFormat.None,0,false), new OpcodeInfo("stind.r8",Opcode.STIND_R8,OperandFormat.None,0,false), new OpcodeInfo("add",Opcode.ADD,OperandFormat.None,0,false), new OpcodeInfo("sub",Opcode.SUB,OperandFormat.None,0,false), new OpcodeInfo("mul",Opcode.MUL,OperandFormat.None,0,false), new OpcodeInfo("div",Opcode.DIV,OperandFormat.None,0,false), new OpcodeInfo("div.un",Opcode.DIV_UN,OperandFormat.None,0,false), new OpcodeInfo("rem",Opcode.REM,OperandFormat.None,0,false), new OpcodeInfo("rem.un",Opcode.REM_UN,OperandFormat.None,0,false), new OpcodeInfo("and",Opcode.AND,OperandFormat.None,0,false), new OpcodeInfo("or",Opcode.OR,OperandFormat.None,0,false), new OpcodeInfo("xor",Opcode.XOR,OperandFormat.None,0,false), new OpcodeInfo("shl",Opcode.SHL,OperandFormat.None,0,false), new OpcodeInfo("shr",Opcode.SHR,OperandFormat.None,0,false), new OpcodeInfo("shr.un",Opcode.SHR_UN,OperandFormat.None,0,false), new OpcodeInfo("neg",Opcode.NEG,OperandFormat.None,0,false), new OpcodeInfo("not",Opcode.NOT,OperandFormat.None,0,false), new OpcodeInfo("conv.i1",Opcode.CONV_I1,OperandFormat.None,0,false), new OpcodeInfo("conv.i2",Opcode.CONV_I2,OperandFormat.None,0,false), new OpcodeInfo("conv.i4",Opcode.CONV_I4,OperandFormat.None,0,false), new OpcodeInfo("conv.i8",Opcode.CONV_I8,OperandFormat.None,0,false), new OpcodeInfo("conv.r4",Opcode.CONV_R4,OperandFormat.None,0,false), new OpcodeInfo("conv.r8",Opcode.CONV_R8,OperandFormat.None,0,false), new OpcodeInfo("conv.u4",Opcode.CONV_U4,OperandFormat.None,0,false), new OpcodeInfo("conv.u8",Opcode.CONV_U8,OperandFormat.None,0,false), new OpcodeInfo("callvirt",Opcode.CALLVIRT,OperandFormat.Method,4,false), new OpcodeInfo("cpobj",Opcode.CPOBJ,OperandFormat.Type,4,false), new OpcodeInfo("ldobj",Opcode.LDOBJ,OperandFormat.Type,4,false), new OpcodeInfo("ldstr",Opcode.LDSTR,OperandFormat.String,4,false), new OpcodeInfo("newobj",Opcode.NEWOBJ,OperandFormat.Method,4,false), new OpcodeInfo("castclass",Opcode.CASTCLASS,OperandFormat.Type,4,false), new OpcodeInfo("isinst",Opcode.ISINST,OperandFormat.Type,4,false), new OpcodeInfo("conv.r.un",Opcode.CONV_R_UN,OperandFormat.None,0,false), new OpcodeInfo("ann.data.s",Opcode.ANN_DATA_S,OperandFormat.ShortBranchTarget,0xFF,false), new OpcodeInfo("unused",Opcode.UNUSED1,OperandFormat.Illegal,0,false), new OpcodeInfo("unbox",Opcode.UNBOX,OperandFormat.Type,4,false), new OpcodeInfo("throw",Opcode.THROW,OperandFormat.None,0,true), new OpcodeInfo("ldfld",Opcode.LDFLD,OperandFormat.Field,4,false), new OpcodeInfo("ldflda",Opcode.LDFLDA,OperandFormat.Field,4,false), new OpcodeInfo("stfld",Opcode.STFLD,OperandFormat.Field,4,false), new OpcodeInfo("ldsfld",Opcode.LDSFLD,OperandFormat.Field,4,false), new OpcodeInfo("ldsflda",Opcode.LDSFLDA,OperandFormat.Field,4,false), new OpcodeInfo("stsfld",Opcode.STSFLD,OperandFormat.Field,4,false), new OpcodeInfo("stobj",Opcode.STOBJ,OperandFormat.Type,4,false), new OpcodeInfo("conv.ovf.i1.un",Opcode.CONV_OVF_I1_UN,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.i2.un",Opcode.CONV_OVF_I2_UN,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.i4.un",Opcode.CONV_OVF_I4_UN,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.i8.un",Opcode.CONV_OVF_I8_UN,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u1.un",Opcode.CONV_OVF_U1_UN,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u2.un",Opcode.CONV_OVF_U2_UN,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u4.un",Opcode.CONV_OVF_U4_UN,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u8.un",Opcode.CONV_OVF_U8_UN,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.i.un",Opcode.CONV_OVF_I_UN,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u.un",Opcode.CONV_OVF_U_UN,OperandFormat.None,0,false), new OpcodeInfo("box",Opcode.BOX,OperandFormat.Type,4,false), new OpcodeInfo("newarr",Opcode.NEWARR,OperandFormat.Type,4,false), new OpcodeInfo("ldlen",Opcode.LDLEN,OperandFormat.None,0,false), new OpcodeInfo("ldelema",Opcode.LDELEMA,OperandFormat.Type,4,false), new OpcodeInfo("ldelem.i1",Opcode.LDELEM_I1,OperandFormat.None,0,false), new OpcodeInfo("ldelem.u1",Opcode.LDELEM_U1,OperandFormat.None,0,false), new OpcodeInfo("ldelem.i2",Opcode.LDELEM_I2,OperandFormat.None,0,false), new OpcodeInfo("ldelem.u2",Opcode.LDELEM_U2,OperandFormat.None,0,false), new OpcodeInfo("ldelem.i4",Opcode.LDELEM_I4,OperandFormat.None,0,false), new OpcodeInfo("ldelem.u4",Opcode.LDELEM_U4,OperandFormat.None,0,false), new OpcodeInfo("ldelem.i8",Opcode.LDELEM_I8,OperandFormat.None,0,false), new OpcodeInfo("ldelem.i",Opcode.LDELEM_I,OperandFormat.None,0,false), new OpcodeInfo("ldelem.r4",Opcode.LDELEM_R4,OperandFormat.None,0,false), new OpcodeInfo("ldelem.r8",Opcode.LDELEM_R8,OperandFormat.None,0,false), new OpcodeInfo("ldelem.ref",Opcode.LDELEM_REF,OperandFormat.None,0,false), new OpcodeInfo("stelem.i",Opcode.STELEM_I,OperandFormat.None,0,false), new OpcodeInfo("stelem.i1",Opcode.STELEM_I1,OperandFormat.None,0,false), new OpcodeInfo("stelem.i2",Opcode.STELEM_I2,OperandFormat.None,0,false), new OpcodeInfo("stelem.i4",Opcode.STELEM_I4,OperandFormat.None,0,false), new OpcodeInfo("stelem.i8",Opcode.STELEM_I8,OperandFormat.None,0,false), new OpcodeInfo("stelem.r4",Opcode.STELEM_R4,OperandFormat.None,0,false), new OpcodeInfo("stelem.r8",Opcode.STELEM_R8,OperandFormat.None,0,false), new OpcodeInfo("stelem.ref",Opcode.STELEM_REF,OperandFormat.None,0,false), new OpcodeInfo("ldelem",Opcode.LDELEM,OperandFormat.Type,4,false), new OpcodeInfo("stelem",Opcode.STELEM,OperandFormat.Type,4,false), new OpcodeInfo("unbox.any",Opcode.UNBOX_ANY,OperandFormat.Type,4,false), new OpcodeInfo("unused",Opcode.UNUSED5,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED6,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED7,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED8,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED9,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED10,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED11,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED12,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED13,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED14,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED15,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED16,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED17,OperandFormat.Illegal,0,false), new OpcodeInfo("conv.ovf.i1",Opcode.CONV_OVF_I1,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u1",Opcode.CONV_OVF_U1,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.i2",Opcode.CONV_OVF_I2,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u2",Opcode.CONV_OVF_U2,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.i4",Opcode.CONV_OVF_I4,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u4",Opcode.CONV_OVF_U4,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.i8",Opcode.CONV_OVF_I8,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u8",Opcode.CONV_OVF_U8,OperandFormat.None,0,false), new OpcodeInfo("unused",Opcode.UNUSED50,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED18,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED19,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED20,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED21,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED22,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED23,OperandFormat.Illegal,0,false), new OpcodeInfo("refanyval",Opcode.REFANYVAL,OperandFormat.Type,4,false), new OpcodeInfo("ckfinite",Opcode.CKFINITE,OperandFormat.None,0,false), new OpcodeInfo("unused",Opcode.UNUSED24,OperandFormat.None,0,false), new OpcodeInfo("unused",Opcode.UNUSED25,OperandFormat.None,0,false), new OpcodeInfo("mkrefany",Opcode.MKREFANY,OperandFormat.Type,4,false), new OpcodeInfo("ann.call",Opcode.ANN_CALL,OperandFormat.Method,4,false), new OpcodeInfo("ann.catch",Opcode.ANN_CATCH,OperandFormat.None,0,false), new OpcodeInfo("ann.dead",Opcode.ANN_DEAD,OperandFormat.Var,2,false), new OpcodeInfo("ann.hoisted",Opcode.ANN_HOISTED,OperandFormat.None,0,false), new OpcodeInfo("ann.hoisted_call",Opcode.ANN_HOISTED_CALL,OperandFormat.Method,4,false), new OpcodeInfo("ann.lab",Opcode.ANN_LAB,OperandFormat.None,0,false), new OpcodeInfo("ann.def",Opcode.ANN_DEF,OperandFormat.None,0,false), new OpcodeInfo("ann.ref.s",Opcode.ANN_REF_S,OperandFormat.ShortVar,1,false), new OpcodeInfo("ann.phi",Opcode.ANN_PHI,OperandFormat.InlinePhi,0xFF,false), new OpcodeInfo("ldtoken",Opcode.LDTOKEN,OperandFormat.Token,4,false), new OpcodeInfo("conv.u2",Opcode.CONV_U2,OperandFormat.None,0,false), new OpcodeInfo("conv.u1",Opcode.CONV_U1,OperandFormat.None,0,false), new OpcodeInfo("conv.i",Opcode.CONV_I,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.i",Opcode.CONV_OVF_I,OperandFormat.None,0,false), new OpcodeInfo("conv.ovf.u",Opcode.CONV_OVF_U,OperandFormat.None,0,false), new OpcodeInfo("add.ovf",Opcode.ADD_OVF,OperandFormat.None,0,false), new OpcodeInfo("add.ovf.un",Opcode.ADD_OVF_UN,OperandFormat.None,0,false), new OpcodeInfo("mul.ovf",Opcode.MUL_OVF,OperandFormat.None,0,false), new OpcodeInfo("mul.ovf.un",Opcode.MUL_OVF_UN,OperandFormat.None,0,false), new OpcodeInfo("sub.ovf",Opcode.SUB_OVF,OperandFormat.None,0,false), new OpcodeInfo("sub.ovf.un",Opcode.SUB_OVF_UN,OperandFormat.None,0,false), new OpcodeInfo("endfinally",Opcode.ENDFINALLY,OperandFormat.None,0,true), new OpcodeInfo("leave",Opcode.LEAVE,OperandFormat.BranchTarget,4,true), new OpcodeInfo("leave.s",Opcode.LEAVE_S,OperandFormat.ShortBranchTarget,1,true), new OpcodeInfo("stind.i",Opcode.STIND_I,OperandFormat.None,0,false), new OpcodeInfo("conv.u",Opcode.CONV_U,OperandFormat.None,0,false), new OpcodeInfo("unused",Opcode.UNUSED26,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED27,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED28,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED29,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED30,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED31,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED32,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED33,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED34,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED35,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED36,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED37,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED38,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED39,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED40,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED41,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED42,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED43,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED44,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED45,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED46,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED47,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED48,OperandFormat.Illegal,0,false), new OpcodeInfo("prefix7",Opcode.PREFIX7,OperandFormat.Illegal,0,false), new OpcodeInfo("prefix6",Opcode.PREFIX6,OperandFormat.Illegal,0,false), new OpcodeInfo("prefix5",Opcode.PREFIX5,OperandFormat.Illegal,0,false), new OpcodeInfo("prefix4",Opcode.PREFIX4,OperandFormat.Illegal,0,false), new OpcodeInfo("prefix3",Opcode.PREFIX3,OperandFormat.Illegal,0,false), new OpcodeInfo("prefix2",Opcode.PREFIX2,OperandFormat.Illegal,0,false), new OpcodeInfo("prefix1",Opcode.PREFIX1,OperandFormat.None,0,false), new OpcodeInfo("prefixref",Opcode.PREFIXREF,OperandFormat.Illegal,0,false), new OpcodeInfo("arglist",Opcode.ARGLIST,OperandFormat.None,0,false), new OpcodeInfo("ceq",Opcode.CEQ,OperandFormat.None,0,false), new OpcodeInfo("cgt",Opcode.CGT,OperandFormat.None,0,false), new OpcodeInfo("cgt.un",Opcode.CGT_UN,OperandFormat.None,0,false), new OpcodeInfo("clt",Opcode.CLT,OperandFormat.None,0,false), new OpcodeInfo("clt.un",Opcode.CLT_UN,OperandFormat.None,0,false), new OpcodeInfo("ldftn",Opcode.LDFTN,OperandFormat.Method,4,false), new OpcodeInfo("ldvirtftn",Opcode.LDVIRTFTN,OperandFormat.Method,4,false), new OpcodeInfo("unused",Opcode.UNUSED56,OperandFormat.Illegal,0,false), new OpcodeInfo("ldarg",Opcode.LDARG,OperandFormat.Var,2,false), new OpcodeInfo("ldarga",Opcode.LDARGA,OperandFormat.Var,2,false), new OpcodeInfo("starg",Opcode.STARG,OperandFormat.Var,2,false), new OpcodeInfo("ldloc",Opcode.LDLOC,OperandFormat.Var,2,false), new OpcodeInfo("ldloca",Opcode.LDLOCA,OperandFormat.Var,2,false), new OpcodeInfo("stloc",Opcode.STLOC,OperandFormat.Var,2,false), new OpcodeInfo("localloc",Opcode.LOCALLOC,OperandFormat.None,0,false), new OpcodeInfo("unused",Opcode.UNUSED57,OperandFormat.Illegal,0,false), new OpcodeInfo("endfilter",Opcode.ENDFILTER,OperandFormat.None,0,true), new OpcodeInfo("unaligned.",Opcode.UNALIGNED,OperandFormat.ShortInt,1,false), new OpcodeInfo("volatile.",Opcode.VOLATILE,OperandFormat.None,0,false), new OpcodeInfo("tail.",Opcode.TAILCALL,OperandFormat.None,0,false), new OpcodeInfo("initobj",Opcode.INITOBJ,OperandFormat.Type,4,false), new OpcodeInfo("ann.live",Opcode.ANN_LIVE,OperandFormat.Var,2,false), new OpcodeInfo("cpblk",Opcode.CPBLK,OperandFormat.None,0,false), new OpcodeInfo("initblk",Opcode.INITBLK,OperandFormat.None,0,false), new OpcodeInfo("ann.ref",Opcode.ANN_REF,OperandFormat.Var,2,false), new OpcodeInfo("rethrow",Opcode.RETHROW,OperandFormat.None,0,true), new OpcodeInfo("unused",Opcode.UNUSED51,OperandFormat.Illegal,0,false), new OpcodeInfo("sizeof",Opcode.SIZEOF,OperandFormat.Type,4,false), new OpcodeInfo("refanytype",Opcode.REFANYTYPE,OperandFormat.None,0,false), new OpcodeInfo("unused",Opcode.UNUSED52,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED53,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED54,OperandFormat.Illegal,0,false), new OpcodeInfo("unused",Opcode.UNUSED55,OperandFormat.Illegal,0,false), new OpcodeInfo("ann.data",Opcode.ANN_DATA,OperandFormat.BranchTarget,0xFF,false), new OpcodeInfo("illegal",Opcode.ILLEGAL,OperandFormat.Illegal,0,false), new OpcodeInfo("endmac",Opcode.MACRO_END,OperandFormat.Illegal,0,false), }; static Instruction() { for (Opcode opcode = 0; opcode < Opcode.COUNT; opcode++) { if (opcodeInfoTable[(int) opcode].opcode != opcode) { throw new IllegalInstructionStreamException("opcode invariant failure"); } } } // Internal classes public abstract class Operand { } public class OperandInt: Operand { // Constructor Methods internal OperandInt(int value) { this.value = value; } // Access Methods public int Value { get { return this.value; } } // Debug Methods public override String ToString() { return ("OperandInt(0x"+this.value.ToString("x")+"/"+this.value+")"); } // State private readonly int value; } public class OperandTarget: Operand { // Constructor Methods internal OperandTarget(int target) { this.target = target; } // Access Methods public int Target { get { return this.target; } } // Debug Methods public override String ToString() { return ("OperandTarget(IL_"+this.target.ToString("x4")+")"); } // State private readonly int target; } public class OperandSingle: Operand { // Constructor Methods internal OperandSingle(float value) { this.value = value; } // Access Methods public float Value { get { return this.value; } } // Debug Methods public override String ToString() { return ("OperandSingle("+this.value+")"); } // State private readonly float value; } public class OperandDouble: Operand { // Constructor Methods internal OperandDouble(double value) { this.value = value; } // Access Methods public double Value { get { return this.value; } } // Debug Methods public override String ToString() { return ("OperandDouble("+this.value+")"); } // State private readonly double value; } public class OperandTargetArray: Operand { // Constructor Methods internal OperandTargetArray(int[] targets) { this.targets = targets; } // Access Methods public int[] Targets { get { return this.targets; } } // Debug Methods public override String ToString() { System.Text.StringBuilder sb = new System.Text.StringBuilder("OperandTargetArray("); if (this.targets.Length > 0) { for (int i = 0; i < this.targets.Length - 1; i++) { sb.Append("IL_"); sb.Append(this.targets[i].ToString("x4")); sb.Append(","); } sb.Append("IL_"); sb.Append(this.targets[this.targets.Length-1].ToString("x4")); } sb.Append(")"); return sb.ToString(); } // State private readonly int[] targets; } public class OperandByteArray: Operand { // Constructor Methods internal OperandByteArray(byte[] value) { this.value = value; } // Access Methods public byte[] Value { get { return this.value; } } // Debug Methods public override String ToString() { System.Text.StringBuilder sb = new System.Text.StringBuilder("OperandByteArray("); if (this.value.Length > 0) { for (int i = 0; i < this.value.Length - 1; i++) { sb.Append(this.value[i]); sb.Append(","); } sb.Append(this.value[this.value.Length-1]); } sb.Append(")"); return sb.ToString(); } // State private readonly byte[] value; } public class OperandLong: Operand { // Constructor Methods internal OperandLong(long value) { this.value = value; } // Access Methods public long Value { get { return this.value; } } // Debug Methods public override String ToString() { return ("OperandLong("+this.value+")"); } // State private readonly long value; } public class OperandString: Operand { // Constructor Methods internal OperandString(String value) { this.value = value; } // Access Methods public String Value { get { return this.value; } } // Debug Methods public override String ToString() { return ("OperandString(\""+this.value+"\")"); } // State private readonly String value; } public class OperandObject: Operand { // Constructor Methods internal OperandObject(MetaDataObject value) { this.value = value; } // Access Methods public MetaDataObject Value { get { return this.value; } } // Debug Methods public override String ToString() { return ("OperandObject("+this.value+")"); } // State private readonly MetaDataObject value; } private class OpcodeInfo { // Constructor Methods internal OpcodeInfo(String name, Opcode opcode, OperandFormat operandFormat, byte operandSize, bool isControl) { this.name = name; this.opcode = opcode; this.operandFormat = operandFormat; this.operandSize = operandSize; this.isControl = isControl; } // State internal readonly String name; internal readonly Opcode opcode; internal readonly OperandFormat operandFormat; internal readonly byte operandSize; internal readonly bool isControl; } private class IllegalInstructionStreamException: Exception { internal IllegalInstructionStreamException(String message): base(message) { } } } }