ab_riscv_interpreter/rv64/
m.rs1#[cfg(test)]
4mod tests;
5pub mod zmmul;
6
7use crate::{
8 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
9 ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
10 RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction,
11 ThreadedExecutionResult,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15
16#[instruction_execution]
17const impl<Reg, Hart> ExecutableInstructionOperands for Rv64MInstruction<Hart>
18where
19 Reg: Register<Type = u64>,
20 Hart: HartConfig<Reg = Reg>,
21{
22}
23
24#[instruction_execution]
25const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv64MInstruction<Hart>
26where
27 Reg: Register<Type = u64>,
28 Hart: HartConfig<Reg = Reg>,
29{
30}
31
32#[instruction_execution]
33const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
34 for Rv64MInstruction<Hart>
35where
36 Reg: [const] Register<Type = u64>,
37 Hart: HartConfig<Reg = Reg>,
38 Regs: [const] RegisterFile<Reg>,
39{
40 #[inline(always)]
41 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
42 fn execute(
43 self,
44 Rs1Rs2OperandValues {
45 rs1_value,
46 rs2_value,
47 }: Rs1Rs2OperandValues<Reg::Type>,
48 _regs: &mut Regs,
49 _env: &mut Env,
50 _memory: &mut Memory,
51 _program_counter: &PC,
52 ) -> ExecutionResult<Reg> {
53 match self {
54 Self::Div { rd, rs1: _, rs2: _ } => {
55 let dividend = rs1_value.cast_signed();
56 let divisor = rs2_value.cast_signed();
57 let value = if divisor == 0 {
58 -1i64
59 } else if dividend == i64::MIN && divisor == -1 {
60 i64::MIN
61 } else {
62 dividend / divisor
63 };
64 ExecutionResult::Continue {
65 rd,
66 value: value.cast_unsigned(),
67 }
68 }
69 Self::Divu { rd, rs1: _, rs2: _ } => {
70 let dividend = rs1_value;
71 let divisor = rs2_value;
72 let value = dividend.checked_div(divisor).unwrap_or(u64::MAX);
73 ExecutionResult::Continue { rd, value }
74 }
75 Self::Rem { rd, rs1: _, rs2: _ } => {
76 let dividend = rs1_value.cast_signed();
77 let divisor = rs2_value.cast_signed();
78 #[expect(
79 clippy::modulo_arithmetic,
80 reason = "This is what the code is supposed to do"
81 )]
82 let value = if divisor == 0 {
83 dividend
84 } else if dividend == i64::MIN && divisor == -1 {
85 0
86 } else {
87 dividend % divisor
88 };
89 ExecutionResult::Continue {
90 rd,
91 value: value.cast_unsigned(),
92 }
93 }
94 Self::Remu { rd, rs1: _, rs2: _ } => {
95 let dividend = rs1_value;
96 let divisor = rs2_value;
97 let value = if divisor == 0 {
98 dividend
99 } else {
100 dividend % divisor
101 };
102 ExecutionResult::Continue { rd, value }
103 }
104
105 Self::Divw { rd, rs1: _, rs2: _ } => {
107 let dividend = rs1_value as i32;
108 let divisor = rs2_value as i32;
109 let value = if divisor == 0 {
110 -1i64
111 } else if dividend == i32::MIN && divisor == -1 {
112 i64::from(i32::MIN)
113 } else {
114 i64::from(dividend / divisor)
115 };
116 ExecutionResult::Continue {
117 rd,
118 value: value.cast_unsigned(),
119 }
120 }
121 Self::Divuw { rd, rs1: _, rs2: _ } => {
122 let dividend = rs1_value as u32;
123 let divisor = rs2_value as u32;
124 let value = match dividend.checked_div(divisor) {
125 Some(value) => i64::from(value.cast_signed()).cast_unsigned(),
126 None => u64::MAX,
127 };
128 ExecutionResult::Continue { rd, value }
129 }
130 Self::Remw { rd, rs1: _, rs2: _ } => {
131 let dividend = rs1_value as i32;
132 let divisor = rs2_value as i32;
133 #[expect(
134 clippy::modulo_arithmetic,
135 reason = "This is what the code is supposed to do"
136 )]
137 let value = if divisor == 0 {
138 i64::from(dividend).cast_unsigned()
139 } else if dividend == i32::MIN && divisor == -1 {
140 0
141 } else {
142 i64::from(dividend % divisor).cast_unsigned()
143 };
144 ExecutionResult::Continue { rd, value }
145 }
146 Self::Remuw { rd, rs1: _, rs2: _ } => {
147 let dividend = rs1_value as u32;
148 let divisor = rs2_value as u32;
149 let value = if divisor == 0 {
150 dividend.cast_signed()
151 } else {
152 (dividend % divisor).cast_signed()
153 };
154 ExecutionResult::Continue {
155 rd,
156 value: i64::from(value).cast_unsigned(),
157 }
158 }
159 }
160 }
161}