14 -- Begin Signature: Arithmetic ----------------------------------------------
17 The Arithmetic module defines the datatype "AluOp" to represent the
18 various sorts of operations you might pass to an ALU like circuit.
19 The "Instruction" class defines its methods to use AluOp as the
20 least-common denomiator (no pun intended) of arithmetic-based instructions.
28 deriving (Eq,Show, Read)
30 data Comparison = LessThan
36 deriving (Eq,Show, Read)
38 data AluOp = Add Sign |
47 SetHi | -- Set high 16 bits of value.
48 Input1 | -- pass input1 through
49 Input2 | -- pass input2 through
50 Invalidate -- Invalidate the result of the
52 deriving (Eq,Show, Read)
55 data ImmediateSize = Imm16Bits | Imm26Bits
57 alu :: Word w => AluOp -> w -> w -> Maybe w
59 -- End Signature: Arithmetic ------------------------------------------------
61 -- If the ALUfunc is "Invalidate", this function returns Nothing,
62 -- otherwise it performs the assiciated ALU operation.
65 alu aluFunc word1 word2
66 = Just (exec_op aluFunc word1 word2)
69 -- signExtend is only used inside combinational circuits.
70 signExtend :: Word w => ImmediateSize -> Immediate -> w
71 signExtend Imm16Bits = fromInt
72 signExtend Imm26Bits = fromInt
75 ------------------------ Integer ALU unit ---------------------------
78 -- Performs integer addition and also returns whether overflow ocurred
79 addOverflowCheck :: Word w => w -> w -> (w,Bool)
84 overflow = out > maxBound || out < minBound
86 overflowErr :: Word w => AluOp -> w -> w -> a
88 = error ("alu (" ++ show op ++ ") " ++ show a ++ " "
89 ++ show b ++ " <-- overflow")
92 NOTE: I'm not worrying about whether overflow
93 calculations are computed correctly, except
94 for signed addition and subtraction. In the
95 other cases, I'm letting the bits fall where
96 they may. Hopefully none of the benchmarks
97 cause overflows at all.
101 -- This function performs the unsigned version of the normal signed
103 unsignedWordOp :: Word w => (w->w->w) -> (w->w->w)
104 unsignedWordOp f a b = sign $ unsign a `f` unsign b
107 -- These functions convert between a Word and a vector of Bools.
109 bitValues :: Word w => [w]
110 bitValues = map (2 ^) [31,30..0]
112 buildVec :: Word w => w -> [Bool]
114 = makeVec (unsign n) bitValues
116 makeVec :: Word w => w -> [w] -> [Bool]
118 makeVec _ [] = [] ---- should we catch this?
121 then True : makeVec (n-b) bs
122 else False : makeVec n bs
124 buildWord :: Word w => [Bool] -> w
126 = sign $ makeInteger bools bitValues
131 = error ("buildWord -- argument too large: " ++ show bools)
132 makeInteger (b:bs) (n:ns)
134 then n + makeInteger bs ns
135 else makeInteger bs ns
137 -- Performs an element-wise boolean operation on corresponding
138 -- pairs of bits of the argument integers
139 bitOp :: Word w => (Bool->Bool->Bool) -> (w->w->w)
141 = buildWord $ zipWith f (buildVec a) (buildVec b)
145 -- This function assumes the ALUfunc argument is not "Invalidate"
146 exec_op :: Word w => AluOp -> w -> w -> w
148 exec_op op@(Add Signed) a b
150 then overflowErr op a b
153 (out,overflow) = addOverflowCheck a b
155 exec_op (Add Unsigned) a b
156 = unsignedWordOp (+) a b
158 exec_op op@(Sub Signed) a b
160 then overflowErr op a b
163 (out,overflow) = addOverflowCheck a (-b)
165 exec_op (Sub Unsigned) a b
166 = unsignedWordOp (-) a b
168 exec_op (Mult Signed) a b
171 exec_op (Mult Unsigned) a b
172 = unsignedWordOp (*) a b
174 exec_op (Div Signed) a b
177 exec_op (Div Unsigned) a b
178 = unsignedWordOp div a b
180 exec_op And a b = bitOp (&&) a b
182 exec_op Or a b = bitOp (||) a b
184 -- eh, this is kinda temporary.
185 --exec_op Not a b = bitOp (\x y -> not x) a b
186 exec_op Not a b = if a == 0 then 1 else 0
188 exec_op Xor a b = bitOp xor a b
194 = buildWord $ drop shiftAmt (buildVec a) ++ replicate shiftAmt False
196 shiftAmt = toInt $ unsign b `mod` 32
199 = buildWord $ replicate shiftAmt False ++ take (32 - shiftAmt) (buildVec a)
201 shiftAmt = toInt $ unsign b `mod` 32
204 = buildWord $ replicate shiftAmt signBit ++ take (32 - shiftAmt) (buildVec a)
206 shiftAmt = toInt $ unsign b `mod` 32
209 exec_op (S relop) a b
210 = if (a `relation` b) then 1 else 0
212 relation = case relop of
221 = a * num_half -- a * 2^n