Write docs and tests for Mima.Vm.Word
This commit is contained in:
parent
a7d4eec3dd
commit
51317c0737
2 changed files with 132 additions and 5 deletions
|
|
@ -1,3 +1,5 @@
|
|||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
|
||||
module Mima.Vm.Word
|
||||
(
|
||||
-- * Types
|
||||
|
|
@ -27,20 +29,42 @@ import Data.Bits
|
|||
import Data.Word
|
||||
import Data.Word.Odd
|
||||
|
||||
type MimaWord = Word24
|
||||
type MimaAddress = LargeValue
|
||||
type LargeValue = Word20
|
||||
type SmallValue = Word16
|
||||
type Opcode = Word4
|
||||
-- | The MiMa operates on words with a width of 24 bits.
|
||||
newtype MimaWord = MimaWord Word24
|
||||
deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show, Bits, FiniteBits)
|
||||
|
||||
-- | MiMa adresses have a width of 20 bits.
|
||||
type MimaAddress = LargeValue
|
||||
|
||||
-- | A large value is the argument to a small opcode (4 bits). It has a width of
|
||||
-- 20 bits.
|
||||
newtype LargeValue = LargeValue Word20
|
||||
deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show, Bits, FiniteBits)
|
||||
|
||||
-- | A small value is the argument to a large opcode (8 bits). It has a width of
|
||||
-- 16 bits.
|
||||
newtype SmallValue = SmallValue Word16
|
||||
deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show, Bits, FiniteBits)
|
||||
|
||||
-- | A small opcode has a width of 4 bits. In the case of a large opcode with a
|
||||
-- width of 8 bits, the most significant 4 bits are always 0xF, so large opcodes
|
||||
-- can be represented by this data type too.
|
||||
newtype Opcode = Opcode Word4
|
||||
deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show, Bits, FiniteBits)
|
||||
|
||||
-- | Return the most significant bit of the input value.
|
||||
topBit :: (FiniteBits b) => b -> Bool
|
||||
topBit b = testBit b $ finiteBitSize b - 1
|
||||
|
||||
-- | Combine three bytes into a 'MimaWord'. The bytes are in big-endian order
|
||||
-- (starting with the most significant byte).
|
||||
bytesToWord :: (Word8, Word8, Word8) -> MimaWord
|
||||
bytesToWord (w1, w2, w3) =
|
||||
let (w1', w2', w3') = (fromIntegral w1, fromIntegral w2, fromIntegral w3)
|
||||
in shiftL w1' 16 .|. shiftL w2' 8 .|. w3'
|
||||
|
||||
-- | Split up a 'MimaWord' into its component bytes. The bytes are in big-endian
|
||||
-- order (starting with the most significant byte).
|
||||
wordToBytes :: MimaWord -> (Word8, Word8, Word8)
|
||||
wordToBytes mw =
|
||||
-- No masks necessary since converting to 'Word8' already cuts off
|
||||
|
|
@ -50,37 +74,51 @@ wordToBytes mw =
|
|||
w3 = fromIntegral mw
|
||||
in (w1, w2, w3)
|
||||
|
||||
-- | This function behaves as if the boolean was the result of an equality check
|
||||
-- for the @EQL@ command: 'False' is represented by only zeroes while 'True' is
|
||||
-- represented by only ones.
|
||||
boolToWord :: Bool -> MimaWord
|
||||
boolToWord False = zeroBits
|
||||
boolToWord True = complement zeroBits
|
||||
|
||||
-- | Fills in the four most significant bits with zeroes.
|
||||
largeValueToWord :: LargeValue -> MimaWord
|
||||
largeValueToWord = fromIntegral
|
||||
|
||||
-- | Performs sign expansion.
|
||||
signedLargeValueToWord :: LargeValue -> MimaWord
|
||||
signedLargeValueToWord lv
|
||||
| topBit lv = 0xF00000 .|. fromIntegral lv
|
||||
| otherwise = fromIntegral lv
|
||||
|
||||
-- | Performs sign expansion.
|
||||
signedSmallValueToLargeValue :: SmallValue -> LargeValue
|
||||
signedSmallValueToLargeValue sv
|
||||
| topBit sv = 0xF0000 .|. fromIntegral sv
|
||||
| otherwise = fromIntegral sv
|
||||
|
||||
-- | Combine a small opcode and a large value into a 'MimaWord'.
|
||||
wordFromSmallOpcode :: Opcode -> LargeValue -> MimaWord
|
||||
wordFromSmallOpcode so lv = shiftL (fromIntegral so) 20 .|. fromIntegral lv
|
||||
|
||||
-- | Combine a large opcode and a small value into a 'MimaWord'. The four most
|
||||
-- significant bits are set to ones.
|
||||
wordFromLargeOpcode :: Opcode -> SmallValue -> MimaWord
|
||||
wordFromLargeOpcode lo sv = 0xF00000 .|. shiftL (fromIntegral lo) 16 .|. fromIntegral sv
|
||||
|
||||
-- | Returns the four most significant bits of the word.
|
||||
getSmallOpcode :: MimaWord -> Opcode
|
||||
getSmallOpcode mw = fromIntegral $ shiftR mw 20
|
||||
|
||||
-- | Returns the fifth to eigth most significant bits of the word. The four most
|
||||
-- significant bits of the word should all be ones.
|
||||
getLargeOpcode :: MimaWord -> Opcode
|
||||
getLargeOpcode mw = fromIntegral $ shiftR mw 16
|
||||
|
||||
-- | A word's 20 least significant bits.
|
||||
getLargeValue :: MimaWord -> LargeValue
|
||||
getLargeValue = fromIntegral
|
||||
|
||||
-- | A word's 16 least significant bits.
|
||||
getSmallValue :: MimaWord -> SmallValue
|
||||
getSmallValue = fromIntegral
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue