1 use crate::{ConditionRegister, InstructionInput, InstructionResult, OverflowFlags};
3 macro_rules! create_instr_variants_ov_cr {
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 macro_rules! create_instr_variants_cr {
30 ($fn:ident, $fn_:ident, $iwidth:ident) => {
31 pub fn $fn_(inputs: InstructionInput) -> InstructionResult {
32 let mut retval = $fn(inputs);
33 let result = retval.rt.expect("expected rt to be set");
34 let cr0 = ConditionRegister::from_signed_int(result as $iwidth, false);
35 retval.cr0 = Some(cr0);
41 create_instr_variants_ov_cr!(divde, divdeo, divde_, divdeo_, i64);
43 pub fn divdeo(inputs: InstructionInput) -> InstructionResult {
44 let dividend = i128::from(inputs.ra as i64) << 64;
45 let divisor = i128::from(inputs.rb as i64);
48 if divisor == 0 || (divisor == -1 && dividend == i128::min_value()) {
52 let result128 = dividend / divisor;
53 if result128 as i64 as i128 != result128 {
57 result = result128 as u64;
63 overflow: Some(OverflowFlags::from_overflow(overflow)),
64 ..InstructionResult::default()
68 create_instr_variants_ov_cr!(divdeu, divdeuo, divdeu_, divdeuo_, i64);
70 pub fn divdeuo(inputs: InstructionInput) -> InstructionResult {
71 let dividend = u128::from(inputs.ra) << 64;
72 let divisor = u128::from(inputs.rb);
79 let resultu128 = dividend / divisor;
80 if resultu128 > u128::from(u64::max_value()) {
84 result = resultu128 as u64;
90 overflow: Some(OverflowFlags::from_overflow(overflow)),
91 ..InstructionResult::default()
95 create_instr_variants_ov_cr!(divd, divdo, divd_, divdo_, i64);
97 pub fn divdo(inputs: InstructionInput) -> InstructionResult {
98 let dividend = inputs.ra as i64;
99 let divisor = inputs.rb as i64;
102 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
106 result = (dividend / divisor) as u64;
111 overflow: Some(OverflowFlags::from_overflow(overflow)),
112 ..InstructionResult::default()
116 create_instr_variants_ov_cr!(divdu, divduo, divdu_, divduo_, i64);
118 pub fn divduo(inputs: InstructionInput) -> InstructionResult {
119 let dividend: u64 = inputs.ra;
120 let divisor: u64 = inputs.rb;
127 result = dividend / divisor;
132 overflow: Some(OverflowFlags::from_overflow(overflow)),
133 ..InstructionResult::default()
137 create_instr_variants_ov_cr!(divwe, divweo, divwe_, divweo_, i32);
139 pub fn divweo(inputs: InstructionInput) -> InstructionResult {
140 let dividend = i64::from(inputs.ra as i32) << 32;
141 let divisor = i64::from(inputs.rb as i32);
144 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
148 let result64 = dividend / divisor;
149 if result64 as i32 as i64 != result64 {
153 result = result64 as u32 as u64;
159 overflow: Some(OverflowFlags::from_overflow(overflow)),
160 ..InstructionResult::default()
164 create_instr_variants_ov_cr!(divweu, divweuo, divweu_, divweuo_, i32);
166 pub fn divweuo(inputs: InstructionInput) -> InstructionResult {
167 let dividend = u64::from(inputs.ra as u32) << 32;
168 let divisor = u64::from(inputs.rb as u32);
175 let resultu64 = dividend / divisor;
176 if resultu64 > u64::from(u32::max_value()) {
180 result = resultu64 as u32 as u64;
186 overflow: Some(OverflowFlags::from_overflow(overflow)),
187 ..InstructionResult::default()
191 create_instr_variants_ov_cr!(divw, divwo, divw_, divwo_, i32);
193 pub fn divwo(inputs: InstructionInput) -> InstructionResult {
194 let dividend = inputs.ra as i32;
195 let divisor = inputs.rb as i32;
198 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
202 result = (dividend / divisor) as u32 as u64;
207 overflow: Some(OverflowFlags::from_overflow(overflow)),
208 ..InstructionResult::default()
212 create_instr_variants_ov_cr!(divwu, divwuo, divwu_, divwuo_, i32);
214 pub fn divwuo(inputs: InstructionInput) -> InstructionResult {
215 let dividend = inputs.ra as u32;
216 let divisor = inputs.rb as u32;
223 result = (dividend / divisor) as u64;
228 overflow: Some(OverflowFlags::from_overflow(overflow)),
229 ..InstructionResult::default()
233 pub fn modsd(inputs: InstructionInput) -> InstructionResult {
234 let dividend = inputs.ra as i64;
235 let divisor = inputs.rb as i64;
237 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
240 result = (dividend % divisor) as u64;
244 ..InstructionResult::default()
248 pub fn modud(inputs: InstructionInput) -> InstructionResult {
249 let dividend: u64 = inputs.ra;
250 let divisor: u64 = inputs.rb;
255 result = dividend % divisor;
259 ..InstructionResult::default()
263 pub fn modsw(inputs: InstructionInput) -> InstructionResult {
264 let dividend = inputs.ra as i32;
265 let divisor = inputs.rb as i32;
267 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
270 result = (dividend % divisor) as u64;
274 ..InstructionResult::default()
278 pub fn moduw(inputs: InstructionInput) -> InstructionResult {
279 let dividend = inputs.ra as u32;
280 let divisor = inputs.rb as u32;
285 result = (dividend % divisor) as u64;
289 ..InstructionResult::default()
293 create_instr_variants_ov_cr!(mullw, mullwo, mullw_, mullwo_, i32);
295 pub fn mullwo(inputs: InstructionInput) -> InstructionResult {
296 let ra = inputs.ra as i32;
297 let rb = inputs.rb as i32;
298 let result = ra.wrapping_mul(rb) as u64;
299 let overflow = ra.checked_mul(rb).is_none();
302 overflow: Some(OverflowFlags::from_overflow(overflow)),
303 ..InstructionResult::default()
307 create_instr_variants_cr!(mulhw, mulhw_, i32);
309 pub fn mulhw(inputs: InstructionInput) -> InstructionResult {
310 let ra = inputs.ra as i32 as i64;
311 let rb = inputs.rb as i32 as i64;
312 let result = ((ra * rb) >> 32) as i32;
313 let result = result as u64;
316 ..InstructionResult::default()
320 create_instr_variants_cr!(mulhwu, mulhwu_, i32);
322 pub fn mulhwu(inputs: InstructionInput) -> InstructionResult {
323 let ra = inputs.ra as u32 as u64;
324 let rb = inputs.rb as u32 as u64;
325 let result = ((ra * rb) >> 32) as u32;
326 let result = result as u64;
329 ..InstructionResult::default()
333 create_instr_variants_ov_cr!(mulld, mulldo, mulld_, mulldo_, i64);
335 pub fn mulldo(inputs: InstructionInput) -> InstructionResult {
336 let ra = inputs.ra as i64;
337 let rb = inputs.rb as i64;
338 let result = ra.wrapping_mul(rb) as u64;
339 let overflow = ra.checked_mul(rb).is_none();
342 overflow: Some(OverflowFlags::from_overflow(overflow)),
343 ..InstructionResult::default()
347 create_instr_variants_cr!(mulhd, mulhd_, i64);
349 pub fn mulhd(inputs: InstructionInput) -> InstructionResult {
350 let ra = inputs.ra as i64 as i128;
351 let rb = inputs.rb as i64 as i128;
352 let result = ((ra * rb) >> 64) as i64;
353 let result = result as u64;
356 ..InstructionResult::default()
360 create_instr_variants_cr!(mulhdu, mulhdu_, i64);
362 pub fn mulhdu(inputs: InstructionInput) -> InstructionResult {
363 let ra = inputs.ra as u128;
364 let rb = inputs.rb as u128;
365 let result = ((ra * rb) >> 64) as u64;
368 ..InstructionResult::default()
372 pub fn maddhd(inputs: InstructionInput) -> InstructionResult {
373 let ra = inputs.ra as i64 as i128;
374 let rb = inputs.rb as i64 as i128;
375 let rc = inputs.rc as i64 as i128;
376 let result = ((ra * rb + rc) >> 64) as u64;
379 ..InstructionResult::default()
383 pub fn maddhdu(inputs: InstructionInput) -> InstructionResult {
384 let ra = inputs.ra as u128;
385 let rb = inputs.rb as u128;
386 let rc = inputs.rc as u128;
387 let result = ((ra * rb + rc) >> 64) as u64;
390 ..InstructionResult::default()
394 pub fn maddld(inputs: InstructionInput) -> InstructionResult {
395 let ra = inputs.ra as i64;
396 let rb = inputs.rb as i64;
397 let rc = inputs.rc as i64;
398 let result = ra.wrapping_mul(rb).wrapping_add(rc) as u64;
401 ..InstructionResult::default()