2 ConditionRegister, InstructionInput, InstructionOutput, InstructionResult,
3 MissingInstructionInput, OverflowFlags,
7 mut overflow: OverflowFlags,
8 inputs: InstructionInput,
9 ) -> Result<OverflowFlags, MissingInstructionInput> {
10 if inputs.try_get_overflow()?.so {
16 macro_rules! create_instr_variants_ov_cr {
17 ($fn:ident, $fno:ident, $fn_:ident, $fno_:ident, $iwidth:ident) => {
18 pub fn $fn(mut inputs: InstructionInput) -> InstructionResult {
19 inputs.overflow = Some(OverflowFlags::default());
20 Ok(InstructionOutput {
25 pub fn $fn_(inputs: InstructionInput) -> InstructionResult {
26 let mut retval = $fno_(inputs)?;
27 let mut cr0 = retval.cr0.as_mut().expect("expected cr0 to be set");
28 cr0.so = inputs.try_get_overflow()?.so;
29 retval.overflow = None;
32 pub fn $fno_(inputs: InstructionInput) -> InstructionResult {
33 let mut retval = $fno(inputs)?;
34 let result = retval.rt.expect("expected rt to be set");
35 let so = retval.overflow.expect("expected overflow to be set").so;
36 let cr0 = ConditionRegister::from_signed_int(result as $iwidth, so);
37 retval.cr0 = Some(cr0);
43 macro_rules! create_instr_variants_cr {
44 ($fn:ident, $fn_:ident, $iwidth:ident) => {
45 pub fn $fn_(inputs: InstructionInput) -> InstructionResult {
46 let mut retval = $fn(inputs)?;
47 let result = retval.rt.expect("expected rt to be set");
48 let cr0 = ConditionRegister::from_signed_int(
50 inputs.try_get_overflow()?.so,
52 retval.cr0 = Some(cr0);
58 create_instr_variants_ov_cr!(add, addo, add_, addo_, i64);
60 pub fn addo(inputs: InstructionInput) -> InstructionResult {
61 let ra = inputs.try_get_ra()? as i64;
62 let rb = inputs.try_get_rb()? as i64;
63 let (result, ov) = ra.overflowing_add(rb);
64 let result = result as u64;
65 let ov32 = (ra as i32).overflowing_add(rb as i32).1;
66 Ok(InstructionOutput {
68 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
69 ..InstructionOutput::default()
73 create_instr_variants_ov_cr!(subf, subfo, subf_, subfo_, i64);
75 pub fn subfo(inputs: InstructionInput) -> InstructionResult {
76 let ra = inputs.try_get_ra()? as i64;
77 let rb = inputs.try_get_rb()? as i64;
78 let (result, ov) = rb.overflowing_sub(ra);
79 let result = result as u64;
80 let ov32 = (rb as i32).overflowing_sub(ra as i32).1;
81 Ok(InstructionOutput {
83 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
84 ..InstructionOutput::default()
88 create_instr_variants_ov_cr!(divde, divdeo, divde_, divdeo_, i64);
90 pub fn divdeo(inputs: InstructionInput) -> InstructionResult {
91 let dividend = i128::from(inputs.try_get_ra()? as i64) << 64;
92 let divisor = i128::from(inputs.try_get_rb()? as i64);
95 if divisor == 0 || (divisor == -1 && dividend == i128::min_value()) {
99 let result128 = dividend / divisor;
100 if result128 as i64 as i128 != result128 {
104 result = result128 as u64;
108 Ok(InstructionOutput {
110 overflow: Some(propagate_so(
111 OverflowFlags::from_overflow(overflow),
114 ..InstructionOutput::default()
118 create_instr_variants_ov_cr!(divdeu, divdeuo, divdeu_, divdeuo_, i64);
120 pub fn divdeuo(inputs: InstructionInput) -> InstructionResult {
121 let dividend = u128::from(inputs.try_get_ra()?) << 64;
122 let divisor = u128::from(inputs.try_get_rb()?);
129 let resultu128 = dividend / divisor;
130 if resultu128 > u128::from(u64::max_value()) {
134 result = resultu128 as u64;
138 Ok(InstructionOutput {
140 overflow: Some(propagate_so(
141 OverflowFlags::from_overflow(overflow),
144 ..InstructionOutput::default()
148 create_instr_variants_ov_cr!(divd, divdo, divd_, divdo_, i64);
150 pub fn divdo(inputs: InstructionInput) -> InstructionResult {
151 let dividend = inputs.try_get_ra()? as i64;
152 let divisor = inputs.try_get_rb()? as i64;
155 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
159 result = (dividend / divisor) as u64;
162 Ok(InstructionOutput {
164 overflow: Some(propagate_so(
165 OverflowFlags::from_overflow(overflow),
168 ..InstructionOutput::default()
172 create_instr_variants_ov_cr!(divdu, divduo, divdu_, divduo_, i64);
174 pub fn divduo(inputs: InstructionInput) -> InstructionResult {
175 let dividend: u64 = inputs.try_get_ra()?;
176 let divisor: u64 = inputs.try_get_rb()?;
183 result = dividend / divisor;
186 Ok(InstructionOutput {
188 overflow: Some(propagate_so(
189 OverflowFlags::from_overflow(overflow),
192 ..InstructionOutput::default()
196 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
197 create_instr_variants_ov_cr!(divwe, divweo, divwe_, divweo_, i64);
199 pub fn divweo(inputs: InstructionInput) -> InstructionResult {
200 let dividend = i64::from(inputs.try_get_ra()? as i32) << 32;
201 let divisor = i64::from(inputs.try_get_rb()? as i32);
204 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
208 let result64 = dividend / divisor;
209 if result64 as i32 as i64 != result64 {
213 result = result64 as u32 as u64;
217 Ok(InstructionOutput {
219 overflow: Some(propagate_so(
220 OverflowFlags::from_overflow(overflow),
223 ..InstructionOutput::default()
227 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
228 create_instr_variants_ov_cr!(divweu, divweuo, divweu_, divweuo_, i64);
230 pub fn divweuo(inputs: InstructionInput) -> InstructionResult {
231 let dividend = u64::from(inputs.try_get_ra()? as u32) << 32;
232 let divisor = u64::from(inputs.try_get_rb()? as u32);
239 let resultu64 = dividend / divisor;
240 if resultu64 > u64::from(u32::max_value()) {
244 result = resultu64 as u32 as u64;
248 Ok(InstructionOutput {
250 overflow: Some(propagate_so(
251 OverflowFlags::from_overflow(overflow),
254 ..InstructionOutput::default()
258 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
259 create_instr_variants_ov_cr!(divw, divwo, divw_, divwo_, i64);
261 pub fn divwo(inputs: InstructionInput) -> InstructionResult {
262 let dividend = inputs.try_get_ra()? as i32;
263 let divisor = inputs.try_get_rb()? as i32;
266 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
270 result = (dividend / divisor) as u32 as u64;
273 Ok(InstructionOutput {
275 overflow: Some(propagate_so(
276 OverflowFlags::from_overflow(overflow),
279 ..InstructionOutput::default()
283 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
284 create_instr_variants_ov_cr!(divwu, divwuo, divwu_, divwuo_, i64);
286 pub fn divwuo(inputs: InstructionInput) -> InstructionResult {
287 let dividend = inputs.try_get_ra()? as u32;
288 let divisor = inputs.try_get_rb()? as u32;
295 result = (dividend / divisor) as u64;
298 Ok(InstructionOutput {
300 overflow: Some(propagate_so(
301 OverflowFlags::from_overflow(overflow),
304 ..InstructionOutput::default()
308 pub fn modsd(inputs: InstructionInput) -> InstructionResult {
309 let dividend = inputs.try_get_ra()? as i64;
310 let divisor = inputs.try_get_rb()? as i64;
312 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
315 result = (dividend % divisor) as u64;
317 Ok(InstructionOutput {
319 ..InstructionOutput::default()
323 pub fn modud(inputs: InstructionInput) -> InstructionResult {
324 let dividend: u64 = inputs.try_get_ra()?;
325 let divisor: u64 = inputs.try_get_rb()?;
330 result = dividend % divisor;
332 Ok(InstructionOutput {
334 ..InstructionOutput::default()
338 pub fn modsw(inputs: InstructionInput) -> InstructionResult {
339 let dividend = inputs.try_get_ra()? as i32;
340 let divisor = inputs.try_get_rb()? as i32;
342 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
345 result = (dividend % divisor) as u64;
347 Ok(InstructionOutput {
349 ..InstructionOutput::default()
353 pub fn moduw(inputs: InstructionInput) -> InstructionResult {
354 let dividend = inputs.try_get_ra()? as u32;
355 let divisor = inputs.try_get_rb()? as u32;
360 result = (dividend % divisor) as u64;
362 Ok(InstructionOutput {
364 ..InstructionOutput::default()
368 create_instr_variants_ov_cr!(mullw, mullwo, mullw_, mullwo_, i64);
370 pub fn mullwo(inputs: InstructionInput) -> InstructionResult {
371 let ra = inputs.try_get_ra()? as i32 as i64;
372 let rb = inputs.try_get_rb()? as i32 as i64;
373 let result = ra.wrapping_mul(rb) as u64;
374 let overflow = result as i32 as i64 != result as i64;
375 Ok(InstructionOutput {
377 overflow: Some(propagate_so(
378 OverflowFlags::from_overflow(overflow),
381 ..InstructionOutput::default()
385 create_instr_variants_cr!(mulhw, mulhw_, i32);
387 pub fn mulhw(inputs: InstructionInput) -> InstructionResult {
388 let ra = inputs.try_get_ra()? as i32 as i64;
389 let rb = inputs.try_get_rb()? as i32 as i64;
390 let result = (ra * rb) >> 32;
391 let mut result = result as u32 as u64;
392 result |= result << 32;
393 Ok(InstructionOutput {
395 ..InstructionOutput::default()
399 create_instr_variants_cr!(mulhwu, mulhwu_, i32);
401 pub fn mulhwu(inputs: InstructionInput) -> InstructionResult {
402 let ra = inputs.try_get_ra()? as u32 as u64;
403 let rb = inputs.try_get_rb()? as u32 as u64;
404 let result = (ra * rb) >> 32;
405 let mut result = result as u32 as u64;
406 result |= result << 32;
407 Ok(InstructionOutput {
409 ..InstructionOutput::default()
413 create_instr_variants_ov_cr!(mulld, mulldo, mulld_, mulldo_, i64);
415 pub fn mulldo(inputs: InstructionInput) -> InstructionResult {
416 let ra = inputs.try_get_ra()? as i64;
417 let rb = inputs.try_get_rb()? as i64;
418 let result = ra.wrapping_mul(rb) as u64;
419 let overflow = ra.checked_mul(rb).is_none();
420 Ok(InstructionOutput {
422 overflow: Some(propagate_so(
423 OverflowFlags::from_overflow(overflow),
426 ..InstructionOutput::default()
430 create_instr_variants_cr!(mulhd, mulhd_, i64);
432 pub fn mulhd(inputs: InstructionInput) -> InstructionResult {
433 let ra = inputs.try_get_ra()? as i64 as i128;
434 let rb = inputs.try_get_rb()? as i64 as i128;
435 let result = ((ra * rb) >> 64) as i64;
436 let result = result as u64;
437 Ok(InstructionOutput {
439 ..InstructionOutput::default()
443 create_instr_variants_cr!(mulhdu, mulhdu_, i64);
445 pub fn mulhdu(inputs: InstructionInput) -> InstructionResult {
446 let ra = inputs.try_get_ra()? as u128;
447 let rb = inputs.try_get_rb()? as u128;
448 let result = ((ra * rb) >> 64) as u64;
449 Ok(InstructionOutput {
451 ..InstructionOutput::default()
455 pub fn maddhd(inputs: InstructionInput) -> InstructionResult {
456 let ra = inputs.try_get_ra()? as i64 as i128;
457 let rb = inputs.try_get_rb()? as i64 as i128;
458 let rc = inputs.try_get_rc()? as i64 as i128;
459 let result = ((ra * rb + rc) >> 64) as u64;
460 Ok(InstructionOutput {
462 ..InstructionOutput::default()
466 pub fn maddhdu(inputs: InstructionInput) -> InstructionResult {
467 let ra = inputs.try_get_ra()? as u128;
468 let rb = inputs.try_get_rb()? as u128;
469 let rc = inputs.try_get_rc()? as u128;
470 let result = ((ra * rb + rc) >> 64) as u64;
471 Ok(InstructionOutput {
473 ..InstructionOutput::default()
477 pub fn maddld(inputs: InstructionInput) -> InstructionResult {
478 let ra = inputs.try_get_ra()? as i64;
479 let rb = inputs.try_get_rb()? as i64;
480 let rc = inputs.try_get_rc()? as i64;
481 let result = ra.wrapping_mul(rb).wrapping_add(rc) as u64;
482 Ok(InstructionOutput {
484 ..InstructionOutput::default()