15 -- Begin Signature: Arithmetic ----------------------------------------------
18 The Arithmetic module defines the datatype "AluOp" to represent the
19 various sorts of operations you might pass to an ALU like circuit.
20 The "Instruction" class defines its methods to use AluOp as the
21 least-common denomiator (no pun intended) of arithmetic-based instructions.
29 deriving (Eq,Show, Read)
31 data Comparison = LessThan
37 deriving (Eq,Show, Read)
39 data AluOp = Add Sign |
48 SetHi | -- Set high 16 bits of value.
49 Input1 | -- pass input1 through
50 Input2 | -- pass input2 through
51 Invalidate -- Invalidate the result of the
53 deriving (Eq,Show, Read)
56 data ImmediateSize = Imm16Bits | Imm26Bits
58 alu :: Word w => AluOp -> w -> w -> Maybe w
60 -- End Signature: Arithmetic ------------------------------------------------
62 -- If the ALUfunc is "Invalidate", this function returns Nothing,
63 -- otherwise it performs the assiciated ALU operation.
66 alu aluFunc word1 word2
67 = Just (exec_op aluFunc word1 word2)
70 -- signExtend is only used inside combinational circuits.
71 signExtend :: Word w => ImmediateSize -> Immediate -> w
72 signExtend Imm16Bits = fromInt
73 signExtend Imm26Bits = fromInt
76 ------------------------ Integer ALU unit ---------------------------
79 -- Performs integer addition and also returns whether overflow ocurred
80 addOverflowCheck :: Word w => w -> w -> (w,Bool)
85 overflow = out > maxBound || out < minBound
87 overflowErr :: Word w => AluOp -> w -> w -> a
89 = error ("alu (" ++ show op ++ ") " ++ show a ++ " "
90 ++ show b ++ " <-- overflow")
93 NOTE: I'm not worrying about whether overflow
94 calculations are computed correctly, except
95 for signed addition and subtraction. In the
96 other cases, I'm letting the bits fall where
97 they may. Hopefully none of the benchmarks
98 cause overflows at all.
102 -- This function performs the unsigned version of the normal signed
104 unsignedWordOp :: Word w => (w->w->w) -> (w->w->w)
105 unsignedWordOp f a b = sign $ unsign a `f` unsign b
108 -- These functions convert between a Word and a vector of Bools.
110 bitValues :: Word w => [w]
111 bitValues = map (2 ^) [31,30..0]
113 buildVec :: Word w => w -> [Bool]
115 = makeVec (unsign n) bitValues
117 makeVec :: Word w => w -> [w] -> [Bool]
119 makeVec _ [] = [] ---- should we catch this?
122 then True : makeVec (n-b) bs
123 else False : makeVec n bs
125 buildWord :: Word w => [Bool] -> w
127 = sign $ makeInteger bools bitValues
132 = error ("buildWord -- argument too large: " ++ show bools)
133 makeInteger (b:bs) (n:ns)
135 then n + makeInteger bs ns
136 else makeInteger bs ns
138 -- Performs an element-wise boolean operation on corresponding
139 -- pairs of bits of the argument integers
140 bitOp :: Word w => (Bool->Bool->Bool) -> (w->w->w)
142 = buildWord $ zipWith f (buildVec a) (buildVec b)
146 -- This function assumes the ALUfunc argument is not "Invalidate"
147 exec_op :: Word w => AluOp -> w -> w -> w
149 exec_op op@(Add Signed) a b
151 then overflowErr op a b
154 (out,overflow) = addOverflowCheck a b
156 exec_op (Add Unsigned) a b
157 = unsignedWordOp (+) a b
159 exec_op op@(Sub Signed) a b
161 then overflowErr op a b
164 (out,overflow) = addOverflowCheck a (-b)
166 exec_op (Sub Unsigned) a b
167 = unsignedWordOp (-) a b
169 exec_op (Mult Signed) a b
172 exec_op (Mult Unsigned) a b
173 = unsignedWordOp (*) a b
175 exec_op (Div Signed) a b
178 exec_op (Div Unsigned) a b
179 = unsignedWordOp div a b
181 exec_op And a b = bitOp (&&) a b
183 exec_op Or a b = bitOp (||) a b
185 -- eh, this is kinda temporary.
186 --exec_op Not a b = bitOp (\x y -> not x) a b
187 exec_op Not a b = if a == 0 then 1 else 0
189 exec_op Xor a b = bitOp xor a b
195 = buildWord $ drop shiftAmt (buildVec a) ++ replicate shiftAmt False
197 shiftAmt = toInt $ unsign b `mod` 32
200 = buildWord $ replicate shiftAmt False ++ take (32 - shiftAmt) (buildVec a)
202 shiftAmt = toInt $ unsign b `mod` 32
205 = buildWord $ replicate shiftAmt signBit ++ take (32 - shiftAmt) (buildVec a)
207 shiftAmt = toInt $ unsign b `mod` 32
210 exec_op (S relop) a b
211 = if (a `relation` b) then 1 else 0
213 relation = case relop of
222 = a * num_half -- a * 2^n