blob: eb780f3a04b451b7fad1e933aa0d7ecbce142ca2 [file] [log] [blame]
Stefan Wallentowitz0731d512020-07-14 21:55:14 +02001# Copyright lowRISC contributors.
2# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3# SPDX-License-Identifier: Apache-2.0
4
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +01005from typing import Dict
Stefan Wallentowitz0731d512020-07-14 21:55:14 +02006
Rupert Swarbrickce970752020-09-18 12:09:24 +01007from .state import OTBNState
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +01008from .isa import (OTBNInsn, RV32RegReg, RV32RegImm, RV32ImmShift,
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +01009 insn_for_mnemonic, logical_byte_shift)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +020010
11
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010012class ADD(RV32RegReg):
13 insn = insn_for_mnemonic('add', 3)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +020014
Rupert Swarbrickce970752020-09-18 12:09:24 +010015 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +010016 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
17 val2 = state.gprs.get_reg(self.grs2).read_unsigned()
18 result = (val1 + val2) & ((1 << 32) - 1)
19 state.gprs.get_reg(self.grd).write_unsigned(result)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +020020
21
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010022class ADDI(RV32RegImm):
23 insn = insn_for_mnemonic('addi', 3)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +020024
Rupert Swarbrickce970752020-09-18 12:09:24 +010025 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +010026 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
27 result = (val1 + self.imm) & ((1 << 32) - 1)
28 state.gprs.get_reg(self.grd).write_unsigned(result)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +020029
30
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010031class LUI(OTBNInsn):
32 insn = insn_for_mnemonic('lui', 2)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +020033
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010034 def __init__(self, op_vals: Dict[str, int]):
35 super().__init__(op_vals)
36 self.grd = op_vals['grd']
37 self.imm = op_vals['imm']
38
Rupert Swarbrickce970752020-09-18 12:09:24 +010039 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +010040 state.gprs.get_reg(self.grd).write_unsigned(self.imm << 12)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010041
42
43class SUB(RV32RegReg):
44 insn = insn_for_mnemonic('sub', 3)
45
Rupert Swarbrickce970752020-09-18 12:09:24 +010046 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +010047 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
48 val2 = state.gprs.get_reg(self.grs2).read_unsigned()
49 result = (val1 - val2) & ((1 << 32) - 1)
50 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010051
52
53class SLL(RV32RegReg):
54 insn = insn_for_mnemonic('sll', 3)
55
Rupert Swarbrickce970752020-09-18 12:09:24 +010056 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +010057 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
58 val2 = state.gprs.get_reg(self.grs2).read_unsigned() & 0x1f
59 result = (val1 << val2) & ((1 << 32) - 1)
60 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010061
62
63class SLLI(RV32ImmShift):
64 insn = insn_for_mnemonic('slli', 3)
65
Rupert Swarbrickce970752020-09-18 12:09:24 +010066 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +010067 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
68 result = (val1 << self.shamt) & ((1 << 32) - 1)
69 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010070
71
72class SRL(RV32RegReg):
73 insn = insn_for_mnemonic('srl', 3)
74
Rupert Swarbrickce970752020-09-18 12:09:24 +010075 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +010076 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
77 val2 = state.gprs.get_reg(self.grs2).read_unsigned() & 0x1f
78 result = val1 >> val2
79 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010080
81
82class SRLI(RV32ImmShift):
83 insn = insn_for_mnemonic('srli', 3)
84
Rupert Swarbrickce970752020-09-18 12:09:24 +010085 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +010086 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
87 result = val1 >> self.shamt
88 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010089
90
91class SRA(RV32RegReg):
92 insn = insn_for_mnemonic('sra', 3)
93
Rupert Swarbrickce970752020-09-18 12:09:24 +010094 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +010095 val1 = state.gprs.get_reg(self.grs1).read_signed()
96 val2 = state.gprs.get_reg(self.grs2).read_unsigned() & 0x1f
97 result = val1 >> val2
98 state.gprs.get_reg(self.grd).write_signed(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +010099
100
101class SRAI(RV32ImmShift):
102 insn = insn_for_mnemonic('srai', 3)
103
Rupert Swarbrickce970752020-09-18 12:09:24 +0100104 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100105 val1 = state.gprs.get_reg(self.grs1).read_signed()
106 val2 = self.shamt
107 result = val1 >> val2
108 state.gprs.get_reg(self.grd).write_signed(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100109
110
111class AND(RV32RegReg):
112 insn = insn_for_mnemonic('and', 3)
113
Rupert Swarbrickce970752020-09-18 12:09:24 +0100114 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100115 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
116 val2 = state.gprs.get_reg(self.grs2).read_unsigned()
117 result = val1 & val2
118 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100119
120
121class ANDI(RV32RegImm):
122 insn = insn_for_mnemonic('andi', 3)
123
Rupert Swarbrickce970752020-09-18 12:09:24 +0100124 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100125 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
126 val2 = self.imm
127 result = val1 & val2
128 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100129
130
131class OR(RV32RegReg):
132 insn = insn_for_mnemonic('or', 3)
133
Rupert Swarbrickce970752020-09-18 12:09:24 +0100134 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100135 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
136 val2 = state.gprs.get_reg(self.grs2).read_unsigned()
137 result = val1 | val2
138 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100139
140
141class ORI(RV32RegImm):
142 insn = insn_for_mnemonic('ori', 3)
143
Rupert Swarbrickce970752020-09-18 12:09:24 +0100144 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100145 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
146 val2 = self.imm
147 result = val1 | val2
148 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100149
150
151class XOR(RV32RegReg):
152 insn = insn_for_mnemonic('xor', 3)
153
Rupert Swarbrickce970752020-09-18 12:09:24 +0100154 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100155 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
156 val2 = state.gprs.get_reg(self.grs2).read_unsigned()
157 result = val1 ^ val2
158 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100159
160
161class XORI(RV32RegImm):
162 insn = insn_for_mnemonic('xori', 3)
163
Rupert Swarbrickce970752020-09-18 12:09:24 +0100164 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100165 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
166 val2 = self.imm
167 result = val1 ^ val2
168 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100169
170
171class LW(OTBNInsn):
172 insn = insn_for_mnemonic('lw', 3)
173
174 def __init__(self, op_vals: Dict[str, int]):
175 super().__init__(op_vals)
176 self.grd = op_vals['grd']
177 self.offset = op_vals['offset']
178 self.grs1 = op_vals['grs1']
179
Rupert Swarbrickce970752020-09-18 12:09:24 +0100180 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100181 base = state.gprs.get_reg(self.grs1).read_unsigned()
182 addr = (base + self.offset) & ((1 << 32) - 1)
183 result = state.dmem.load_u32(addr)
184 state.gprs.get_reg(self.grd).write_unsigned(result)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100185
186
187class SW(OTBNInsn):
188 insn = insn_for_mnemonic('sw', 3)
189
190 def __init__(self, op_vals: Dict[str, int]):
191 super().__init__(op_vals)
192 self.grs2 = op_vals['grs2']
193 self.offset = op_vals['offset']
194 self.grs1 = op_vals['grs1']
195
Rupert Swarbrickce970752020-09-18 12:09:24 +0100196 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100197 base = state.gprs.get_reg(self.grs1).read_unsigned()
198 addr = (base + self.offset) & ((1 << 32) - 1)
199 value = state.gprs.get_reg(self.grs2).read_unsigned()
200 state.dmem.store_u32(addr, value)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100201
202
203class BEQ(OTBNInsn):
204 insn = insn_for_mnemonic('beq', 3)
205
206 def __init__(self, op_vals: Dict[str, int]):
207 super().__init__(op_vals)
208 self.grs1 = op_vals['grs1']
209 self.grs2 = op_vals['grs2']
210 self.offset = op_vals['offset']
211
Rupert Swarbrickce970752020-09-18 12:09:24 +0100212 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100213 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
214 val2 = state.gprs.get_reg(self.grs2).read_unsigned()
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100215 if val1 == val2:
Rupert Swarbrickce970752020-09-18 12:09:24 +0100216 state.pc_next = self.offset
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100217
218
219class BNE(OTBNInsn):
220 insn = insn_for_mnemonic('bne', 3)
221
222 def __init__(self, op_vals: Dict[str, int]):
223 super().__init__(op_vals)
224 self.grs1 = op_vals['grs1']
225 self.grs2 = op_vals['grs2']
226 self.offset = op_vals['offset']
227
Rupert Swarbrickce970752020-09-18 12:09:24 +0100228 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100229 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
230 val2 = state.gprs.get_reg(self.grs2).read_unsigned()
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100231 if val1 != val2:
Rupert Swarbrickce970752020-09-18 12:09:24 +0100232 state.pc_next = self.offset
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100233
234
235class JAL(OTBNInsn):
236 insn = insn_for_mnemonic('jal', 2)
237
238 def __init__(self, op_vals: Dict[str, int]):
239 super().__init__(op_vals)
240 self.grd = op_vals['grd']
241 self.offset = op_vals['offset']
242
Rupert Swarbrickce970752020-09-18 12:09:24 +0100243 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100244 link_pc = (state.pc + 4) & ((1 << 32) - 1)
245 state.gprs.get_reg(self.grd).write_unsigned(link_pc)
Rupert Swarbrickce970752020-09-18 12:09:24 +0100246 state.pc_next = self.offset
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100247
248
249class JALR(OTBNInsn):
250 insn = insn_for_mnemonic('jalr', 3)
251
252 def __init__(self, op_vals: Dict[str, int]):
253 super().__init__(op_vals)
254 self.grd = op_vals['grd']
255 self.grs1 = op_vals['grs1']
256 self.offset = op_vals['offset']
257
Rupert Swarbrickce970752020-09-18 12:09:24 +0100258 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100259 val1 = state.gprs.get_reg(self.grs1).read_unsigned()
260 link_pc = (state.pc + 4) & ((1 << 32) - 1)
261
262 state.gprs.get_reg(self.grd).write_unsigned(link_pc)
263 state.pc_next = (val1 + self.offset) & ((1 << 32) - 1)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100264
265
266class CSRRS(OTBNInsn):
267 insn = insn_for_mnemonic('csrrs', 3)
268
269 def __init__(self, op_vals: Dict[str, int]):
270 super().__init__(op_vals)
271 self.grd = op_vals['grd']
272 self.csr = op_vals['csr']
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100273 self.grs1 = op_vals['grs1']
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100274
Rupert Swarbrickce970752020-09-18 12:09:24 +0100275 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100276 old_val = state.read_csr(self.csr)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100277 bits_to_set = state.gprs.get_reg(self.grs1).read_unsigned()
278 new_val = old_val | bits_to_set
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100279
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100280 state.gprs.get_reg(self.grd).write_unsigned(old_val)
281 state.write_csr(self.csr, new_val)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100282
283
284class CSRRW(OTBNInsn):
285 insn = insn_for_mnemonic('csrrw', 3)
286
287 def __init__(self, op_vals: Dict[str, int]):
288 super().__init__(op_vals)
289 self.grd = op_vals['grd']
290 self.csr = op_vals['csr']
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100291 self.grs1 = op_vals['grs1']
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100292
Rupert Swarbrickce970752020-09-18 12:09:24 +0100293 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100294 new_val = state.gprs.get_reg(self.grs1).read_unsigned()
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100295
Rupert Swarbrickb35a77d2020-10-01 17:44:25 +0100296 if self.grd != 0:
297 old_val = state.read_csr(self.csr)
298 state.gprs.get_reg(self.grd).write_unsigned(old_val)
299
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100300 state.write_csr(self.csr, new_val)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100301
302
303class ECALL(OTBNInsn):
304 insn = insn_for_mnemonic('ecall', 0)
305
306 def __init__(self, op_vals: Dict[str, int]):
307 super().__init__(op_vals)
308 pass
309
Rupert Swarbrickce970752020-09-18 12:09:24 +0100310 def execute(self, state: OTBNState) -> None:
Rupert Swarbrickd9a03a72020-09-10 16:56:21 +0100311 # INTR_STATE is the interrupt state register. Bit 0 (which is being
312 # set) is the 'done' flag.
Rupert Swarbrickce970752020-09-18 12:09:24 +0100313 state.ext_regs.set_bits('INTR_STATE', 1 << 0)
Rupert Swarbrickd9a03a72020-09-10 16:56:21 +0100314 # STATUS is a status register. Bit 0 (being cleared) is the 'busy' flag
Rupert Swarbrickce970752020-09-18 12:09:24 +0100315 state.ext_regs.clear_bits('STATUS', 1 << 0)
Rupert Swarbrickd9a03a72020-09-10 16:56:21 +0100316
317 # As well as the external register, clear an internal 'running' flag to
318 # tell the simulation to stop.
Rupert Swarbrickce970752020-09-18 12:09:24 +0100319 state.running = False
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100320
321
322class LOOP(OTBNInsn):
323 insn = insn_for_mnemonic('loop', 2)
324
325 def __init__(self, op_vals: Dict[str, int]):
326 super().__init__(op_vals)
327 self.grs = op_vals['grs']
328 self.bodysize = op_vals['bodysize']
329
Rupert Swarbrickce970752020-09-18 12:09:24 +0100330 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100331 num_iters = state.gprs.get_reg(self.grs).read_unsigned()
Rupert Swarbrickce970752020-09-18 12:09:24 +0100332 state.loop_start(num_iters, self.bodysize)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100333
334
335class LOOPI(OTBNInsn):
336 insn = insn_for_mnemonic('loopi', 2)
337
338 def __init__(self, op_vals: Dict[str, int]):
339 super().__init__(op_vals)
340 self.iterations = op_vals['iterations']
341 self.bodysize = op_vals['bodysize']
342
Rupert Swarbrickce970752020-09-18 12:09:24 +0100343 def execute(self, state: OTBNState) -> None:
344 state.loop_start(self.iterations, self.bodysize)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100345
346
347class BNADD(OTBNInsn):
348 insn = insn_for_mnemonic('bn.add', 6)
349
350 def __init__(self, op_vals: Dict[str, int]):
351 super().__init__(op_vals)
352 self.wrd = op_vals['wrd']
353 self.wrs1 = op_vals['wrs1']
354 self.wrs2 = op_vals['wrs2']
355 self.shift_type = op_vals['shift_type']
356 self.shift_bytes = op_vals['shift_bytes']
357 self.flag_group = op_vals['flag_group']
358
Rupert Swarbrickce970752020-09-18 12:09:24 +0100359 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100360 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
361 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
362 b_shifted = logical_byte_shift(b, self.shift_type, self.shift_bytes)
363
Rupert Swarbrickce970752020-09-18 12:09:24 +0100364 (result, flags) = state.add_with_carry(a, b_shifted, 0)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100365 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100366 state.set_flags(self.flag_group, flags)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200367
368
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100369class BNADDC(OTBNInsn):
370 insn = insn_for_mnemonic('bn.addc', 6)
371
372 def __init__(self, op_vals: Dict[str, int]):
373 super().__init__(op_vals)
374 self.wrd = op_vals['wrd']
375 self.wrs1 = op_vals['wrs1']
376 self.wrs2 = op_vals['wrs2']
377 self.shift_type = op_vals['shift_type']
378 self.shift_bytes = op_vals['shift_bytes']
379 self.flag_group = op_vals['flag_group']
380
Rupert Swarbrickce970752020-09-18 12:09:24 +0100381 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100382 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
383 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
384 b_shifted = logical_byte_shift(b, self.shift_type, self.shift_bytes)
385
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100386 carry = int(state.csrs.flags[self.flag_group].C)
387 (result, flags) = state.add_with_carry(a, b_shifted, carry)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100388 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100389 state.set_flags(self.flag_group, flags)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200390
391
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100392class BNADDI(OTBNInsn):
393 insn = insn_for_mnemonic('bn.addi', 4)
394
395 def __init__(self, op_vals: Dict[str, int]):
396 super().__init__(op_vals)
397 self.wrd = op_vals['wrd']
398 self.wrs = op_vals['wrs']
399 self.imm = op_vals['imm']
400 self.flag_group = op_vals['flag_group']
401
Rupert Swarbrickce970752020-09-18 12:09:24 +0100402 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100403 a = state.wdrs.get_reg(self.wrs).read_unsigned()
404 b = self.imm
405
Rupert Swarbrickce970752020-09-18 12:09:24 +0100406 (result, flags) = state.add_with_carry(a, b, 0)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100407 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100408 state.set_flags(self.flag_group, flags)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200409
410
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100411class BNADDM(OTBNInsn):
412 insn = insn_for_mnemonic('bn.addm', 3)
413
414 def __init__(self, op_vals: Dict[str, int]):
415 super().__init__(op_vals)
416 self.wrd = op_vals['wrd']
417 self.wrs1 = op_vals['wrs1']
418 self.wrs2 = op_vals['wrs2']
419
Rupert Swarbrickce970752020-09-18 12:09:24 +0100420 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100421 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
422 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
Rupert Swarbrick840e3292020-10-02 08:43:18 +0100423 result = a + b
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100424
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100425 mod_val = state.wsrs.MOD.read_unsigned()
426 if result >= mod_val:
427 result -= mod_val
428
Rupert Swarbrick840e3292020-10-02 08:43:18 +0100429 result = result & ((1 << 256) - 1)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100430 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200431
432
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100433class BNMULQACC(OTBNInsn):
434 insn = insn_for_mnemonic('bn.mulqacc', 6)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200435
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100436 def __init__(self, op_vals: Dict[str, int]):
437 super().__init__(op_vals)
438 self.zero_acc = op_vals['zero_acc']
439 self.wrs1 = op_vals['wrs1']
440 self.wrs1_qwsel = op_vals['wrs1_qwsel']
441 self.wrs2 = op_vals['wrs2']
442 self.wrs2_qwsel = op_vals['wrs2_qwsel']
443 self.acc_shift_imm = op_vals['acc_shift_imm']
444
Rupert Swarbrickce970752020-09-18 12:09:24 +0100445 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100446 a_qw = state.get_quarter_word_unsigned(self.wrs1, self.wrs1_qwsel)
447 b_qw = state.get_quarter_word_unsigned(self.wrs2, self.wrs2_qwsel)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200448
449 mul_res = a_qw * b_qw
450
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100451 acc = state.wsrs.ACC.read_unsigned()
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100452 if self.zero_acc:
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200453 acc = 0
454
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100455 acc += (mul_res << self.acc_shift_imm)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200456
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100457 truncated = acc & ((1 << 256) - 1)
458 state.wsrs.ACC.write_unsigned(truncated)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200459
460
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100461class BNMULQACCWO(OTBNInsn):
462 insn = insn_for_mnemonic('bn.mulqacc.wo', 7)
463
464 def __init__(self, op_vals: Dict[str, int]):
465 super().__init__(op_vals)
466 self.zero_acc = op_vals['zero_acc']
467 self.wrd = op_vals['wrd']
468 self.wrs1 = op_vals['wrs1']
469 self.wrs1_qwsel = op_vals['wrs1_qwsel']
470 self.wrs2 = op_vals['wrs2']
471 self.wrs2_qwsel = op_vals['wrs2_qwsel']
472 self.acc_shift_imm = op_vals['acc_shift_imm']
473
Rupert Swarbrickce970752020-09-18 12:09:24 +0100474 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100475 a_qw = state.get_quarter_word_unsigned(self.wrs1, self.wrs1_qwsel)
476 b_qw = state.get_quarter_word_unsigned(self.wrs2, self.wrs2_qwsel)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100477
478 mul_res = a_qw * b_qw
479
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100480 acc = state.wsrs.ACC.read_unsigned()
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100481 if self.zero_acc:
482 acc = 0
483
484 acc += (mul_res << self.acc_shift_imm)
485
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100486 truncated = acc & ((1 << 256) - 1)
487 state.wdrs.get_reg(self.wrd).write_unsigned(truncated)
488 state.wsrs.ACC.write_unsigned(truncated)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100489
490
491class BNMULQACCSO(OTBNInsn):
492 insn = insn_for_mnemonic('bn.mulqacc.so', 8)
493
494 def __init__(self, op_vals: Dict[str, int]):
495 super().__init__(op_vals)
496 self.zero_acc = op_vals['zero_acc']
497 self.wrd = op_vals['wrd']
498 self.wrd_hwsel = op_vals['wrd_hwsel']
499 self.wrs1 = op_vals['wrs1']
500 self.wrs1_qwsel = op_vals['wrs1_qwsel']
501 self.wrs2 = op_vals['wrs2']
502 self.wrs2_qwsel = op_vals['wrs2_qwsel']
503 self.acc_shift_imm = op_vals['acc_shift_imm']
504
Rupert Swarbrickce970752020-09-18 12:09:24 +0100505 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100506 a_qw = state.get_quarter_word_unsigned(self.wrs1, self.wrs1_qwsel)
507 b_qw = state.get_quarter_word_unsigned(self.wrs2, self.wrs2_qwsel)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100508
509 mul_res = a_qw * b_qw
510
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100511 acc = state.wsrs.ACC.read_unsigned()
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100512 if self.zero_acc:
513 acc = 0
514
515 acc += (mul_res << self.acc_shift_imm)
516
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100517 lo_part = acc & ((1 << 128) - 1)
518 hi_part = acc >> 128
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100519
Felix Millerb57138e2020-09-28 22:24:39 +0200520 state.set_half_word_unsigned(self.wrd, self.wrd_hwsel, lo_part)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100521 state.wsrs.ACC.write_unsigned(hi_part)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100522
523
524class BNSUB(OTBNInsn):
525 insn = insn_for_mnemonic('bn.sub', 6)
526
527 def __init__(self, op_vals: Dict[str, int]):
528 super().__init__(op_vals)
529 self.wrd = op_vals['wrd']
530 self.wrs1 = op_vals['wrs1']
531 self.wrs2 = op_vals['wrs2']
532 self.shift_type = op_vals['shift_type']
533 self.shift_bytes = op_vals['shift_bytes']
534 self.flag_group = op_vals['flag_group']
535
Rupert Swarbrickce970752020-09-18 12:09:24 +0100536 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100537 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
538 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
539 b_shifted = logical_byte_shift(b, self.shift_type, self.shift_bytes)
540
541 (result, flags) = state.sub_with_borrow(a, b_shifted, 0)
542 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100543 state.set_flags(self.flag_group, flags)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200544
545
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100546class BNSUBB(OTBNInsn):
547 insn = insn_for_mnemonic('bn.subb', 6)
548
549 def __init__(self, op_vals: Dict[str, int]):
550 super().__init__(op_vals)
551 self.wrd = op_vals['wrd']
552 self.wrs1 = op_vals['wrs1']
553 self.wrs2 = op_vals['wrs2']
554 self.shift_type = op_vals['shift_type']
555 self.shift_bytes = op_vals['shift_bytes']
556 self.flag_group = op_vals['flag_group']
557
Rupert Swarbrickce970752020-09-18 12:09:24 +0100558 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100559 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
560 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
561 b_shifted = logical_byte_shift(b, self.shift_type, self.shift_bytes)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100562 borrow = int(state.csrs.flags[self.flag_group].C)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100563
564 (result, flags) = state.sub_with_borrow(a, b_shifted, borrow)
565 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100566 state.set_flags(self.flag_group, flags)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200567
568
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100569class BNSUBI(OTBNInsn):
570 insn = insn_for_mnemonic('bn.subi', 4)
571
572 def __init__(self, op_vals: Dict[str, int]):
573 super().__init__(op_vals)
574 self.wrd = op_vals['wrd']
575 self.wrs = op_vals['wrs']
576 self.imm = op_vals['imm']
577 self.flag_group = op_vals['flag_group']
578
Rupert Swarbrickce970752020-09-18 12:09:24 +0100579 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100580 a = state.wdrs.get_reg(self.wrs).read_unsigned()
581 b = self.imm
582
583 (result, flags) = state.sub_with_borrow(a, b, 0)
584 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100585 state.set_flags(self.flag_group, flags)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200586
587
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100588class BNSUBM(OTBNInsn):
589 insn = insn_for_mnemonic('bn.subm', 3)
590
591 def __init__(self, op_vals: Dict[str, int]):
592 super().__init__(op_vals)
593 self.wrd = op_vals['wrd']
594 self.wrs1 = op_vals['wrs1']
595 self.wrs2 = op_vals['wrs2']
596
Rupert Swarbrickce970752020-09-18 12:09:24 +0100597 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100598 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
599 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
600
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100601 mod_val = state.wsrs.MOD.read_unsigned()
602
Rupert Swarbrick31ffc1d2020-10-02 10:13:55 +0100603 diff = a - b
604 if diff < 0:
605 diff += mod_val
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100606
Rupert Swarbrick31ffc1d2020-10-02 10:13:55 +0100607 result = diff & ((1 << 256) - 1)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100608 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200609
610
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100611class BNAND(OTBNInsn):
Rupert Swarbrick2398dc12020-09-23 10:06:45 +0100612 insn = insn_for_mnemonic('bn.and', 6)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200613
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100614 def __init__(self, op_vals: Dict[str, int]):
615 super().__init__(op_vals)
616 self.wrd = op_vals['wrd']
617 self.wrs1 = op_vals['wrs1']
618 self.wrs2 = op_vals['wrs2']
619 self.shift_type = op_vals['shift_type']
620 self.shift_bytes = op_vals['shift_bytes']
Rupert Swarbrick2398dc12020-09-23 10:06:45 +0100621 self.flag_group = op_vals['flag_group']
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100622
Rupert Swarbrickce970752020-09-18 12:09:24 +0100623 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100624 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
625 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
626 b_shifted = logical_byte_shift(b, self.shift_type, self.shift_bytes)
627
Rupert Swarbricke53d8fe2020-09-21 15:32:51 +0100628 result = a & b_shifted
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100629 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100630 state.set_mlz_flags(self.flag_group, result)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200631
632
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100633class BNOR(OTBNInsn):
Rupert Swarbrick2398dc12020-09-23 10:06:45 +0100634 insn = insn_for_mnemonic('bn.or', 6)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200635
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100636 def __init__(self, op_vals: Dict[str, int]):
637 super().__init__(op_vals)
638 self.wrd = op_vals['wrd']
639 self.wrs1 = op_vals['wrs1']
640 self.wrs2 = op_vals['wrs2']
641 self.shift_type = op_vals['shift_type']
642 self.shift_bytes = op_vals['shift_bytes']
Rupert Swarbrick2398dc12020-09-23 10:06:45 +0100643 self.flag_group = op_vals['flag_group']
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100644
Rupert Swarbrickce970752020-09-18 12:09:24 +0100645 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100646 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
647 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
648 b_shifted = logical_byte_shift(b, self.shift_type, self.shift_bytes)
649
Rupert Swarbricke53d8fe2020-09-21 15:32:51 +0100650 result = a | b_shifted
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100651 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100652 state.set_mlz_flags(self.flag_group, result)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200653
654
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100655class BNNOT(OTBNInsn):
Rupert Swarbrick2398dc12020-09-23 10:06:45 +0100656 insn = insn_for_mnemonic('bn.not', 5)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200657
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100658 def __init__(self, op_vals: Dict[str, int]):
659 super().__init__(op_vals)
660 self.wrd = op_vals['wrd']
661 self.wrs = op_vals['wrs']
662 self.shift_type = op_vals['shift_type']
663 self.shift_bytes = op_vals['shift_bytes']
Rupert Swarbrick2398dc12020-09-23 10:06:45 +0100664 self.flag_group = op_vals['flag_group']
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100665
Rupert Swarbrickce970752020-09-18 12:09:24 +0100666 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100667 a = state.wdrs.get_reg(self.wrs).read_unsigned()
668 a_shifted = logical_byte_shift(a, self.shift_type, self.shift_bytes)
669
670 result = a_shifted ^ ((1 << 256) - 1)
671 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100672 state.set_mlz_flags(self.flag_group, result)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200673
674
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100675class BNXOR(OTBNInsn):
Rupert Swarbrick2398dc12020-09-23 10:06:45 +0100676 insn = insn_for_mnemonic('bn.xor', 6)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200677
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100678 def __init__(self, op_vals: Dict[str, int]):
679 super().__init__(op_vals)
680 self.wrd = op_vals['wrd']
681 self.wrs1 = op_vals['wrs1']
682 self.wrs2 = op_vals['wrs2']
683 self.shift_type = op_vals['shift_type']
684 self.shift_bytes = op_vals['shift_bytes']
Rupert Swarbrick2398dc12020-09-23 10:06:45 +0100685 self.flag_group = op_vals['flag_group']
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100686
Rupert Swarbrickce970752020-09-18 12:09:24 +0100687 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100688 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
689 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
690 b_shifted = logical_byte_shift(b, self.shift_type, self.shift_bytes)
691
Rupert Swarbricke53d8fe2020-09-21 15:32:51 +0100692 result = a ^ b_shifted
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100693 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100694 state.set_mlz_flags(self.flag_group, result)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200695
696
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100697class BNRSHI(OTBNInsn):
698 insn = insn_for_mnemonic('bn.rshi', 4)
699
700 def __init__(self, op_vals: Dict[str, int]):
701 super().__init__(op_vals)
702 self.wrd = op_vals['wrd']
703 self.wrs1 = op_vals['wrs1']
704 self.wrs2 = op_vals['wrs2']
705 self.imm = op_vals['imm']
706
Rupert Swarbrickce970752020-09-18 12:09:24 +0100707 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100708 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
709 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
710
711 result = (((a << 256) | b) >> self.imm) & ((1 << 256) - 1)
712 state.wdrs.get_reg(self.wrd).write_unsigned(result)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200713
714
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100715class BNRSEL(OTBNInsn):
716 insn = insn_for_mnemonic('bn.sel', 5)
717
718 def __init__(self, op_vals: Dict[str, int]):
719 super().__init__(op_vals)
720 self.wrd = op_vals['wrd']
721 self.wrs1 = op_vals['wrs1']
722 self.wrs2 = op_vals['wrs2']
723 self.flag_group = op_vals['flag_group']
724 self.flag = op_vals['flag']
725
Rupert Swarbrickce970752020-09-18 12:09:24 +0100726 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100727 flag_is_set = state.csrs.flags[self.flag_group].get_by_idx(self.flag)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100728 wrs = self.wrs1 if flag_is_set else self.wrs2
729 value = state.wdrs.get_reg(wrs).read_unsigned()
730 state.wdrs.get_reg(self.wrd).write_unsigned(value)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200731
732
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100733class BNCMP(OTBNInsn):
734 insn = insn_for_mnemonic('bn.cmp', 5)
735
736 def __init__(self, op_vals: Dict[str, int]):
737 super().__init__(op_vals)
738 self.wrs1 = op_vals['wrs1']
739 self.wrs2 = op_vals['wrs2']
740 self.shift_type = op_vals['shift_type']
741 self.shift_bytes = op_vals['shift_bytes']
742 self.flag_group = op_vals['flag_group']
743
Rupert Swarbrickce970752020-09-18 12:09:24 +0100744 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100745 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
746 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
747 b_shifted = logical_byte_shift(b, self.shift_type, self.shift_bytes)
748
749 (_, flags) = state.sub_with_borrow(a, b_shifted, 0)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100750 state.set_flags(self.flag_group, flags)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200751
752
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100753class BNCMPB(OTBNInsn):
754 insn = insn_for_mnemonic('bn.cmpb', 5)
755
756 def __init__(self, op_vals: Dict[str, int]):
757 super().__init__(op_vals)
758 self.wrs1 = op_vals['wrs1']
759 self.wrs2 = op_vals['wrs2']
760 self.shift_type = op_vals['shift_type']
761 self.shift_bytes = op_vals['shift_bytes']
762 self.flag_group = op_vals['flag_group']
763
Rupert Swarbrickce970752020-09-18 12:09:24 +0100764 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100765 a = state.wdrs.get_reg(self.wrs1).read_unsigned()
766 b = state.wdrs.get_reg(self.wrs2).read_unsigned()
767 b_shifted = logical_byte_shift(b, self.shift_type, self.shift_bytes)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100768 borrow = int(state.csrs.flags[self.flag_group].C)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100769
770 (_, flags) = state.sub_with_borrow(a, b_shifted, borrow)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100771 state.set_flags(self.flag_group, flags)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200772
773
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100774class BNLID(OTBNInsn):
775 insn = insn_for_mnemonic('bn.lid', 5)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200776
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100777 def __init__(self, op_vals: Dict[str, int]):
778 super().__init__(op_vals)
779 self.grd = op_vals['grd']
780 self.grd_inc = op_vals['grd_inc']
781 self.offset = op_vals['offset']
782 self.grs1 = op_vals['grs1']
783 self.grs1_inc = op_vals['grs1_inc']
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200784
Rupert Swarbrickce970752020-09-18 12:09:24 +0100785 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100786 grs1_val = state.gprs.get_reg(self.grs1).read_unsigned()
787 addr = (grs1_val + self.offset) & ((1 << 32) - 1)
788 grd_val = state.gprs.get_reg(self.grd).read_unsigned()
789
790 wrd = grd_val & 0x1f
791 value = state.dmem.load_u256(addr)
792 state.wdrs.get_reg(wrd).write_unsigned(value)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200793
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100794 if self.grd_inc:
Rupert Swarbrick9ea7ad42020-09-28 17:37:04 +0100795 new_grd_val = (grd_val + 1) & 0x1f
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100796 state.gprs.get_reg(self.grd).write_unsigned(new_grd_val)
797
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100798 if self.grs1_inc:
Felix Miller05616102020-10-06 00:13:44 +0200799 new_grs1_val = (grs1_val + 32) & ((1 << 32) - 1)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100800 state.gprs.get_reg(self.grs1).write_unsigned(new_grs1_val)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200801
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200802
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100803class BNSID(OTBNInsn):
804 insn = insn_for_mnemonic('bn.sid', 5)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200805
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100806 def __init__(self, op_vals: Dict[str, int]):
807 super().__init__(op_vals)
808 self.grs2 = op_vals['grs2']
809 self.grs2_inc = op_vals['grs2_inc']
810 self.offset = op_vals['offset']
811 self.grs1 = op_vals['grs1']
812 self.grs1_inc = op_vals['grs1_inc']
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200813
Rupert Swarbrickce970752020-09-18 12:09:24 +0100814 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100815 grs1_val = state.gprs.get_reg(self.grs1).read_unsigned()
816 addr = (grs1_val + self.offset) & ((1 << 32) - 1)
Rupert Swarbrick992f0b92020-09-08 12:24:52 +0100817
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100818 grs2_val = state.gprs.get_reg(self.grs2).read_unsigned()
819 wrs = grs2_val & 0x1f
820 wrs_val = state.wdrs.get_reg(wrs).read_unsigned()
821
822 state.dmem.store_u256(addr, wrs_val)
823
824 if self.grs1_inc:
Felix Miller05616102020-10-06 00:13:44 +0200825 new_grs1_val = (grs1_val + 32) & ((1 << 32) - 1)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100826 state.gprs.get_reg(self.grs1).write_unsigned(new_grs1_val)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200827
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100828 if self.grs2_inc:
Rupert Swarbrick9ea7ad42020-09-28 17:37:04 +0100829 new_grs2_val = (grs2_val + 1) & 0x1f
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100830 state.gprs.get_reg(self.grs2).write_unsigned(new_grs2_val)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200831
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100832
833class BNMOV(OTBNInsn):
834 insn = insn_for_mnemonic('bn.mov', 2)
835
836 def __init__(self, op_vals: Dict[str, int]):
837 super().__init__(op_vals)
838 self.wrd = op_vals['wrd']
839 self.wrs = op_vals['wrs']
840
Rupert Swarbrickce970752020-09-18 12:09:24 +0100841 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100842 value = state.wdrs.get_reg(self.wrs).read_unsigned()
843 state.wdrs.get_reg(self.wrd).write_unsigned(value)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200844
845
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100846class BNMOVR(OTBNInsn):
847 insn = insn_for_mnemonic('bn.movr', 4)
848
849 def __init__(self, op_vals: Dict[str, int]):
850 super().__init__(op_vals)
851 self.grd = op_vals['grd']
852 self.grd_inc = op_vals['grd_inc']
853 self.grs = op_vals['grs']
854 self.grs_inc = op_vals['grs_inc']
855
Rupert Swarbrickce970752020-09-18 12:09:24 +0100856 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100857 grd_val = state.gprs.get_reg(self.grd).read_unsigned()
858 grs_val = state.gprs.get_reg(self.grs).read_unsigned()
859
860 wrd = grd_val & 0x1f
861 wrs = grs_val & 0x1f
862
863 value = state.wdrs.get_reg(wrs).read_unsigned()
864 state.wdrs.get_reg(wrd).write_unsigned(value)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100865
866 if self.grd_inc:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100867 new_grd_val = (grd_val + 1) & ((1 << 32) - 1)
868 state.gprs.get_reg(self.grd).write_unsigned(new_grd_val)
869
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100870 if self.grs_inc:
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100871 new_grs_val = (grs_val + 1) & ((1 << 32) - 1)
872 state.gprs.get_reg(self.grs).write_unsigned(new_grs_val)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200873
874
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100875class BNWSRRS(OTBNInsn):
876 insn = insn_for_mnemonic('bn.wsrrs', 3)
877
878 def __init__(self, op_vals: Dict[str, int]):
879 super().__init__(op_vals)
880 self.wrd = op_vals['wrd']
881 self.wsr = op_vals['wsr']
882 self.wrs = op_vals['wrs']
883
Rupert Swarbrickce970752020-09-18 12:09:24 +0100884 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100885 old_val = state.wsrs.read_at_idx(self.wsr)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100886 bits_to_set = state.wdrs.get_reg(self.wrs).read_unsigned()
887 new_val = old_val | bits_to_set
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100888
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100889 state.wdrs.get_reg(self.wrd).write_unsigned(old_val)
890 state.wsrs.write_at_idx(self.wsr, new_val)
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200891
892
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100893class BNWSRRW(OTBNInsn):
894 insn = insn_for_mnemonic('bn.wsrrw', 3)
895
896 def __init__(self, op_vals: Dict[str, int]):
897 super().__init__(op_vals)
898 self.wrd = op_vals['wrd']
899 self.wsr = op_vals['wsr']
900 self.wrs = op_vals['wrs']
901
Rupert Swarbrickce970752020-09-18 12:09:24 +0100902 def execute(self, state: OTBNState) -> None:
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100903 old_val = state.wsrs.read_at_idx(self.wsr)
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100904 new_val = state.wdrs.get_reg(self.wrs).read_unsigned()
Stefan Wallentowitz0731d512020-07-14 21:55:14 +0200905
Rupert Swarbrick7ffe17d2020-09-25 15:23:04 +0100906 state.wdrs.get_reg(self.wrd).write_unsigned(old_val)
Rupert Swarbrick2f6cc462020-09-24 15:19:41 +0100907 state.wsrs.write_at_idx(self.wsr, new_val)
Rupert Swarbrickaadb1e32020-08-28 17:16:28 +0100908
909
910INSN_CLASSES = [
911 ADD, ADDI, LUI, SUB, SLL, SLLI, SRL, SRLI, SRA, SRAI,
912 AND, ANDI, OR, ORI, XOR, XORI,
913 LW, SW,
914 BEQ, BNE, JAL, JALR,
915 CSRRS, CSRRW,
916 ECALL,
917 LOOP, LOOPI,
918
919 BNADD, BNADDC, BNADDI, BNADDM,
920 BNMULQACC, BNMULQACCWO, BNMULQACCSO,
921 BNSUB, BNSUBB, BNSUBI, BNSUBM,
922 BNAND, BNOR, BNNOT, BNXOR,
923 BNRSHI,
924 BNRSEL,
925 BNCMP, BNCMPB,
926 BNLID, BNSID,
927 BNMOV, BNMOVR,
928 BNWSRRS, BNWSRRW
929]