module LibRISCV.Internal.Decoder.Instruction where

import Data.Bits
import Data.Word

-- Convert to an unsigned word (in two's complement) to a signed number.
fromTwoscomp :: Word32 -> Word32 -> Word32
fromTwoscomp :: Word32 -> Word32 -> Word32
fromTwoscomp Word32
numBits Word32
n = Word32 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Word32) -> Word32 -> Word32
forall a b. (a -> b) -> a -> b
$ -(Word32
n Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
mask) Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ (Word32
n Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32 -> Word32
forall a. Bits a => a -> a
complement Word32
mask)
  where
    mask :: Word32
    mask :: Word32
mask = Word32
2 Word32 -> Word32 -> Word32
forall a b. (Num a, Integral b) => a -> b -> a
^ (Word32
numBits Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
1)

-- Extract a bit field from a RISC-V instruction word.
instrField :: Int -> Int -> Word32 -> Word32
instrField :: Int -> Int -> Word32 -> Word32
instrField Int
start Int
end Word32
w = Int -> Int -> Word32
mask Int
start (Int
end Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftR Word32
w Int
start
  where
    -- Create a 32-bit bit mask in the range [start,end-1].
    mask :: Int -> Int -> Word32
    mask :: Int -> Int -> Word32
mask Int
start Int
end = Word32 -> Word32
forall a. Bits a => a -> a
complement (Word32 -> Word32) -> Word32 -> Word32
forall a b. (a -> b) -> a -> b
$ Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shift (Word32
forall a. Bounded a => a
maxBound :: Word32) (Int
end Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
start)

------------------------------------------------------------------------

immI :: Word32 -> Word32
immI :: Word32 -> Word32
immI = Word32 -> Word32 -> Word32
fromTwoscomp Word32
12 (Word32 -> Word32) -> (Word32 -> Word32) -> Word32 -> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Word32 -> Word32
instrField Int
20 Int
31

immS :: Word32 -> Word32
immS :: Word32 -> Word32
immS Word32
i =
    Word32 -> Word32 -> Word32
fromTwoscomp Word32
12 (Word32 -> Word32) -> Word32 -> Word32
forall a b. (a -> b) -> a -> b
$
        Word32 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Word32) -> Word32 -> Word32
forall a b. (a -> b) -> a -> b
$
            (Int -> Int -> Word32 -> Word32
instrField Int
25 Int
31 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shift` Int
5) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Int -> Int -> Word32 -> Word32
instrField Int
07 Int
11 Word32
i

immU :: Word32 -> Word32
immU :: Word32 -> Word32
immU Word32
i = Int -> Int -> Word32 -> Word32
instrField Int
12 Int
31 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
12

{- FOURMOLU_DISABLE -}
immB :: Word32 -> Word32
immB :: Word32 -> Word32
immB Word32
i = Word32 -> Word32 -> Word32
fromTwoscomp Word32
13 (Word32 -> Word32) -> Word32 -> Word32
forall a b. (a -> b) -> a -> b
$
         (Int -> Int -> Word32 -> Word32
instrField Int
31 Int
31 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shift` Int
12)
     Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Int -> Int -> Word32 -> Word32
instrField Int
07 Int
07 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shift` Int
11)
     Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Int -> Int -> Word32 -> Word32
instrField Int
25 Int
30 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shift` Int
05)
     Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Int -> Int -> Word32 -> Word32
instrField Int
08 Int
11 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shift` Int
01)

immJ :: Word32 -> Word32
immJ :: Word32 -> Word32
immJ Word32
i = Word32 -> Word32 -> Word32
fromTwoscomp Word32
21 (Word32 -> Word32) -> Word32 -> Word32
forall a b. (a -> b) -> a -> b
$
         (Int -> Int -> Word32 -> Word32
instrField Int
31 Int
31 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shift` Int
20)
     Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Int -> Int -> Word32 -> Word32
instrField Int
12 Int
19 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shift` Int
12)
     Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Int -> Int -> Word32 -> Word32
instrField Int
20 Int
20 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shift` Int
11)
     Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Int -> Int -> Word32 -> Word32
instrField Int
21 Int
30 Word32
i Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shift` Int
1)
{- FOURMOLU_ENABLE -}

mkShamt :: Word32 -> Word32
mkShamt :: Word32 -> Word32
mkShamt = Int -> Int -> Word32 -> Word32
instrField Int
20 Int
25

mkRs1 :: Word32 -> Word32
mkRs1 :: Word32 -> Word32
mkRs1 = Int -> Int -> Word32 -> Word32
instrField Int
15 Int
19

mkRs2 :: Word32 -> Word32
mkRs2 :: Word32 -> Word32
mkRs2 = Int -> Int -> Word32 -> Word32
instrField Int
20 Int
24

mkRd :: Word32 -> Word32
mkRd :: Word32 -> Word32
mkRd = Int -> Int -> Word32 -> Word32
instrField Int
7 Int
11