Beispiel #1
0
        private void Jump(uint address)
        {
            if (address % 2 != 0)
            {
                ExecutionException.Throw(ExecutionError.JumpToUnalignedAddress);
            }

            Ip = (int)(address / 2);
        }
Beispiel #2
0
        private bool ExecuteNextInstruction()
        {
            var instruction = _decoder.Decode(_memoryAccessor.GetShort(_memory, (uint)Ip * 2));

            _tracing.TraceCall(instruction, Ip);
            Ip++;

            int  signedA, signedB;
            uint address;

            ulong ulongResult;

            switch (instruction.Opcode)
            {
            case Opcode.And:
                Registers[instruction.RegisterA] &= Registers[instruction.RegisterB];
                break;

            case Opcode.Add:
                Registers[instruction.RegisterA] += Registers[instruction.RegisterB];
                break;

            case Opcode.Ashl:
                Registers[instruction.RegisterA] = (uint)((int)Registers[instruction.RegisterA] << (int)Registers[instruction.RegisterB]);
                break;

            case Opcode.Ashr:
                Registers[instruction.RegisterA] = (uint)((int)Registers[instruction.RegisterA] >> (int)Registers[instruction.RegisterB]);
                break;

            case Opcode.Beq:
                if (CompareStatusUnsigned == 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Bge:
                if (CompareStatusSigned >= 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Bgeu:
                if (CompareStatusUnsigned >= 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Bgt:
                if (CompareStatusSigned > 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Bgtu:
                if (CompareStatusUnsigned > 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Ble:
                if (CompareStatusSigned <= 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Bleu:
                if (CompareStatusUnsigned <= 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Blt:
                if (CompareStatusSigned < 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Bltu:
                if (CompareStatusUnsigned < 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Bne:
                if (CompareStatusUnsigned != 0)
                {
                    Ip = BranchNewIp(instruction.Value);
                }
                break;

            case Opcode.Brk:
                return(false);

                Break();
                break;

            case Opcode.Cmp:
                signedA = (int)Registers[instruction.RegisterA];
                signedB = (int)Registers[instruction.RegisterB];
                CompareStatusUnsigned = Registers[instruction.RegisterA].CompareTo(Registers[instruction.RegisterB]);
                CompareStatusSigned   = signedA.CompareTo(signedB);
                break;

            case Opcode.Dec:
                Registers[instruction.RegisterA] = (uint)(Registers[instruction.RegisterA] - instruction.Value);
                break;

            case Opcode.Div:
                signedA = (int)Registers[instruction.RegisterA];
                signedB = (int)Registers[instruction.RegisterB];
                if (signedB == 0)
                {
                    ExecutionException.Throw(ExecutionError.DivisionByZero);
                }
                else if (signedA == int.MinValue && signedB == -1)
                {
                    unchecked
                    {
                        Registers[instruction.RegisterA] = (uint)int.MinValue;
                    }
                }
                else
                {
                    Registers[instruction.RegisterA] = (uint)(signedA / signedB);
                }
                break;

            case Opcode.Gsr:
                Registers[instruction.RegisterA] = SpecialRegisters[instruction.Value];
                break;

            case Opcode.Inc:
                Registers[instruction.RegisterA] = (uint)(Registers[instruction.RegisterA] + instruction.Value);
                break;

            case Opcode.Jmp:
                Jump(Registers[instruction.RegisterA]);
                break;

            case Opcode.Jmpa:
                Jump(GetLongImmediate());
                break;

            case Opcode.Jsr:
                JumpToSubroutine(Registers[instruction.RegisterA]);
                break;

            case Opcode.Jsra:
                address = GetLongImmediate();
                JumpToSubroutine(address);
                break;

            case Opcode.LdB:
                Registers[instruction.RegisterA] = _memoryAccessor.GetByte(_memory, Registers[instruction.RegisterB]);
                break;

            case Opcode.LdL:
                Registers[instruction.RegisterA] = _memoryAccessor.GetLong(_memory, Registers[instruction.RegisterB]);
                break;

            case Opcode.LdS:
                Registers[instruction.RegisterA] = _memoryAccessor.GetShort(_memory, Registers[instruction.RegisterB]);
                break;

            case Opcode.LdaB:
                Registers[instruction.RegisterA] = _memoryAccessor.GetByte(_memory, GetLongImmediate());
                Ip += 2;
                break;

            case Opcode.LdaL:
                Registers[instruction.RegisterA] = _memoryAccessor.GetLong(_memory, GetLongImmediate());
                Ip += 2;
                break;

            case Opcode.LdaS:
                Registers[instruction.RegisterA] = _memoryAccessor.GetShort(_memory, GetLongImmediate());
                Ip += 2;
                break;

            case Opcode.LdiL:
                Registers[instruction.RegisterA] = GetLongImmediate();
                break;

            case Opcode.LdiB:
                Registers[instruction.RegisterA] = GetLongImmediate() & 0xFF;
                break;

            case Opcode.LdiS:
                Registers[instruction.RegisterA] = GetLongImmediate() & 0xFFFF;
                break;

            case Opcode.LdoB:
                address = (uint)(Registers[instruction.RegisterB] + GetShortSignedImmediate());
                Registers[instruction.RegisterA] = _memoryAccessor.GetByte(_memory, address);
                break;

            case Opcode.LdoL:
                address = (uint)(Registers[instruction.RegisterB] + GetShortSignedImmediate());
                Registers[instruction.RegisterA] = _memoryAccessor.GetLong(_memory, address);
                break;

            case Opcode.LdoS:
                address = (uint)(Registers[instruction.RegisterB] + GetShortSignedImmediate());
                Registers[instruction.RegisterA] = _memoryAccessor.GetShort(_memory, address);
                break;

            case Opcode.Lshr:
                Registers[instruction.RegisterA] = Registers[instruction.RegisterA] >> (int)Registers[instruction.RegisterB];
                break;

            case Opcode.Mod:
                signedA = (int)Registers[instruction.RegisterA];
                signedB = (int)Registers[instruction.RegisterB];
                Registers[instruction.RegisterA] = (uint)(signedA % signedB);
                break;

            case Opcode.Mov:
                Registers[instruction.RegisterA] = Registers[instruction.RegisterB];
                break;

            case Opcode.Mul:
                signedA     = (int)Registers[instruction.RegisterA];
                signedB     = (int)Registers[instruction.RegisterB];
                ulongResult = (ulong)(signedA * signedB);
                Registers[instruction.RegisterA] = (uint)ulongResult;
                break;

            case Opcode.MulX:
                signedA       = (int)Registers[instruction.RegisterA];
                signedB       = (int)Registers[instruction.RegisterB];
                ulongResult   = (ulong)(signedA * signedB);
                ulongResult >>= 32;
                Registers[instruction.RegisterA] = (uint)ulongResult;
                break;

            case Opcode.Neg:
                signedB = (int)Registers[instruction.RegisterB];
                signedB = -signedB;
                Registers[instruction.RegisterA] = (uint)signedB;
                break;

            case Opcode.Nop:
                break;

            case Opcode.Not:
                Registers[instruction.RegisterA] = ~Registers[instruction.RegisterB];
                break;

            case Opcode.Or:
                Registers[instruction.RegisterA] |= Registers[instruction.RegisterB];
                break;

            case Opcode.Pop:
                Registers[instruction.RegisterB] = Pop(instruction.RegisterA);
                break;

            case Opcode.Push:
                Push(instruction.RegisterA, Registers[instruction.RegisterB]);
                break;

            case Opcode.Ret:
                ReturnFromSubroutine();
                break;

            case Opcode.SexB:
                Registers[instruction.RegisterA] = (uint)(sbyte)Registers[instruction.RegisterB];
                break;

            case Opcode.SexS:
                Registers[instruction.RegisterA] = (uint)(short)Registers[instruction.RegisterB];
                break;

            case Opcode.Ssr:
                SpecialRegisters[instruction.Value] = Registers[instruction.RegisterA];
                break;

            case Opcode.StB:
                _memoryAccessor.StoreByte(_memory, Registers[instruction.RegisterA], (byte)Registers[instruction.RegisterB]);
                break;

            case Opcode.StL:
                _memoryAccessor.StoreLong(_memory, Registers[instruction.RegisterA], Registers[instruction.RegisterB]);
                break;

            case Opcode.StS:
                _memoryAccessor.StoreShort(_memory, Registers[instruction.RegisterA], (ushort)Registers[instruction.RegisterB]);
                break;

            case Opcode.StaB:
                _memoryAccessor.StoreByte(_memory, GetLongImmediate(), (byte)Registers[instruction.RegisterA]);
                break;

            case Opcode.StaL:
                _memoryAccessor.StoreLong(_memory, GetLongImmediate(), Registers[instruction.RegisterA]);
                break;

            case Opcode.StaS:
                _memoryAccessor.StoreShort(_memory, GetLongImmediate(), (ushort)Registers[instruction.RegisterA]);
                break;

            case Opcode.StoB:
                address = (uint)(Registers[instruction.RegisterA] + GetShortSignedImmediate());
                _memoryAccessor.StoreByte(_memory, address, (byte)Registers[instruction.RegisterB]);
                break;

            case Opcode.StoL:
                address = (uint)(Registers[instruction.RegisterA] + GetShortSignedImmediate());
                _memoryAccessor.StoreLong(_memory, address, Registers[instruction.RegisterB]);
                break;

            case Opcode.StoS:
                address = (uint)(Registers[instruction.RegisterA] + GetShortSignedImmediate());
                _memoryAccessor.StoreShort(_memory, address, (ushort)Registers[instruction.RegisterB]);
                break;

            case Opcode.Sub:
                Registers[instruction.RegisterA] = Registers[instruction.RegisterA] - Registers[instruction.RegisterB];
                break;

            case Opcode.Swi:
                SwiRequestIndex = GetLongImmediate();
                Exception(ExceptionReason.SoftwareInterrupt);
                break;

            case Opcode.Udiv:
                Registers[instruction.RegisterA] /= Registers[instruction.RegisterB];
                break;

            case Opcode.Umod:
                Registers[instruction.RegisterA] %= Registers[instruction.RegisterB];
                break;

            case Opcode.UmulX:
                ulongResult   = Registers[instruction.RegisterA] * Registers[instruction.RegisterB];
                ulongResult >>= 32;
                Registers[instruction.RegisterA] = (uint)ulongResult;
                break;

            case Opcode.Xor:
                Registers[instruction.RegisterA] ^= Registers[instruction.RegisterB];
                break;

            case Opcode.ZexB:
                Registers[instruction.RegisterA] = Registers[instruction.RegisterB] & 0xFF;
                break;

            case Opcode.ZexS:
                Registers[instruction.RegisterA] = Registers[instruction.RegisterB] & 0xFFFF;
                break;

            default:
                ExecutionException.Throw(ExecutionError.IllegalOpcode);
                break;
            }

            _instructionsExecuted += 1;
            return(true);
        }