1 use crate::{ConditionRegister, InstructionInput, InstructionResult, OverflowFlags};
3 macro_rules! create_instr_variants {
4 ($fn:ident, $fno:ident, $fn_:ident, $fno_:ident, $iwidth:ident) => {
5 pub fn $fn(inputs: InstructionInput) -> InstructionResult {
11 pub fn $fn_(inputs: InstructionInput) -> InstructionResult {
12 let mut retval = $fno_(inputs);
13 let mut cr0 = retval.cr0.as_mut().expect("expected cr0 to be set");
15 retval.overflow = None;
18 pub fn $fno_(inputs: InstructionInput) -> InstructionResult {
19 let mut retval = $fno(inputs);
20 let result = retval.rt.expect("expected rt to be set");
21 let so = retval.overflow.expect("expected overflow to be set").so;
22 let cr0 = ConditionRegister::from_signed_int(result as $iwidth, so);
23 retval.cr0 = Some(cr0);
29 create_instr_variants!(divde, divdeo, divde_, divdeo_, i64);
31 pub fn divdeo(inputs: InstructionInput) -> InstructionResult {
32 let dividend = i128::from(inputs.ra as i64) << 64;
33 let divisor = i128::from(inputs.rb as i64);
36 if divisor == 0 || (divisor == -1 && dividend == i128::min_value()) {
40 let result128 = dividend / divisor;
41 if result128 as i64 as i128 != result128 {
45 result = result128 as u64;
51 overflow: Some(OverflowFlags::from_overflow(overflow)),
52 ..InstructionResult::default()
56 create_instr_variants!(divdeu, divdeuo, divdeu_, divdeuo_, i64);
58 pub fn divdeuo(inputs: InstructionInput) -> InstructionResult {
59 let dividend = u128::from(inputs.ra) << 64;
60 let divisor = u128::from(inputs.rb);
67 let resultu128 = dividend / divisor;
68 if resultu128 > u128::from(u64::max_value()) {
72 result = resultu128 as u64;
78 overflow: Some(OverflowFlags::from_overflow(overflow)),
79 ..InstructionResult::default()
83 create_instr_variants!(divd, divdo, divd_, divdo_, i64);
85 pub fn divdo(inputs: InstructionInput) -> InstructionResult {
86 let dividend = inputs.ra as i64;
87 let divisor = inputs.rb as i64;
90 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
94 result = (dividend / divisor) as u64;
99 overflow: Some(OverflowFlags::from_overflow(overflow)),
100 ..InstructionResult::default()
104 create_instr_variants!(divdu, divduo, divdu_, divduo_, i64);
106 pub fn divduo(inputs: InstructionInput) -> InstructionResult {
107 let dividend: u64 = inputs.ra;
108 let divisor: u64 = inputs.rb;
115 result = dividend / divisor;
120 overflow: Some(OverflowFlags::from_overflow(overflow)),
121 ..InstructionResult::default()
125 create_instr_variants!(divwe, divweo, divwe_, divweo_, i32);
127 pub fn divweo(inputs: InstructionInput) -> InstructionResult {
128 let dividend = i64::from(inputs.ra as i32) << 32;
129 let divisor = i64::from(inputs.rb as i32);
132 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
136 let result64 = dividend / divisor;
137 if result64 as i32 as i64 != result64 {
141 result = result64 as u32 as u64;
147 overflow: Some(OverflowFlags::from_overflow(overflow)),
148 ..InstructionResult::default()
152 create_instr_variants!(divweu, divweuo, divweu_, divweuo_, i32);
154 pub fn divweuo(inputs: InstructionInput) -> InstructionResult {
155 let dividend = u64::from(inputs.ra as u32) << 32;
156 let divisor = u64::from(inputs.rb as u32);
163 let resultu64 = dividend / divisor;
164 if resultu64 > u64::from(u32::max_value()) {
168 result = resultu64 as u32 as u64;
174 overflow: Some(OverflowFlags::from_overflow(overflow)),
175 ..InstructionResult::default()
179 create_instr_variants!(divw, divwo, divw_, divwo_, i32);
181 pub fn divwo(inputs: InstructionInput) -> InstructionResult {
182 let dividend = inputs.ra as i32;
183 let divisor = inputs.rb as i32;
186 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
190 result = (dividend / divisor) as u32 as u64;
195 overflow: Some(OverflowFlags::from_overflow(overflow)),
196 ..InstructionResult::default()
200 create_instr_variants!(divwu, divwuo, divwu_, divwuo_, i32);
202 pub fn divwuo(inputs: InstructionInput) -> InstructionResult {
203 let dividend = inputs.ra as u32;
204 let divisor = inputs.rb as u32;
211 result = (dividend / divisor) as u64;
216 overflow: Some(OverflowFlags::from_overflow(overflow)),
217 ..InstructionResult::default()
221 pub fn modsd(inputs: InstructionInput) -> InstructionResult {
222 let dividend = inputs.ra as i64;
223 let divisor = inputs.rb as i64;
225 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
228 result = (dividend % divisor) as u64;
232 ..InstructionResult::default()
236 pub fn modud(inputs: InstructionInput) -> InstructionResult {
237 let dividend: u64 = inputs.ra;
238 let divisor: u64 = inputs.rb;
243 result = dividend % divisor;
247 ..InstructionResult::default()
251 pub fn modsw(inputs: InstructionInput) -> InstructionResult {
252 let dividend = inputs.ra as i32;
253 let divisor = inputs.rb as i32;
255 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
258 result = (dividend % divisor) as u64;
262 ..InstructionResult::default()
266 pub fn moduw(inputs: InstructionInput) -> InstructionResult {
267 let dividend = inputs.ra as u32;
268 let divisor = inputs.rb as u32;
273 result = (dividend % divisor) as u64;
277 ..InstructionResult::default()