import Data.Word
import Data.Int
---data Reg = AF | BC | DE | HL | AF' | BC' | DE' | HL'
--- | I | R | IX | IY | SP | PC deriving (Show, Eq)
-
-- regs, as seen by the programmer
data Reg = A | B | C | D | E | H | L deriving (Show, Eq)
-data RegPair = BC | DE | HL | SP deriving (Show, Eq)
+-- reg pairs specified in the z80 manual
+data BC = BC
+data DE = DE
+data HL = HL
+data SP = SP
+data AF = AF
+data IX = IX
+data IY = IY
+
+-- sets of reg pairs used in the z80 manual
+data RegPair a b c d = R1 a | R2 b | R3 c | R4 d deriving (Show, Eq)
+type RegPair_dd = RegPair BC DE HL SP
+type RegPair_qq = RegPair BC DE HL AF
+type RegPair_ss = RegPair BC DE HL SP
+type RegPair_pp = RegPair BC DE IX SP
+type RegPair_rr = RegPair BC DE IY SP
+
+-- spec for arithmetic instructions
+data ArithSpec =
+ AOp_R Reg
+ | AOp_N Word8
+ | AOp_PHL
+ | AOp_PIX Int8
+ | AOp_PIY Int8
+
+-- spec for shift and rotate instructions
+data SRSpec =
+ SROp_R Reg
+ | SROp_PHL
+ | SROp_PIX Int8
+ | SROp_PIY Int8
+
+-- spec for bitwise instructions
+data BitwiseSpec =
+ BOp_R Reg
+ | BOp_PHL
+ | BOp_PIX Int8
+ | BOp_PIY Int8
+
+-- condition codes for jump/call instructions
+data Cond =
+ CNonZero
+ | CZero
+ | CNoCarry
+ | CCarry
+ | CParityOdd
+ | CParityEven
+ | CSignPositive
+ | CSignNegative
--- XXX Should
+-- instructions
data Instruction =
-- 8-bit load group
LD_R_R' Reg Reg
| LD_I_A
| LD_R_A
-- 16-bit load group
- | LD_DD_NN RegPair Word16
+ | LD_DD_NN RegPair_dd Word16
| LD_IX_NN Word16
| LD_IY_NN Word16
| LD_HL_PNN Word16
- | LD_DD_PNN RegPair Word16
+ | LD_DD_PNN RegPair_dd Word16
| LD_IX_PNN Word16
| LD_IY_PNN Word16
| LD_PNN_HL Word16
- | LD_PNN_DD Word16 RegPair
+ | LD_PNN_DD Word16 RegPair_dd
| LD_PNN_IX Word16
| LD_PNN_IY Word16
| LD_SP_HL
| LD_SP_IX
| LD_SP_IY
- | PUSH_QQ RegPair
+ | PUSH_QQ RegPair_qq
| PUSH_IX
| PUSH_IY
- | POP_QQ RegPair
+ | POP_QQ RegPair_qq
| POP_IX
| POP_IY
- -- TODO: exchange, block transfer and search group
- -- TODO: others
+ -- exchange, block transfer and search group
+ | EX_DE_HL
+ | EX_AF_AF'
+ | EXX
+ | EX_PSP_HL
+ | EX_PSP_IX
+ | EX_PSP_IY
+ | LDI
+ | LDIR
+ | LDD
+ | LDDR
+ | CPI
+ | CPIR
+ | CPD
+ | CPDR
+ -- 8-bit arithmetic group
+ | ADD_A_S ArithSpec
+ | ADC_A_S ArithSpec
+ | SUB_A_S ArithSpec
+ | SBC_A_S ArithSpec
+ | AND_A_S ArithSpec
+ | OR_A_S ArithSpec
+ | XOR_A_S ArithSpec
+ | CP_A_S ArithSpec
+ | INC ArithSpec
+ | DEC ArithSpec
+ -- general purpose arithmetic and cpu control groups
+ | DAA
+ | CPL
+ | NEG
+ | CCF
+ | SCF
+ | NOP
+ | HALT
+ | DI
+ | EI
+ | IM0
+ | IM1
+ | IM2
+ -- 16-bit arithmetic group
+ | ADD_HL_SS RegPair_ss
+ | ADC_HL_SS RegPair_ss
+ | SBC_HL_SS RegPair_ss
+ | ADD_IX_PP RegPair_pp
+ | ADD_IY_RR RegPair_rr
+ | INC_SS RegPair_ss
+ | INC_IX
+ | INC_IY
+ | DEC_SS RegPair_ss
+ | DEC_IX
+ | DEC_IY
+ -- rotate and shift group
+ | RLCA
+ | RLA
+ | RRCA
+ | RRA
+ | RLC SRSpec
+ | RL SRSpec
+ | RRC SRSpec
+ | RR SRSpec
+ | SLA SRSpec
+ | SRA SRSpec
+ | SRL SRSpec
+ | RLD
+ | RRD
+ -- bit set, reset and test group
+ | BIT BitwiseSpec
+ | SET BitwiseSpec
+ | RES BitwiseSpec
+ -- jump group
+ | JP_NN Word16
+ | JP_CC_NN Cond Word16
+ | JR_E Int8
+ | JR_C_E Int8
+ | JR_NC_E Int8
+ | JR_Z_E Int8
+ | JR_NZ_E Int8
+ | JP_HL
+ | JP_IX
+ | JP_IY
+ | DJNZ_E Int8
+ -- call and return group
+ | CALL_NN Word16
+ | CALL_CC_NN Cond Word16
+ | RET
+ | RET_CC Cond
+ | RETI
+ | RETN
+ | RST_P Word8 -- actually an offset?
+ -- input and output group
+ | IN_A_PN Word8
+ | IN_R_PC Reg
+ | INI
+ | INIR
+ | IND
+ | INDR
+ | OUT_N_A Word8
+ | OUT_PC_R Reg
+ | OUTI
+ | OUTIR
+ | OUTD
+ | OUTDR