Пример #1
0
 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);
     }
 }
Пример #2
0
        /// <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;
        }
Пример #3
0
        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");
                    }
            }
        }
Пример #4
0
 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;
             }
     }
 }
Пример #5
0
        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");
                    }
            }
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
 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++;
 }
Пример #8
0
 private void EmitGoto(InstructionReference reference)
 {
     _emitter.Emit(OpCodes.Br, reference);
 }
Пример #9
0
        /// <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);
        }
Пример #10
0
        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;
            }
        }
Пример #11
0
        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());
            }
        }
Пример #12
0
        /// <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));
                }
            }
        }
Пример #13
0
 public ForStatement()
 {
     AfterRefence         = new InstructionReference();
     BodyReference        = new InstructionReference();
     ConditionalReference = new InstructionReference();
 }
Пример #14
0
 public override void DecodeArguments(Memory.MemoryBin bin, ref InstructionDecodeContext context, ref int offset, ref InstructionReference instructionReference)
 {
     /* No Args */
 }
Пример #15
0
 public IfStatement(Expression condition, Statement body)
 {
     Condition    = condition;
     Body         = body;
     AfterRefence = new InstructionReference();
 }