rollback >> return (LD_R_R' dry drz)
else return HALT
-- x = 2
- 2 -> return . decodeALU y . AOp_R $ decodeReg prefixed z
+ 2 -> let drz = decodeReg prefixed z
+ dalu = decodeALU y
+ aop = if prefixed == DDPrefixed then AOp_PIX else AOp_PIY
+ in if (prefixed == DDPrefixed || prefixed == FDPrefixed) && drz == PHL
+ then fetch >>= return . dalu . aop . fromIntegral
+ else return . dalu $ AOp_R drz
-- x = 3
3 -> case z of
-- z = 0, 1
0 -> return . RET_CC $ decodeCond y
1 -> case q of
- 0 -> return . POP_QQ $ decodeRegPair_qq p
+ 0 -> return $ case (prefixed, decodeRegPair_qq p) of
+ (DDPrefixed, R3 HL) -> POP_IX
+ (FDPrefixed, R3 HL) -> POP_IY
+ (_, _) -> POP_QQ $ decodeRegPair_qq p
1 -> if p > 3
then return . IllegalInstruction $ "decode: opcode = " ++ show b
- else return $ [ RET, EXX, JP_HL, LD_SP_HL ] !! fromIntegral p
+ else return $ case p of
+ 0 -> RET
+ 1 -> EXX
+ 2 -> case prefixed of
+ Unprefixed -> JP_HL
+ DDPrefixed -> JP_IX
+ FDPrefixed -> JP_IY
+ 3 -> case prefixed of
+ Unprefixed -> LD_SP_HL
+ DDPrefixed -> LD_SP_IX
+ FDPrefixed -> LD_SP_IY
-- z = 2
2 -> do
lb <- fetch
-- z = 5
5 -> case q of
-- q = 0, 1
- 0 -> return . PUSH_QQ $ decodeRegPair_qq p
+ 0 -> return $ case (prefixed, decodeRegPair_qq p) of
+ (DDPrefixed, R3 HL) -> PUSH_IX
+ (FDPrefixed, R3 HL) -> PUSH_IY
+ (_, _) -> PUSH_QQ $ decodeRegPair_qq p
1 -> case p of
0 -> do
lb <- fetch
else LD_DD_PNN (decodeRegPair_dd p) w
4 -> return NEG
-- z = 5, 6
- 5 -> return $ if y /= 1 then RETN else RETI
- 6 -> return $ IM y -- handle interrupt mode based on y's value
+ 5 -> return $ case y of
+ 0 -> RETN
+ 1 -> RETI
+ _ -> RET
+ -- if y /= 1 then RETN else RETI
+ 6 -> return $ decodeIM y
7 -> return $
[ LD_I_A, LD_R_A, LD_A_I, LD_A_R, RRD, RLD, NOP, NOP ] !! fromIntegral y
-- x = 2
6 -> OR_A_S
7 -> CP_A_S
+decodeIM :: Word8 -> Instruction
+decodeIM b = case b `mod` 4 of
+ 0 -> IM0
+ 1 -> IM0
+ 2 -> IM1
+ 3 -> IM2
+
decodeSR :: Word8 -> SRSpec -> Instruction
decodeSR b = case b of
0 -> RLC