Beispiel #1
0
 public void ADD_16(WordRegister op1, ushort op2)
 {
     uint result = (uint)(op1.Word + op2);
     byte lookup = (byte)(
         (byte)((op1.Word & 0x0800) >> 11) |
         (byte)((op2 & 0x0800) >> 10) |
         (byte)((result & 0x0800) >> 9));
     op1.Word = (ushort)result;
     _registerFile.F = (byte)(
         (_registerFile.F & (FlagRegisterDefinition.V | FlagRegisterDefinition.Z | FlagRegisterDefinition.S)) |
         ((result & 0x10000) != 0 ? FlagRegisterDefinition.C : (byte)0) |
         (byte)((result >> 8) & (FlagRegisterDefinition._3 | FlagRegisterDefinition._5)) |
         _lookupTables.HalfcarryAdd[lookup]);
 }
Beispiel #2
0
 public void Push(WordRegister register)
 {
     Push(register.Word);
 }
Beispiel #3
0
 public void Push(WordRegister register)
 {
     CpuTicks += 11;
     _cpuStack.Push(register);
 }
Beispiel #4
0
 public void Pop(WordRegister register)
 {
     ushort memoryContent;
     Pop(out memoryContent);
     register.Word = memoryContent;
 }
Beispiel #5
0
 public void Pop(WordRegister register)
 {
     CpuTicks += 10;
     _cpuStack.Pop(register);
 }
Beispiel #6
0
        public void LD_nndd(WordRegister register)
        {
            // Read write address from PC address
            ushort address = _memory.ReadWord(_registerFile.PC);
            _registerFile.PC += 2;

            _memory.WriteWord(address, register.Word);
        }
Beispiel #7
0
 public void ADD_16(WordRegister op1, ushort op2)
 {
     _alu.ADD_16(op1, op2);
 }
Beispiel #8
0
        public void LD_ddnn(WordRegister register)
        {
            // Read write address from PC address
            ushort address = _memory.ReadWord(_registerFile.PC);
            _registerFile.PC += 2;

            register.Word = _memory.ReadWord(address);
        }
Beispiel #9
0
        private void Execute_DDFD_Prefix(WordRegister RegisterI_, byte opcode)
        {
            ByteRegister _I__;
            ushort Address;

            if (opcode == 0x76)     // HALT
            {
                // The first check is for HALT otherwise it could be
                // interpreted as LD (I_ + d),(I_ + d)
                _cpuTicks += 4;
                _registerFile.Halted = true;
            }
            else if ((opcode & 0xC0) == 0x40)   // LD r,r'
            {
                ByteRegister reg1 = GetByteRegisterByOpcode((byte)(opcode >> 3));
                ByteRegister reg2 = GetByteRegisterByOpcode(opcode);

                if (reg1 == null)
                {
                    // The target is (I_ + d)
                    _cpuTicks += 19;
                    Address = (ushort)(RegisterI_.Word + (sbyte)_memory.ReadByte(_registerFile.PC++));
                    _memory.WriteByte(Address, reg2.Value);
                }
                else if (reg2 == null)
                {
                    // The source is (I_ + d)
                    _cpuTicks += 19;
                    Address = (ushort)(RegisterI_.Word + (sbyte)_memory.ReadByte(_registerFile.PC++));
                    reg1.Value = _memory.ReadByte(Address);
                }
                else
                {
                    // Source and target are normal registers but HL is now substituted by I_
                    if (reg1 == _registerFile.RegisterHL.High)
                        reg1 = RegisterI_.High;
                    if (reg1 == _registerFile.RegisterHL.Low)
                        reg1 = RegisterI_.Low;

                    if (reg2 == _registerFile.RegisterHL.High)
                        reg2 = RegisterI_.High;
                    if (reg2 == _registerFile.RegisterHL.Low)
                        reg2 = RegisterI_.Low;

                    _cpuTicks += 8;
                    reg1.Value = reg2.Value;
                }
            }
            else if ((opcode & 0xC0) == 0x80)
            {
                // Operation beetween accumulator and other registers
                // Usually are identified by 10 ooo rrr where ooo is the operation and rrr is the source register
                ByteRegister reg = GetByteRegisterByOpcode(opcode);
                byte _Value;

                if (reg == null)
                {
                    // The source is (I_ + d)
                    _cpuTicks += 19;
                    _Value = _memory.ReadByte((ushort)(RegisterI_.Word + (sbyte)_memory.ReadByte(_registerFile.PC++)));
                }
                else
                {
                    // The source is a normal registry but HL is substituted by I_
                    _cpuTicks += 8;
                    if (reg == _registerFile.RegisterHL.High)
                        _Value = RegisterI_.High.Value;
                    else if (reg == _registerFile.RegisterHL.Low)
                        _Value = RegisterI_.Low.Value;
                    else
                        _Value = reg.Value;
                }

                switch (opcode & 0xF8)
                {
                    case 0x80:  // ADD A,r
                        _alu.ADC_A_r(_Value);
                        break;
                    case 0x88:  // ADC A,r
                        _alu.ADC_A_r(_Value);
                        break;
                    case 0x90:  // SUB r
                        _alu.SUB_r(_Value);
                        break;
                    case 0x98:  // SBC A,r
                        _alu.SBC_A_r(_Value);
                        break;
                    case 0xA0:  // AND r
                        _alu.AND_r(_Value);
                        break;
                    case 0xA8:  // XOR r
                        _alu.XOR_r(_Value);
                        break;
                    case 0xB0:  // OR r
                        _alu.OR_r(_Value);
                        break;
                    case 0xB8:  // CP r
                        CP_r(_Value);
                        break;
                    default:
                        throw new Exception("Wrong place in the right time...");
                }

            }
            else
            {

                switch (opcode)
                {
                    case 0x09:      // ADD I_,BC
                        _cpuTicks += 15;
                        ADD_16(RegisterI_, _registerFile.BC);
                        break;

                    case 0x19:      // ADD I_,DE
                        _cpuTicks += 15;
                        ADD_16(RegisterI_, _registerFile.DE);
                        break;

                    case 0x21:      // LD I_,nnnn
                        _cpuTicks += 14;
                        RegisterI_.Word = _memory.ReadWord(_registerFile.PC);
                        _registerFile.PC += 2;
                        break;

                    case 0x22:      // LD (nnnn),I_
                        _cpuTicks += 20;
                        LD_nndd(RegisterI_);
                        break;

                    case 0x23:      // INC I_
                        _cpuTicks += 10;
                        RegisterI_.Word++;
                        break;

                    case 0x24:      // INC I_.h
                        _cpuTicks += 8;
                        INC(RegisterI_.High);
                        break;

                    case 0x25:      // DEC I_.h
                        _cpuTicks += 8;
                        DEC(RegisterI_.High);
                        break;

                    case 0x26:      // LD I_.h,nn
                        _cpuTicks += 11;
                        RegisterI_.High.Value = _memory.ReadByte(_registerFile.PC++);
                        break;

                    case 0x29:      // ADD I_,I_
                        _cpuTicks += 15;
                        ADD_16(RegisterI_, RegisterI_.Word);
                        break;

                    case 0x2A:      // LD I_,(nnnn)
                        _cpuTicks += 20;
                        LD_ddnn(RegisterI_);
                        break;

                    case 0x2B:      // DEC I_
                        _cpuTicks += 10;
                        RegisterI_.Word--;
                        break;

                    case 0x2C:      // INC I_.l
                        _cpuTicks += 8;
                        INC(RegisterI_.Low);
                        break;

                    case 0x2D:      // DEC I_.l
                        _cpuTicks += 8;
                        DEC(RegisterI_.Low);
                        break;

                    case 0x2E:      // LD I_.l,nn
                        _cpuTicks += 11;
                        RegisterI_.Low.Value = _memory.ReadByte(_registerFile.PC++);
                        break;

                    case 0x34:      // INC (I_ + d)
                        _cpuTicks += 23;
                        Address = (ushort)(RegisterI_.Word + (sbyte)_memory.ReadByte(_registerFile.PC++));
                        _I__ = new ByteRegister(_memory.ReadByte(Address));
                        INC(_I__);
                        _memory.WriteByte(Address, _I__.Value);
                        break;

                    case 0x35:      // DEC (I_ + d)
                        _cpuTicks += 23;
                        Address = (ushort)(RegisterI_.Word + (sbyte)_memory.ReadByte(_registerFile.PC++));
                        _I__ = new ByteRegister(_memory.ReadByte(Address));
                        DEC(_I__);
                        _memory.WriteByte(Address, _I__.Value);
                        break;

                    case 0x36:      // LD (I_ + d),nn
                        _cpuTicks += 19;
                        Address = (ushort)(RegisterI_.Word + (sbyte)_memory.ReadByte(_registerFile.PC++));
                        _memory.WriteByte(Address, _memory.ReadByte(_registerFile.PC++));
                        break;

                    case 0x39:      // ADD I_,SP
                        _cpuTicks += 15;
                        ADD_16(RegisterI_, _registerFile.SP);
                        break;

                    case 0xCB:      // {DD|FD}CBxx opcodes
                        {
                            Address = (ushort)(RegisterI_.Word + (sbyte)_memory.ReadByte(_registerFile.PC++));
                            Execute_DDFD_CB_Prefix(Address, _memory.ReadByte(_registerFile.PC++));
                        }
                        break;
                    case 0xE1:      // POP I_
                        _cpuTicks += 14;
                        Pop(RegisterI_);
                        break;

                    case 0xE3:      // EX (SP),I_
                        _cpuTicks += 23;
                        {
                            ushort _w = _memory.ReadWord(_registerFile.SP);
                            _memory.WriteWord(_registerFile.SP, RegisterI_.Word);
                            RegisterI_.Word = _w;
                        }
                        break;
                    case 0xE5:      // PUSH I_
                        _cpuTicks += 15;
                        Push(RegisterI_);
                        break;

                    case 0xE9:      // JP I_
                        _cpuTicks += 8;
                        _registerFile.PC = RegisterI_.Word;
                        break;

                    // Note EB (EX DE,HL) does not get modified to use either IX or IY;
                    // this is because all EX DE,HL does is switch an internal flip-flop
                    // in the Z80 which says which way round DE and HL are, which can't
                    // be used with IX or IY. (This is also why EX DE,HL is very quick
                    // at only 4 T states).

                    case 0xF9:      // LD SP,I_
                        _cpuTicks += 10;
                        _registerFile.SP = RegisterI_.Word;
                        break;

                    default:
                        // Instruction did not involve H or L, so backtrack one instruction and parse again
                        _cpuTicks += 4;
                        _registerFile.PC--;
                        break;

                }
            }
        }