From 4a1ab0d58aa89fee297a6ca696f4d76f1156810e Mon Sep 17 00:00:00 2001 From: Lucian Mogosanu Date: Sun, 14 Dec 2014 02:50:31 +0200 Subject: [PATCH] ZXS: Decode: Handle CB and ED-prefixed opcodes --- src/Z80/ISA.hs | 13 ++++---- src/ZXS/Decode.hs | 86 ++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 86 insertions(+), 13 deletions(-) diff --git a/src/Z80/ISA.hs b/src/Z80/ISA.hs index 2ec3c73..41317d4 100644 --- a/src/Z80/ISA.hs +++ b/src/Z80/ISA.hs @@ -137,9 +137,7 @@ data Instruction = | HALT | DI | EI - | IM0 - | IM1 - | IM2 + | IM Word8 -- 16-bit arithmetic group | ADD_HL_SS RegPair_ss | ADC_HL_SS RegPair_ss @@ -163,13 +161,14 @@ data Instruction = | RR SRSpec | SLA SRSpec | SRA SRSpec + | SLL SRSpec | SRL SRSpec | RLD | RRD -- bit set, reset and test group - | BIT BitwiseSpec - | SET BitwiseSpec - | RES BitwiseSpec + | BIT Word8 BitwiseSpec + | SET Word8 BitwiseSpec + | RES Word8 BitwiseSpec -- jump group | JP_NN Word16 | JP_CC_NN Cond Word16 @@ -194,12 +193,14 @@ data Instruction = -- input and output group | IN_A_PN Word8 | IN_R_PC Reg + | IN_PC -- only set the flag | INI | INIR | IND | INDR | OUT_PN_A Word8 | OUT_PC_R Reg + | OUT_PC_Zero | OUTI | OUTIR | OUTD diff --git a/src/ZXS/Decode.hs b/src/ZXS/Decode.hs index 820cec3..f048bc1 100644 --- a/src/ZXS/Decode.hs +++ b/src/ZXS/Decode.hs @@ -71,9 +71,8 @@ decode = do -- z = 7 7 -> if y > 7 then return . IllegalInstruction $ "decode: opcode = " ++ show b - else return . snd . head $ filter (\ (y', _) -> y' == y) - [ (0, RLCA), (1, RRCA), (2, RLA), (3, RRA) - , (4, DAA), (5, CPL), (6, SCF), (7, CCF) ] + else return $ + [ RLCA, RRCA, RLA, RRA, DAA, CPL, SCF, CCF ] !! fromIntegral y -- x = 1 1 -> if z /= 6 && y /= 6 then return $ LD_R_R' (decodeReg y) (decodeReg z) @@ -88,8 +87,7 @@ decode = do 0 -> return . POP_QQ $ decodeRegPair_qq p 1 -> if p > 3 then return . IllegalInstruction $ "decode: opcode = " ++ show b - else return . snd . head $ filter (\ (y', _) -> y' == y) - [ (0, RET), (1, EXX), (2, JP_HL), (3, LD_SP_HL) ] + else return $ [ RET, EXX, JP_HL, LD_SP_HL ] !! fromIntegral y -- z = 2 2 -> do lb <- fetch @@ -132,10 +130,65 @@ decode = do -- x > 3 _ -> return . IllegalInstruction $ "decode: opcode = " ++ show b +-- decode prefixed opcodes decodeCB, decodeDD, decodeED, decodeFD :: ZXS Instruction -decodeCB = undefined + +-- CB-prefixed opcodes +decodeCB = do + b <- fetch + let x = (b `shiftR` 6) .&. 0x03 + y = (b `shiftR` 3) .&. 0x07 + z = (b `shiftR` 0) .&. 0x07 + case x of + 0 -> return . decodeSR y . SROp_R $ decodeReg z + 1 -> return . BIT y . BOp_R $ decodeReg z + 2 -> return . RES y . BOp_R $ decodeReg z + 3 -> return . SET y . BOp_R $ decodeReg z + +decodeED = do + b <- fetch + let x = (b `shiftR` 6) .&. 0x03 + y = (b `shiftR` 3) .&. 0x07 + z = (b `shiftR` 0) .&. 0x07 + p = (y `shiftR` 1) .&. 0x03 + q = (y `shiftR` 0) .&. 0x01 + case x of + 0 -> return NOP -- NONI? + 3 -> return NOP -- NONI? + -- x = 1 + 1 -> case z of + -- z = 0 + 0 -> if y == 6 + then return IN_PC + else return . IN_R_PC $ decodeReg y + -- z = 1 + 1 -> if y == 6 + then return OUT_PC_Zero + else return . OUT_PC_R $ decodeReg y + -- z = 2, 3, 4 + 2 -> let op = if q == 0 then SBC_HL_SS else ADC_HL_SS + in return . op $ decodeRegPair_ss p + 3 -> do + lb <- fetch + hb <- fetch + let w = bbToWord hb lb + return $ if q == 0 + then LD_PNN_DD w $ decodeRegPair_dd p + 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 + 7 -> return $ + [ LD_I_A, LD_R_A, LD_A_I, LD_A_R, RRD, RLD, NOP, NOP ] !! fromIntegral y + -- x = 2 + 2 -> if z <= 3 && y >= 4 + then return $ decodeBLI (y `mod` 4) z + else return NOP -- NONI? + +-- TODO: these are trickier and will require using extra logic in the decode +-- function above and the getPrefixed field in the CPU. To bear in mind. decodeDD = undefined -decodeED = undefined decodeFD = undefined bbToWord :: Word8 -> Word8 -> Word16 @@ -191,3 +244,22 @@ decodeALU b = case b of 5 -> XOR_A_S 6 -> OR_A_S 7 -> CP_A_S + +decodeSR :: Word8 -> SRSpec -> Instruction +decodeSR b = case b of + 0 -> RLC + 1 -> RRC + 2 -> RL + 3 -> RR + 4 -> SLA + 5 -> SRA + 6 -> SLL + 7 -> SRL + +decodeBLI :: Word8 -> Word8 -> Instruction +decodeBLI a b = [ + [ LDI, CPI, INI, OUTI ], + [ LDD, CPD, IND, OUTD ], + [ LDIR, CPIR, INIR, OUTIR ], + [ LDDR, CPDR, INDR, OUTDR ] + ] !! fromIntegral a !! fromIntegral b -- 1.7.10.4