public void EqualityTest_NotRegister16() { var r = new Register16(0); Assert.False(r.Equals(null)); Assert.False(r.Equals(0)); }
public void NonDefaultConstructorTest(ushort value) { var r1 = new Register16(value); var r2 = new Register16(value); Assert.Equal(r1, r2); }
public INC16(Gameboy parent, byte opcode) : base(parent) { target = OpcodeUtils.BitsToRegister16((opcode & 0b1110000) >> 4); Cycles = 8; Disassembly = "inc " + OpcodeUtils.Register16ToString(target); }
private void InternalAddressBus_SampleFrom(Register16 source) { switch (source) { case Register16.BC: InternalAddressBus = BC; break; case Register16.DE: InternalAddressBus = DE; break; case Register16.HL: InternalAddressBus = HL; break; case Register16.IX: InternalAddressBus = IX; break; case Register16.IY: InternalAddressBus = IY; break; default: throw new NotImplementedException(); } if (TraceMicroInstructions) { TraceMicroInstruction(new MicroInstruction(Z80MicroInstructionTypes.InternalAddressBusSampleFrom, source)); } }
public void GetHashCodeTest() { var r = new Register16(10); Assert.Equal(r.GetHashCode(), new Register16(10).GetHashCode()); Assert.NotEqual(r.GetHashCode(), new Register16(20).GetHashCode()); }
public void SettingLoShouldChangeCombinedValueTest() { var r = new Register16(); r.Lo = 0xaa; r.Value.Should().Be(0x00AA); }
public static Register GetHigherPart(Register16 register16) { switch (register16) { case Register16.BC: return(Register.B); case Register16.DE: return(Register.D); case Register16.HL: return(Register.H); case Register16.IX: return(Register.IXh); case Register16.IY: return(Register.IYh); case Register16.SP: case Register16.AF: case Register16.AF2: default: throw new InvalidOperationException(); } }
public ADD16(Gameboy parent, byte opcode) : base(parent) { source = OpcodeUtils.BitsToRegister16((opcode & 0b110000) >> 4); Disassembly = "add hl, " + OpcodeUtils.Register16ToString(source); Cycles = 8; }
public void InitRegister16(Register16 register, ushort debugInitialValue) { switch (register) { case Register16.BC: BC = debugInitialValue; break; case Register16.DE: DE = debugInitialValue; break; case Register16.HL: HL = debugInitialValue; break; case Register16.SP: SP = debugInitialValue; break; case Register16.IX: IX = debugInitialValue; break; case Register16.IY: IY = debugInitialValue; break; default: throw new NotImplementedException(); } }
public void CanChangeValue() { cpu.registers.af = 0; Register16 reg = new Register16(cpu, "af"); reg.Target = 0xFFF0; Assert.Equal(0xFFF0, reg.Target); Assert.Equal(0xFFF0, cpu.registers.af); }
private void Push(Z80 z80, Register16 register) { z80.SP.Value++; z80.Memory.Set(z80.SP.Value, register.High.Value); z80.SP.Value++; z80.Memory.Set(z80.SP.Value, register.Low.Value); }
public void SettingHiShouldChangeCombinedValueTest() { var r = new Register16(); r.Hi = 0xbb; r.Value.Should().Be(0xbb00); }
public static Register GetLowerPart(Register16 register16) { switch (register16) { case Register16.BC: return(Register.C); case Register16.DE: return(Register.E); case Register16.HL: return(Register.L); case Register16.IX: return(Register.IXl); case Register16.IY: return(Register.IYl); case Register16.SP: case Register16.AF: case Register16.AF2: default: throw new InvalidOperationException(); } }
public static Action add(CPU cpu, Register16 o1, Register16 o2) => () => { ushort hl = o1.Target; o1.Target += o2.Target; cpu.HalfCarry = (hl & 0xFFF) + (o2.Target & 0xFFF) > 0xFFF; cpu.AddSub = false; cpu.Carry = hl + o2.Target > 0xFFFF; };
private TStates ExchangeRegisters(Register16 register1, Register16 register2) { var register1Value = register1.Value; register1.Value = register2.Value; register2.Value = register1Value; return(TStates.Count(4)); }
public void NewCreatedRegisterShouldBeZeroedTest() { var r = new Register16(); r.Value.Should().Be(0); r.Hi.Should().Be(0); r.Lo.Should().Be(0); }
private TStates LoadFromMemoryIntoRegister(Z80 z80, Register16 register) { var address = ByteHelper.CreateUShort(z80.Buffer[3], z80.Buffer[2]); var low = z80.Memory.Get(address); var high = z80.Memory.Get(++address); register.Value = ByteHelper.CreateUShort(high, low); return(TStates.Count(20)); }
public void SettingValueShouldChangeAllValuesTest() { var r = new Register16(); r.Value = 0xbeef; r.Value.Should().Be(0xbeef); r.Hi.Should().Be(0xbe); r.Lo.Should().Be(0xef); }
public static Action adc(CPU cpu, Register16 o1, Register16 o2) => () => { cpu.registers.hl += (ushort)(o2.Target + Convert.ToByte(cpu.Carry)); cpu.Sign = cpu.registers.a > 0x7F; cpu.Zero = cpu.registers.a == 0; cpu.HalfCarry = true; // TODO cpu.Overflow = true; // TODO cpu.AddSub = false; cpu.Carry = false; // TODO };
private static byte GetPrefix(ref Register16 r) { if (r.Value < 8) { return(r.Value); } r = new Register16((byte)(r.Value - 8)); return(1); }
public LDA(Gameboy parent, byte opcode) : base(parent) { load = (opcode & 0b1000) > 0; regpair = (opcode & 0b10000) > 0 ? Register16.DE : Register16.BC; Cycles = 8; TickAccurate = true; Disassembly = load ? "ld a, [" + OpcodeUtils.Register16ToString(regpair) + "]" : "ld [" + OpcodeUtils.Register16ToString(regpair) + "], a"; }
public void EmptyRegister16() { // Arrange var register16 = new Register16(new Register8(), new Register8()); // Act // Assert Assert.That(register16.Value == 0x0000); }
public LD16(Gameboy parent, byte opcode) : base(parent) { target = OpcodeUtils.BitsToRegister16((opcode & 0b110000) >> 4); targetLow = target == Register16.BC ? Register.C : target == Register16.DE ? Register.E : Register.L; targetHigh = target == Register16.BC ? Register.B : target == Register16.DE ? Register.D : Register.H; Cycles = 12; Length = 3; TickAccurate = true; Disassembly = "ld " + OpcodeUtils.Register16ToString(target) + ", $" + (parent.Memory[parent.PC + 1] + (parent.Memory[parent.PC + 2] << 8)).ToString("X2"); }
public POP(Gameboy parent, byte opcode) : base(parent) { target = OpcodeUtils.BitsToRegister16((opcode & 0b110000) >> 4); if (target == Register16.SP) { target = Register16.AF; } Cycles = 12; Disassembly = "pop " + OpcodeUtils.Register16ToString(target); }
private void Pop(Z80 z80, Register16 register) { var lowValue = z80.Memory.Get(z80.SP.Value); z80.SP.Value++; var highValue = z80.Memory.Get(z80.SP.Value); z80.SP.Value++; register.Value = BitConverter.ToUInt16(new[] { highValue, lowValue }, 0); }
public PUSH(Gameboy parent, byte opcode) : base(parent) { source = OpcodeUtils.BitsToRegister16((opcode & 0b110000) >> 4); if (source == Register16.SP) { source = Register16.AF; } Cycles = 16; Disassembly = "push " + OpcodeUtils.Register16ToString(source); }
public Z80(Memory memory, Ports ports) { Memory = memory; Ports = ports; F = new Registers.Flags(); F_ = new Registers.Flags(); PC = new Register16("PC"); SP = new Register16("SP"); A = new Register8("A"); B = new Register8("B"); C = new Register8("C"); D = new Register8("D"); E = new Register8("E"); H = new Register8("H"); L = new Register8("L"); A_ = new Register8("A"); B_ = new Register8("B"); C_ = new Register8("C"); D_ = new Register8("D"); E_ = new Register8("E"); H_ = new Register8("H"); L_ = new Register8("L"); I = new Register8("I"); R = new Register8("R"); AF = new Register16(A, F); BC = new Register16(B, C); DE = new Register16(D, E); HL = new Register16(H, L); IX = new Register16("IX"); IY = new Register16("IY"); AF_ = new Register16(A_, F_); BC_ = new Register16(B_, C_); DE_ = new Register16(D_, E_); HL_ = new Register16(H_, L_); InstructionSet = new InstructionSet(); Buffer = new List <byte>(); PC.Value = 0x0; SP.Value = 0XFFFF; Buffer.Clear(); }
private TStates ExchangeStackPointer(Z80 z80, Register16 register) { var low = register.Low.Value; var high = register.High.Value; var sp = z80.SP.Value; register.Low.Value = z80.Memory.Get(sp); register.High.Value = z80.Memory.Get((ushort)(sp + 1)); z80.Memory.Set(sp, low); z80.Memory.Set((ushort)(sp + 1), high); return(TStates.Count(19)); }
public void SetRegister16(Register16 register, ushort value) { switch (register) { case Register16.Af: AF = value; break; case Register16.Bc: BC = value; break; case Register16.De: DE = value; break; case Register16.Hl: HL = value; break; case Register16.Sp: SP = value; break; } }
public void SettingRegister8ValuePartOfRegister16() { // Arrange var firstRegister8 = new Register8(); var secondRegister8 = new Register8(); var register16 = new Register16(firstRegister8, secondRegister8); // Act firstRegister8.Value = 0xAA; // Assert Assert.That(register16.Value == 0xAA00); Assert.That(firstRegister8.Value == 0xAA); Assert.That(secondRegister8.Value == 0x00); }
public void SettingRegister16Value() { // Arrange var firstRegister8 = new Register8(); var secondRegister8 = new Register8(); var register16 = new Register16(firstRegister8, secondRegister8); // Act register16.Value = 0x1122; // Assert Assert.That(register16.Value == 0x1122); Assert.That(firstRegister8.Value == 0x11); Assert.That(secondRegister8.Value == 0x22); }
public ushort GetRegister16(Register16 register) { switch (register) { case Register16.Af: return(AF); case Register16.Bc: return(BC); case Register16.De: return(DE); case Register16.Hl: return(HL); case Register16.Sp: return(SP); default: return(0); } }
public static string Register16ToString(Register16 reg) { switch (reg) { case Register16.AF: return("af"); case Register16.BC: return("bc"); case Register16.DE: return("de"); case Register16.HL: return("hl"); case Register16.PC: return("pc"); case Register16.SP: return("sp"); default: return("Unknown register pair"); } }
public static Action inc(CPU cpu, Register16 o) => () => ++o.Target;
private void Register16_Increment(Register16 register) { switch (register) { case Register16.BC: BC = (ushort)(BC + 1); break; case Register16.DE: DE = (ushort)(DE + 1); break; case Register16.HL: HL = (ushort)(HL + 1); break; case Register16.SP: SP = (ushort)(SP + 1); break; case Register16.IX: IX = (ushort)(IX + 1); break; case Register16.IY: IY = (ushort)(IY + 1); break; default: throw new NotImplementedException(); } if (TraceMicroInstructions) { TraceMicroInstruction(new MicroInstruction(Z80MicroInstructionTypes.Register16Increment, register)); } }
private void SwitchRegister16(Register16 firstRegister) { if (firstRegister == Register16.AF) { SwitchALUAlternateRegisterSet(); } else // if (firstRegister == Register16.DE) { // Here we don't implement a real switch with table index arithmetic for performance reasons // -> just swap the two values in memory ushort temp = DE; DE = HL; HL = temp; } if (TraceMicroInstructions) { TraceMicroInstruction(new MicroInstruction(Z80MicroInstructionTypes.Register16SwitchTwoRegisters, firstRegister)); } }
public ushort GetRegister16(Register16 register) { switch (register) { case Register16.Af: return AF; case Register16.Bc: return BC; case Register16.De: return DE; case Register16.Hl: return HL; case Register16.Sp: return SP; default: return 0; } }
public static Action dec(CPU cpu, Register16 o) => () => --o.Target;
public void CanGetChangedValue() { cpu.registers.af = 0x0510; Register16 reg = new Register16(cpu, "af"); cpu.registers.af = 0x1011; Assert.Equal(0x1011, reg.Target); }
public static Register GetLowerPart(Register16 register16) { switch (register16) { case Register16.BC: return Register.C; case Register16.DE: return Register.E; case Register16.HL: return Register.L; case Register16.IX: return Register.IXl; case Register16.IY: return Register.IYl; case Register16.SP: case Register16.AF: case Register16.AF2: default: throw new InvalidOperationException(); } }
public static Action sbc(CPU cpu, Register16 o1, Operand<ushort> o) => () => { cpu.registers.hl -= o.Target; cpu.Sign = cpu.registers.hl > 0x7F; cpu.Zero = cpu.registers.hl == 0; cpu.HalfCarry = true; // TODO cpu.Overflow = true; // TODO cpu.AddSub = true; cpu.Carry = false; // TODO };
public static Action ex(CPU cpu, Register16 o1, Register16 o2) => () => { ushort de = cpu.registers.de; // TODO use o1, o2? cpu.registers.de = cpu.registers.hl; cpu.registers.hl = de; };
public void CanGetOriginalValue() { cpu.registers.af = 0x0506; Register16 reg = new Register16(cpu, "af"); Assert.Equal(0x0506, reg.Target); }
public static Action push(CPU cpu, Register16 o) => () => cpu.Push(o.Target);
public static Action pop(CPU cpu, Register16 o) => () => o.Target = cpu.Pop();
public static Register GetHigherPart(Register16 register16) { switch (register16) { case Register16.BC: return Register.B; case Register16.DE: return Register.D; case Register16.HL: return Register.H; case Register16.IX: return Register.IXh; case Register16.IY: return Register.IYh; case Register16.SP: case Register16.AF: case Register16.AF2: default: throw new InvalidOperationException(); } }
public static Action ex(CPU cpu, Indirect8 o1, Register16 o2) => () => { // TODO };