ckb_vm/instructions/
execute.rs

1use super::{
2    super::{machine::Machine, Error},
3    common, extract_opcode, instruction_length,
4    utils::update_register,
5    Instruction, InstructionOpcode, Itype, R4type, R5type, Register, Rtype, Stype, Utype,
6};
7use crate::memory::Memory;
8use ckb_vm_definitions::{
9    for_each_inst_array1, for_each_inst_match2,
10    instructions::{self as insts, paste},
11    registers::RA,
12};
13
14pub fn handle_sub<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
15    let i = Rtype(inst);
16    common::sub(machine, i.rd(), i.rs1(), i.rs2());
17    Ok(())
18}
19
20pub fn handle_subw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
21    let i = Rtype(inst);
22    common::subw(machine, i.rd(), i.rs1(), i.rs2());
23    Ok(())
24}
25
26pub fn handle_add<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
27    let i = Rtype(inst);
28    common::add(machine, i.rd(), i.rs1(), i.rs2());
29    Ok(())
30}
31
32pub fn handle_addw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
33    let i = Rtype(inst);
34    common::addw(machine, i.rd(), i.rs1(), i.rs2());
35    Ok(())
36}
37
38pub fn handle_xor<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
39    let i = Rtype(inst);
40    common::xor(machine, i.rd(), i.rs1(), i.rs2());
41    Ok(())
42}
43
44pub fn handle_or<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
45    let i = Rtype(inst);
46    common::or(machine, i.rd(), i.rs1(), i.rs2());
47    Ok(())
48}
49
50pub fn handle_and<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
51    let i = Rtype(inst);
52    common::and(machine, i.rd(), i.rs1(), i.rs2());
53    Ok(())
54}
55
56pub fn handle_sll<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
57    let i = Rtype(inst);
58    let shift_value =
59        machine.registers()[i.rs2()].clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
60    let value = machine.registers()[i.rs1()].clone() << shift_value;
61    update_register(machine, i.rd(), value);
62
63    Ok(())
64}
65
66pub fn handle_sllw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
67    let i = Rtype(inst);
68    let shift_value = machine.registers()[i.rs2()].clone() & Mac::REG::from_u8(0x1F);
69    let value = machine.registers()[i.rs1()].clone() << shift_value;
70    update_register(machine, i.rd(), value.sign_extend(&Mac::REG::from_u8(32)));
71    Ok(())
72}
73
74pub fn handle_srl<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
75    let i = Rtype(inst);
76    let shift_value =
77        machine.registers()[i.rs2()].clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
78    let value = machine.registers()[i.rs1()].clone() >> shift_value;
79    update_register(machine, i.rd(), value);
80    Ok(())
81}
82
83pub fn handle_srlw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
84    let i = Rtype(inst);
85    let shift_value = machine.registers()[i.rs2()].clone() & Mac::REG::from_u8(0x1F);
86    let value = machine.registers()[i.rs1()].zero_extend(&Mac::REG::from_u8(32)) >> shift_value;
87    update_register(machine, i.rd(), value.sign_extend(&Mac::REG::from_u8(32)));
88    Ok(())
89}
90
91pub fn handle_sra<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
92    let i = Rtype(inst);
93    let shift_value =
94        machine.registers()[i.rs2()].clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
95    let value = machine.registers()[i.rs1()].signed_shr(&shift_value);
96    update_register(machine, i.rd(), value);
97    Ok(())
98}
99
100pub fn handle_sraw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
101    let i = Rtype(inst);
102    let shift_value = machine.registers()[i.rs2()].clone() & Mac::REG::from_u8(0x1F);
103    let value = machine.registers()[i.rs1()]
104        .sign_extend(&Mac::REG::from_u8(32))
105        .signed_shr(&shift_value);
106    update_register(machine, i.rd(), value.sign_extend(&Mac::REG::from_u8(32)));
107    Ok(())
108}
109
110pub fn handle_slt<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
111    let i = Rtype(inst);
112    let rs1_value = &machine.registers()[i.rs1()];
113    let rs2_value = &machine.registers()[i.rs2()];
114    let value = rs1_value.lt_s(rs2_value);
115    update_register(machine, i.rd(), value);
116    Ok(())
117}
118
119pub fn handle_sltu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
120    let i = Rtype(inst);
121    let rs1_value = &machine.registers()[i.rs1()];
122    let rs2_value = &machine.registers()[i.rs2()];
123    let value = rs1_value.lt(rs2_value);
124    update_register(machine, i.rd(), value);
125    Ok(())
126}
127
128pub fn handle_lb_version0<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
129    let i = Itype(inst);
130    common::lb(machine, i.rd(), i.rs1(), i.immediate_s(), true)?;
131    Ok(())
132}
133
134pub fn handle_lb_version1<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
135    let i = Itype(inst);
136    common::lb(machine, i.rd(), i.rs1(), i.immediate_s(), false)?;
137    Ok(())
138}
139
140pub fn handle_lh_version0<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
141    let i = Itype(inst);
142    common::lh(machine, i.rd(), i.rs1(), i.immediate_s(), true)?;
143    Ok(())
144}
145
146pub fn handle_lh_version1<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
147    let i = Itype(inst);
148    common::lh(machine, i.rd(), i.rs1(), i.immediate_s(), false)?;
149    Ok(())
150}
151
152pub fn handle_lw_version0<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
153    let i = Itype(inst);
154    common::lw(machine, i.rd(), i.rs1(), i.immediate_s(), true)?;
155    Ok(())
156}
157
158pub fn handle_lw_version1<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
159    let i = Itype(inst);
160    common::lw(machine, i.rd(), i.rs1(), i.immediate_s(), false)?;
161    Ok(())
162}
163
164pub fn handle_ld_version0<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
165    let i = Itype(inst);
166    common::ld(machine, i.rd(), i.rs1(), i.immediate_s(), true)?;
167    Ok(())
168}
169
170pub fn handle_ld_version1<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
171    let i = Itype(inst);
172    common::ld(machine, i.rd(), i.rs1(), i.immediate_s(), false)?;
173    Ok(())
174}
175
176pub fn handle_lbu_version0<Mac: Machine>(
177    machine: &mut Mac,
178    inst: Instruction,
179) -> Result<(), Error> {
180    let i = Itype(inst);
181    common::lbu(machine, i.rd(), i.rs1(), i.immediate_s(), true)?;
182    Ok(())
183}
184
185pub fn handle_lbu_version1<Mac: Machine>(
186    machine: &mut Mac,
187    inst: Instruction,
188) -> Result<(), Error> {
189    let i = Itype(inst);
190    common::lbu(machine, i.rd(), i.rs1(), i.immediate_s(), false)?;
191    Ok(())
192}
193
194pub fn handle_lhu_version0<Mac: Machine>(
195    machine: &mut Mac,
196    inst: Instruction,
197) -> Result<(), Error> {
198    let i = Itype(inst);
199    common::lhu(machine, i.rd(), i.rs1(), i.immediate_s(), true)?;
200    Ok(())
201}
202
203pub fn handle_lhu_version1<Mac: Machine>(
204    machine: &mut Mac,
205    inst: Instruction,
206) -> Result<(), Error> {
207    let i = Itype(inst);
208    common::lhu(machine, i.rd(), i.rs1(), i.immediate_s(), false)?;
209    Ok(())
210}
211
212pub fn handle_lwu_version0<Mac: Machine>(
213    machine: &mut Mac,
214    inst: Instruction,
215) -> Result<(), Error> {
216    let i = Itype(inst);
217    common::lwu(machine, i.rd(), i.rs1(), i.immediate_s(), true)?;
218    Ok(())
219}
220
221pub fn handle_lwu_version1<Mac: Machine>(
222    machine: &mut Mac,
223    inst: Instruction,
224) -> Result<(), Error> {
225    let i = Itype(inst);
226    common::lwu(machine, i.rd(), i.rs1(), i.immediate_s(), false)?;
227    Ok(())
228}
229
230pub fn handle_addi<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
231    let i = Itype(inst);
232    common::addi(machine, i.rd(), i.rs1(), i.immediate_s());
233    Ok(())
234}
235
236pub fn handle_addiw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
237    let i = Itype(inst);
238    common::addiw(machine, i.rd(), i.rs1(), i.immediate_s());
239    Ok(())
240}
241
242pub fn handle_xori<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
243    let i = Itype(inst);
244    common::xori(machine, i.rd(), i.rs1(), i.immediate_s());
245    Ok(())
246}
247
248pub fn handle_lr_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
249    let i = Rtype(inst);
250    let address = machine.registers()[i.rs1()].clone();
251    let value = machine.memory_mut().load32(&address)?;
252    update_register(machine, i.rd(), value.sign_extend(&Mac::REG::from_u8(32)));
253    machine.memory_mut().set_lr(&address);
254    Ok(())
255}
256
257pub fn handle_sc_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
258    let i = Rtype(inst);
259    let address = machine.registers()[i.rs1()].clone();
260    let condition = address.eq(machine.memory().lr());
261    let mem_value = condition.cond(
262        &machine.registers()[i.rs2()].clone(),
263        &machine.memory_mut().load32(&address)?,
264    );
265    let rd_value = condition.cond(&Mac::REG::from_u8(0), &Mac::REG::from_u8(1));
266    machine.memory_mut().store32(&address, &mem_value)?;
267    update_register(machine, i.rd(), rd_value);
268    machine.memory_mut().set_lr(&Mac::REG::from_u64(u64::MAX));
269    Ok(())
270}
271
272pub fn handle_amoswap_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
273    let i = Rtype(inst);
274    let rs1_value = machine.registers()[i.rs1()].clone();
275    let rs2_value = machine.registers()[i.rs2()].clone();
276    let mem_value = machine.memory_mut().load32(&rs1_value)?;
277    let mem_value = mem_value.sign_extend(&Mac::REG::from_u8(32));
278    update_register(machine, i.rd(), mem_value);
279    machine.memory_mut().store32(&rs1_value, &rs2_value)?;
280    Ok(())
281}
282
283pub fn handle_amoadd_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
284    let i = Rtype(inst);
285    let rs1_value = machine.registers()[i.rs1()].clone();
286    let rs2_value = machine.registers()[i.rs2()].clone();
287    let mem_value = machine.memory_mut().load32(&rs1_value)?;
288    let mem_value = mem_value.sign_extend(&Mac::REG::from_u8(32));
289    update_register(machine, i.rd(), mem_value.clone());
290    let mem_value = rs2_value.overflowing_add(&mem_value);
291    machine.memory_mut().store32(&rs1_value, &mem_value)?;
292    Ok(())
293}
294
295pub fn handle_amoxor_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
296    let i = Rtype(inst);
297    let rs1_value = machine.registers()[i.rs1()].clone();
298    let rs2_value = machine.registers()[i.rs2()].clone();
299    let mem_value = machine.memory_mut().load32(&rs1_value)?;
300    let mem_value = mem_value.sign_extend(&Mac::REG::from_u8(32));
301    update_register(machine, i.rd(), mem_value.clone());
302    let mem_value = rs2_value ^ mem_value;
303    machine.memory_mut().store32(&rs1_value, &mem_value)?;
304    Ok(())
305}
306
307pub fn handle_amoand_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
308    let i = Rtype(inst);
309    let rs1_value = machine.registers()[i.rs1()].clone();
310    let rs2_value = machine.registers()[i.rs2()].clone();
311    let mem_value = machine.memory_mut().load32(&rs1_value)?;
312    let mem_value = mem_value.sign_extend(&Mac::REG::from_u8(32));
313    update_register(machine, i.rd(), mem_value.clone());
314    let mem_value = rs2_value & mem_value;
315    machine.memory_mut().store32(&rs1_value, &mem_value)?;
316    Ok(())
317}
318
319pub fn handle_amoor_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
320    let i = Rtype(inst);
321    let rs1_value = machine.registers()[i.rs1()].clone();
322    let rs2_value = machine.registers()[i.rs2()].clone();
323    let mem_value = machine.memory_mut().load32(&rs1_value)?;
324    let mem_value = mem_value.sign_extend(&Mac::REG::from_u8(32));
325    update_register(machine, i.rd(), mem_value.clone());
326    let mem_value = rs2_value | mem_value;
327    machine.memory_mut().store32(&rs1_value, &mem_value)?;
328    Ok(())
329}
330
331pub fn handle_amomin_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
332    let i = Rtype(inst);
333    let rs1_value = machine.registers()[i.rs1()].clone();
334    let rs2_value = machine.registers()[i.rs2()].sign_extend(&Mac::REG::from_u8(32));
335    let mem_value = machine.memory_mut().load32(&rs1_value)?;
336    let mem_value = mem_value.sign_extend(&Mac::REG::from_u8(32));
337    update_register(machine, i.rd(), mem_value.clone());
338    let mem_value = rs2_value.lt_s(&mem_value).cond(&rs2_value, &mem_value);
339    machine.memory_mut().store32(&rs1_value, &mem_value)?;
340    Ok(())
341}
342
343pub fn handle_amomax_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
344    let i = Rtype(inst);
345    let rs1_value = machine.registers()[i.rs1()].clone();
346    let rs2_value = machine.registers()[i.rs2()].sign_extend(&Mac::REG::from_u8(32));
347    let mem_value = machine.memory_mut().load32(&rs1_value)?;
348    let mem_value = mem_value.sign_extend(&Mac::REG::from_u8(32));
349    update_register(machine, i.rd(), mem_value.clone());
350    let mem_value = rs2_value.ge_s(&mem_value).cond(&rs2_value, &mem_value);
351    machine.memory_mut().store32(&rs1_value, &mem_value)?;
352    Ok(())
353}
354
355pub fn handle_amominu_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
356    let i = Rtype(inst);
357    let rs1_value = machine.registers()[i.rs1()].clone();
358    let rs2_value = machine.registers()[i.rs2()].zero_extend(&Mac::REG::from_u8(32));
359    let mem_value = machine.memory_mut().load32(&rs1_value)?;
360    let mem_value_sext = mem_value.sign_extend(&Mac::REG::from_u8(32));
361    update_register(machine, i.rd(), mem_value_sext);
362    let mem_value = rs2_value.lt(&mem_value).cond(&rs2_value, &mem_value);
363    machine.memory_mut().store32(&rs1_value, &mem_value)?;
364    Ok(())
365}
366
367pub fn handle_amomaxu_w<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
368    let i = Rtype(inst);
369    let rs1_value = machine.registers()[i.rs1()].clone();
370    let rs2_value = machine.registers()[i.rs2()].zero_extend(&Mac::REG::from_u8(32));
371    let mem_value = machine.memory_mut().load32(&rs1_value)?;
372    let mem_value_sext = mem_value.sign_extend(&Mac::REG::from_u8(32));
373    update_register(machine, i.rd(), mem_value_sext);
374    let mem_value = rs2_value.ge(&mem_value).cond(&rs2_value, &mem_value);
375    machine.memory_mut().store32(&rs1_value, &mem_value)?;
376    Ok(())
377}
378
379pub fn handle_lr_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
380    let i = Rtype(inst);
381    let address = machine.registers()[i.rs1()].clone();
382    let value = machine.memory_mut().load64(&address)?;
383    update_register(machine, i.rd(), value);
384    machine.memory_mut().set_lr(&address);
385    Ok(())
386}
387
388pub fn handle_sc_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
389    let i = Rtype(inst);
390    let address = machine.registers()[i.rs1()].clone();
391    let condition = address.eq(machine.memory().lr());
392    let mem_value = condition.cond(
393        &machine.registers()[i.rs2()].clone(),
394        &machine.memory_mut().load64(&address)?,
395    );
396    let rd_value = condition.cond(&Mac::REG::from_u8(0), &Mac::REG::from_u8(1));
397    machine.memory_mut().store64(&address, &mem_value)?;
398    update_register(machine, i.rd(), rd_value);
399    machine.memory_mut().set_lr(&Mac::REG::from_u64(u64::MAX));
400    Ok(())
401}
402
403pub fn handle_amoswap_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
404    let i = Rtype(inst);
405    let rs1_value = machine.registers()[i.rs1()].clone();
406    let rs2_value = machine.registers()[i.rs2()].clone();
407    let mem_value = machine.memory_mut().load64(&rs1_value)?;
408    update_register(machine, i.rd(), mem_value);
409    machine.memory_mut().store64(&rs1_value, &rs2_value)?;
410    Ok(())
411}
412
413pub fn handle_amoadd_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
414    let i = Rtype(inst);
415    let rs1_value = machine.registers()[i.rs1()].clone();
416    let rs2_value = machine.registers()[i.rs2()].clone();
417    let mem_value = machine.memory_mut().load64(&rs1_value)?;
418    update_register(machine, i.rd(), mem_value.clone());
419    let mem_value = rs2_value.overflowing_add(&mem_value);
420    machine.memory_mut().store64(&rs1_value, &mem_value)?;
421    Ok(())
422}
423
424pub fn handle_amoxor_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
425    let i = Rtype(inst);
426    let rs1_value = machine.registers()[i.rs1()].clone();
427    let rs2_value = machine.registers()[i.rs2()].clone();
428    let mem_value = machine.memory_mut().load64(&rs1_value)?;
429    update_register(machine, i.rd(), mem_value.clone());
430    let mem_value = rs2_value ^ mem_value;
431    machine.memory_mut().store64(&rs1_value, &mem_value)?;
432    Ok(())
433}
434
435pub fn handle_amoand_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
436    let i = Rtype(inst);
437    let rs1_value = machine.registers()[i.rs1()].clone();
438    let rs2_value = machine.registers()[i.rs2()].clone();
439    let mem_value = machine.memory_mut().load64(&rs1_value)?;
440    update_register(machine, i.rd(), mem_value.clone());
441    let mem_value = rs2_value & mem_value;
442    machine.memory_mut().store64(&rs1_value, &mem_value)?;
443    Ok(())
444}
445
446pub fn handle_amoor_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
447    let i = Rtype(inst);
448    let rs1_value = machine.registers()[i.rs1()].clone();
449    let rs2_value = machine.registers()[i.rs2()].clone();
450    let mem_value = machine.memory_mut().load64(&rs1_value)?;
451    update_register(machine, i.rd(), mem_value.clone());
452    let mem_value = rs2_value | mem_value;
453    machine.memory_mut().store64(&rs1_value, &mem_value)?;
454    Ok(())
455}
456
457pub fn handle_amomin_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
458    let i = Rtype(inst);
459    let rs1_value = machine.registers()[i.rs1()].clone();
460    let rs2_value = machine.registers()[i.rs2()].clone();
461    let mem_value = machine.memory_mut().load64(&rs1_value)?;
462    update_register(machine, i.rd(), mem_value.clone());
463    let mem_value = rs2_value.lt_s(&mem_value).cond(&rs2_value, &mem_value);
464    machine.memory_mut().store64(&rs1_value, &mem_value)?;
465    Ok(())
466}
467
468pub fn handle_amomax_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
469    let i = Rtype(inst);
470    let rs1_value = machine.registers()[i.rs1()].clone();
471    let rs2_value = machine.registers()[i.rs2()].clone();
472    let mem_value = machine.memory_mut().load64(&rs1_value)?;
473    update_register(machine, i.rd(), mem_value.clone());
474    let mem_value = rs2_value.ge_s(&mem_value).cond(&rs2_value, &mem_value);
475    machine.memory_mut().store64(&rs1_value, &mem_value)?;
476    Ok(())
477}
478
479pub fn handle_amominu_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
480    let i = Rtype(inst);
481    let rs1_value = machine.registers()[i.rs1()].clone();
482    let rs2_value = machine.registers()[i.rs2()].clone();
483    let mem_value = machine.memory_mut().load64(&rs1_value)?;
484    update_register(machine, i.rd(), mem_value.clone());
485    let mem_value = rs2_value.lt(&mem_value).cond(&rs2_value, &mem_value);
486    machine.memory_mut().store64(&rs1_value, &mem_value)?;
487    Ok(())
488}
489
490pub fn handle_amomaxu_d<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
491    let i = Rtype(inst);
492    let rs1_value = machine.registers()[i.rs1()].clone();
493    let rs2_value = machine.registers()[i.rs2()].clone();
494    let mem_value = machine.memory_mut().load64(&rs1_value)?;
495    update_register(machine, i.rd(), mem_value.clone());
496    let mem_value = rs2_value.ge(&mem_value).cond(&rs2_value, &mem_value);
497    machine.memory_mut().store64(&rs1_value, &mem_value)?;
498    Ok(())
499}
500
501pub fn handle_ori<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
502    let i = Itype(inst);
503    common::ori(machine, i.rd(), i.rs1(), i.immediate_s());
504    Ok(())
505}
506
507pub fn handle_andi<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
508    let i = Itype(inst);
509    common::andi(machine, i.rd(), i.rs1(), i.immediate_s());
510    Ok(())
511}
512
513pub fn handle_slti<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
514    let i = Itype(inst);
515    let rs1_value = &machine.registers()[i.rs1()];
516    let imm_value = Mac::REG::from_i32(i.immediate_s());
517    let value = rs1_value.lt_s(&imm_value);
518    update_register(machine, i.rd(), value);
519    Ok(())
520}
521
522pub fn handle_sltiu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
523    let i = Itype(inst);
524    let rs1_value = &machine.registers()[i.rs1()];
525    let imm_value = Mac::REG::from_i32(i.immediate_s());
526    let value = rs1_value.lt(&imm_value);
527    update_register(machine, i.rd(), value);
528    Ok(())
529}
530
531pub fn handle_jalr_version0<Mac: Machine>(
532    machine: &mut Mac,
533    inst: Instruction,
534) -> Result<(), Error> {
535    let i = Itype(inst);
536    let size = instruction_length(inst);
537    let link = machine.pc().overflowing_add(&Mac::REG::from_u8(size));
538    update_register(machine, i.rd(), link);
539    let mut next_pc =
540        machine.registers()[i.rs1()].overflowing_add(&Mac::REG::from_i32(i.immediate_s()));
541    next_pc = next_pc & (!Mac::REG::one());
542    machine.update_pc(next_pc);
543    Ok(())
544}
545
546pub fn handle_jalr_version1<Mac: Machine>(
547    machine: &mut Mac,
548    inst: Instruction,
549) -> Result<(), Error> {
550    let i = Itype(inst);
551    let size = instruction_length(inst);
552    let link = machine.pc().overflowing_add(&Mac::REG::from_u8(size));
553    let mut next_pc =
554        machine.registers()[i.rs1()].overflowing_add(&Mac::REG::from_i32(i.immediate_s()));
555    next_pc = next_pc & (!Mac::REG::one());
556    update_register(machine, i.rd(), link);
557    machine.update_pc(next_pc);
558    Ok(())
559}
560
561pub fn handle_slli<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
562    let i = Itype(inst);
563    common::slli(machine, i.rd(), i.rs1(), i.immediate_u());
564    Ok(())
565}
566
567pub fn handle_srli<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
568    let i = Itype(inst);
569    common::srli(machine, i.rd(), i.rs1(), i.immediate_u());
570    Ok(())
571}
572
573pub fn handle_srai<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
574    let i = Itype(inst);
575    common::srai(machine, i.rd(), i.rs1(), i.immediate_u());
576    Ok(())
577}
578
579pub fn handle_slliw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
580    let i = Itype(inst);
581    common::slliw(machine, i.rd(), i.rs1(), i.immediate_u());
582    Ok(())
583}
584
585pub fn handle_srliw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
586    let i = Itype(inst);
587    common::srliw(machine, i.rd(), i.rs1(), i.immediate_u());
588    Ok(())
589}
590
591pub fn handle_sraiw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
592    let i = Itype(inst);
593    common::sraiw(machine, i.rd(), i.rs1(), i.immediate_u());
594    Ok(())
595}
596
597pub fn handle_sb<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
598    let i = Stype(inst);
599    common::sb(machine, i.rs1(), i.rs2(), i.immediate_s())?;
600    Ok(())
601}
602
603pub fn handle_sh<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
604    let i = Stype(inst);
605    common::sh(machine, i.rs1(), i.rs2(), i.immediate_s())?;
606    Ok(())
607}
608
609pub fn handle_sw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
610    let i = Stype(inst);
611    common::sw(machine, i.rs1(), i.rs2(), i.immediate_s())?;
612    Ok(())
613}
614
615pub fn handle_sd<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
616    let i = Stype(inst);
617    common::sd(machine, i.rs1(), i.rs2(), i.immediate_s())?;
618    Ok(())
619}
620
621pub fn handle_beq<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
622    let i = Stype(inst);
623    let pc = machine.pc();
624    let rs1_value = &machine.registers()[i.rs1()];
625    let rs2_value = &machine.registers()[i.rs2()];
626    let condition = rs1_value.eq(rs2_value);
627    let new_pc = condition.cond(
628        &Mac::REG::from_i32(i.immediate_s()).overflowing_add(pc),
629        &Mac::REG::from_u8(instruction_length(inst)).overflowing_add(pc),
630    );
631    machine.update_pc(new_pc);
632    Ok(())
633}
634
635pub fn handle_bne<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
636    let i = Stype(inst);
637    let pc = machine.pc();
638    let rs1_value = &machine.registers()[i.rs1()];
639    let rs2_value = &machine.registers()[i.rs2()];
640    let condition = rs1_value.ne(rs2_value);
641    let new_pc = condition.cond(
642        &Mac::REG::from_i32(i.immediate_s()).overflowing_add(pc),
643        &Mac::REG::from_u8(instruction_length(inst)).overflowing_add(pc),
644    );
645    machine.update_pc(new_pc);
646    Ok(())
647}
648
649pub fn handle_blt<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
650    let i = Stype(inst);
651    let pc = machine.pc();
652    let rs1_value = &machine.registers()[i.rs1()];
653    let rs2_value = &machine.registers()[i.rs2()];
654    let condition = rs1_value.lt_s(rs2_value);
655    let new_pc = condition.cond(
656        &Mac::REG::from_i32(i.immediate_s()).overflowing_add(pc),
657        &Mac::REG::from_u8(instruction_length(inst)).overflowing_add(pc),
658    );
659    machine.update_pc(new_pc);
660    Ok(())
661}
662
663pub fn handle_bge<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
664    let i = Stype(inst);
665    let pc = machine.pc();
666    let rs1_value = &machine.registers()[i.rs1()];
667    let rs2_value = &machine.registers()[i.rs2()];
668    let condition = rs1_value.ge_s(rs2_value);
669    let new_pc = condition.cond(
670        &Mac::REG::from_i32(i.immediate_s()).overflowing_add(pc),
671        &Mac::REG::from_u8(instruction_length(inst)).overflowing_add(pc),
672    );
673    machine.update_pc(new_pc);
674    Ok(())
675}
676
677pub fn handle_bltu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
678    let i = Stype(inst);
679    let pc = machine.pc();
680    let rs1_value = &machine.registers()[i.rs1()];
681    let rs2_value = &machine.registers()[i.rs2()];
682    let condition = rs1_value.lt(rs2_value);
683    let new_pc = condition.cond(
684        &Mac::REG::from_i32(i.immediate_s()).overflowing_add(pc),
685        &Mac::REG::from_u8(instruction_length(inst)).overflowing_add(pc),
686    );
687    machine.update_pc(new_pc);
688    Ok(())
689}
690
691pub fn handle_bgeu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
692    let i = Stype(inst);
693    let pc = machine.pc();
694    let rs1_value = &machine.registers()[i.rs1()];
695    let rs2_value = &machine.registers()[i.rs2()];
696    let condition = rs1_value.ge(rs2_value);
697    let new_pc = condition.cond(
698        &Mac::REG::from_i32(i.immediate_s()).overflowing_add(pc),
699        &Mac::REG::from_u8(instruction_length(inst)).overflowing_add(pc),
700    );
701    machine.update_pc(new_pc);
702    Ok(())
703}
704
705pub fn handle_lui<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
706    let i = Utype(inst);
707    update_register(machine, i.rd(), Mac::REG::from_i32(i.immediate_s()));
708    Ok(())
709}
710
711pub fn handle_auipc<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
712    let i = Utype(inst);
713    let value = machine
714        .pc()
715        .overflowing_add(&Mac::REG::from_i32(i.immediate_s()));
716    update_register(machine, i.rd(), value);
717    Ok(())
718}
719
720pub fn handle_ecall<Mac: Machine>(machine: &mut Mac, _inst: Instruction) -> Result<(), Error> {
721    // The semantic of ECALL is determined by the hardware, which
722    // is not part of the spec, hence here the implementation is
723    // deferred to the machine. This way custom ECALLs might be
724    // provided for different environments.
725    machine.ecall()?;
726    Ok(())
727}
728
729pub fn handle_ebreak<Mac: Machine>(machine: &mut Mac, _inst: Instruction) -> Result<(), Error> {
730    machine.ebreak()?;
731    Ok(())
732}
733
734pub fn handle_fencei<Mac: Machine>(_machine: &mut Mac, _inst: Instruction) -> Result<(), Error> {
735    Ok(())
736}
737
738pub fn handle_fence<Mac: Machine>(_machine: &mut Mac, _inst: Instruction) -> Result<(), Error> {
739    Ok(())
740}
741
742pub fn handle_jal<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
743    let i = Utype(inst);
744    common::jal(machine, i.rd(), i.immediate_s(), instruction_length(inst));
745    Ok(())
746}
747
748pub fn handle_mul<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
749    let i = Rtype(inst);
750    let rs1_value = &machine.registers()[i.rs1()];
751    let rs2_value = &machine.registers()[i.rs2()];
752    let value = rs1_value.overflowing_mul(rs2_value);
753    update_register(machine, i.rd(), value);
754    Ok(())
755}
756
757pub fn handle_mulw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
758    let i = Rtype(inst);
759    let rs1_value = &machine.registers()[i.rs1()];
760    let rs2_value = &machine.registers()[i.rs2()];
761    let value = rs1_value
762        .zero_extend(&Mac::REG::from_u8(32))
763        .overflowing_mul(&rs2_value.zero_extend(&Mac::REG::from_u8(32)));
764    update_register(machine, i.rd(), value.sign_extend(&Mac::REG::from_u8(32)));
765    Ok(())
766}
767
768pub fn handle_mulh<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
769    let i = Rtype(inst);
770    let rs1_value = &machine.registers()[i.rs1()];
771    let rs2_value = &machine.registers()[i.rs2()];
772    let value = rs1_value.overflowing_mul_high_signed(rs2_value);
773    update_register(machine, i.rd(), value);
774    Ok(())
775}
776
777pub fn handle_mulhsu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
778    let i = Rtype(inst);
779    let rs1_value = &machine.registers()[i.rs1()];
780    let rs2_value = &machine.registers()[i.rs2()];
781    let value = rs1_value.overflowing_mul_high_signed_unsigned(rs2_value);
782    update_register(machine, i.rd(), value);
783    Ok(())
784}
785
786pub fn handle_mulhu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
787    let i = Rtype(inst);
788    let rs1_value = &machine.registers()[i.rs1()];
789    let rs2_value = &machine.registers()[i.rs2()];
790    let value = rs1_value.overflowing_mul_high_unsigned(rs2_value);
791    update_register(machine, i.rd(), value);
792    Ok(())
793}
794
795pub fn handle_div<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
796    let i = Rtype(inst);
797    let rs1_value = &machine.registers()[i.rs1()];
798    let rs2_value = &machine.registers()[i.rs2()];
799    let value = rs1_value.overflowing_div_signed(rs2_value);
800    update_register(machine, i.rd(), value);
801    Ok(())
802}
803
804pub fn handle_divw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
805    let i = Rtype(inst);
806    let rs1_value = &machine.registers()[i.rs1()];
807    let rs2_value = &machine.registers()[i.rs2()];
808    let rs1_value = rs1_value.sign_extend(&Mac::REG::from_u8(32));
809    let rs2_value = rs2_value.sign_extend(&Mac::REG::from_u8(32));
810    let value = rs1_value.overflowing_div_signed(&rs2_value);
811    update_register(machine, i.rd(), value.sign_extend(&Mac::REG::from_u8(32)));
812    Ok(())
813}
814
815pub fn handle_divu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
816    let i = Rtype(inst);
817    let rs1_value = &machine.registers()[i.rs1()];
818    let rs2_value = &machine.registers()[i.rs2()];
819    let value = rs1_value.overflowing_div(rs2_value);
820    update_register(machine, i.rd(), value);
821    Ok(())
822}
823
824pub fn handle_divuw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
825    let i = Rtype(inst);
826    let rs1_value = &machine.registers()[i.rs1()];
827    let rs2_value = &machine.registers()[i.rs2()];
828    let rs1_value = rs1_value.zero_extend(&Mac::REG::from_u8(32));
829    let rs2_value = rs2_value.zero_extend(&Mac::REG::from_u8(32));
830    let value = rs1_value.overflowing_div(&rs2_value);
831    update_register(machine, i.rd(), value.sign_extend(&Mac::REG::from_u8(32)));
832    Ok(())
833}
834
835pub fn handle_rem<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
836    let i = Rtype(inst);
837    let rs1_value = &machine.registers()[i.rs1()];
838    let rs2_value = &machine.registers()[i.rs2()];
839    let value = rs1_value.overflowing_rem_signed(rs2_value);
840    update_register(machine, i.rd(), value);
841    Ok(())
842}
843
844pub fn handle_remw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
845    let i = Rtype(inst);
846    let rs1_value = &machine.registers()[i.rs1()];
847    let rs2_value = &machine.registers()[i.rs2()];
848    let rs1_value = rs1_value.sign_extend(&Mac::REG::from_u8(32));
849    let rs2_value = rs2_value.sign_extend(&Mac::REG::from_u8(32));
850    let value = rs1_value.overflowing_rem_signed(&rs2_value);
851    update_register(machine, i.rd(), value.sign_extend(&Mac::REG::from_u8(32)));
852    Ok(())
853}
854
855pub fn handle_remu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
856    let i = Rtype(inst);
857    let rs1_value = &machine.registers()[i.rs1()];
858    let rs2_value = &machine.registers()[i.rs2()];
859    let value = rs1_value.overflowing_rem(rs2_value);
860    update_register(machine, i.rd(), value);
861    Ok(())
862}
863
864pub fn handle_remuw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
865    let i = Rtype(inst);
866    let rs1_value = &machine.registers()[i.rs1()];
867    let rs2_value = &machine.registers()[i.rs2()];
868    let rs1_value = rs1_value.zero_extend(&Mac::REG::from_u8(32));
869    let rs2_value = rs2_value.zero_extend(&Mac::REG::from_u8(32));
870    let value = rs1_value.overflowing_rem(&rs2_value);
871    update_register(machine, i.rd(), value.sign_extend(&Mac::REG::from_u8(32)));
872    Ok(())
873}
874
875pub fn handle_adduw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
876    let i = Rtype(inst);
877    let rs1_value = &machine.registers()[i.rs1()];
878    let rs2_value = &machine.registers()[i.rs2()];
879    let rs1_u = rs1_value.zero_extend(&Mac::REG::from_u8(32));
880    let value = rs2_value.overflowing_add(&rs1_u);
881    update_register(machine, i.rd(), value);
882    Ok(())
883}
884
885pub fn handle_andn<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
886    let i = Rtype(inst);
887    let rs1_value = &machine.registers()[i.rs1()];
888    let rs2_value = &machine.registers()[i.rs2()];
889    let value = rs1_value.clone() & !rs2_value.clone();
890    update_register(machine, i.rd(), value);
891    Ok(())
892}
893
894pub fn handle_bclr<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
895    let i = Rtype(inst);
896    let rs1_value = &machine.registers()[i.rs1()];
897    let rs2_value = &machine.registers()[i.rs2()];
898    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
899    let value = rs1_value.clone() & !(Mac::REG::one() << shamt);
900    update_register(machine, i.rd(), value);
901    Ok(())
902}
903
904pub fn handle_bclri<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
905    let i = Itype(inst);
906    let rs1_value = &machine.registers()[i.rs1()];
907    let rs2_value = &Mac::REG::from_u32(i.immediate_u());
908    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
909    let value = rs1_value.clone() & !(Mac::REG::one() << shamt);
910    update_register(machine, i.rd(), value);
911    Ok(())
912}
913
914pub fn handle_bext<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
915    let i = Rtype(inst);
916    let rs1_value = &machine.registers()[i.rs1()];
917    let rs2_value = &machine.registers()[i.rs2()];
918    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
919    let value = Mac::REG::one() & (rs1_value.clone() >> shamt);
920    update_register(machine, i.rd(), value);
921    Ok(())
922}
923
924pub fn handle_bexti<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
925    let i = Itype(inst);
926    let rs1_value = &machine.registers()[i.rs1()];
927    let rs2_value = &Mac::REG::from_u32(i.immediate_u());
928    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
929    let value = Mac::REG::one() & (rs1_value.clone() >> shamt);
930    update_register(machine, i.rd(), value);
931    Ok(())
932}
933
934pub fn handle_binv<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
935    let i = Rtype(inst);
936    let rs1_value = &machine.registers()[i.rs1()];
937    let rs2_value = &machine.registers()[i.rs2()];
938    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
939    let value = rs1_value.clone() ^ (Mac::REG::one() << shamt);
940    update_register(machine, i.rd(), value);
941    Ok(())
942}
943
944pub fn handle_binvi<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
945    let i = Itype(inst);
946    let rs1_value = &machine.registers()[i.rs1()];
947    let rs2_value = &Mac::REG::from_u32(i.immediate_u());
948    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
949    let value = rs1_value.clone() ^ (Mac::REG::one() << shamt);
950    update_register(machine, i.rd(), value);
951    Ok(())
952}
953
954pub fn handle_bset<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
955    let i = Rtype(inst);
956    let rs1_value = &machine.registers()[i.rs1()];
957    let rs2_value = &machine.registers()[i.rs2()];
958    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
959    let value = rs1_value.clone() | (Mac::REG::one() << shamt);
960    update_register(machine, i.rd(), value);
961    Ok(())
962}
963
964pub fn handle_bseti<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
965    let i = Itype(inst);
966    let rs1_value = &machine.registers()[i.rs1()];
967    let rs2_value = &Mac::REG::from_u32(i.immediate_u());
968    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
969    let value = rs1_value.clone() | (Mac::REG::one() << shamt);
970    update_register(machine, i.rd(), value);
971    Ok(())
972}
973
974pub fn handle_clmul<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
975    let i = Rtype(inst);
976    let rs1_value = &machine.registers()[i.rs1()];
977    let rs2_value = &machine.registers()[i.rs2()];
978    let value = rs1_value.clmul(rs2_value);
979    update_register(machine, i.rd(), value);
980    Ok(())
981}
982
983pub fn handle_clmulh<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
984    let i = Rtype(inst);
985    let rs1_value = &machine.registers()[i.rs1()];
986    let rs2_value = &machine.registers()[i.rs2()];
987    let value = rs1_value.clmulh(rs2_value);
988    update_register(machine, i.rd(), value);
989    Ok(())
990}
991
992pub fn handle_clmulr<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
993    let i = Rtype(inst);
994    let rs1_value = &machine.registers()[i.rs1()];
995    let rs2_value = &machine.registers()[i.rs2()];
996    let value = rs1_value.clmulr(rs2_value);
997    update_register(machine, i.rd(), value);
998    Ok(())
999}
1000
1001pub fn handle_clz<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1002    let i = Rtype(inst);
1003    let rs1_value = &machine.registers()[i.rs1()];
1004    let value = rs1_value.clz();
1005    update_register(machine, i.rd(), value);
1006    Ok(())
1007}
1008
1009pub fn handle_clzw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1010    let i = Rtype(inst);
1011    let rs1_value = &machine.registers()[i.rs1()];
1012    let value = rs1_value
1013        .zero_extend(&Mac::REG::from_u8(32))
1014        .clz()
1015        .overflowing_sub(&Mac::REG::from_u8(32));
1016    update_register(machine, i.rd(), value);
1017    Ok(())
1018}
1019
1020pub fn handle_cpop<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1021    let i = Rtype(inst);
1022    let rs1_value = &machine.registers()[i.rs1()];
1023    let value = rs1_value.cpop();
1024    update_register(machine, i.rd(), value);
1025    Ok(())
1026}
1027
1028pub fn handle_cpopw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1029    let i = Rtype(inst);
1030    let rs1_value = &machine.registers()[i.rs1()];
1031    let value = rs1_value.zero_extend(&Mac::REG::from_u8(32)).cpop();
1032    update_register(machine, i.rd(), value);
1033    Ok(())
1034}
1035
1036pub fn handle_ctz<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1037    let i = Rtype(inst);
1038    let rs1_value = &machine.registers()[i.rs1()];
1039    let value = rs1_value.ctz();
1040    update_register(machine, i.rd(), value);
1041    Ok(())
1042}
1043
1044pub fn handle_ctzw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1045    let i = Rtype(inst);
1046    let rs1_value = &machine.registers()[i.rs1()];
1047    let value = (rs1_value.clone() | Mac::REG::from_u64(0xffff_ffff_0000_0000)).ctz();
1048    update_register(machine, i.rd(), value);
1049    Ok(())
1050}
1051
1052pub fn handle_max<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1053    let i = Rtype(inst);
1054    let rs1_value = &machine.registers()[i.rs1()];
1055    let rs2_value = &machine.registers()[i.rs2()];
1056    let value = rs1_value.ge_s(rs2_value).cond(rs1_value, rs2_value);
1057    update_register(machine, i.rd(), value);
1058    Ok(())
1059}
1060
1061pub fn handle_maxu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1062    let i = Rtype(inst);
1063    let rs1_value = &machine.registers()[i.rs1()];
1064    let rs2_value = &machine.registers()[i.rs2()];
1065    let value = rs1_value.ge(rs2_value).cond(rs1_value, rs2_value);
1066    update_register(machine, i.rd(), value);
1067    Ok(())
1068}
1069
1070pub fn handle_min<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1071    let i = Rtype(inst);
1072    let rs1_value = &machine.registers()[i.rs1()];
1073    let rs2_value = &machine.registers()[i.rs2()];
1074    let value = rs1_value.lt_s(rs2_value).cond(rs1_value, rs2_value);
1075    update_register(machine, i.rd(), value);
1076    Ok(())
1077}
1078
1079pub fn handle_minu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1080    let i = Rtype(inst);
1081    let rs1_value = &machine.registers()[i.rs1()];
1082    let rs2_value = &machine.registers()[i.rs2()];
1083    let value = rs1_value.lt(rs2_value).cond(rs1_value, rs2_value);
1084    update_register(machine, i.rd(), value);
1085    Ok(())
1086}
1087
1088pub fn handle_orcb<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1089    let i = Rtype(inst);
1090    let rs1_value = &machine.registers()[i.rs1()];
1091    let value = rs1_value.orcb();
1092    update_register(machine, i.rd(), value);
1093    Ok(())
1094}
1095
1096pub fn handle_orn<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1097    let i = Rtype(inst);
1098    let rs1_value = &machine.registers()[i.rs1()];
1099    let rs2_value = &machine.registers()[i.rs2()];
1100    let value = rs1_value.clone() | !rs2_value.clone();
1101    update_register(machine, i.rd(), value);
1102    Ok(())
1103}
1104
1105pub fn handle_rev8<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1106    let i = Rtype(inst);
1107    let rs1_value = &machine.registers()[i.rs1()];
1108    let value = rs1_value.rev8();
1109    update_register(machine, i.rd(), value);
1110    Ok(())
1111}
1112
1113pub fn handle_rol<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1114    let i = Rtype(inst);
1115    let rs1_value = &machine.registers()[i.rs1()];
1116    let rs2_value = &machine.registers()[i.rs2()];
1117    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
1118    let value = rs1_value.rol(&shamt);
1119    update_register(machine, i.rd(), value);
1120    Ok(())
1121}
1122
1123pub fn handle_rolw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1124    let i = Rtype(inst);
1125    let rs1_value = &machine.registers()[i.rs1()];
1126    let rs2_value = &machine.registers()[i.rs2()];
1127    let shamt = rs2_value.clone() & Mac::REG::from_u8(31);
1128    let twins = rs1_value
1129        .zero_extend(&Mac::REG::from_u8(32))
1130        .overflowing_mul(&Mac::REG::from_u64(0x_0000_0001_0000_0001));
1131    let value = twins.rol(&shamt).sign_extend(&Mac::REG::from_u8(32));
1132    update_register(machine, i.rd(), value);
1133    Ok(())
1134}
1135
1136pub fn handle_ror<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1137    let i = Rtype(inst);
1138    let rs1_value = &machine.registers()[i.rs1()];
1139    let rs2_value = &machine.registers()[i.rs2()];
1140    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
1141    let value = rs1_value.ror(&shamt);
1142    update_register(machine, i.rd(), value);
1143    Ok(())
1144}
1145
1146pub fn handle_rori<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1147    let i = Itype(inst);
1148    let rs1_value = &machine.registers()[i.rs1()];
1149    let rs2_value = &Mac::REG::from_u32(i.immediate_u());
1150    let shamt = rs2_value.clone() & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
1151    let value = rs1_value.ror(&shamt);
1152    update_register(machine, i.rd(), value);
1153    Ok(())
1154}
1155
1156pub fn handle_roriw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1157    let i = Itype(inst);
1158    let rs1_value = &machine.registers()[i.rs1()];
1159    let rs2_value = &Mac::REG::from_u32(i.immediate_u());
1160    let shamt = rs2_value.clone() & Mac::REG::from_u8(31);
1161    let twins = rs1_value
1162        .zero_extend(&Mac::REG::from_u8(32))
1163        .overflowing_mul(&Mac::REG::from_u64(0x_0000_0001_0000_0001));
1164    let value = twins.ror(&shamt).sign_extend(&Mac::REG::from_u8(32));
1165    update_register(machine, i.rd(), value);
1166    Ok(())
1167}
1168
1169pub fn handle_rorw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1170    let i = Rtype(inst);
1171    let rs1_value = &machine.registers()[i.rs1()];
1172    let rs2_value = &machine.registers()[i.rs2()];
1173    let shamt = rs2_value.clone() & Mac::REG::from_u8(31);
1174    let twins = rs1_value
1175        .zero_extend(&Mac::REG::from_u8(32))
1176        .overflowing_mul(&Mac::REG::from_u64(0x_0000_0001_0000_0001));
1177    let value = twins.ror(&shamt).sign_extend(&Mac::REG::from_u8(32));
1178    update_register(machine, i.rd(), value);
1179    Ok(())
1180}
1181
1182pub fn handle_sextb<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1183    let i = Rtype(inst);
1184    let rs1_value = &machine.registers()[i.rs1()];
1185    let shift = &Mac::REG::from_u8(Mac::REG::BITS - 8);
1186    let value = rs1_value.signed_shl(shift).signed_shr(shift);
1187    update_register(machine, i.rd(), value);
1188    Ok(())
1189}
1190
1191pub fn handle_sexth<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1192    let i = Rtype(inst);
1193    let rs1_value = &machine.registers()[i.rs1()];
1194    let shift = &Mac::REG::from_u8(Mac::REG::BITS - 16);
1195    let value = rs1_value.signed_shl(shift).signed_shr(shift);
1196    update_register(machine, i.rd(), value);
1197    Ok(())
1198}
1199
1200pub fn handle_sh1add<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1201    let i = Rtype(inst);
1202    let rs1_value = &machine.registers()[i.rs1()];
1203    let rs2_value = &machine.registers()[i.rs2()];
1204    let value = (rs1_value.clone() << Mac::REG::from_u32(1)).overflowing_add(rs2_value);
1205    update_register(machine, i.rd(), value);
1206    Ok(())
1207}
1208
1209pub fn handle_sh1adduw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1210    let i = Rtype(inst);
1211    let rs1_value = &machine.registers()[i.rs1()];
1212    let rs2_value = &machine.registers()[i.rs2()];
1213    let rs1_z = rs1_value.clone().zero_extend(&Mac::REG::from_u8(32));
1214    let value = (rs1_z << Mac::REG::from_u32(1)).overflowing_add(rs2_value);
1215    update_register(machine, i.rd(), value);
1216    Ok(())
1217}
1218
1219pub fn handle_sh2add<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1220    let i = Rtype(inst);
1221    let rs1_value = &machine.registers()[i.rs1()];
1222    let rs2_value = &machine.registers()[i.rs2()];
1223    let value = (rs1_value.clone() << Mac::REG::from_u32(2)).overflowing_add(rs2_value);
1224    update_register(machine, i.rd(), value);
1225    Ok(())
1226}
1227
1228pub fn handle_sh2adduw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1229    let i = Rtype(inst);
1230    let rs1_value = &machine.registers()[i.rs1()];
1231    let rs2_value = &machine.registers()[i.rs2()];
1232    let rs1_z = rs1_value.clone().zero_extend(&Mac::REG::from_u8(32));
1233    let value = (rs1_z << Mac::REG::from_u32(2)).overflowing_add(rs2_value);
1234    update_register(machine, i.rd(), value);
1235    Ok(())
1236}
1237
1238pub fn handle_sh3add<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1239    let i = Rtype(inst);
1240    let rs1_value = &machine.registers()[i.rs1()];
1241    let rs2_value = &machine.registers()[i.rs2()];
1242    let value = (rs1_value.clone() << Mac::REG::from_u32(3)).overflowing_add(rs2_value);
1243    update_register(machine, i.rd(), value);
1244    Ok(())
1245}
1246
1247pub fn handle_sh3adduw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1248    let i = Rtype(inst);
1249    let rs1_value = &machine.registers()[i.rs1()];
1250    let rs2_value = &machine.registers()[i.rs2()];
1251    let rs1_z = rs1_value.clone().zero_extend(&Mac::REG::from_u8(32));
1252    let value = (rs1_z << Mac::REG::from_u32(3)).overflowing_add(rs2_value);
1253    update_register(machine, i.rd(), value);
1254    Ok(())
1255}
1256
1257pub fn handle_slliuw<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1258    let i = Itype(inst);
1259    let rs1_value = &machine.registers()[i.rs1()];
1260    let rs2_value = Mac::REG::from_u32(i.immediate_u());
1261    let rs1_u = rs1_value.clone().zero_extend(&Mac::REG::from_u8(32));
1262    let shamt = rs2_value & Mac::REG::from_u8(Mac::REG::SHIFT_MASK);
1263    let value = rs1_u << shamt;
1264    update_register(machine, i.rd(), value);
1265    Ok(())
1266}
1267
1268pub fn handle_xnor<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1269    let i = Rtype(inst);
1270    let rs1_value = &machine.registers()[i.rs1()];
1271    let rs2_value = &machine.registers()[i.rs2()];
1272    let value = rs1_value.clone() ^ !rs2_value.clone();
1273    update_register(machine, i.rd(), value);
1274    Ok(())
1275}
1276
1277pub fn handle_zexth<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1278    let i = Rtype(inst);
1279    let rs1_value = &machine.registers()[i.rs1()];
1280    let value = rs1_value.zero_extend(&Mac::REG::from_u8(16));
1281    update_register(machine, i.rd(), value);
1282    Ok(())
1283}
1284
1285pub fn handle_wide_mul<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1286    let i = R4type(inst);
1287    let rs1_value = &machine.registers()[i.rs1()];
1288    let rs2_value = &machine.registers()[i.rs2()];
1289    let value_h = rs1_value.overflowing_mul_high_signed(rs2_value);
1290    let value_l = rs1_value.overflowing_mul(rs2_value);
1291    update_register(machine, i.rd(), value_h);
1292    update_register(machine, i.rs3(), value_l);
1293    Ok(())
1294}
1295
1296pub fn handle_wide_mulu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1297    let i = R4type(inst);
1298    let rs1_value = &machine.registers()[i.rs1()];
1299    let rs2_value = &machine.registers()[i.rs2()];
1300    let value_h = rs1_value.overflowing_mul_high_unsigned(rs2_value);
1301    let value_l = rs1_value.overflowing_mul(rs2_value);
1302    update_register(machine, i.rd(), value_h);
1303    update_register(machine, i.rs3(), value_l);
1304    Ok(())
1305}
1306
1307pub fn handle_wide_mulsu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1308    let i = R4type(inst);
1309    let rs1_value = &machine.registers()[i.rs1()];
1310    let rs2_value = &machine.registers()[i.rs2()];
1311    let value_h = rs1_value.overflowing_mul_high_signed_unsigned(rs2_value);
1312    let value_l = rs1_value.overflowing_mul(rs2_value);
1313    update_register(machine, i.rd(), value_h);
1314    update_register(machine, i.rs3(), value_l);
1315    Ok(())
1316}
1317
1318pub fn handle_wide_div<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1319    let i = R4type(inst);
1320    let rs1_value = &machine.registers()[i.rs1()];
1321    let rs2_value = &machine.registers()[i.rs2()];
1322    let value_h = rs1_value.overflowing_div_signed(rs2_value);
1323    let value_l = rs1_value.overflowing_rem_signed(rs2_value);
1324    update_register(machine, i.rd(), value_h);
1325    update_register(machine, i.rs3(), value_l);
1326    Ok(())
1327}
1328
1329pub fn handle_wide_divu<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1330    let i = R4type(inst);
1331    let rs1_value = &machine.registers()[i.rs1()];
1332    let rs2_value = &machine.registers()[i.rs2()];
1333    let value_h = rs1_value.overflowing_div(rs2_value);
1334    let value_l = rs1_value.overflowing_rem(rs2_value);
1335    update_register(machine, i.rd(), value_h);
1336    update_register(machine, i.rs3(), value_l);
1337    Ok(())
1338}
1339
1340pub fn handle_far_jump_rel<Mac: Machine>(
1341    machine: &mut Mac,
1342    inst: Instruction,
1343) -> Result<(), Error> {
1344    let i = Utype(inst);
1345    let size = instruction_length(inst);
1346    let link = machine.pc().overflowing_add(&Mac::REG::from_u8(size));
1347    let next_pc = machine
1348        .pc()
1349        .overflowing_add(&Mac::REG::from_i32(i.immediate_s()))
1350        & (!Mac::REG::one());
1351    update_register(machine, RA, link);
1352    machine.update_pc(next_pc);
1353    Ok(())
1354}
1355
1356pub fn handle_far_jump_abs<Mac: Machine>(
1357    machine: &mut Mac,
1358    inst: Instruction,
1359) -> Result<(), Error> {
1360    let i = Utype(inst);
1361    let size = instruction_length(inst);
1362    let link = machine.pc().overflowing_add(&Mac::REG::from_u8(size));
1363    let next_pc = Mac::REG::from_i32(i.immediate_s()) & (!Mac::REG::one());
1364    update_register(machine, RA, link);
1365    machine.update_pc(next_pc);
1366    Ok(())
1367}
1368
1369pub fn handle_adc<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1370    let i = Rtype(inst);
1371    let rd_value = &machine.registers()[i.rd()];
1372    let rs1_value = &machine.registers()[i.rs1()];
1373    let r = rd_value.overflowing_add(rs1_value);
1374    update_register(machine, i.rd(), r);
1375    let rd_value = &machine.registers()[i.rd()];
1376    let rs1_value = &machine.registers()[i.rs1()];
1377    let r = rd_value.lt(rs1_value);
1378    update_register(machine, i.rs1(), r);
1379    let rd_value = &machine.registers()[i.rd()];
1380    let rs2_value = &machine.registers()[i.rs2()];
1381    let r = rd_value.overflowing_add(rs2_value);
1382    update_register(machine, i.rd(), r);
1383    let rd_value = &machine.registers()[i.rd()];
1384    let rs2_value = &machine.registers()[i.rs2()];
1385    let r = rd_value.lt(rs2_value);
1386    update_register(machine, i.rs2(), r);
1387    let rs1_value = machine.registers()[i.rs1()].clone();
1388    let rs2_value = machine.registers()[i.rs2()].clone();
1389    let r = rs1_value | rs2_value;
1390    update_register(machine, i.rs1(), r);
1391    Ok(())
1392}
1393
1394pub fn handle_sbb<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1395    let i = R4type(inst);
1396    let rd_value = &machine.registers()[i.rd()];
1397    let rs1_value = &machine.registers()[i.rs1()];
1398    let r = rd_value.overflowing_sub(rs1_value);
1399    update_register(machine, i.rs1(), r);
1400    let rd_value = &machine.registers()[i.rd()];
1401    let rs1_value = &machine.registers()[i.rs1()];
1402    let r = rd_value.lt(rs1_value);
1403    update_register(machine, i.rs3(), r);
1404    let rs1_value = &machine.registers()[i.rs1()];
1405    let rs2_value = &machine.registers()[i.rs2()];
1406    let r = rs1_value.overflowing_sub(rs2_value);
1407    update_register(machine, i.rd(), r);
1408    let rd_value = &machine.registers()[i.rd()];
1409    let rs1_value = &machine.registers()[i.rs1()];
1410    let r = rs1_value.lt(rd_value);
1411    update_register(machine, i.rs2(), r);
1412    let rs2_value = machine.registers()[i.rs2()].clone();
1413    let rs3_value = machine.registers()[i.rs3()].clone();
1414    let r = rs2_value | rs3_value;
1415    update_register(machine, i.rs1(), r);
1416    Ok(())
1417}
1418
1419pub fn handle_adcs<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1420    let i = R4type(inst);
1421    let rs1_value = machine.registers()[i.rs1()].clone();
1422    let rs2_value = machine.registers()[i.rs2()].clone();
1423    let r = rs1_value.overflowing_add(&rs2_value);
1424    update_register(machine, i.rd(), r.clone());
1425    let r = r.lt(&rs1_value);
1426    update_register(machine, i.rs3(), r);
1427    Ok(())
1428}
1429
1430pub fn handle_sbbs<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1431    let i = R4type(inst);
1432    let rs1_value = machine.registers()[i.rs1()].clone();
1433    let rs2_value = machine.registers()[i.rs2()].clone();
1434    let r = rs1_value.overflowing_sub(&rs2_value);
1435    update_register(machine, i.rd(), r);
1436    let r = rs1_value.lt(&rs2_value);
1437    update_register(machine, i.rs3(), r);
1438    Ok(())
1439}
1440
1441pub fn handle_add3a<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1442    let i = R5type(inst);
1443    {
1444        let rd_value = machine.registers()[i.rd()].clone();
1445        let rs1_value = machine.registers()[i.rs1()].clone();
1446        let r = rd_value.overflowing_add(&rs1_value);
1447        update_register(machine, i.rd(), r);
1448    }
1449    {
1450        let rd_value = &machine.registers()[i.rd()];
1451        let rs1_value = &machine.registers()[i.rs1()];
1452        let r = rd_value.lt(rs1_value);
1453        update_register(machine, i.rs2(), r);
1454    }
1455    {
1456        let rs2_value = &machine.registers()[i.rs2()];
1457        let rs4_value = &machine.registers()[i.rs4()];
1458        let r = rs2_value.overflowing_add(rs4_value);
1459        update_register(machine, i.rs3(), r);
1460    }
1461    Ok(())
1462}
1463
1464pub fn handle_add3b<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1465    let i = R5type(inst);
1466    {
1467        let rs1_value = machine.registers()[i.rs1()].clone();
1468        let rs2_value = machine.registers()[i.rs2()].clone();
1469        let r = rs1_value.overflowing_add(&rs2_value);
1470        update_register(machine, i.rd(), r);
1471    }
1472    {
1473        let rd_value = &machine.registers()[i.rd()];
1474        let rs1_value = &machine.registers()[i.rs1()];
1475        let r = rd_value.lt(rs1_value);
1476        update_register(machine, i.rs1(), r);
1477    }
1478    {
1479        let rs1_value = &machine.registers()[i.rs1()];
1480        let rs4_value = &machine.registers()[i.rs4()];
1481        let r = rs1_value.overflowing_add(rs4_value);
1482        update_register(machine, i.rs3(), r);
1483    }
1484    Ok(())
1485}
1486
1487pub fn handle_add3c<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1488    let i = R5type(inst);
1489    {
1490        let rs1_value = machine.registers()[i.rs1()].clone();
1491        let rs2_value = machine.registers()[i.rs2()].clone();
1492        let r = rs1_value.overflowing_add(&rs2_value);
1493        update_register(machine, i.rd(), r);
1494    }
1495    {
1496        let rd_value = &machine.registers()[i.rd()];
1497        let rs1_value = &machine.registers()[i.rs1()];
1498        let rs4_value = &machine.registers()[i.rs4()];
1499        let r = rd_value.lt(rs1_value);
1500        let r = r.overflowing_add(rs4_value);
1501        update_register(machine, i.rs3(), r);
1502    }
1503    Ok(())
1504}
1505
1506pub fn handle_custom_load_uimm<Mac: Machine>(
1507    machine: &mut Mac,
1508    inst: Instruction,
1509) -> Result<(), Error> {
1510    let i = Utype(inst);
1511    update_register(machine, i.rd(), Mac::REG::from_u32(i.immediate_u()));
1512    Ok(())
1513}
1514
1515pub fn handle_custom_load_imm<Mac: Machine>(
1516    machine: &mut Mac,
1517    inst: Instruction,
1518) -> Result<(), Error> {
1519    let i = Utype(inst);
1520    let value = Mac::REG::from_i32(i.immediate_s());
1521    update_register(machine, i.rd(), value);
1522    Ok(())
1523}
1524
1525pub fn handle_unloaded<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1526    handle_invalid_op(machine, inst)
1527}
1528
1529pub fn handle_custom_trace_end<Mac: Machine>(
1530    machine: &mut Mac,
1531    inst: Instruction,
1532) -> Result<(), Error> {
1533    handle_invalid_op(machine, inst)
1534}
1535
1536pub fn handle_invalid_op<Mac: Machine>(_machine: &mut Mac, inst: Instruction) -> Result<(), Error> {
1537    Err(Error::InvalidOp(extract_opcode(inst)))
1538}
1539
1540macro_rules! handle_single_opcode {
1541    ($name:ident, $real_name:ident, $code:expr, $machine:ident, $inst:ident) => {
1542        paste! {
1543            Ok([< handle_ $real_name:lower >]($machine, $inst)?)
1544        }
1545    };
1546}
1547
1548pub fn execute_instruction<Mac: Machine>(
1549    inst: Instruction,
1550    machine: &mut Mac,
1551) -> Result<(), Error> {
1552    let op = extract_opcode(inst);
1553    for_each_inst_match2!(
1554        handle_single_opcode,
1555        op,
1556        handle_invalid_op(machine, inst),
1557        machine,
1558        inst
1559    )
1560}
1561
1562pub fn execute<Mac: Machine>(inst: Instruction, machine: &mut Mac) -> Result<(), Error> {
1563    let instruction_size = instruction_length(inst);
1564    let next_pc = machine
1565        .pc()
1566        .overflowing_add(&Mac::REG::from_u8(instruction_size));
1567    machine.update_pc(next_pc);
1568    let r = execute_instruction(inst, machine);
1569    machine.commit_pc();
1570    r
1571}
1572
1573pub fn execute_with_thread<Mac: Machine>(
1574    inst: Instruction,
1575    machine: &mut Mac,
1576    thread: &Thread<Mac>,
1577) -> Result<(), Error> {
1578    let instruction_size = instruction_length(inst);
1579    let next_pc = machine
1580        .pc()
1581        .overflowing_add(&Mac::REG::from_u8(instruction_size));
1582    machine.update_pc(next_pc);
1583    let r = thread(machine, inst);
1584    machine.commit_pc();
1585    r
1586}
1587
1588pub type Thread<Mac> = fn(&mut Mac, Instruction) -> Result<(), Error>;
1589
1590const FASTPATH_THREADS: usize = insts::MAXIMUM_OPCODE as usize + 1 - insts::MINIMAL_OPCODE as usize;
1591
1592pub struct ThreadFactory<Mac: Machine> {
1593    // Right now we are only dealing with fastpath opcodes, later we might
1594    // (or might not?) expand this with some opcodes in the slowpath category.
1595    threads: [Thread<Mac>; FASTPATH_THREADS],
1596}
1597
1598macro_rules! thread_func_item {
1599    ($name:ident, $real_name:ident, $code:expr, $t:ident) => {
1600        paste! {
1601            [< handle_ $real_name:lower >]::<$t> as Thread<$t>
1602        }
1603    };
1604}
1605
1606impl<Mac: Machine> ThreadFactory<Mac> {
1607    pub fn create() -> Self {
1608        let threads = for_each_inst_array1!(thread_func_item, Mac);
1609        Self { threads }
1610    }
1611
1612    pub fn get(&self, op: InstructionOpcode) -> Option<&Thread<Mac>> {
1613        self.threads
1614            .get((op as usize).wrapping_sub(insts::MINIMAL_OPCODE as usize))
1615    }
1616
1617    pub fn get_cloned(&self, op: InstructionOpcode) -> Option<Thread<Mac>> {
1618        self.get(op).cloned()
1619    }
1620}
1621
1622impl<Mac: Machine> std::ops::Index<InstructionOpcode> for ThreadFactory<Mac> {
1623    type Output = Thread<Mac>;
1624
1625    fn index(&self, opcode: InstructionOpcode) -> &Thread<Mac> {
1626        self.get(opcode).unwrap()
1627    }
1628}