public override void DecodeArguments(Memory.MemoryBin bin, ref InstructionDecodeContext context, ref int offset, ref InstructionReference instructionReference) { if (decodeArgumentsFunction != null) { decodeArgumentsFunction(this, bin, ref context, ref offset, ref instructionReference.param1, ref instructionReference.param2); } }
/// <summary> /// Effectue le décodage des instructions /// </summary> /// <param name="bin"></param> /// <param name="offset"></param> /// <param name="context">Contexte de décodage. Par défaut, prend la valeur du mode actuel du CPU</param> /// <returns></returns> public InstructionsBin Decode(MemoryBin bin, int offset, InstructionDecodeContext context) { context.Source = bin; var decodeResult = new List<InstructionReference>(); var length = bin.Length; int originalOffset = 0; while (offset < length) { var code = bin.ReadInt1(originalOffset = offset); offset++; var match = knownInstructions[code]; var instructionReference = new InstructionReference(); instructionReference.instruction = match; instructionReference.offset = originalOffset; match.DecodeArguments(bin, ref context, ref offset, ref instructionReference); decodeResult.Add(instructionReference); } var result = new InstructionsBin() { DecodeContext = context, Instructions = decodeResult.ToArray() }; return result; }
public override void DecodeArguments(Memory.MemoryBin bin, ref InstructionDecodeContext context, ref int offset, ref InstructionReference instructionReference) { switch (AddrMode) { case AddressingModes.ImpliedAccumulator: { break; } case AddressingModes.Absolute: case AddressingModes.AbsoluteIndexedX: { instructionReference.param1 = DecodeInt2Argument(bin, ref offset); break; } case AddressingModes.Direct: case AddressingModes.DirectIndexedX: { instructionReference.param1 = DecodeInt1Argument(bin, ref offset); break; } default: { throw new InvalidOperationException("Addressing mode unknown for instruction ASL"); } } }
public override void DecodeArguments(Memory.MemoryBin bin, ref InstructionDecodeContext context, ref int offset, ref InstructionReference instructionReference) { switch (AddrMode) { case AddressingModes.AbsoluteLong: { instructionReference.param1 = DecodeInt3Argument(bin, ref offset); break; } default: { instructionReference.param1 = DecodeInt2Argument(bin, ref offset); break; } } }
public override void DecodeArguments(Memory.MemoryBin bin, ref InstructionDecodeContext context, ref int offset, ref InstructionReference instructionReference) { switch (AddrMode) { case AddressingModes.ImmediateMemoryFlag: case AddressingModes.ImmediateIndexFlag: case AddressingModes.Immediate8Bit: { instructionReference.param1 = DecodeI1I2ArgumentForMFlag(bin, ref offset, ref context); break; } case AddressingModes.Absolute: case AddressingModes.AbsoluteIndexedX: case AddressingModes.AbsoluteIndexedY: { instructionReference.param1 = DecodeInt2Argument(bin, ref offset); break; } case AddressingModes.AbsoluteLong: case AddressingModes.AbsoluteIndexedLong: { instructionReference.param1 = DecodeInt3Argument(bin, ref offset); break; } case AddressingModes.Direct: case AddressingModes.DirectIndirect: case AddressingModes.DirectIndirectLong: case AddressingModes.DirectIndexedX: case AddressingModes.DirectIndexedIndirect: case AddressingModes.DirectIndirectIndexed: case AddressingModes.DirectIndirectIndexedLong: case AddressingModes.StackRelative: case AddressingModes.StackRelativeIndirectIndexed: { instructionReference.param1 = DecodeInt1Argument(bin, ref offset); break; } default: { throw new InvalidOperationException("Addressing mode unknown for instruction ADC"); } } }
/// <summary> /// Decode une unique instruction à partir de l'offset spécifié dans le bin spécifié à l'aide du contexte courrant, et la stoque dans decodedInstruction /// </summary> /// <param name="bin"></param> /// <param name="offset"></param> /// <param name="context"></param> /// <param name="decodedInstruction"></param> public void DecodeOnce(MemoryBin bin, ref int offset, ref InstructionDecodeContext context, ref InstructionReference decodedInstruction) { var code = bin.ReadInt1(offset); offset++; var match = knownInstructions[code]; decodedInstruction.instruction = match; decodedInstruction.offset = offset - 1; match.DecodeArguments(bin, ref context, ref offset, ref decodedInstruction); }
public override void DecodeArguments(Memory.MemoryBin bin, ref InstructionDecodeContext context, ref int offset, ref InstructionReference instructionReference) { /* on skip le byte suivant, qui est censé être une signature */ offset++; }
private void EmitGoto(InstructionReference reference) { _emitter.Emit(OpCodes.Br, reference); }
/// <summary> /// Exécute une seule instruction en partant de l'addresse spécifiée /// </summary> /// <param name="bin">Mémoire à utiliser pour la référence</param> /// <param name="startAddress">Adresse, ou rien pour utiliser le PC actuel</param> public void RunOnce(MemoryBin bin, int startAddress = -1) { if (bin == null) throw new ArgumentNullException("bin"); if (startAddress >= 0) platform.CPU.PC = startAddress; var refInstruction = new InstructionReference(); var context = platform.CPU.BuildCurrentContext(); platform.Decoder.DecodeOnce(bin, ref platform.CPU.PC, ref context, ref refInstruction); refInstruction.instruction.Run(refInstruction.param1, refInstruction.param2); }
private void WrappedInterpretThreadFunction() { try { var currentInstruction = new InstructionReference(); var currentContext = platform.CPU.BuildCurrentContext(); var cpu = platform.CPU; var decoder = platform.Decoder; while (!stop) { // On pourrait peut être le mettre en cache et je màj uniquement // après une instruction qui le modifie cpu.UpdateCurrentContext(ref currentContext); decoder.DecodeOnce(interpreterMemory, ref cpu.PC, ref currentContext, ref currentInstruction); if (trace) { Debug.WriteLine(currentInstruction.StringRepresentation()); } currentInstruction.instruction.Run(currentInstruction.param1, currentInstruction.param2); } } finally { interpreting = false; } }
List <Instruction> EmitCall() { var invoke_method = _hook_field.FieldType.Resolve().Method("Invoke"); VariableDefinition local_field_instance = new VariableDefinition(invoke_method.ReturnType) ; InstructionReference call_invoke = new InstructionReference(), store_result = new InstructionReference() ; bool has_return_type = invoke_method.ReturnType.FullName != "System.Void"; if (this._is_cancellable) { _variables.Add(local_field_instance); return(AnonymousExtensions.ParseAnonymousInstruction( new { OpCodes.Ldsfld, _hook_field }, new { OpCodes.Dup }, new { OpCodes.Brtrue_S, call_invoke }, new { OpCodes.Pop }, new { OpCodes.Ldc_I4_1 }, new { OpCodes.Br_S, store_result }, new Func <IEnumerable <object> >(() => { IEnumerable <object> collection = null; if (this._parameters.Count() > 0) { var first = this._parameters.First(); call_invoke = call_invoke.Create( _is_by_reference && first.ParameterType.IsValueType ? OpCodes.Ldarga : OpCodes.Ldarg, first ); collection = new object[] { call_invoke, this._parameters.Skip(1) .Select(x => new { OpCode = _is_by_reference && x.ParameterType.IsValueType ? OpCodes.Ldarga : OpCodes.Ldarg, Operand = x }), // adds the return result new Func <IEnumerable <object> >(() => { if (_result_variable != null) { return new [] { new { OpCode = _is_by_reference ? OpCodes.Ldloca : OpCodes.Ldloc, _result_variable } }; } return Enumerable.Empty <object>(); }).Invoke(), new { OpCodes.Callvirt, invoke_method } }; } else { collection = new object[] { // adds the return result new Func <IEnumerable <object> >(() => { if (_result_variable != null) { return new object [] { call_invoke = call_invoke.Create( _is_by_reference ? OpCodes.Ldloca : OpCodes.Ldloc, _result_variable ), new { OpCodes.Callvirt, invoke_method } }; } else { return new [] { call_invoke = call_invoke.Create(OpCodes.Callvirt, invoke_method) }; } }).Invoke() }; } return collection; }).Invoke(), store_result = store_result.Create(OpCodes.Stloc, local_field_instance), new { OpCodes.Ldloc, local_field_instance } ).ToList()); } else { return(AnonymousExtensions.ParseAnonymousInstruction( new { OpCodes.Ldsfld, _hook_field }, new { OpCodes.Dup }, new { OpCodes.Brtrue_S, call_invoke }, new { OpCodes.Pop }, new { OpCodes.Br_S, store_result }, new Func <IEnumerable <object> >(() => { IEnumerable <object> collection = null; if (this._parameters.Count() > 0) { var first = this._parameters.First(); call_invoke = call_invoke.Create( _is_by_reference && first.ParameterType.IsValueType ? OpCodes.Ldarga : OpCodes.Ldarg, first ); collection = new object[] { call_invoke, this._parameters.Skip(1) .Select(x => new { OpCode = _is_by_reference && x.ParameterType.IsValueType? OpCodes.Ldarga : OpCodes.Ldarg, Operand = x }), // adds the return result new Func <IEnumerable <object> >(() => { if (_result_variable != null) { return new [] { new { OpCode = _is_by_reference ? OpCodes.Ldloca : OpCodes.Ldloc, _result_variable } }; } return Enumerable.Empty <object>(); }).Invoke(), //new { OpCodes.Callvirt, invoke_method } new Func <IEnumerable <object> >(() => { IEnumerable <object> res = new [] { new { OpCodes.Callvirt, invoke_method } }; if (has_return_type) { res = res.Concat(new[] { new { OpCodes.Pop } }); } return res; }).Invoke() }; } else { //collection = new object[] //{ // new Func<IEnumerable<object>>(() => // { // IEnumerable<object> res; if (_result_variable != null) { collection = new object[] { call_invoke = call_invoke.Create( _is_by_reference ? OpCodes.Ldloca : OpCodes.Ldloc, _result_variable ), new { OpCodes.Callvirt, invoke_method } }; } else { collection = new[] { call_invoke = call_invoke.Create(OpCodes.Callvirt, invoke_method) }; } if (has_return_type) { collection = collection.Concat(new[] { new { OpCodes.Pop } }); } // return res; // }).Invoke() //}; } return collection; }).Invoke(), store_result = store_result.Create( OpCodes.Nop // invoke_method.ReturnType.FullName == "System.Void" ? OpCodes.Nop : OpCodes.Pop ) ).ToList()); } }
/// <summary> /// Ecrit une instruction. C'est un peut chiant car il faut spécifier à la fois l'instruction, l'addrMode, le type des args et les args mais bon, /// pour l'instant ça devrait faire l'affaire /// </summary> /// <param name="bin"></param> /// <param name="offset"></param> /// <param name="opCode"></param> /// <param name="addrMode"></param> /// <param name="param1Type"></param> /// <param name="param1"></param> /// <param name="param2"></param> public void Write(MemoryBin bin, ref int offset, OpCodes opCode, AddressingModes addrMode = AddressingModes.Direct, ArgumentType param1Type = ArgumentType.I1, int param1 = 0, int param2 = 0) { var originalOffset = offset; /* d'abord, on cherche l'instruction */ Instruction match_instruction = null; var match_code = from instruction in cpu.DecodeTable.KnownInstructions where instruction.Code == opCode select instruction; switch(match_code.Count()) { case 0: throw new InvalidOperationException(String.Format("Instruction not found : {0}", opCode)); case 1: { /* on se prend pas la tête sur le mode d'addr */ match_instruction = match_code.First(); break; } default: { /* on cherche le bon mode */ match_instruction = (from code_item in match_code where code_item.AddrMode == addrMode select code_item).FirstOrDefault(); if(match_instruction== null) throw new InvalidOperationException(String.Format("Instruction {0} was found, but the addrMode {1} has no binding", opCode, addrMode)); break; } } /* on écrit le code */ bin.WriteInt1(offset, match_instruction.AssociatedHexCode); offset++; /* s'il y a des arguments, on les écrit */ if (match_instruction.HaveArgs) { WriteParameter(bin, ref offset, param1Type, param1); if (addrMode == AddressingModes.BlockMove) { /* c'est le seul mode qui a deux arguments, et il a la même * taille que le premier argument * */ WriteParameter(bin, ref offset, param1Type, param2); } } if (enableInstructionValidation) { /* on vérifie l'instruction écrite */ var instructionDecode = new InstructionReference(); var context = cpu.BuildCurrentContext(); cpu.Platform.Decoder.DecodeOnce(bin, ref originalOffset, ref context, ref instructionDecode); if (instructionDecode.instruction.Code != opCode || instructionDecode.param1 != param1 || instructionDecode.param2 != param2) { throw new InvalidProgramException(String.Format("Instruction decode mismatch.\r\nEncoded:{0}({1},{2}) [{3}]\r\nDecoded:{4}({5},{6}) [{7}]", opCode, param1, param2, addrMode, instructionDecode.instruction.Code, instructionDecode.param1, instructionDecode.param2, instructionDecode.instruction.AddrMode)); } else if (originalOffset != offset) { throw new InvalidProgramException(String.Format("Instruction decode mismatch, Invalid offset. Difference : {0}", offset - originalOffset)); } } }
public ForStatement() { AfterRefence = new InstructionReference(); BodyReference = new InstructionReference(); ConditionalReference = new InstructionReference(); }
public override void DecodeArguments(Memory.MemoryBin bin, ref InstructionDecodeContext context, ref int offset, ref InstructionReference instructionReference) { /* No Args */ }
public IfStatement(Expression condition, Statement body) { Condition = condition; Body = body; AfterRefence = new InstructionReference(); }