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]); }
public void Push(WordRegister register) { Push(register.Word); }
public void Push(WordRegister register) { CpuTicks += 11; _cpuStack.Push(register); }
public void Pop(WordRegister register) { ushort memoryContent; Pop(out memoryContent); register.Word = memoryContent; }
public void Pop(WordRegister register) { CpuTicks += 10; _cpuStack.Pop(register); }
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); }
public void ADD_16(WordRegister op1, ushort op2) { _alu.ADD_16(op1, op2); }
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); }
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; } } }