public void ComplementCarryTest() { var bitUnit = new BitUnit(new Memory()); byte flags = 0b00010000; bitUnit.ComplementCarry(ref flags); Assert.Equal(0b00000000, flags); flags = 0b10100000; bitUnit.ComplementCarry(ref flags); Assert.Equal(0b10010000, flags); }
private void CreateBitUnitOpCodes() { CreateOpCode(0x07, () => { bitUnit.RotateLeft(ref A, ref F, true); }, "RLCA"); CreateOpCode(0x17, () => { bitUnit.RotateLeftThroughCarry(ref A, ref F, true); }, "RLA"); CreateOpCode(0x0F, () => { bitUnit.RotateRight(ref A, ref F, true); }, "RRCA"); CreateOpCode(0x1F, () => { bitUnit.RotateRightThroughCarry(ref A, ref F, true); }, "RRA"); CreateOpCode(0x2F, () => bitUnit.Complement(ref A, ref F), "CPL"); CreateOpCode(0x3F, () => bitUnit.ComplementCarry(ref F), "CCF"); foreach (byte code in Enumerable.Range(0x40, 0x40)) { int target = (code - 0x40) % 8; int index = (code - 0x40) / 8; switch (target) { case 0: CreatePrefixedOpCode(code, () => bitUnit.TestBit(B, index, ref F), $"BIT {index}, B"); break; case 1: CreatePrefixedOpCode(code, () => bitUnit.TestBit(C, index, ref F), $"BIT {index}, C"); break; case 2: CreatePrefixedOpCode(code, () => bitUnit.TestBit(D, index, ref F), $"BIT {index}, D"); break; case 3: CreatePrefixedOpCode(code, () => bitUnit.TestBit(E, index, ref F), $"BIT {index}, E"); break; case 4: CreatePrefixedOpCode(code, () => bitUnit.TestBit(H, index, ref F), $"BIT {index}, H"); break; case 5: CreatePrefixedOpCode(code, () => bitUnit.TestBit(L, index, ref F), $"BIT {index}, L"); break; case 6: CreatePrefixedOpCode(code, () => { ReadFromMemory(H, L, out var data); bitUnit.TestBit(data, index, ref F); }, $"BIT {index}, (HL)"); break; case 7: CreatePrefixedOpCode(code, () => bitUnit.TestBit(A, index, ref F), $"BIT {index}, A"); break; } ; } CreatePrefixedOpCode(0x00, () => bitUnit.RotateLeft(ref B, ref F, false), "RLC B"); CreatePrefixedOpCode(0x01, () => bitUnit.RotateLeft(ref C, ref F, false), "RLC C"); CreatePrefixedOpCode(0x02, () => bitUnit.RotateLeft(ref D, ref F, false), "RLC D"); CreatePrefixedOpCode(0x03, () => bitUnit.RotateLeft(ref E, ref F, false), "RLC E"); CreatePrefixedOpCode(0x04, () => bitUnit.RotateLeft(ref H, ref F, false), "RLC H"); CreatePrefixedOpCode(0x05, () => bitUnit.RotateLeft(ref L, ref F, false), "RLC L"); CreatePrefixedOpCode(0x06, () => bitUnit.RotateLeft(H, L, ref F), "RLC (HL)"); CreatePrefixedOpCode(0x07, () => bitUnit.RotateLeft(ref A, ref F, false), "RLC A"); CreatePrefixedOpCode(0x08, () => bitUnit.RotateRight(ref B, ref F, false), "RRC B"); CreatePrefixedOpCode(0x09, () => bitUnit.RotateRight(ref C, ref F, false), "RRC C"); CreatePrefixedOpCode(0x0A, () => bitUnit.RotateRight(ref D, ref F, false), "RRC D"); CreatePrefixedOpCode(0x0B, () => bitUnit.RotateRight(ref E, ref F, false), "RRC E"); CreatePrefixedOpCode(0x0C, () => bitUnit.RotateRight(ref H, ref F, false), "RRC H"); CreatePrefixedOpCode(0x0D, () => bitUnit.RotateRight(ref L, ref F, false), "RRC L"); CreatePrefixedOpCode(0x0E, () => bitUnit.RotateRight(H, L, ref F), "RRC (HL)"); CreatePrefixedOpCode(0x0F, () => bitUnit.RotateRight(ref A, ref F, false), "RRC A"); CreatePrefixedOpCode(0x10, () => bitUnit.RotateLeftThroughCarry(ref B, ref F, false), "RL B"); CreatePrefixedOpCode(0x11, () => bitUnit.RotateLeftThroughCarry(ref C, ref F, false), "RL C"); CreatePrefixedOpCode(0x12, () => bitUnit.RotateLeftThroughCarry(ref D, ref F, false), "RL D"); CreatePrefixedOpCode(0x13, () => bitUnit.RotateLeftThroughCarry(ref E, ref F, false), "RL E"); CreatePrefixedOpCode(0x14, () => bitUnit.RotateLeftThroughCarry(ref H, ref F, false), "RL H"); CreatePrefixedOpCode(0x15, () => bitUnit.RotateLeftThroughCarry(ref L, ref F, false), "RL L"); CreatePrefixedOpCode(0x16, () => bitUnit.RotateLeftThroughCarry(H, L, ref F), "RL (HL)"); CreatePrefixedOpCode(0x17, () => bitUnit.RotateLeftThroughCarry(ref A, ref F, false), "RL A"); CreatePrefixedOpCode(0x18, () => bitUnit.RotateRightThroughCarry(ref B, ref F, false), "RR B"); CreatePrefixedOpCode(0x19, () => bitUnit.RotateRightThroughCarry(ref C, ref F, false), "RR C"); CreatePrefixedOpCode(0x1A, () => bitUnit.RotateRightThroughCarry(ref D, ref F, false), "RR D"); CreatePrefixedOpCode(0x1B, () => bitUnit.RotateRightThroughCarry(ref E, ref F, false), "RR E"); CreatePrefixedOpCode(0x1C, () => bitUnit.RotateRightThroughCarry(ref H, ref F, false), "RR H"); CreatePrefixedOpCode(0x1D, () => bitUnit.RotateRightThroughCarry(ref L, ref F, false), "RR L"); CreatePrefixedOpCode(0x1E, () => bitUnit.RotateRightThroughCarry(H, L, ref F), "RR (HL)"); CreatePrefixedOpCode(0x1F, () => bitUnit.RotateRightThroughCarry(ref A, ref F, false), "RR A"); CreatePrefixedOpCode(0x20, () => bitUnit.ShiftLeftArithmetic(ref B, ref F), "SLA B"); CreatePrefixedOpCode(0x21, () => bitUnit.ShiftLeftArithmetic(ref C, ref F), "SLA C"); CreatePrefixedOpCode(0x22, () => bitUnit.ShiftLeftArithmetic(ref D, ref F), "SLA D"); CreatePrefixedOpCode(0x23, () => bitUnit.ShiftLeftArithmetic(ref E, ref F), "SLA E"); CreatePrefixedOpCode(0x24, () => bitUnit.ShiftLeftArithmetic(ref H, ref F), "SLA H"); CreatePrefixedOpCode(0x25, () => bitUnit.ShiftLeftArithmetic(ref L, ref F), "SLA L"); CreatePrefixedOpCode(0x26, () => bitUnit.ShiftLeftArithmetic(H, L, ref F), "SLA (HL)"); CreatePrefixedOpCode(0x27, () => bitUnit.ShiftLeftArithmetic(ref A, ref F), "SLA A"); CreatePrefixedOpCode(0x28, () => bitUnit.ShiftRightArithmetic(ref B, ref F), "SRA B"); CreatePrefixedOpCode(0x29, () => bitUnit.ShiftRightArithmetic(ref C, ref F), "SRA C"); CreatePrefixedOpCode(0x2A, () => bitUnit.ShiftRightArithmetic(ref D, ref F), "SRA D"); CreatePrefixedOpCode(0x2B, () => bitUnit.ShiftRightArithmetic(ref E, ref F), "SRA E"); CreatePrefixedOpCode(0x2C, () => bitUnit.ShiftRightArithmetic(ref H, ref F), "SRA H"); CreatePrefixedOpCode(0x2D, () => bitUnit.ShiftRightArithmetic(ref L, ref F), "SRA L"); CreatePrefixedOpCode(0x2E, () => bitUnit.ShiftRightArithmetic(H, L, ref F), "SRA (HL)"); CreatePrefixedOpCode(0x2F, () => bitUnit.ShiftRightArithmetic(ref A, ref F), "SRA A"); CreatePrefixedOpCode(0x30, () => bitUnit.Swap(ref B, ref F), "SWAP B"); CreatePrefixedOpCode(0x31, () => bitUnit.Swap(ref C, ref F), "SWAP C"); CreatePrefixedOpCode(0x32, () => bitUnit.Swap(ref D, ref F), "SWAP D"); CreatePrefixedOpCode(0x33, () => bitUnit.Swap(ref E, ref F), "SWAP E"); CreatePrefixedOpCode(0x34, () => bitUnit.Swap(ref H, ref F), "SWAP H"); CreatePrefixedOpCode(0x35, () => bitUnit.Swap(ref L, ref F), "SWAP L"); CreatePrefixedOpCode(0x36, () => bitUnit.Swap(H, L, ref F), "SWAP (HL)"); CreatePrefixedOpCode(0x37, () => bitUnit.Swap(ref A, ref F), "SWAP A"); CreatePrefixedOpCode(0x38, () => bitUnit.ShiftRightLogic(ref B, ref F), "SRL B"); CreatePrefixedOpCode(0x39, () => bitUnit.ShiftRightLogic(ref C, ref F), "SRL C"); CreatePrefixedOpCode(0x3A, () => bitUnit.ShiftRightLogic(ref D, ref F), "SRL D"); CreatePrefixedOpCode(0x3B, () => bitUnit.ShiftRightLogic(ref E, ref F), "SRL E"); CreatePrefixedOpCode(0x3C, () => bitUnit.ShiftRightLogic(ref H, ref F), "SRL H"); CreatePrefixedOpCode(0x3D, () => bitUnit.ShiftRightLogic(ref L, ref F), "SRL L"); CreatePrefixedOpCode(0x3E, () => bitUnit.ShiftRightLogic(H, L, ref F), "SRL (HL)"); CreatePrefixedOpCode(0x3F, () => bitUnit.ShiftRightLogic(ref A, ref F), "SRL A"); // RES and SET instructions all share the same pattern foreach (byte code in Enumerable.Range(0x80, 0x80)) { bool bitValue = code >= 0xC0; int target = (code - 0x80) % 8; int index = (code - (bitValue == true ? 0xC0 : 0x80)) / 8; switch (target) { case 0: CreatePrefixedOpCode(code, () => bitUnit.SetBit(ref B, index, bitValue), $"{(bitValue ? "SET" : "RES")} {index}, B"); break; case 1: CreatePrefixedOpCode(code, () => bitUnit.SetBit(ref C, index, bitValue), $"{(bitValue ? "SET" : "RES")} {index}, C"); break; case 2: CreatePrefixedOpCode(code, () => bitUnit.SetBit(ref D, index, bitValue), $"{(bitValue ? "SET" : "RES")} {index}, D"); break; case 3: CreatePrefixedOpCode(code, () => bitUnit.SetBit(ref E, index, bitValue), $"{(bitValue ? "SET" : "RES")} {index}, E"); break; case 4: CreatePrefixedOpCode(code, () => bitUnit.SetBit(ref H, index, bitValue), $"{(bitValue ? "SET" : "RES")} {index}, H"); break; case 5: CreatePrefixedOpCode(code, () => bitUnit.SetBit(ref L, index, bitValue), $"{(bitValue ? "SET" : "RES")} {index}, L"); break; case 6: CreatePrefixedOpCode(code, () => bitUnit.SetBit(H, L, index, bitValue), $"{(bitValue ? "SET" : "RES")} {index}, (HL)"); break; case 7: CreatePrefixedOpCode(code, () => bitUnit.SetBit(ref A, index, bitValue), $"{(bitValue ? "SET" : "RES")} {index}, A"); break; } ; } }