-
Notifications
You must be signed in to change notification settings - Fork 14
/
ExecuteM.fs
189 lines (175 loc) · 6.34 KB
/
ExecuteM.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
module ISA.RISCV.Execute.M
open ISA.RISCV.Decode.M
open ISA.RISCV.Arch
open ISA.RISCV.MachineState
open ISA.RISCV.Utils.Bits
let mulhu (x : uint64, y : uint64) : uint64 =
let x0 = uint64(uint32 x)
let y0 = uint64(uint32 y)
let x1 = x >>> 32
let y1 = y >>> 32
let t = x1 * y0 + ((x0 * y0) >>> 32)
let y2 = uint64(uint32 t)
let y3 = t >>> 32
let y4 = x0 * y1 + y2
let t = x1 * y1 + y3 + (y4 >>> 32)
let y5 = uint64(uint32 t)
let y6 = (t >>> 32) <<< 32
y6 ||| y5
let mulh (x : int64, y : int64) : int64 =
let neg = (x < 0L) <> (y < 0L)
let x1 = uint64(if x < 0L then -x else x)
let y1 = uint64(if y < 0L then -y else y)
let res = mulhu(x1, y1)
let resd = if (x * y) = 0L then 1L else 0L
if neg then int64(~~~res) + resd else int64 res
let mulhsu (x : int64, y : uint64) : int64 =
let neg = x < 0L
let x1 = uint64(if x < 0L then -x else x)
let res = mulhu(x1, y)
let resd = if (x * int64 y) = 0L then 1L else 0L
if neg then int64(~~~res) + resd else int64 res
//=================================================
// MUL - Multiplication operation - sign * sign
let execMUL (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rdVal = (mstate.getRegister rs1) * (mstate.getRegister rs2)
let mstate = mstate.setRegister rd rdVal
mstate.incPC
//=================================================
// MULH - Multiplication operation - sign * sign and return high 32 bits
let execMULH (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let hRes =
match mstate.Arch.archBits with
| RV32 ->
let rdVal = (mstate.getRegister rs1) * (mstate.getRegister rs2)
rdVal.bitSlice 63 32
| _ ->
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
mulh(rs1Val, rs2Val)
let mstate = mstate.setRegister rd hRes
mstate.incPC
//=================================================
// MULHSU - Multiplication operation - Multiplication operation - sign * unsign and return high 32 bits
let execMULHSU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let hRes =
match mstate.Arch.archBits with
| RV32 ->
let rdVal = rs1Val * int64(uint32 rs2Val)
rdVal.bitSlice 63 32
| _ ->
mulhsu(rs1Val, uint64 rs2Val)
let mstate = mstate.setRegister rd hRes
mstate.incPC
//=================================================
// MULHU - Multiplication operation - Multiplication operation - unsign * unsign and return high 32 bits
let execMULHU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let hRes =
match mstate.Arch.archBits with
| RV32 ->
let rdVal = int64(uint32 rs1Val) * int64(uint32 rs2Val)
rdVal.bitSlice 63 32
| _ ->
int64(mulhu(uint64 rs1Val, uint64 rs2Val))
let mstate = mstate.setRegister rd hRes
mstate.incPC
//=================================================
// DIV - Division operation
let execDIV (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let minSigned =
match mstate.Arch.archBits with
| RV32 -> 0x80000000L
| _ -> 0x8000000000000000L
let rdVal =
if rs2Val = 0L then
-1L
else if rs1Val = minSigned && rs2Val = -1L then
rs1Val
else
rs1Val / rs2Val
let mstate = mstate.setRegister rd rdVal
mstate.incPC
//=================================================
// DIVU - Division unsign operation
let execDIVU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let rdVal =
match mstate.Arch.archBits with
| RV32 ->
let maxUnsigned = 0xFFFFFFFFL
if rs2Val = 0L then
maxUnsigned
else
int64(uint32 rs1Val / uint32 rs2Val)
| _ ->
let maxUnsigned = 0xFFFFFFFFFFFFFFFFL
if rs2Val = 0L then
maxUnsigned
else
int64(uint64 rs1Val / uint64 rs2Val)
let mstate = mstate.setRegister rd rdVal
mstate.incPC
//=================================================
// REM - Rem operation
let execREM (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let minSigned =
match mstate.Arch.archBits with
| RV32 -> 0x80000000L
| _ -> 0x8000000000000000L
let rdVal =
if rs2Val = 0L then
rs1Val
else if rs1Val = minSigned && rs2Val = -1L then
0L
else
rs1Val % rs2Val
let mstate = mstate.setRegister rd rdVal
mstate.incPC
//=================================================
// REMU - Rem unsign operation
let execREMU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let rdVal =
match mstate.Arch.archBits with
| RV32 ->
if rs2Val = 0L then
rs1Val
else
int64(uint32 rs1Val % uint32 rs2Val)
| _ ->
if rs2Val = 0L then
rs1Val
else
int64(uint64 rs1Val % uint64 rs2Val)
let mstate = mstate.setRegister rd rdVal
mstate.incPC
// Execute M-instructions
let Execute (instr : InstructionM) (mstate : MachineState) =
match instr with
| MUL i ->
execMUL i.rd i.rs1 i.rs2 mstate
| MULH i ->
execMULH i.rd i.rs1 i.rs2 mstate
| MULHSU i ->
execMULHSU i.rd i.rs1 i.rs2 mstate
| MULHU i ->
execMULHU i.rd i.rs1 i.rs2 mstate
| DIV i ->
execDIV i.rd i.rs1 i.rs2 mstate
| DIVU i ->
execDIVU i.rd i.rs1 i.rs2 mstate
| REM i ->
execREM i.rd i.rs1 i.rs2 mstate
| REMU i ->
execREMU i.rd i.rs1 i.rs2 mstate
| _ -> mstate.setRunState (Trap InstructionExecute)