public static int DEC_r(IZ80CPU cpu, byte[] instruction) { var reg = instruction[0].ExtractBits(3, 3); byte val; switch (reg) { case 0b111: cpu.Registers.A--; val = cpu.Registers.A; break; case 0b000: cpu.Registers.B--; val = cpu.Registers.B; break; case 0b001: cpu.Registers.C--; val = cpu.Registers.C; break; case 0b010: cpu.Registers.D--; val = cpu.Registers.D; break; case 0b011: cpu.Registers.E--; val = cpu.Registers.E; break; case 0b100: cpu.Registers.H--; val = cpu.Registers.H; break; case 0b101: cpu.Registers.L--; val = cpu.Registers.L; break; default: throw new InvalidOperationException(); } DecrementByteSetConditionBits(cpu, val); return(4); }
public static int LD_IY_nn_mem(IZ80CPU cpu, byte[] instruction) { var nn = Utilities.LETo16Bit(instruction[2], instruction[3]); cpu.Registers.IY = cpu.ReadWord(nn); return(20); }
private static byte RotateByteRight(IZ80CPU cpu, byte val) { cpu.Registers.HalfCarry = false; cpu.Registers.Subtract = false; cpu.Registers.Carry = val.GetBit(0); return((byte)((val >> 1) | (val.GetBitAsByte(0) << 7))); }
private static void AddWordsWithCarryAndSetConditionBits(IZ80CPU cpu, bool subtract, ushort b) { var a = cpu.Registers.HL; var c = (ushort)(cpu.Registers.Carry ? 1 : 0); if (subtract) { b = b.TwosComplement(); c = c.TwosComplement(); } var sum = a + b + c; var noCarrySum = a ^ b ^ c; var carryInto = sum ^ noCarrySum; var halfCarry = carryInto & 0x1000; var carry = carryInto & 0x10000; var overflow = carryInto & 0x8000; var result = (ushort)sum; cpu.Registers.Sign = result.IsNegative(); cpu.Registers.Zero = result == 0; cpu.Registers.HalfCarry = halfCarry != 0; cpu.Registers.ParityOrOverflow = overflow != 0; cpu.Registers.Subtract = subtract; cpu.Registers.Carry = carry != 0; cpu.Registers.HL = result; }
public static int JP_cc_nn(IZ80CPU cpu, byte[] instruction) { var condition = instruction[0].ExtractBits(3, 3); var shouldJump = false; switch (condition) { case 0b000: shouldJump = !cpu.Registers.Zero; break; case 0b001: shouldJump = cpu.Registers.Zero; break; case 0b010: shouldJump = !cpu.Registers.Carry; break; case 0b011: shouldJump = cpu.Registers.Carry; break; case 0b100: shouldJump = !cpu.Registers.ParityOrOverflow; break; case 0b101: shouldJump = cpu.Registers.ParityOrOverflow; break; case 0b110: shouldJump = !cpu.Registers.Sign; break; case 0b111: shouldJump = cpu.Registers.Sign; break; default: throw new InvalidOperationException(); } if (shouldJump) { cpu.Registers.PC = Utilities.LETo16Bit(instruction[1], instruction[2]); } return(10); }
private static void SubBytes(IZ80CPU cpu, byte a, byte b, bool useCarryFlag = false) { var carryFlagValue = ((byte)(useCarryFlag ? 1 : 0)).TwosComplement(); b = b.TwosComplement(); AddMultipleBytesAndSetConditionBits(cpu, true, a, b, carryFlagValue); }
public static int ADD_IY_pp(IZ80CPU cpu, byte[] instruction) { cpu.InsertWaitMachineCycle(4); ushort val = 0; switch (instruction[1]) { case 0x09: val = cpu.Registers.BC; break; case 0x19: val = cpu.Registers.DE; break; case 0x29: val = cpu.Registers.IY; break; case 0x39: val = cpu.Registers.SP; break; default: throw new InvalidOperationException(); } var upperReg = val.GetUpperByte(); var upperIY = cpu.Registers.IXUpper; cpu.Registers.IY += val; cpu.Registers.HalfCarry = upperIY.WillHalfCarry(upperReg); cpu.Registers.Subtract = false; cpu.Registers.Carry = upperIY.WillCarry(upperReg); cpu.InsertWaitMachineCycle(3); return(15); }
public static int CPDR(IZ80CPU cpu, byte[] instruction) { var data = cpu.ReadMemory(cpu.Registers.HL); var cmp = cpu.Registers.A - data; cpu.Registers.HL--; cpu.Registers.BC--; cpu.Registers.Sign = cmp < 0; cpu.Registers.Zero = cmp == 0; cpu.Registers.HalfCarry = cpu.Registers.A.WillHalfCarry(data); cpu.Registers.Subtract = true; cpu.Registers.ParityOrOverflow = cpu.Registers.BC != 0; cpu.InsertWaitMachineCycle(5); if (cpu.Registers.Zero || cpu.Registers.BC == 0) { return(16); } cpu.Registers.PC -= 2; cpu.InsertWaitMachineCycle(5); return(21); }
public static int RET(IZ80CPU cpu, byte[] instruction) { cpu.Registers.PC = cpu.Registers.PC.SetLowerByte(cpu.PopByte()); cpu.Registers.PC = cpu.Registers.PC.SetUpperByte(cpu.PopByte()); return(10); }
public static int DJNZ_e(IZ80CPU cpu, byte[] instruction) { // FIXME: The opcode fetch has the tick after it, then the memory read for the operand cpu.ControlLines.SystemClock.Tick(); cpu.Registers.B--; if (cpu.Registers.B == 0) { return(8); } var offset = (int)instruction[1]; offset += 2; if (offset < 0) { cpu.Registers.PC -= (ushort)Math.Abs(offset); } else { cpu.Registers.PC += (ushort)offset; } cpu.InsertWaitMachineCycle(5); return(13); }
public static int CALL_nn(IZ80CPU cpu, byte[] instruction) { cpu.PushWord(cpu.Registers.PC, 1); cpu.Registers.PC = Utilities.LETo16Bit(instruction[1], instruction[2]); return(17); }
public static int POP_IY(IZ80CPU cpu, byte[] instruction) { cpu.Registers.IYLower = cpu.PopByte(); cpu.Registers.IYUpper = cpu.PopByte(); return(14); }
private static byte RotateByteLeft(IZ80CPU cpu, byte val) { cpu.Registers.HalfCarry = false; cpu.Registers.Subtract = false; cpu.Registers.Carry = cpu.Registers.A.GetBit(7); return((byte)((cpu.Registers.A << 1) | (cpu.Registers.A.GetBitAsByte(7) >> 7))); }
public static int LD_IY_plus_d_mem_n(IZ80CPU cpu, byte[] instruction) { cpu.ControlLines.SystemClock.TickMultiple(2); cpu.WriteMemory(cpu.Registers.IX.CalculateIndex(instruction[2]), instruction[3]); return(19); }
public static int DEC_IX(IZ80CPU cpu, byte[] instruction) { cpu.ControlLines.SystemClock.TickMultiple(2); cpu.Registers.IX--; return(10); }
public static int LD_nn_mem_A(IZ80CPU cpu, byte[] instruction) { var addr = Utilities.LETo16Bit(instruction[1], instruction[2]); cpu.WriteMemory(addr, cpu.Registers.A); return(13); }
public static int LD_A_nn_mem(IZ80CPU cpu, byte[] instruction) { var addr = Utilities.LETo16Bit(instruction[1], instruction[2]); cpu.Registers.A = cpu.ReadMemory(addr); return(13); }
public static int EI(IZ80CPU cpu, byte[] instruction) { cpu.Registers.IFF1 = true; cpu.Registers.IFF2 = true; return(4); }
public static int LD_SP_IY(IZ80CPU cpu, byte[] instruction) { cpu.ControlLines.SystemClock.TickMultiple(2); cpu.Registers.SP = cpu.Registers.IY; return(10); }
public static int LD_r_n(IZ80CPU cpu, byte[] instruction) { var dst = instruction[0].ExtractBits(3, 3); WriteByteToCpuRegister(cpu, dst, instruction[1]); return(7); }
public static int RST_p(IZ80CPU cpu, byte[] instruction) { cpu.ControlLines.SystemClock.Tick(); cpu.PushWord(cpu.Registers.PC); cpu.Registers.PC = (ushort)(instruction[0].ExtractBits(3, 3) * 8); return(11); }
public static int LD_HL_nn_mem(IZ80CPU cpu, byte[] instruction) { var nn = Utilities.LETo16Bit(instruction[1], instruction[2]); cpu.Registers.HL = cpu.ReadWord(nn); return(16); }
public static int LD_IY_nn(IZ80CPU cpu, byte[] instruction) { var nn = Utilities.LETo16Bit(instruction[2], instruction[3]); cpu.Registers.IY = nn; return(14); }
public static int LD_R_A(IZ80CPU cpu, byte[] instruction) { cpu.ControlLines.SystemClock.Tick(); cpu.Registers.R = cpu.Registers.A; return(9); }
public static int RETI(IZ80CPU cpu, byte[] instruction) { cpu.Registers.PC = cpu.Registers.PC.SetLowerByte(cpu.PopByte()); cpu.Registers.PC = cpu.Registers.PC.SetUpperByte(cpu.PopByte()); cpu.InterruptsBeingServiced.Pop(); return(14); }
public static int LD_nn_mem_IY(IZ80CPU cpu, byte[] instruction) { var addr = Utilities.LETo16Bit(instruction[2], instruction[3]); cpu.WriteWord(addr, cpu.Registers.IY); return(20); }
public static int ADC_A_n(IZ80CPU cpu, byte[] instruction) { var data = instruction[1]; AddBytes(cpu, cpu.Registers.A, data, true); return(7); }
public static int ADC_A_HL_mem(IZ80CPU cpu, byte[] instruction) { var data = cpu.ReadMemory(cpu.Registers.HL); AddBytes(cpu, cpu.Registers.A, data, true); return(7); }
public static int LD_nn_mem_HL(IZ80CPU cpu, byte[] instruction) { var addr = Utilities.LETo16Bit(instruction[1], instruction[2]); cpu.WriteWord(addr, cpu.Registers.HL); return(16); }
public static int SCF(IZ80CPU cpu, byte[] instruction) { cpu.Registers.HalfCarry = false; cpu.Registers.Subtract = false; cpu.Registers.Carry = true; return(4); }