2 CarryFlags, ConditionRegister, InstructionInput, InstructionOutput, InstructionResult,
3 MissingInstructionInput, OverflowFlags,
5 use std::convert::TryFrom;
8 mut overflow: OverflowFlags,
9 inputs: InstructionInput,
10 ) -> Result<OverflowFlags, MissingInstructionInput> {
11 if inputs.try_get_overflow()?.so {
17 macro_rules! create_instr_variants_ov_cr {
18 ($fn:ident, $fno:ident, $fn_:ident, $fno_:ident, $iwidth:ident) => {
19 pub fn $fn(mut inputs: InstructionInput) -> InstructionResult {
20 inputs.overflow = Some(OverflowFlags::default());
21 Ok(InstructionOutput {
26 pub fn $fn_(inputs: InstructionInput) -> InstructionResult {
27 let mut retval = $fno_(inputs)?;
28 let mut cr0 = retval.cr0.as_mut().expect("expected cr0 to be set");
29 cr0.so = inputs.try_get_overflow()?.so;
30 retval.overflow = None;
33 pub fn $fno_(inputs: InstructionInput) -> InstructionResult {
34 let mut retval = $fno(inputs)?;
35 let result = retval.rt.expect("expected rt to be set");
36 let so = retval.overflow.expect("expected overflow to be set").so;
37 let cr0 = ConditionRegister::from_signed_int(result as $iwidth, so);
38 retval.cr0 = Some(cr0);
44 macro_rules! create_instr_variants_cr {
45 ($fn:ident, $fn_:ident, $iwidth:ident) => {
46 pub fn $fn_(inputs: InstructionInput) -> InstructionResult {
47 let mut retval = $fn(inputs)?;
48 let result = retval.rt.expect("expected rt to be set");
49 let cr0 = ConditionRegister::from_signed_int(
51 inputs.try_get_overflow()?.so,
53 retval.cr0 = Some(cr0);
59 pub fn addi(inputs: InstructionInput) -> InstructionResult {
60 let ra = inputs.try_get_ra()? as i64;
61 let immediate = inputs.try_get_immediate_s16()? as i64;
62 let result = ra.wrapping_add(immediate) as u64;
63 Ok(InstructionOutput {
65 ..InstructionOutput::default()
69 pub fn addis(inputs: InstructionInput) -> InstructionResult {
70 let ra = inputs.try_get_ra()? as i64;
71 let immediate = inputs.try_get_immediate_s16()? as i64;
72 let result = ra.wrapping_add(immediate << 16) as u64;
73 Ok(InstructionOutput {
75 ..InstructionOutput::default()
79 create_instr_variants_ov_cr!(add, addo, add_, addo_, i64);
81 pub fn addo(inputs: InstructionInput) -> InstructionResult {
82 let ra = inputs.try_get_ra()? as i64;
83 let rb = inputs.try_get_rb()? as i64;
84 let (result, ov) = ra.overflowing_add(rb);
85 let result = result as u64;
86 let ov32 = (ra as i32).overflowing_add(rb as i32).1;
87 Ok(InstructionOutput {
89 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
90 ..InstructionOutput::default()
94 create_instr_variants_cr!(addic, addic_, i64);
96 pub fn addic(inputs: InstructionInput) -> InstructionResult {
97 let ra = inputs.try_get_ra()? as i64;
98 let immediate = inputs.try_get_immediate_s16()? as i64;
99 let result = ra.wrapping_add(immediate) as u64;
100 let ca = (ra as u64).overflowing_add(immediate as u64).1;
101 let ca32 = (ra as u32).overflowing_add(immediate as u32).1;
102 Ok(InstructionOutput {
104 carry: Some(CarryFlags { ca, ca32 }),
105 ..InstructionOutput::default()
109 create_instr_variants_ov_cr!(subf, subfo, subf_, subfo_, i64);
111 pub fn subfo(inputs: InstructionInput) -> InstructionResult {
112 let ra = inputs.try_get_ra()? as i64;
113 let rb = inputs.try_get_rb()? as i64;
114 let (result, ov) = rb.overflowing_sub(ra);
115 let result = result as u64;
116 let ov32 = (rb as i32).overflowing_sub(ra as i32).1;
117 Ok(InstructionOutput {
119 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
120 ..InstructionOutput::default()
124 pub fn subfic(inputs: InstructionInput) -> InstructionResult {
125 let ra: u64 = inputs.try_get_ra()?;
126 let immediate: u64 = inputs.try_get_immediate_s16()? as i64 as u64;
128 let result = not_ra.wrapping_add(immediate).wrapping_add(1);
130 .checked_add(immediate)
131 .and_then(|v| v.checked_add(1))
133 let ca32 = (not_ra as u32)
134 .checked_add(immediate as u32)
135 .and_then(|v| v.checked_add(1))
137 Ok(InstructionOutput {
139 carry: Some(CarryFlags { ca, ca32 }),
140 ..InstructionOutput::default()
144 create_instr_variants_ov_cr!(addc, addco, addc_, addco_, i64);
146 pub fn addco(inputs: InstructionInput) -> InstructionResult {
147 let ra = inputs.try_get_ra()? as i64;
148 let rb = inputs.try_get_rb()? as i64;
149 let (result, ov) = ra.overflowing_add(rb);
150 let result = result as u64;
151 let ov32 = (ra as i32).overflowing_add(rb as i32).1;
152 let ca = (ra as u64).overflowing_add(rb as u64).1;
153 let ca32 = (ra as u32).overflowing_add(rb as u32).1;
154 Ok(InstructionOutput {
156 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
157 carry: Some(CarryFlags { ca, ca32 }),
158 ..InstructionOutput::default()
162 create_instr_variants_ov_cr!(subfc, subfco, subfc_, subfco_, i64);
164 pub fn subfco(inputs: InstructionInput) -> InstructionResult {
165 let ra = inputs.try_get_ra()? as i64;
166 let rb = inputs.try_get_rb()? as i64;
167 let (result, ov) = rb.overflowing_sub(ra);
168 let result = result as u64;
169 let ov32 = (rb as i32).overflowing_sub(ra as i32).1;
170 let ca = !(rb as u64).overflowing_sub(ra as u64).1;
171 let ca32 = !(rb as u32).overflowing_sub(ra as u32).1;
172 Ok(InstructionOutput {
174 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
175 carry: Some(CarryFlags { ca, ca32 }),
176 ..InstructionOutput::default()
180 create_instr_variants_ov_cr!(adde, addeo, adde_, addeo_, i64);
182 pub fn addeo(inputs: InstructionInput) -> InstructionResult {
183 let ra: u64 = inputs.try_get_ra()?;
184 let rb: u64 = inputs.try_get_rb()?;
185 let carry_in = inputs.try_get_carry()?.ca;
186 let result_i128 = ra as i64 as i128 + rb as i64 as i128 + carry_in as i128;
187 let result_u128 = ra as u128 + rb as u128 + carry_in as u128;
188 let result32_i128 = ra as i32 as i128 + rb as i32 as i128 + carry_in as i128;
189 let result32_u128 = ra as u32 as u128 + rb as u32 as u128 + carry_in as u128;
190 let result = result_u128 as u64;
191 let ov = i64::try_from(result_i128).is_err();
192 let ov32 = i32::try_from(result32_i128).is_err();
193 let ca = u64::try_from(result_u128).is_err();
194 let ca32 = u32::try_from(result32_u128).is_err();
195 Ok(InstructionOutput {
197 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
198 carry: Some(CarryFlags { ca, ca32 }),
199 ..InstructionOutput::default()
203 create_instr_variants_ov_cr!(subfe, subfeo, subfe_, subfeo_, i64);
205 pub fn subfeo(inputs: InstructionInput) -> InstructionResult {
206 let ra: u64 = inputs.try_get_ra()?;
207 let rb: u64 = inputs.try_get_rb()?;
208 let carry_in = inputs.try_get_carry()?.ca;
210 let result_i128 = not_ra as i64 as i128 + rb as i64 as i128 + carry_in as i128;
211 let result_u128 = not_ra as u128 + rb as u128 + carry_in as u128;
212 let result32_i128 = not_ra as i32 as i128 + rb as i32 as i128 + carry_in as i128;
213 let result32_u128 = not_ra as u32 as u128 + rb as u32 as u128 + carry_in as u128;
214 let result = result_u128 as u64;
215 let ov = i64::try_from(result_i128).is_err();
216 let ov32 = i32::try_from(result32_i128).is_err();
217 let ca = u64::try_from(result_u128).is_err();
218 let ca32 = u32::try_from(result32_u128).is_err();
219 Ok(InstructionOutput {
221 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
222 carry: Some(CarryFlags { ca, ca32 }),
223 ..InstructionOutput::default()
227 create_instr_variants_ov_cr!(addme, addmeo, addme_, addmeo_, i64);
229 pub fn addmeo(inputs: InstructionInput) -> InstructionResult {
230 let ra: u64 = inputs.try_get_ra()?;
232 let carry_in = inputs.try_get_carry()?.ca;
233 let result_i128 = ra as i64 as i128 + rb as i64 as i128 + carry_in as i128;
234 let result_u128 = ra as u128 + rb as u128 + carry_in as u128;
235 let result32_i128 = ra as i32 as i128 + rb as i32 as i128 + carry_in as i128;
236 let result32_u128 = ra as u32 as u128 + rb as u32 as u128 + carry_in as u128;
237 let result = result_u128 as u64;
238 let ov = i64::try_from(result_i128).is_err();
239 let ov32 = i32::try_from(result32_i128).is_err();
240 let ca = u64::try_from(result_u128).is_err();
241 let ca32 = u32::try_from(result32_u128).is_err();
242 Ok(InstructionOutput {
244 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
245 carry: Some(CarryFlags { ca, ca32 }),
246 ..InstructionOutput::default()
250 create_instr_variants_ov_cr!(subfme, subfmeo, subfme_, subfmeo_, i64);
252 pub fn subfmeo(inputs: InstructionInput) -> InstructionResult {
253 let ra: u64 = inputs.try_get_ra()?;
255 let carry_in = inputs.try_get_carry()?.ca;
257 let result_i128 = not_ra as i64 as i128 + rb as i64 as i128 + carry_in as i128;
258 let result_u128 = not_ra as u128 + rb as u128 + carry_in as u128;
259 let result32_i128 = not_ra as i32 as i128 + rb as i32 as i128 + carry_in as i128;
260 let result32_u128 = not_ra as u32 as u128 + rb as u32 as u128 + carry_in as u128;
261 let result = result_u128 as u64;
262 let ov = i64::try_from(result_i128).is_err();
263 let ov32 = i32::try_from(result32_i128).is_err();
264 let ca = u64::try_from(result_u128).is_err();
265 let ca32 = u32::try_from(result32_u128).is_err();
266 Ok(InstructionOutput {
268 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
269 carry: Some(CarryFlags { ca, ca32 }),
270 ..InstructionOutput::default()
274 create_instr_variants_ov_cr!(addze, addzeo, addze_, addzeo_, i64);
276 pub fn addzeo(inputs: InstructionInput) -> InstructionResult {
277 let ra: u64 = inputs.try_get_ra()?;
278 let carry_in = inputs.try_get_carry()?.ca;
279 let result_i128 = ra as i64 as i128 + carry_in as i128;
280 let result_u128 = ra as u128 + carry_in as u128;
281 let result32_i128 = ra as i32 as i128 + carry_in as i128;
282 let result32_u128 = ra as u32 as u128 + carry_in as u128;
283 let result = result_u128 as u64;
284 let ov = i64::try_from(result_i128).is_err();
285 let ov32 = i32::try_from(result32_i128).is_err();
286 let ca = u64::try_from(result_u128).is_err();
287 let ca32 = u32::try_from(result32_u128).is_err();
288 Ok(InstructionOutput {
290 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
291 carry: Some(CarryFlags { ca, ca32 }),
292 ..InstructionOutput::default()
296 create_instr_variants_ov_cr!(subfze, subfzeo, subfze_, subfzeo_, i64);
298 pub fn subfzeo(inputs: InstructionInput) -> InstructionResult {
299 let ra: u64 = inputs.try_get_ra()?;
300 let carry_in = inputs.try_get_carry()?.ca;
302 let result_i128 = not_ra as i64 as i128 + carry_in as i128;
303 let result_u128 = not_ra as u128 + carry_in as u128;
304 let result32_i128 = not_ra as i32 as i128 + carry_in as i128;
305 let result32_u128 = not_ra as u32 as u128 + carry_in as u128;
306 let result = result_u128 as u64;
307 let ov = i64::try_from(result_i128).is_err();
308 let ov32 = i32::try_from(result32_i128).is_err();
309 let ca = u64::try_from(result_u128).is_err();
310 let ca32 = u32::try_from(result32_u128).is_err();
311 Ok(InstructionOutput {
313 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
314 carry: Some(CarryFlags { ca, ca32 }),
315 ..InstructionOutput::default()
319 pub fn addex(inputs: InstructionInput) -> InstructionResult {
320 let ra: u64 = inputs.try_get_ra()?;
321 let rb: u64 = inputs.try_get_rb()?;
324 } = inputs.try_get_overflow()?;
325 let result_u128 = ra as u128 + rb as u128 + carry_in as u128;
326 let result32_u128 = ra as u32 as u128 + rb as u32 as u128 + carry_in as u128;
327 let result = result_u128 as u64;
328 let carry = u64::try_from(result_u128).is_err();
329 let carry32 = u32::try_from(result32_u128).is_err();
330 Ok(InstructionOutput {
332 // doesn't change `so` on purpose
333 overflow: Some(OverflowFlags {
338 ..InstructionOutput::default()
342 create_instr_variants_ov_cr!(neg, nego, neg_, nego_, i64);
344 pub fn nego(inputs: InstructionInput) -> InstructionResult {
345 let ra = inputs.try_get_ra()? as i64;
346 let result = ra.wrapping_neg() as u64;
347 let ov = ra.checked_neg().is_none();
348 let ov32 = (ra as i32).checked_neg().is_none();
349 Ok(InstructionOutput {
351 overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
352 ..InstructionOutput::default()
356 create_instr_variants_ov_cr!(divde, divdeo, divde_, divdeo_, i64);
358 pub fn divdeo(inputs: InstructionInput) -> InstructionResult {
359 let dividend = i128::from(inputs.try_get_ra()? as i64) << 64;
360 let divisor = i128::from(inputs.try_get_rb()? as i64);
363 if divisor == 0 || (divisor == -1 && dividend == i128::min_value()) {
367 let result128 = dividend / divisor;
368 if result128 as i64 as i128 != result128 {
372 result = result128 as u64;
376 Ok(InstructionOutput {
378 overflow: Some(propagate_so(
379 OverflowFlags::from_overflow(overflow),
382 ..InstructionOutput::default()
386 create_instr_variants_ov_cr!(divdeu, divdeuo, divdeu_, divdeuo_, i64);
388 pub fn divdeuo(inputs: InstructionInput) -> InstructionResult {
389 let dividend = u128::from(inputs.try_get_ra()?) << 64;
390 let divisor = u128::from(inputs.try_get_rb()?);
397 let resultu128 = dividend / divisor;
398 if resultu128 > u128::from(u64::max_value()) {
402 result = resultu128 as u64;
406 Ok(InstructionOutput {
408 overflow: Some(propagate_so(
409 OverflowFlags::from_overflow(overflow),
412 ..InstructionOutput::default()
416 create_instr_variants_ov_cr!(divd, divdo, divd_, divdo_, i64);
418 pub fn divdo(inputs: InstructionInput) -> InstructionResult {
419 let dividend = inputs.try_get_ra()? as i64;
420 let divisor = inputs.try_get_rb()? as i64;
423 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
427 result = (dividend / divisor) as u64;
430 Ok(InstructionOutput {
432 overflow: Some(propagate_so(
433 OverflowFlags::from_overflow(overflow),
436 ..InstructionOutput::default()
440 create_instr_variants_ov_cr!(divdu, divduo, divdu_, divduo_, i64);
442 pub fn divduo(inputs: InstructionInput) -> InstructionResult {
443 let dividend: u64 = inputs.try_get_ra()?;
444 let divisor: u64 = inputs.try_get_rb()?;
451 result = dividend / divisor;
454 Ok(InstructionOutput {
456 overflow: Some(propagate_so(
457 OverflowFlags::from_overflow(overflow),
460 ..InstructionOutput::default()
464 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
465 create_instr_variants_ov_cr!(divwe, divweo, divwe_, divweo_, i64);
467 pub fn divweo(inputs: InstructionInput) -> InstructionResult {
468 let dividend = i64::from(inputs.try_get_ra()? as i32) << 32;
469 let divisor = i64::from(inputs.try_get_rb()? as i32);
472 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
476 let result64 = dividend / divisor;
477 if result64 as i32 as i64 != result64 {
481 result = result64 as u32 as u64;
485 Ok(InstructionOutput {
487 overflow: Some(propagate_so(
488 OverflowFlags::from_overflow(overflow),
491 ..InstructionOutput::default()
495 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
496 create_instr_variants_ov_cr!(divweu, divweuo, divweu_, divweuo_, i64);
498 pub fn divweuo(inputs: InstructionInput) -> InstructionResult {
499 let dividend = u64::from(inputs.try_get_ra()? as u32) << 32;
500 let divisor = u64::from(inputs.try_get_rb()? as u32);
507 let resultu64 = dividend / divisor;
508 if resultu64 > u64::from(u32::max_value()) {
512 result = resultu64 as u32 as u64;
516 Ok(InstructionOutput {
518 overflow: Some(propagate_so(
519 OverflowFlags::from_overflow(overflow),
522 ..InstructionOutput::default()
526 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
527 create_instr_variants_ov_cr!(divw, divwo, divw_, divwo_, i64);
529 pub fn divwo(inputs: InstructionInput) -> InstructionResult {
530 let dividend = inputs.try_get_ra()? as i32;
531 let divisor = inputs.try_get_rb()? as i32;
534 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
538 result = (dividend / divisor) as u32 as u64;
541 Ok(InstructionOutput {
543 overflow: Some(propagate_so(
544 OverflowFlags::from_overflow(overflow),
547 ..InstructionOutput::default()
551 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
552 create_instr_variants_ov_cr!(divwu, divwuo, divwu_, divwuo_, i64);
554 pub fn divwuo(inputs: InstructionInput) -> InstructionResult {
555 let dividend = inputs.try_get_ra()? as u32;
556 let divisor = inputs.try_get_rb()? as u32;
563 result = (dividend / divisor) as u64;
566 Ok(InstructionOutput {
568 overflow: Some(propagate_so(
569 OverflowFlags::from_overflow(overflow),
572 ..InstructionOutput::default()
576 pub fn modsd(inputs: InstructionInput) -> InstructionResult {
577 let dividend = inputs.try_get_ra()? as i64;
578 let divisor = inputs.try_get_rb()? as i64;
580 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
583 result = (dividend % divisor) as u64;
585 Ok(InstructionOutput {
587 ..InstructionOutput::default()
591 pub fn modud(inputs: InstructionInput) -> InstructionResult {
592 let dividend: u64 = inputs.try_get_ra()?;
593 let divisor: u64 = inputs.try_get_rb()?;
598 result = dividend % divisor;
600 Ok(InstructionOutput {
602 ..InstructionOutput::default()
606 pub fn modsw(inputs: InstructionInput) -> InstructionResult {
607 let dividend = inputs.try_get_ra()? as i32;
608 let divisor = inputs.try_get_rb()? as i32;
610 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
613 result = (dividend % divisor) as u64;
615 Ok(InstructionOutput {
617 ..InstructionOutput::default()
621 pub fn moduw(inputs: InstructionInput) -> InstructionResult {
622 let dividend = inputs.try_get_ra()? as u32;
623 let divisor = inputs.try_get_rb()? as u32;
628 result = (dividend % divisor) as u64;
630 Ok(InstructionOutput {
632 ..InstructionOutput::default()
636 pub fn mulli(inputs: InstructionInput) -> InstructionResult {
637 let ra = inputs.try_get_ra()? as i64;
638 let immediate = inputs.try_get_immediate_s16()? as i64;
639 let result = ra.wrapping_mul(immediate) as u64;
640 Ok(InstructionOutput {
642 ..InstructionOutput::default()
646 create_instr_variants_ov_cr!(mullw, mullwo, mullw_, mullwo_, i64);
648 pub fn mullwo(inputs: InstructionInput) -> InstructionResult {
649 let ra = inputs.try_get_ra()? as i32 as i64;
650 let rb = inputs.try_get_rb()? as i32 as i64;
651 let result = ra.wrapping_mul(rb) as u64;
652 let overflow = result as i32 as i64 != result as i64;
653 Ok(InstructionOutput {
655 overflow: Some(propagate_so(
656 OverflowFlags::from_overflow(overflow),
659 ..InstructionOutput::default()
663 create_instr_variants_cr!(mulhw, mulhw_, i32);
665 pub fn mulhw(inputs: InstructionInput) -> InstructionResult {
666 let ra = inputs.try_get_ra()? as i32 as i64;
667 let rb = inputs.try_get_rb()? as i32 as i64;
668 let result = (ra * rb) >> 32;
669 let mut result = result as u32 as u64;
670 result |= result << 32;
671 Ok(InstructionOutput {
673 ..InstructionOutput::default()
677 create_instr_variants_cr!(mulhwu, mulhwu_, i32);
679 pub fn mulhwu(inputs: InstructionInput) -> InstructionResult {
680 let ra = inputs.try_get_ra()? as u32 as u64;
681 let rb = inputs.try_get_rb()? as u32 as u64;
682 let result = (ra * rb) >> 32;
683 let mut result = result as u32 as u64;
684 result |= result << 32;
685 Ok(InstructionOutput {
687 ..InstructionOutput::default()
691 create_instr_variants_ov_cr!(mulld, mulldo, mulld_, mulldo_, i64);
693 pub fn mulldo(inputs: InstructionInput) -> InstructionResult {
694 let ra = inputs.try_get_ra()? as i64;
695 let rb = inputs.try_get_rb()? as i64;
696 let result = ra.wrapping_mul(rb) as u64;
697 let overflow = ra.checked_mul(rb).is_none();
698 Ok(InstructionOutput {
700 overflow: Some(propagate_so(
701 OverflowFlags::from_overflow(overflow),
704 ..InstructionOutput::default()
708 create_instr_variants_cr!(mulhd, mulhd_, i64);
710 pub fn mulhd(inputs: InstructionInput) -> InstructionResult {
711 let ra = inputs.try_get_ra()? as i64 as i128;
712 let rb = inputs.try_get_rb()? as i64 as i128;
713 let result = ((ra * rb) >> 64) as i64;
714 let result = result as u64;
715 Ok(InstructionOutput {
717 ..InstructionOutput::default()
721 create_instr_variants_cr!(mulhdu, mulhdu_, i64);
723 pub fn mulhdu(inputs: InstructionInput) -> InstructionResult {
724 let ra = inputs.try_get_ra()? as u128;
725 let rb = inputs.try_get_rb()? as u128;
726 let result = ((ra * rb) >> 64) as u64;
727 Ok(InstructionOutput {
729 ..InstructionOutput::default()
733 pub fn maddhd(inputs: InstructionInput) -> InstructionResult {
734 let ra = inputs.try_get_ra()? as i64 as i128;
735 let rb = inputs.try_get_rb()? as i64 as i128;
736 let rc = inputs.try_get_rc()? as i64 as i128;
737 let result = ((ra * rb + rc) >> 64) as u64;
738 Ok(InstructionOutput {
740 ..InstructionOutput::default()
744 pub fn maddhdu(inputs: InstructionInput) -> InstructionResult {
745 let ra = inputs.try_get_ra()? as u128;
746 let rb = inputs.try_get_rb()? as u128;
747 let rc = inputs.try_get_rc()? as u128;
748 let result = ((ra * rb + rc) >> 64) as u64;
749 Ok(InstructionOutput {
751 ..InstructionOutput::default()
755 pub fn maddld(inputs: InstructionInput) -> InstructionResult {
756 let ra = inputs.try_get_ra()? as i64;
757 let rb = inputs.try_get_rb()? as i64;
758 let rc = inputs.try_get_rc()? as i64;
759 let result = ra.wrapping_mul(rb).wrapping_add(rc) as u64;
760 Ok(InstructionOutput {
762 ..InstructionOutput::default()
766 pub fn cmpdi(inputs: InstructionInput) -> InstructionResult {
767 let ra = inputs.try_get_ra()? as i64;
768 let immediate = inputs.try_get_immediate_s16()? as i64;
769 let so = inputs.try_get_overflow()?.so;
770 let cr0 = ConditionRegister::from_ordering(ra.cmp(&immediate), so);
771 Ok(InstructionOutput {
773 ..InstructionOutput::default()
777 pub fn cmpwi(inputs: InstructionInput) -> InstructionResult {
778 let ra = inputs.try_get_ra()? as i32;
779 let immediate = inputs.try_get_immediate_s16()? as i32;
780 let so = inputs.try_get_overflow()?.so;
781 let cr0 = ConditionRegister::from_ordering(ra.cmp(&immediate), so);
782 Ok(InstructionOutput {
784 ..InstructionOutput::default()
788 pub fn cmpldi(inputs: InstructionInput) -> InstructionResult {
789 let ra = inputs.try_get_ra()? as u64;
790 let immediate = inputs.try_get_immediate_u16()? as u64;
791 let so = inputs.try_get_overflow()?.so;
792 let cr0 = ConditionRegister::from_ordering(ra.cmp(&immediate), so);
793 Ok(InstructionOutput {
795 ..InstructionOutput::default()
799 pub fn cmplwi(inputs: InstructionInput) -> InstructionResult {
800 let ra = inputs.try_get_ra()? as u32;
801 let immediate = inputs.try_get_immediate_u16()? as u32;
802 let so = inputs.try_get_overflow()?.so;
803 let cr0 = ConditionRegister::from_ordering(ra.cmp(&immediate), so);
804 Ok(InstructionOutput {
806 ..InstructionOutput::default()
810 pub fn cmpd(inputs: InstructionInput) -> InstructionResult {
811 let ra = inputs.try_get_ra()? as i64;
812 let rb = inputs.try_get_rb()? as i64;
813 let so = inputs.try_get_overflow()?.so;
814 let cr0 = ConditionRegister::from_ordering(ra.cmp(&rb), so);
815 Ok(InstructionOutput {
817 ..InstructionOutput::default()
821 pub fn cmpw(inputs: InstructionInput) -> InstructionResult {
822 let ra = inputs.try_get_ra()? as i32;
823 let rb = inputs.try_get_rb()? as i32;
824 let so = inputs.try_get_overflow()?.so;
825 let cr0 = ConditionRegister::from_ordering(ra.cmp(&rb), so);
826 Ok(InstructionOutput {
828 ..InstructionOutput::default()
832 pub fn cmpld(inputs: InstructionInput) -> InstructionResult {
833 let ra = inputs.try_get_ra()? as u64;
834 let rb = inputs.try_get_rb()? as u64;
835 let so = inputs.try_get_overflow()?.so;
836 let cr0 = ConditionRegister::from_ordering(ra.cmp(&rb), so);
837 Ok(InstructionOutput {
839 ..InstructionOutput::default()
843 pub fn cmplw(inputs: InstructionInput) -> InstructionResult {
844 let ra = inputs.try_get_ra()? as u32;
845 let rb = inputs.try_get_rb()? as u32;
846 let so = inputs.try_get_overflow()?.so;
847 let cr0 = ConditionRegister::from_ordering(ra.cmp(&rb), so);
848 Ok(InstructionOutput {
850 ..InstructionOutput::default()
854 pub fn cmprb_0(inputs: InstructionInput) -> InstructionResult {
855 let ra = inputs.try_get_ra()? as u8;
856 let rb: u64 = inputs.try_get_rb()?;
857 let eq = ra >= rb as u8 && ra <= (rb >> 8) as u8;
858 let cr0 = ConditionRegister {
864 Ok(InstructionOutput {
866 ..InstructionOutput::default()