ZXS: Decode remaining prefixed opcodes
authorLucian Mogosanu <lucian.mogosanu@gmail.com>
Tue, 23 Dec 2014 23:49:53 +0000 (01:49 +0200)
committerLucian Mogosanu <lucian.mogosanu@gmail.com>
Wed, 24 Dec 2014 00:02:49 +0000 (02:02 +0200)
src/Z80/ISA.hs
src/ZXS/Decode.hs

index 015ae53..1565368 100644 (file)
@@ -138,7 +138,9 @@ data Instruction =
   | HALT
   | DI
   | EI
-  | IM Word8
+  | IM0
+  | IM1
+  | IM2
   -- 16-bit arithmetic group
   | ADD_HL_SS RegPair_ss
   | ADC_HL_SS RegPair_ss
@@ -362,7 +364,9 @@ instance Show Instruction where
     HALT  -> "halt"
     DI    -> "di"
     EI    -> "ei"
-    IM _  -> "im FIXME" -- must be 0, 1 or 2
+    IM0  -> "im 0"
+    IM1  -> "im 1"
+    IM2  -> "im 2"
     -- 16-bit arithmetic group
     ADD_HL_SS ss  -> "add hl," ++ show ss
     ADC_HL_SS ss  -> "adc hl," ++ show ss
index f966dbd..ed55985 100644 (file)
@@ -148,16 +148,34 @@ decode = do
               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
@@ -185,7 +203,10 @@ decode = do
       -- 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
@@ -247,8 +268,12 @@ decodeED prefixed = do
           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
@@ -375,6 +400,13 @@ decodeALU b = case b of
   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