private IEnumerable <Group> GroupInstruction() { var body = this._Function.Body; if (_Index >= body.Length) { yield break; } var instruction = body[_Index++]; IEnumerable <Group> enumerable; var info = OpcodeInfo.Get(instruction.Op); if (info.ChainCount >= 0) { enumerable = GroupBasicInstruction(info.ChainCount); } else if (instruction.Op == Opcode.Construct) { (var parameterCount, _) = ((byte, ClassDefinition))instruction.Argument; enumerable = GroupBasicInstruction(parameterCount); } else if (instruction.Op == Opcode.Call) { (_, _, var functionType) = ((short, ushort, FunctionDefinition))instruction.Argument; var parameterCount = functionType.Parameters == null ? 0 : functionType.Parameters.Length; parameterCount++; // EndCall enumerable = GroupBasicInstruction(parameterCount); } else if (instruction.Op == Opcode.Switch) { enumerable = GroupSwitchInstruction(); } else if (instruction.Op == Opcode.SwitchCase) { enumerable = GroupSwitchCaseInstruction(); } else if (instruction.Op == Opcode.SwitchDefault) { enumerable = GroupSwitchDefaultInstruction(); } else { throw new NotImplementedException(); } var group = new Group(instruction); foreach (var child in enumerable) { group.Children.Add(child); } yield return(group); }
private static unsafe delegate*<VirtualMachine, void> GetFunctionPointer(OpcodeInfo opcode, int mode) { if (opcode == null) return null; if (opcode.Emulators[mode] != null) return (delegate*<VirtualMachine, void>)((IntPtr)typeof(Delegate).GetField("_methodPtrAux", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(opcode.Emulators[mode])).ToPointer(); return null; }
public static DecodedOperands?TryDecode(OpcodeInfo opcode, ReadOnlySpan <byte> rawData, PrefixState prefixes) { try { return(Decode(opcode, rawData, prefixes, out _)); } catch { return(null); } }
/// <summary> /// Initializes a new instance of the Instruction class. /// </summary> /// <param name="opcodeInfo">Information about the instruction opcode.</param> /// <param name="rawCodes">Machine code for the instruction.</param> /// <param name="cs">Segment where instruction was decoded from.</param> /// <param name="ip">Offset where instruction was decoded from.</param> /// <param name="bigMode">Indicates whether the instruction should be decoded in big (32-bit) mode.</param> internal Instruction(OpcodeInfo opcodeInfo, byte[] rawCodes, ushort cs, uint ip, bool bigMode) { if (opcodeInfo != null) { for (int i = 0; i < 12; i++) { this.operandCodes[i] = rawCodes[opcodeInfo.Length + i]; } } this.Opcode = opcodeInfo; this.CS = cs; this.offset = ip; this.BigMode = bigMode; }
/// <summary> /// Assigns new values to the instruction instance. /// </summary> /// <param name="opcodeInfo">Information about the instruction opcode.</param> /// <param name="rawCodes">Operand data starting with the first byte after the opcode.</param> /// <param name="cs">Code segment of the instruction.</param> /// <param name="ip">Offset in the current code segment of the instruction.</param> /// <param name="bigMode">Indicates whether the instruction should be decoded in big (32-bit) mode.</param> internal void Assign(OpcodeInfo opcodeInfo, IntPtr rawCodes, ushort cs, uint ip, bool bigMode) { unsafe { byte *ptr = (byte *)rawCodes.ToPointer(); for (int i = 0; i < this.operandCodes.Length; i++) { this.operandCodes[i] = ptr[i]; } } this.Opcode = opcodeInfo; this.CS = cs; this.offset = ip; this.BigMode = bigMode; this.formattedValue = null; }
/// <summary> /// Writes a start trace of the Dispatch method. /// </summary> /// <param name="opcode">The dispatched opcode.</param> /// <param name="index">Optional dispatch paremeter.</param> /// <param name="value">Optional dispatch paremeter.</param> /// <param name="ptr">Optional dispatch paremeter.</param> /// <param name="opt">Optional dispatch paremeter.</param> /// <remarks> /// The trace text is output as a <see cref="TraceEventType.Verbose"/> event type. /// </remarks> public void WriteDispatchBegin(int opcode, int index, IntPtr value, IntPtr ptr, float opt) { if (_traceSource.Switch.ShouldTrace(TraceEventType.Verbose)) { string message = "Dispatch (Begin) "; OpcodeInfo opcodeInfo = LookupOpcodeInfo(opcode); if (opcodeInfo != null) { message += opcodeInfo.FormatArguments(index, value, ptr, opt); } else { message += String.Format("Opcode={0} Index={1}, Value={2} Ptr={3} Opt={4}.", opcode, index, value, ptr, opt); } WriteEvent(TraceEventType.Verbose, message); } }
internal void Assign(OpcodeInfo opcodeInfo, IntPtr rawCodes, Processor processor, uint ip) { base.Assign(opcodeInfo, rawCodes, processor.CS, ip, processor.GlobalSize != 0); this.EAX = (uint)processor.EAX; this.EBX = (uint)processor.EBX; this.ECX = (uint)processor.ECX; this.EDX = (uint)processor.EDX; this.ESI = processor.ESI; this.EDI = processor.EDI; this.EBP = processor.EBP; this.DS = processor.DS; this.ES = processor.ES; this.FS = processor.FS; this.GS = processor.GS; this.SS = processor.SS; this.ESP = processor.ESP; this.Flags = processor.Flags.Value & ~EFlags.Reserved1; this.CR0 = processor.CR0; }
internal static void Initialize() { var isb = new InstructionSetBuilder(); isb.BuildSet(); foreach (var info in isb.OneByteOpcodes) oneByteCodes[info.Opcode] = new OpcodeInfo(info); foreach (var info in isb.TwoByteOpcodes) { int byte1 = info.Opcode & 0xFF; int byte2 = (info.Opcode >> 8) & 0xFF; if (info.ModRmByte != ModRmInfo.OnlyRm) { if (twoByteCodes[byte1] == null) twoByteCodes[byte1] = new OpcodeInfo[256]; twoByteCodes[byte1][byte2] = new OpcodeInfo(info); } else { if (twoByteRmCodes[byte1] == null) twoByteRmCodes[byte1] = new OpcodeInfo[256][]; if (twoByteRmCodes[byte1][byte2] == null) twoByteRmCodes[byte1][byte2] = new OpcodeInfo[8]; twoByteRmCodes[byte1][byte2][info.ExtendedRmOpcode] = new OpcodeInfo(info); } } foreach (var info in isb.ExtendedOpcodes) { if (rmCodes[info.Opcode] == null) rmCodes[info.Opcode] = new OpcodeInfo[8]; rmCodes[info.Opcode][info.ExtendedRmOpcode] = new OpcodeInfo(info); } allCodes = new OpcodeCollection(); InitializeNativeArrays(); }
public static DecodedOperands Decode(OpcodeInfo opcode, ReadOnlySpan <byte> rawData, PrefixState prefixes) => Decode(opcode, rawData, prefixes, out _);
private static DecodedOperands Decode(OpcodeInfo opcode, ReadOnlySpan <byte> rawData, PrefixState prefixes, out int length) { var reader = new OperandReader(rawData); var operands = new DecodedOperands(); length = 0; if (opcode.Operands.Count == 0) { return(operands); } if (opcode.ModRmInfo != ModRmInfo.None) { byte modRmByte = reader.ReadByte(); int mod = (modRmByte & 0xC0) >> 6; int rm = modRmByte & 0x07; for (int i = 0; i < opcode.Operands.Count; i++) { var type = opcode.Operands[i]; if (type == OperandType.RegisterOrMemoryByte) { operands.SetOperand(i, DecodeRmbw(mod, rm, true, prefixes, ref reader)); } else if (IsPointerOperand(type)) { var operand = DecodeRmbw(mod, rm, false, prefixes, ref reader); if (type == OperandType.EffectiveAddress) { operand.Type = CodeOperandType.EffectiveAddress; } else if (type == OperandType.FullLinearAddress) { operand.Type = CodeOperandType.FullLinearAddress; } else if (type == OperandType.RegisterOrMemoryWordNearPointer) { operand.Type = CodeOperandType.AbsoluteJumpAddress; } else if (type == OperandType.IndirectFarPointer) { operand.Type = CodeOperandType.IndirectFarMemoryAddress; } else if (type == OperandType.MemoryInt16 || type == OperandType.RegisterOrMemory16) { operand.OperandSize = CodeOperandSize.Word; } else if (type == OperandType.MemoryInt32 || type == OperandType.RegisterOrMemory32) { operand.OperandSize = CodeOperandSize.DoubleWord; } else if (type == OperandType.MemoryInt64) { operand.OperandSize = CodeOperandSize.QuadWord; } else if (type == OperandType.MemoryFloat32) { operand.OperandSize = CodeOperandSize.Single; } else if (type == OperandType.MemoryFloat64) { operand.OperandSize = CodeOperandSize.Double; } else if (type == OperandType.MemoryFloat80) { operand.OperandSize = CodeOperandSize.LongDouble; } operands.SetOperand(i, operand); } } if (opcode.ModRmInfo == ModRmInfo.All) { int reg = (modRmByte & 0x38) >> 3; for (int i = 0; i < opcode.Operands.Count; i++) { var type = opcode.Operands[i]; if (type == OperandType.RegisterByte) { operands.SetOperand(i, DecodeRb(reg)); } else if (type == OperandType.RegisterWord) { operands.SetOperand(i, DecodeRw(reg, prefixes)); } else if (type == OperandType.SegmentRegister) { operands.SetOperand(i, DecodeSreg(reg)); } } } } for (int i = 0; i < opcode.Operands.Count; i++) { var type = opcode.Operands[i]; if (IsKnownRegister(type)) { operands.SetOperand(i, new CodeOperand(DecodeKnownRegister(type, (prefixes & PrefixState.OperandSize) != 0))); } else if (type == OperandType.ImmediateByte) { operands.SetOperand(i, new CodeOperand(CodeOperandType.Immediate, reader.ReadByte(), CodeOperandSize.Byte)); } else if (type == OperandType.ImmediateByteExtend || type == OperandType.ImmediateRelativeByte) { var operand = new CodeOperand(CodeOperandType.Immediate, (uint)(int)reader.ReadSByte(), GetOperandSize(false, prefixes)); if (type == OperandType.ImmediateRelativeByte) { operand.Type = CodeOperandType.RelativeJumpAddress; } operands.SetOperand(i, operand); } else if (type == OperandType.ImmediateInt16) { operands.SetOperand(i, new CodeOperand(CodeOperandType.Immediate, reader.ReadUInt16(), CodeOperandSize.Word)); } else if (type == OperandType.ImmediateInt32) { operands.SetOperand(i, new CodeOperand(CodeOperandType.Immediate, reader.ReadUInt32(), CodeOperandSize.DoubleWord)); } else if (type == OperandType.ImmediateWord) { uint value; if ((prefixes & PrefixState.OperandSize) == 0) { value = reader.ReadUInt16(); } else { value = reader.ReadUInt32(); } operands.SetOperand(i, new CodeOperand(CodeOperandType.Immediate, value, GetOperandSize(false, prefixes))); } else if (type == OperandType.ImmediateRelativeWord) { uint value; if ((prefixes & PrefixState.OperandSize) == 0) { value = (uint)(int)reader.ReadInt16(); } else { value = reader.ReadUInt32(); } operands.SetOperand(i, new CodeOperand(CodeOperandType.RelativeJumpAddress, value, GetOperandSize(false, prefixes))); } else if (type == OperandType.MemoryOffsetByte || type == OperandType.MemoryOffsetWord) { uint value; if ((prefixes & PrefixState.AddressSize) == 0) { value = (uint)(int)reader.ReadInt16(); } else { value = reader.ReadUInt32(); } operands.SetOperand(i, new CodeOperand(CodeMemoryBase.DisplacementOnly, value, GetOperandSize(type == OperandType.MemoryOffsetByte, prefixes))); } else if (type == OperandType.ImmediateFarPointer) { uint value; if ((prefixes & PrefixState.AddressSize) == 0) { value = reader.ReadUInt16(); } else { value = reader.ReadUInt32(); } ushort segment = reader.ReadUInt16(); operands.SetOperand(i, CodeOperand.FarPointer(segment, value)); } } length = reader.Position; return(operands); }
public static int CalculateOperandLength(OpcodeInfo opcode, ReadOnlySpan <byte> rawData, PrefixState prefixes) { Decode(opcode, rawData, prefixes, out int length); return(length); }
private Instruction MakeInstruction(int offset, OpcodeInfo opcodeInfo, ushort extraData) { Operand operand1, operand2; // Handle simple instructions if (opcodeInfo.FirstOperand == DisassemblyOperand.None) { switch (opcodeInfo.Operation) { case Operation.Nop: return(new ControlInstruction(offset, ControlInstructionType.NoOperation)); case Operation.Stop: return(new ControlInstruction(offset, ControlInstructionType.Stop)); case Operation.Halt: return(new ControlInstruction(offset, ControlInstructionType.Halt)); case Operation.Di: return(new ControlInstruction(offset, ControlInstructionType.DisableInterrupts)); case Operation.Ei: return(new ControlInstruction(offset, ControlInstructionType.EnableInterrupts)); case Operation.Ret: return(new ReturnInstruction(offset)); case Operation.Reti: return(new ReturnInstruction(offset, true)); case Operation.Rlca: return(new ShiftInstruction(offset, ShiftInstructionFlags.RotateRightCircular, Operand.DirectA)); case Operation.Rrca: return(new ShiftInstruction(offset, ShiftInstructionFlags.RotateLeftCircular, Operand.DirectA)); case Operation.Rla: return(new ShiftInstruction(offset, ShiftInstructionFlags.RotateRight, Operand.DirectA)); case Operation.Rra: return(new ShiftInstruction(offset, ShiftInstructionFlags.RotateLeft, Operand.DirectA)); case Operation.Daa: return(new UtilityInstruction(offset, UtilityOperation.DecimalAdjustAfter)); case Operation.Cpl: return(new UtilityInstruction(offset, UtilityOperation.DecimalAdjustAfter)); case Operation.Scf: return(new UtilityInstruction(offset, UtilityOperation.DecimalAdjustAfter)); case Operation.Ccf: return(new UtilityInstruction(offset, UtilityOperation.DecimalAdjustAfter)); default: throw new NotImplementedException() /*return new ControlInstruction(offset, ControlInstructionType.NoOperation)*/; } } // Handle jump instructions (and the conditional return instruction too) else if (opcodeInfo.Operation == Operation.Jp || opcodeInfo.Operation == Operation.Jr || opcodeInfo.Operation == Operation.Call || opcodeInfo.Operation == Operation.Rst || opcodeInfo.Operation == Operation.Ret) { Label label; JumpType jumpType; Condition condition; ushort mappedOffset, destination; switch (opcodeInfo.FirstOperand) { case DisassemblyOperand.NotZero: condition = Condition.NotZero; break; case DisassemblyOperand.Zero: condition = Condition.Zero; break; case DisassemblyOperand.NotCarry: condition = Condition.CarryClear; break; case DisassemblyOperand.Carry: condition = Condition.CarrySet; break; default: condition = Condition.Always; break; } switch (opcodeInfo.Operation) { case Operation.Ret: return(new ReturnInstruction(offset, condition)); case Operation.Jr: jumpType = JumpType.Relative; break; case Operation.Jp: jumpType = JumpType.Absolute; break; default: jumpType = JumpType.FunctionCall; break; } if (offset < 0x8000) { mappedOffset = (ushort)offset; } else { mappedOffset = (ushort)(0x4000 | (offset & 0x3FFF)); } if (opcodeInfo.Operation == Operation.Rst) { destination = opcodeInfo.EmbeddedValue; } else if (opcodeInfo.Operation == Operation.Jr) { unchecked { destination = (ushort)(mappedOffset + 2 + (sbyte)(byte)extraData); } // Add 2 to the offset because of the jump instruction length } else { destination = extraData; } if (destination >= 0x8000 || (IsRomBanked && destination >= 0x4000 && mappedOffset < 0x4000)) { return(new JumpInstruction(offset, jumpType, condition, extraData)); } else if (jumpType == JumpType.FunctionCall) { label = DefineFunctionLabel((offset & ~0x3FFF) | destination); } else { label = DefineLabel((offset & ~0x3FFF) | destination); } return(new ResolvedJumpInstruction(offset, jumpType, condition, destination, label)); } // Handle single-operand instructions else if (opcodeInfo.SecondOperand == DisassemblyOperand.None) { operand1 = MakeOperand(opcodeInfo.FirstOperand, opcodeInfo.EmbeddedValue, extraData); switch (opcodeInfo.Operation) { case Operation.Inc: return(new ArithmeticInstruction(offset, ArithmeticOperation.Add, operand1, new Operand <byte>(1))); case Operation.Dec: return(new ArithmeticInstruction(offset, ArithmeticOperation.Substract, operand1, new Operand <byte>(1))); case Operation.Pop: return(new PopInstruction(offset, operand1)); case Operation.Push: return(new PushInstruction(offset, operand1)); case Operation.Rlc: return(new ShiftInstruction(offset, ShiftInstructionFlags.RotateRightCircular, operand1)); case Operation.Rrc: return(new ShiftInstruction(offset, ShiftInstructionFlags.RotateLeftCircular, operand1)); case Operation.Rl: return(new ShiftInstruction(offset, ShiftInstructionFlags.RotateRight, operand1)); case Operation.Rr: return(new ShiftInstruction(offset, ShiftInstructionFlags.RotateLeft, operand1)); case Operation.Sla: return(new ShiftInstruction(offset, ShiftInstructionFlags.ShiftLeftArithmetical, operand1)); case Operation.Sra: return(new ShiftInstruction(offset, ShiftInstructionFlags.ShiftRightArithmetical, operand1)); case Operation.Srl: return(new ShiftInstruction(offset, ShiftInstructionFlags.ShiftRightLogical, operand1)); case Operation.Swap: return(new SwapInstruction(offset, operand1)); default: throw new InvalidOperationException(); } } // Handle remaining instructions else { operand1 = MakeOperand(opcodeInfo.FirstOperand, opcodeInfo.EmbeddedValue, extraData); operand2 = MakeOperand(opcodeInfo.SecondOperand, opcodeInfo.EmbeddedValue, extraData); switch (opcodeInfo.Operation) { case Operation.Ld: return(new LoadInstruction(offset, operand1, operand2)); case Operation.Ldi: return(new LoadInstruction(offset, LoadOperationType.IncrementHl, operand1, operand2)); case Operation.Ldd: return(new LoadInstruction(offset, LoadOperationType.DecrementHl, operand1, operand2)); case Operation.Add: return(new ArithmeticInstruction(offset, ArithmeticOperation.Add, operand1, operand2)); case Operation.Adc: return(new ArithmeticInstruction(offset, ArithmeticOperation.AddWithCarry, operand1, operand2)); case Operation.Sub: return(new ArithmeticInstruction(offset, ArithmeticOperation.Substract, operand1, operand2)); case Operation.Sbc: return(new ArithmeticInstruction(offset, ArithmeticOperation.SubstractWithCarry, operand1, operand2)); case Operation.And: return(new ArithmeticInstruction(offset, ArithmeticOperation.And, operand1, operand2)); case Operation.Xor: return(new ArithmeticInstruction(offset, ArithmeticOperation.Xor, operand1, operand2)); case Operation.Or: return(new ArithmeticInstruction(offset, ArithmeticOperation.Or, operand1, operand2)); case Operation.Cp: return(new ArithmeticInstruction(offset, ArithmeticOperation.Compare, operand1, operand2)); case Operation.Bit: return(new BitInstruction(offset, BitOperation.Test, operand1, operand2)); case Operation.Set: return(new BitInstruction(offset, BitOperation.Set, operand1, operand2)); case Operation.Res: return(new BitInstruction(offset, BitOperation.Clear, operand1, operand2)); default: throw new InvalidOperationException(); } } }
public void read(Reader reader) { foreach (ScriptSub sub in subs) { sub.scriptCode.Clear(); sub.blankLines.Clear(); sub.labels.Clear(); sub.jumpTable.Clear(); bool finishedScriptCode = false; int scriptCodeLength = reader.ReadByte() << 8; scriptCodeLength |= reader.ReadByte(); sub.scriptCode.Clear(); while (!finishedScriptCode) { byte scriptOpcode = reader.ReadByte(); if (scriptOpcode == 0xFF) { scriptOpcode = reader.ReadByte(); if (scriptOpcode == 0xFF) { scriptOpcode = reader.ReadByte(); if (scriptOpcode == 0xFF) { scriptOpcode = reader.ReadByte(); if (scriptOpcode == 0xFF) { finishedScriptCode = true; } } } } if (!finishedScriptCode) { OpcodeInfo opInfo = new OpcodeInfo(); opInfo.opcode = scriptOpcode; uint paramCount = (uint)opcodeList[scriptOpcode].paramCount; opInfo.parameters.Clear(); for (int p = 0; p < paramCount; p++) { ParamInfo param = new ParamInfo(); int paramType = reader.ReadByte(); // if 0 then int constant, else variable if (paramType != 0) { param.isVariable = true; param.value = reader.ReadByte(); int arrayIndex = reader.ReadByte(); if (arrayIndex > 0x80) { arrayIndex = 0x80 - arrayIndex; } param.arrayIndex = (sbyte)arrayIndex; } else { param.isVariable = false; param.arrayIndex = -1; int byte1 = reader.ReadByte(); int constVal = 0; if (byte1 < 0x80) // unsigned uint16 { constVal = byte1 << 8; constVal |= reader.ReadByte(); } else // signed uint16 { constVal = (byte1 - 0x80) << 8; constVal |= reader.ReadByte(); constVal = -constVal; } param.value = constVal; } opInfo.parameters.Add(param); } sub.scriptCode.Add(opInfo); } } int blankLineUnused = reader.ReadByte(); int blankLineCount = reader.ReadByte(); for (int u = 0; u < blankLineCount; u++) { int blankLineID = reader.ReadByte() << 8; blankLineID |= reader.ReadByte(); sub.blankLines.Add(blankLineID); } int labelUnused = reader.ReadByte(); int labelCount = reader.ReadByte(); for (int l = 0; l < labelCount; l++) { LabelInfo label = new LabelInfo(); label.scriptCodePos = reader.ReadByte() << 8; label.scriptCodePos |= reader.ReadByte(); label.id = reader.ReadByte() << 8; label.id |= reader.ReadByte(); label.lineID = reader.ReadByte() << 8; label.lineID |= reader.ReadByte(); sub.labels.Add(label); } int jumpTableUnused = reader.ReadByte(); int jumpTableCount = reader.ReadByte(); for (int s = 0; s < jumpTableCount; ++s) { SwitchInfo info = new SwitchInfo(); info.scriptCodePos = reader.ReadByte() << 8; info.scriptCodePos |= reader.ReadByte(); int caseCount = reader.ReadByte() << 8; caseCount |= reader.ReadByte(); info.defaultScriptCodePos = reader.ReadByte() << 8; info.defaultScriptCodePos |= reader.ReadByte(); info.defaultCaseLineID = reader.ReadByte() << 8; info.defaultCaseLineID |= reader.ReadByte(); info.endScriptCodePos = reader.ReadByte() << 8; info.endScriptCodePos |= reader.ReadByte(); // if (info.defaultScriptCodePos == 0) // info.defaultScriptCodePos = info.endScriptCodePos; int lowestCase = 0x8000; int highestCase = 0; info.cases.Clear(); for (int c = 0; c < caseCount; c++) { SwitchCaseInfo caseInfo = new SwitchCaseInfo(); caseInfo.scriptCodePos = reader.ReadByte() << 8; caseInfo.scriptCodePos |= reader.ReadByte(); caseInfo.caseNum = reader.ReadByte() << 8; caseInfo.caseNum |= reader.ReadByte(); if (caseInfo.caseNum < lowestCase) { lowestCase = caseInfo.caseNum; } if (caseInfo.caseNum > highestCase) { highestCase = caseInfo.caseNum; } caseInfo.lineID = reader.ReadByte() << 8; caseInfo.lineID |= reader.ReadByte(); info.cases.Add(caseInfo); } info.lowestCase = lowestCase; info.highestCase = highestCase; // Take any duds and make em default cases // for (int m = lowestCase; m <= highestCase; ++m) // { // int jump = sub.scriptCode[caseTablePos + m]; // if (jump == 0) // sub.scriptCode[caseTablePos + m] = sub.jumpTable[startSwitchTablePos + 2]; // } // wow this is weird // it manually goes and sets up the offsets instead of doing it at compile-time like later RSDK versions int pos = 0; foreach (OpcodeInfo opcodeInfo in sub.scriptCode) { if (pos == info.scriptCodePos) { opcodeInfo.parameters[1].value = pos; break; } pos += opcodeInfo.size; } sub.jumpTable.Add(info); } } reader.Close(); }
public Instruction(TokenStream tokenStream, OpcodeInfo opcode) : base(tokenStream) { this.opcode = opcode; }
private IEnumerable <Group> GroupInstruction() { var body = this._Function.Body; if (_Index >= body.Count) { yield break; } var instruction = body[_Index++]; IEnumerable <Group> enumerable; var info = OpcodeInfo.Get(instruction.Op); if (info.ChainCount >= 0) { enumerable = GroupBasicInstruction(info.ChainCount); } else if (instruction.Op == Opcode.Constructor) { var(parameterCount, _) = (Constructor)instruction.Argument; enumerable = GroupBasicInstruction(parameterCount); } else if (instruction.Op == Opcode.FinalFunc) { var(_, _, function) = (FinalFunc)instruction.Argument; var parameterCount = function.Parameters.Count; parameterCount++; // EndCall enumerable = GroupBasicInstruction(parameterCount); } else if (instruction.Op == Opcode.VirtualFunc) { // TODO(gibbed): dodgy af /*var (_, _, name) = ((short, ushort, string))instruction.Argument; * var candidates = this._Cache.Definitions.Where(d => d.Name == name).ToArray(); * if (candidates.Length != 1) * { * enumerable = GroupBasicInstruction(1); * } * else * { * var function = (FunctionDefinition)candidates[0]; * var parameterCount = function.Parameters.Count; * parameterCount++; // EndCall * enumerable = GroupBasicInstruction(parameterCount); * }*/ enumerable = GroupCallNameInstruction(); } else if (instruction.Op == Opcode.Switch) { enumerable = GroupSwitchInstruction(); } else if (instruction.Op == Opcode.SwitchLabel) { enumerable = GroupSwitchCaseInstruction(); } else if (instruction.Op == Opcode.SwitchDefault) { enumerable = GroupSwitchDefaultInstruction(); } else { throw new NotImplementedException(); } var group = new Group(instruction); foreach (var child in enumerable) { group.Children.Add(child); } yield return(group); }
private static Exception GetPartiallyNotImplementedException(VirtualMachine vm, OpcodeInfo info) => new NotImplementedException($"Instruction '{info.Name}' not implemented for {vm.Processor.AddressSize}-bit addressing, {vm.Processor.OperandSize}-bit operand size.");