ab_riscv_interpreter/
m_64_ext.rs1#[cfg(test)]
4mod tests;
5
6use ab_riscv_primitives::instruction::m_64_ext::M64ExtInstruction;
7use ab_riscv_primitives::registers::{Register, Registers};
8
9#[inline(always)]
11pub fn execute_m_64_ext<Reg>(regs: &mut Registers<Reg>, instruction: M64ExtInstruction<Reg>)
12where
13 Reg: Register<Type = u64>,
14 [(); Reg::N]:,
15{
16 match instruction {
17 M64ExtInstruction::Mul { rd, rs1, rs2 } => {
18 let value = regs.read(rs1).wrapping_mul(regs.read(rs2));
19 regs.write(rd, value);
20 }
21 M64ExtInstruction::Mulh { rd, rs1, rs2 } => {
22 let (_lo, prod) = regs
23 .read(rs1)
24 .cast_signed()
25 .widening_mul(regs.read(rs2).cast_signed());
26 regs.write(rd, prod.cast_unsigned());
27 }
28 M64ExtInstruction::Mulhsu { rd, rs1, rs2 } => {
29 let prod = (regs.read(rs1).cast_signed() as i128) * (regs.read(rs2) as i128);
30 let value = prod >> 64;
31 regs.write(rd, value.cast_unsigned() as u64);
32 }
33 M64ExtInstruction::Mulhu { rd, rs1, rs2 } => {
34 let prod = (regs.read(rs1) as u128) * (regs.read(rs2) as u128);
35 let value = prod >> 64;
36 regs.write(rd, value as u64);
37 }
38 M64ExtInstruction::Div { rd, rs1, rs2 } => {
39 let dividend = regs.read(rs1).cast_signed();
40 let divisor = regs.read(rs2).cast_signed();
41 let value = if divisor == 0 {
42 -1i64
43 } else if dividend == i64::MIN && divisor == -1 {
44 i64::MIN
45 } else {
46 dividend / divisor
47 };
48 regs.write(rd, value.cast_unsigned());
49 }
50 M64ExtInstruction::Divu { rd, rs1, rs2 } => {
51 let dividend = regs.read(rs1);
52 let divisor = regs.read(rs2);
53 let value = if divisor == 0 {
54 u64::MAX
55 } else {
56 dividend / divisor
57 };
58 regs.write(rd, value);
59 }
60 M64ExtInstruction::Rem { rd, rs1, rs2 } => {
61 let dividend = regs.read(rs1).cast_signed();
62 let divisor = regs.read(rs2).cast_signed();
63 let value = if divisor == 0 {
64 dividend
65 } else if dividend == i64::MIN && divisor == -1 {
66 0
67 } else {
68 dividend % divisor
69 };
70 regs.write(rd, value.cast_unsigned());
71 }
72 M64ExtInstruction::Remu { rd, rs1, rs2 } => {
73 let dividend = regs.read(rs1);
74 let divisor = regs.read(rs2);
75 let value = if divisor == 0 {
76 dividend
77 } else {
78 dividend % divisor
79 };
80 regs.write(rd, value);
81 }
82
83 M64ExtInstruction::Mulw { rd, rs1, rs2 } => {
85 let prod = (regs.read(rs1) as i32).wrapping_mul(regs.read(rs2) as i32);
86 regs.write(rd, (prod as i64).cast_unsigned());
87 }
88 M64ExtInstruction::Divw { rd, rs1, rs2 } => {
89 let dividend = regs.read(rs1) as i32;
90 let divisor = regs.read(rs2) as i32;
91 let value = if divisor == 0 {
92 -1i64
93 } else if dividend == i32::MIN && divisor == -1 {
94 i32::MIN as i64
95 } else {
96 (dividend / divisor) as i64
97 };
98 regs.write(rd, value.cast_unsigned());
99 }
100 M64ExtInstruction::Divuw { rd, rs1, rs2 } => {
101 let dividend = regs.read(rs1) as u32;
102 let divisor = regs.read(rs2) as u32;
103 let value = if divisor == 0 {
104 u64::MAX
105 } else {
106 ((dividend / divisor).cast_signed() as i64).cast_unsigned()
107 };
108 regs.write(rd, value);
109 }
110 M64ExtInstruction::Remw { rd, rs1, rs2 } => {
111 let dividend = regs.read(rs1) as i32;
112 let divisor = regs.read(rs2) as i32;
113 let value = if divisor == 0 {
114 (dividend as i64).cast_unsigned()
115 } else if dividend == i32::MIN && divisor == -1 {
116 0
117 } else {
118 ((dividend % divisor) as i64).cast_unsigned()
119 };
120 regs.write(rd, value);
121 }
122 M64ExtInstruction::Remuw { rd, rs1, rs2 } => {
123 let dividend = regs.read(rs1) as u32;
124 let divisor = regs.read(rs2) as u32;
125 let value = if divisor == 0 {
126 dividend.cast_signed() as i64
127 } else {
128 (dividend % divisor).cast_signed() as i64
129 };
130 regs.write(rd, value.cast_unsigned());
131 }
132 }
133}