]> localhost Git - glBoy.git/commitdiff
Added tests for ALU. Implemented all 8-buit arithmatic.
authorMichael McMaster <email@michaelmcmaster.name>
Sun, 19 Dec 2010 11:06:09 +0000 (21:06 +1000)
committerMichael McMaster <email@michaelmcmaster.name>
Sun, 19 Dec 2010 11:06:09 +0000 (21:06 +1000)
ALU.cc [new file with mode: 0644]
ALU.hh [new file with mode: 0755]
DWORD.hh [new file with mode: 0644]
Test.cc [new file with mode: 0644]

diff --git a/ALU.cc b/ALU.cc
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ALU.hh b/ALU.hh
new file mode 100755 (executable)
index 0000000..a59402e
--- /dev/null
+++ b/ALU.hh
@@ -0,0 +1,487 @@
+<?xml version="1.0" encoding="UTF-8" ?>\r
+<opcodes>\r
+<!--\r
+       Z80 Core Emulation\r
+       Copyright 2010, Michael McMaster <email@michaelmcmaster.name>\r
+-->\r
+\r
+<!--\r
+code gen expectations:\r
+masks result in each instruction being unrolled and the mask name being replaced\r
+with an actual register\r
+operand = op8();\r
+operand="UPPERCASE" is 16bit operand, in NATIVE(x86) byte order, but read in little-endian order from instruction pointer. N = op16(). ACTUALLY, NO. Return a struct DWORD, and enforce constraints!\r
+-->\r
+\r
+<registerMask name="r" bits="3">\r
+       <reg name="A" mask="111" />\r
+       <reg name="B" mask="000" />\r
+       <reg name="C" mask="001" />\r
+       <reg name="D" mask="010" />\r
+       <reg name="E" mask="011" />\r
+       <reg name="H" mask="100" />\r
+       <reg name="L" mask="101" />\r
+</registerMask>\r
+\r
+<registerMask name="d" alias="s" bits="2">\r
+       <reg name="BC" mask="00" />\r
+       <reg name="DE" mask="01" />\r
+       <reg name="HL" mask="10" />\r
+       <reg name="SP" mask="11" />\r
+</registerMask>\r
+\r
+<registerMask name="q" bits="2">\r
+       <reg name="BC" mask="00" />\r
+       <reg name="DE" mask="01" />\r
+       <reg name="HL" mask="10" />\r
+       <reg name="AF" mask="11" />\r
+</registerMask>\r
+\r
+<registerMask name="p" bits="2">\r
+       <reg name="BC" mask="00" />\r
+       <reg name="DE" mask="01" />\r
+       <reg name="IX" mask="10" />\r
+       <reg name="SP" mask="11" />\r
+</registerMask>\r
+\r
+<registerMask name="R" bits="2">\r
+       <reg name="BC" mask="00" />\r
+       <reg name="DE" mask="01" />\r
+       <reg name="IY" mask="10" />\r
+       <reg name="SP" mask="11" />\r
+</registerMask>\r
+\r
+<!--\r
+                               8-BIT LD Instructions\r
+-->\r
+\r
+<instruction name="LD r,r'" clock="4">\r
+<opcode mask="01rr" />\r
+r = r2;\r
+</instruction>\r
+\r
+<instruction name="LD r,n" clock="7">\r
+<opcode mask="00r110" operand="n"/>\r
+r = n;\r
+</instruction>\r
+\r
+<instruction name="LD r,(HL)" clock="7">\r
+<opcode mask="01r110" />\r
+r = m_mem.read8(m_reg.HL);\r
+</instruction>\r
+\r
+<instruction name="LD r,(IX+d)" clock="19">\r
+<opcode prefix="0xDD" mask="01r110" signed_operand="d"/>\r
+r = m_mem.read8(m_reg.IX, d);\r
+</instruction>\r
+\r
+<instruction name="LD r,(IY+d)" clock="19">\r
+<opcode prefix="0xFD" mask="01r110" signed_operand="d"/>\r
+r = m_mem.read8(m_reg.IY, d);\r
+</instruction>\r
+\r
+<instruction name="LD (HL),r" clock="7">\r
+<opcode mask="01110r"/>\r
+m_mem.write8(m_reg.HL, r);\r
+</instruction>\r
+\r
+<instruction name="LD (IX+d),r" clock="19">\r
+<opcode prefix="0xDD" mask="01110r" signed_operand="d"/>\r
+m_mem.write8(m_reg.IX, d, r);\r
+</instruction>\r
+\r
+<instruction name="LD (IY+d),r" clock="19">\r
+<opcode prefix="0xFD" mask="01110r" signed_operand="d"/>\r
+m_mem.write8(m_reg.IY, d, r);\r
+</instruction>\r
+\r
+<instruction name="LD (HL),n" clock="10">\r
+<opcode mask="00110110" operand="n"/>\r
+m_mem.write8(m_reg.HL, n);\r
+</instruction>\r
+\r
+<instruction name="LD (IX+d),r" clock="19">\r
+<opcode prefix="0xDD" mask="00110110" signed_operand="d" operand="n"/>\r
+m_mem.write8(m_reg.IX, d, n);\r
+</instruction>\r
+\r
+<instruction name="LD (IY+d),n" clock="19">\r
+<opcode prefix="0xFD" mask="00110110" signed_operand="d" operand="n"/>\r
+m_mem.write8(m_reg.IY, d, n);\r
+</instruction>\r
+\r
+<instruction name="LD A,(BC)" clock="7">\r
+<opcode mask="00001010"/>\r
+m_reg.A = m_mem.read8(m_reg.BC);\r
+</instruction>\r
+\r
+<instruction name="LD A,(DE)" clock="7">\r
+<opcode mask="00011010"/>\r
+m_reg.A = m_mem.read8(m_reg.DE);\r
+</instruction>\r
+\r
+<instruction name="LD A,(nn)" clock="13">\r
+<opcode mask="00111010" operand="N"/>\r
+m_reg.A = m_mem.read8(N);\r
+</instruction>\r
+\r
+<instruction name="LD (BC),A" clock="7">\r
+<opcode mask="00000010"/>\r
+m_mem.write8(m_reg.BC, m_reg.A);\r
+</instruction>\r
+\r
+<instruction name="LD (DE),A" clock="7">\r
+<opcode mask="00010010"/>\r
+m_mem.write8(m_reg.DE, m_reg.A);\r
+</instruction>\r
+\r
+<instruction name="LD (nn),A" clock="13">\r
+<opcode mask="00110010" operand="N"/>\r
+m_mem.write8(N, m_reg.A);\r
+</instruction>\r
+\r
+<instruction name="LD A,I" clock="9">\r
+<opcode prefix="0xED" mask="01010111"/>\r
+m_reg.F.set(m_reg.I, *this);\r
+m_reg.A = m_reg.I;\r
+</instruction>\r
+\r
+<instruction name="LD A,R" clock="9">\r
+<opcode prefix="0xED" mask="01011111"/>\r
+m_reg.F.set(m_reg.R, *this);\r
+m_reg.A = m_reg.R;\r
+</instruction>\r
+\r
+<instruction name="LD I,A" clock="9">\r
+<opcode prefix="0xED" mask="01000111"/>\r
+m_reg.I = m_reg.A;\r
+</instruction>\r
+\r
+<instruction name="LD R,A" clock="9">\r
+<opcode prefix="0xED" mask="01001111"/>\r
+m_reg.R = m_reg.A;\r
+</instruction>\r
+\r
+<!--\r
+                               16-BIT LD Instructions\r
+-->\r
+\r
+<instruction name="LD dd,nn" clock="10">\r
+<opcode mask="00d0001" operand="N" />\r
+d = N;\r
+</instruction>\r
+\r
+<instruction name="LD IX,nn" clock="14">\r
+<opcode prefix="0xDD" mask="00100001" operand="N" />\r
+m_reg.IX = N;\r
+</instruction>\r
+\r
+<instruction name="LD IY,nn" clock="14">\r
+<opcode prefix="0xFD" mask="00100001" operand="N" />\r
+m_reg.IY = N;\r
+</instruction>\r
+\r
+<instruction name="LD HL,(nn)" clock="16">\r
+<opcode mask="00101010" operand="N" />\r
+m_reg.HL = m_mem.read16(N);\r
+</instruction>\r
+\r
+<instruction name="LD dd,(nn)" clock="20">\r
+<opcode prefix="0xED" mask="01d1011" operand="N" />\r
+d = m_mem.read16(N);\r
+</instruction>\r
+\r
+<instruction name="LD IX,(nn)" clock="20">\r
+<opcode prefix="0xDD" mask="00101010" operand="N" />\r
+m_reg.IX = m_mem.read16(N);\r
+</instruction>\r
+\r
+<instruction name="LD IY,(nn)" clock="20">\r
+<opcode prefix="0xFD" mask="00101010" operand="N" />\r
+m_reg.IY = m_mem.read16(N);\r
+</instruction>\r
+\r
+<instruction name="LD (nn),HL" clock="16">\r
+<opcode mask="00100010" operand="N" />\r
+m_mem.write16(N, m_reg.HL);\r
+</instruction>\r
+\r
+<instruction name="LD (nn),dd" clock="20">\r
+<opcode prefix="0xED" mask="01d0011" operand="N" />\r
+m_mem.write16(N, d);\r
+</instruction>\r
+\r
+<instruction name="LD (nn),IX" clock="20">\r
+<opcode prefix="0xDD" mask="00100010" operand="N" />\r
+m_mem.write16(N, m_reg.IX);\r
+</instruction>\r
+\r
+<instruction name="LD (nn),IY" clock="20">\r
+<opcode prefix="0xFD" mask="00100010" operand="N" />\r
+m_mem.write16(N, m_reg.IY);\r
+</instruction>\r
+\r
+<instruction name="LD SP,HL" clock="6">\r
+<opcode mask="11111001" />\r
+m_reg.SP = m_reg.HL;\r
+</instruction>\r
+\r
+<instruction name="LD SP,IX" clock="10">\r
+<opcode prefix="0xDD" mask="11111001" />\r
+m_reg.SP = m_reg.IX;\r
+</instruction>\r
+\r
+<instruction name="LD SP,IY" clock="10">\r
+<opcode prefix="0xFD" mask="11111001" />\r
+m_reg.SP = m_reg.IY;\r
+</instruction>\r
+\r
+<instruction name="push qq" clock="11">\r
+<opcode mask="11q0101" />\r
+m_reg.SP.dec(2);\r
+m_mem.write16(m_reg.SP, q);\r
+</instruction>\r
+\r
+<instruction name="push IX" clock="15">\r
+<opcode prefix="0xDD" mask="11100101" />\r
+m_reg.SP.dec(2);\r
+m_mem.write16(m_reg.SP, m_reg.IX);\r
+</instruction>\r
+\r
+<instruction name="push IY" clock="15">\r
+<opcode prefix="0xFD" mask="11100101" />\r
+m_reg.SP.dec(2);\r
+m_mem.write16(m_reg.SP, m_reg.IY);\r
+</instruction>\r
+\r
+<instruction name="pop qq" clock="10">\r
+<opcode mask="11q0001" />\r
+q = m_mem.read16(m_reg.SP);\r
+m_reg.SP.inc(2);\r
+</instruction>\r
+\r
+<instruction name="pop IX" clock="14">\r
+<opcode prefix="0xDD" mask="11100001" />\r
+m_reg.IX = m_mem.read16(m_reg.SP);\r
+m_reg.SP.inc(2);\r
+</instruction>\r
+\r
+<instruction name="pop IY" clock="14">\r
+<opcode prefix="0xDD" mask="11111101" />\r
+m_reg.IY = m_mem.read16(m_reg.SP);\r
+m_reg.SP.inc(2);;\r
+</instruction>\r
+\r
+\r
+<!--\r
+                               Exchange, block transfer, and search\r
+-->\r
+\r
+<instruction name="EX DE,HL" clock="4">\r
+<opcode mask="111010111" />\r
+       DWORD tmp(m_reg.DE);\r
+       m_reg.DE = m_reg.HL;\r
+       m_reg.HL = tmp;\r
+</instruction>\r
+\r
+<instruction name="EX AF,AF'" clock="4">\r
+<opcode mask="111010111" />\r
+       DWORD tmp(m_reg.AF);\r
+       m_reg.AF = m_regDash.AF;\r
+       m_regDash.AF = tmp;\r
+</instruction>\r
+\r
+<instruction name="EXX'" clock="4">\r
+<opcode mask="11011000" />\r
+       DWORD tmpBC(m_reg.BC);\r
+       DWORD tmpDE(m_reg.BC);\r
+       DWORD tmpHL(m_reg.BC);\r
+       m_reg.BC = m_regDash.BC;\r
+       m_reg.DE = m_regDash.DE;\r
+       m_reg.HL = m_regDash.HL;\r
+       m_regDash.BC = tmpBC;\r
+       m_regDash.DE = tmpDE;\r
+       m_regDash.HL = tmpHL;\r
+</instruction>\r
+\r
+<instruction name="EX (SP),HL'" clock="19">\r
+<opcode mask="11100011" />\r
+       DWORD tmp(m_reg.HL);\r
+       m_reg.HL = m_mem.read16(m_reg.SP);\r
+       m_mem.write16(m_reg.SP, tmp);\r
+</instruction>\r
+\r
+<instruction name="EX (SP),IX'" clock="23">\r
+<opcode prefix="0xDD" mask="11100011" />\r
+       DWORD tmp(m_reg.IX);\r
+       m_reg.IX = m_mem.read16(m_reg.SP);\r
+       m_mem.write16(m_reg.SP, tmp);\r
+</instruction>\r
+\r
+<instruction name="EX (SP),IY'" clock="23">\r
+<opcode prefix="0xFD" mask="11100011" />\r
+       DWORD tmp(m_reg.IY);\r
+       m_reg.IY = m_mem.read16(m_reg.SP);\r
+       m_mem.write16(m_reg.SP, tmp);\r
+</instruction>\r
+\r
+<instruction name="LDI'" clock="16">\r
+<opcode prefix="0xED" mask="10100000" />\r
+       m_mem.write8(m_reg.DE, m_mem.read8(m_reg.HL));\r
+       m_reg.DE.inc();\r
+       m_reg.HL.inc();\r
+       m_reg.BC.dec();\r
+       m_reg.F.setCounter(m_reg.BC);\r
+</instruction>\r
+\r
+<instruction name="LDIR'" clock="0">\r
+<opcode prefix="0xED" mask="10110000" />\r
+       do\r
+       {\r
+               m_mem.write8(m_reg.DE, m_mem.read8(m_reg.HL));\r
+               m_reg.DE.inc();\r
+               m_reg.HL.inc();\r
+               m_reg.BC.dec();\r
+\r
+               clock += 21; // Increment for each loop iteration\r
+               interrupt(); // Check for interrupts at each iteration\r
+       } while (m_reg.BC.host() != 0);\r
+       m_reg.F.setCounter(m_reg.BC);\r
+       clock += 16; // Increment again when leaving loop.\r
+</instruction>\r
+\r
+<instruction name="LDD'" clock="16">\r
+<opcode prefix="0xED" mask="10101000" />\r
+       m_mem.write8(m_reg.DE, m_mem.read8(m_reg.HL));\r
+       m_reg.DE.dec();\r
+       m_reg.HL.dec();\r
+       m_reg.BC.dec();\r
+       m_reg.F.setCounter(m_reg.BC);\r
+</instruction>\r
+\r
+<instruction name="LDDR'" clock="0">\r
+<opcode prefix="0xED" mask="10111000" />\r
+       do\r
+       {\r
+               m_mem.write8(m_reg.DE, m_mem.read8(m_reg.HL));\r
+               m_reg.DE.dec();\r
+               m_reg.HL.dec();\r
+               m_reg.BC.dec();\r
+\r
+               clock += 21; // Increment for each loop iteration\r
+               interrupt(); // Check for interrupts at each iteration\r
+       } while (m_reg.BC.host() != 0);\r
+       m_reg.F.setCounter(m_reg.BC);\r
+       clock += 16; // Increment again when leaving loop.\r
+</instruction>\r
+\r
+<instruction name="CPI'" clock="16">\r
+<opcode prefix="0xED" mask="10100000" />\r
+       m_reg.BC.dec();\r
+       m_reg.F.setSub(m_reg.A, m_reg.read8(r_reg.HL), m_reg.BC);\r
+       m_reg.HL.inc();\r
+</instruction>\r
+\r
+<instruction name="CPIR'" clock="0">\r
+<opcode prefix="0xED" mask="10110001" />\r
+       bool equal;\r
+       do\r
+       {\r
+               m_reg.BC.dec();\r
+               m_reg.F.setSub(m_reg.A, m_reg.read8(r_reg.HL), m_reg.BC);\r
+               equal = (m_reg.A == m_reg.read8(r_reg.HL));\r
+               m_reg.HL.inc();\r
+\r
+               clock += 21; // Increment for each loop iteration\r
+               interrupt(); // Check for interrupts at each iteration\r
+       } while (m_reg.BC.host() != 0 && !equal);\r
+       clock += 16; // Increment again when leaving loop.\r
+\r
+</instruction>\r
+\r
+<instruction name="CPD'" clock="16">\r
+<opcode prefix="0xED" mask="10101001" />\r
+       m_reg.BC.dec();\r
+       m_reg.F.setSub(m_reg.A, m_reg.read8(r_reg.HL), m_reg.BC);\r
+       m_reg.HL.dec();\r
+</instruction>\r
+\r
+<instruction name="CPDR'" clock="0">\r
+<opcode prefix="0xED" mask="10111001" />\r
+       bool equal;\r
+       do\r
+       {\r
+               m_reg.BC.dec();\r
+               m_reg.F.setSub(m_reg.A, m_reg.read8(r_reg.HL), m_reg.BC);\r
+               equal = (m_reg.A == m_reg.read8(r_reg.HL));\r
+               m_reg.HL.dec();\r
+\r
+               clock += 21; // Increment for each loop iteration\r
+               interrupt(); // Check for interrupts at each iteration\r
+       } while (m_reg.BC.host() != 0 && !equal);\r
+       clock += 16; // Increment again when leaving loop.\r
+\r
+</instruction>\r
+\r
+op8_t doAdd8(op8_t a, op8_t b, Flags& flags, bool carry)\r
+{\r
+       op8_t result(a + b);\r
+\r
+       if (carry && flags.C)\r
+       {\r
+               ++result;\r
+       }\r
+\r
+       flags.byte =\r
+               (result & 0x80) |                       // S  MSB\r
+               ((result == 0) ? 0x40 : 0) |            // Z\r
+                                                                                               // U5  TODO\r
+               ((a ^ b ^ result) & 0x10) |             // H\r
+                                                                                               // U3 TODO\r
+\r
+               // If a and b have the same sign, and the result\r
+               // has a different sign, then we overflowed the\r
+               // register.\r
+               // Can never overflow if a and b have different signs. (even with\r
+               // carry, since 127 + -1 + carry == 127).\r
+               // Step 1) Determine whether a and b have the same sign. (a NXOR b)\r
+               // Step 2) Determine whether the result has // a different sign.\r
+               ((((~(a ^ b)) & (result ^ a)) & 0x80) >> 5) |// P\r
+\r
+                                                                                               // N\r
+               (((op16_t(a) + op16_t(b)) & 0x100) >> 8) // C\r
+}\r
+<!--\r
+                               8-bit arithmetic\r
+-->\r
+<instruction name="ADD A,r'" clock="4">\r
+<opcode mask="100000r" />\r
+       m_reg.A = doAdd8(m_reg.A, r, m_reg.F, false);\r
+</instruction>\r
+\r
+<instruction name="ADD A,n'" clock="7">\r
+<opcode mask="11000110" operand="n" />\r
+       m_reg.A = doAdd8(m_reg.A, n, m_reg.F, false);\r
+</instruction>\r
+\r
+<instruction name="ADD A,(HL)'" clock="7">\r
+<opcode mask="11000110" />\r
+       m_reg.A = doAdd8(m_reg.A, m_mem.read8(m_reg.HL), m_reg.F, false);\r
+</instruction>\r
+\r
+<instruction name="ADD A,(IX+d)'" clock="19">\r
+<opcode prefix="0xDD" mask="11011101" signed_operand="d" />\r
+       m_reg.A = doAdd8(m_reg.A, m_mem.read8(m_reg.IX, d), m_reg.F, false);\r
+</instruction>\r
+\r
+<instruction name="ADD A,(IY+d)'" clock="19">\r
+<opcode prefix="0xFD" mask="10000110" signed_operand="d" />\r
+       m_reg.A = doAdd8(m_reg.A, m_mem.read8(m_reg.IY, d), m_reg.F, false);\r
+</instruction>\r
+\r
+<instruction name="ADC A,r'" clock="4">\r
+<opcode mask="10001r" />\r
+       m_reg.A = doAdc8(m_reg.A, r, m_reg.F, true);\r
+</instruction>\r
+\r
+</opcodes>\r
diff --git a/DWORD.hh b/DWORD.hh
new file mode 100644 (file)
index 0000000..0c23bd5
--- /dev/null
+++ b/DWORD.hh
@@ -0,0 +1,178 @@
+/** \r
+ * Emulated representation of the Z80 CPU registers.\r
+ *\r
+ * The Z80 cpu supports switching between multiple register sets.  Each Register\r
+ * object only stores the details of a single register set.\r
+*\r
+* 16bit Register Pairs are represented in a Struct to enable simple byte-order\r
+* conversions where required.\r
+ *\r
+ * Authors: Michael McMaster <email@michaelmcmaster.name>\r
+ * Copyright: Michael McMaster <email@michaelmcmaster.name>\r
+ */ \r
+#pragma once\r
+\r
+#include "mm80.hh"\r
+\r
+namespace mm80\r
+{\r
+\r
+class Core;\r
+\r
+/** 8-bit packed representation of the Z80 flags register.\r
+ *\r
+ *   C    Carry.  LSB of Flag register\r
+ *   N    Add/Subtract\r
+ *   P    (V) Parity/Overflow\r
+ *   U3   3rd bit of last 8bit op that altered flags\r
+ *   H    Half-Carry (BCD)\r
+ *   U5   5th bit of last 8bit op that altered flags\r
+ *   Z    Zero Flag\r
+ *   S    Sign Flag. MSB of Flag register\r
+ */\r
+struct Flags\r
+{\r
+       union\r
+       {\r
+               struct\r
+               {\r
+                       unsigned C:1; /// Carry.  LSB of Flag register\r
+                       unsigned N:1; /// Add/Subtract\r
+                       unsigned P:1; /// (V) Parity/Overflow\r
+                       unsigned U3:1; /// 3rd bit of last 8bit op that altered flags\r
+                       unsigned H:1; /// Half-Carry (BCD)\r
+                       unsigned U5:1; /// 5th bit of last 8bit op that altered flags\r
+                       unsigned Z:1; /// Zero Flag\r
+                       unsigned S:1; /// Sign Flag. MSB of Flag register\r
+               };\r
+               reg8_t byte;\r
+       };\r
+\r
+       Flags();\r
+\r
+       // Update the flags based on an operands value (eg. for simple assignment)\r
+       void set(op8_t operand, const Core& context);\r
+\r
+       // Update the flags when changing BC\r
+       void setCounter(op16_t BC);\r
+\r
+       // Set from A - B\r
+       void setSub(op8_t A, op8_t B, reg16_t BC);\r
+};\r
+\r
+struct DWORD\r
+{\r
+       // Always constructed, and stored, in Z80 byte order.\r
+       union\r
+       {\r
+               reg16_t dword;\r
+               struct\r
+               {\r
+                       reg8_t l;\r
+                       reg8_t h;\r
+               };\r
+       };\r
+\r
+       reg16_t z80() const { return dword; }\r
+       reg16_t host() const\r
+       {\r
+#ifdef HOST_LITTLE_ENDIAN\r
+               return dword;\r
+#else\r
+               return (reg16_t(h) << 8) | l;\r
+#endif\r
+       }\r
+\r
+       void inc(u8_t val = 1) const\r
+       {\r
+#ifdef HOST_LITTLE_ENDIAN\r
+               ++dword;\r
+#else\r
+               reg16_t tmp(host() + val);\r
+               l = tmp & 0xf;\r
+               h = tmp >> 8;\r
+#endif\r
+       }\r
+\r
+       void dec(u8_t val = 1) const\r
+       {\r
+#ifdef HOST_LITTLE_ENDIAN\r
+               --dword;\r
+#else\r
+               reg16_t tmp(host() - val);\r
+               l = tmp & 0xf;\r
+               h = tmp >> 8;\r
+#endif\r
+       }\r
+};\r
+\r
+// Create a dword from z80-ordered mem.\r
+static DWORD CreateDWORD(u8_t* in)\r
+{\r
+       DWORD result;\r
+       result.l = in[0];\r
+       result.h = in[1];\r
+       return result;\r
+}\r
+\r
+/** Z80 register access.\r
+ *\r
+ * Registers may be accessed in either 8-bit (eg. A) \r
+ * or by their 16-bit pair (eg. AF)\r
+ *\r
+ */\r
+struct Registers\r
+{\r
+       Registers();\r
+\r
+#define Z80_REG_STRUCT(h,l) \\r
+       struct \\r
+       { \\r
+               l; \\r
+               h; \\r
+       };\r
+#endif\r
+\r
+       // Note: The order of these unions/structs is important, as\r
+       // offsets are taken into the Register struct\r
+       reg8_t[0] begin8;\r
+       reg16_t[0] begin16;\r
+\r
+       union\r
+       {\r
+               Z80_REG_STRUCT(reg8_t B, reg8_t C);\r
+               DWORD BC;\r
+       };\r
+\r
+       union\r
+       {\r
+               Z80_REG_STRUCT(reg8_t D, reg8_t E);\r
+               DWORD DE;\r
+       };\r
+\r
+       union\r
+       {\r
+               Z80_REG_STRUCT(reg8_t H, reg8_t L);\r
+               DWORD HL;\r
+       };\r
+\r
+       union\r
+       {\r
+               Z80_REG_STRUCT(reg8_t A, Flags F,);\r
+               DWORD AF;\r
+       };\r
+\r
+\r
+#undef Z80_REG_STRUCT\r
+\r
+       // Special Purpose\r
+       reg8_t I;      // Interrupt Vector\r
+       reg8_t R;      // Memory Refresh\r
+       DWORD IX;     // Index Register\r
+       DWORD IY;     // Index Register\r
+       DWORD SP;     // Stack Pointer\r
+       DWORD PC;     // Program Counter\r
+};\r
+\r
+}\r
+\r
diff --git a/Test.cc b/Test.cc
new file mode 100644 (file)
index 0000000..e69de29