content: {-# LANGUAGE ScopedTypeVariables #-}
  module Spec.ExecuteM where
  import Spec.Decode
  import Spec.Machine
  import Utility.Utility
  import Control.Monad
  import Prelude
  
  execute :: forall p t. (RiscvMachine p t) => InstructionM -> p ()
  -- begin ast
  execute (Mul rd rs1 rs2) = do
    x <- getRegister rs1
    y <- getRegister rs2
    setRegister rd (x * y)
  execute (Mulh rd rs1 rs2) = do
    x <- getRegister rs1
    y <- getRegister rs2
    setRegister rd (highBits ((regToZ_signed x) * (regToZ_signed y)) :: t)
  execute (Mulhsu rd rs1 rs2) = do
    x <- getRegister rs1
    y <- getRegister rs2
    setRegister rd (highBits ((regToZ_signed x) * (regToZ_unsigned y)) :: t)
  execute (Mulhu rd rs1 rs2) = do
    x <- getRegister rs1
    y <- getRegister rs2
    setRegister rd (highBits ((regToZ_unsigned x) * (regToZ_unsigned y)) :: t)
  execute (Div rd rs1 rs2) = do
    x <- getRegister rs1
    y <- getRegister rs2
    let q | x == minSigned && y == -1 = x
          | y == 0 = -1
          | otherwise = quot x y
      in setRegister rd q
  execute (Divu rd rs1 rs2) = do
    x <- getRegister rs1
    y <- getRegister rs2
    let q | y == 0 = maxUnsigned
          | otherwise = divu x y
      in setRegister rd q
  execute (Rem rd rs1 rs2) = do
    x <- getRegister rs1
    y <- getRegister rs2
    let r | x == minSigned && y == -1 = 0
          | y == 0 = x
          | otherwise = rem x y
      in setRegister rd r
  execute (Remu rd rs1 rs2) = do
    x <- getRegister rs1
    y <- getRegister rs2
    let r | y == 0 = x
          | otherwise = remu x y
      in setRegister rd r
  -- end ast
  execute inst = error $ "dispatch bug: " ++ show inst
  