2 ConditionRegister, InstructionInput, InstructionOutput, InstructionResult, OverflowFlags,
5 macro_rules! create_instr_variants_ov_cr {
6 ($fn:ident, $fno:ident, $fn_:ident, $fno_:ident, $iwidth:ident) => {
7 pub fn $fn(inputs: InstructionInput) -> InstructionResult {
13 pub fn $fn_(inputs: InstructionInput) -> InstructionResult {
14 let mut retval = $fno_(inputs)?;
15 let mut cr0 = retval.cr0.as_mut().expect("expected cr0 to be set");
17 retval.overflow = None;
20 pub fn $fno_(inputs: InstructionInput) -> InstructionResult {
21 let mut retval = $fno(inputs)?;
22 let result = retval.rt.expect("expected rt to be set");
23 let so = retval.overflow.expect("expected overflow to be set").so;
24 let cr0 = ConditionRegister::from_signed_int(result as $iwidth, so);
25 retval.cr0 = Some(cr0);
31 macro_rules! create_instr_variants_cr {
32 ($fn:ident, $fn_:ident, $iwidth:ident) => {
33 pub fn $fn_(inputs: InstructionInput) -> InstructionResult {
34 let mut retval = $fn(inputs)?;
35 let result = retval.rt.expect("expected rt to be set");
36 let cr0 = ConditionRegister::from_signed_int(result as $iwidth, false);
37 retval.cr0 = Some(cr0);
43 create_instr_variants_ov_cr!(add, addo, add_, addo_, i64);
45 pub fn addo(inputs: InstructionInput) -> InstructionResult {
46 let ra = inputs.try_get_ra()? as i64;
47 let rb = inputs.try_get_rb()? as i64;
48 let (result, ov) = ra.overflowing_add(rb);
49 let result = result as u64;
50 let ov32 = (ra as i32).overflowing_add(rb as i32).1;
51 Ok(InstructionOutput {
53 overflow: Some(OverflowFlags { so: ov, ov, ov32 }),
54 ..InstructionOutput::default()
58 create_instr_variants_ov_cr!(subf, subfo, subf_, subfo_, i64);
60 pub fn subfo(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) = rb.overflowing_sub(ra);
64 let result = result as u64;
65 let ov32 = (rb as i32).overflowing_sub(ra as i32).1;
66 Ok(InstructionOutput {
68 overflow: Some(OverflowFlags { so: ov, ov, ov32 }),
69 ..InstructionOutput::default()
73 create_instr_variants_ov_cr!(divde, divdeo, divde_, divdeo_, i64);
75 pub fn divdeo(inputs: InstructionInput) -> InstructionResult {
76 let dividend = i128::from(inputs.try_get_ra()? as i64) << 64;
77 let divisor = i128::from(inputs.try_get_rb()? as i64);
80 if divisor == 0 || (divisor == -1 && dividend == i128::min_value()) {
84 let result128 = dividend / divisor;
85 if result128 as i64 as i128 != result128 {
89 result = result128 as u64;
93 Ok(InstructionOutput {
95 overflow: Some(OverflowFlags::from_overflow(overflow)),
96 ..InstructionOutput::default()
100 create_instr_variants_ov_cr!(divdeu, divdeuo, divdeu_, divdeuo_, i64);
102 pub fn divdeuo(inputs: InstructionInput) -> InstructionResult {
103 let dividend = u128::from(inputs.try_get_ra()?) << 64;
104 let divisor = u128::from(inputs.try_get_rb()?);
111 let resultu128 = dividend / divisor;
112 if resultu128 > u128::from(u64::max_value()) {
116 result = resultu128 as u64;
120 Ok(InstructionOutput {
122 overflow: Some(OverflowFlags::from_overflow(overflow)),
123 ..InstructionOutput::default()
127 create_instr_variants_ov_cr!(divd, divdo, divd_, divdo_, i64);
129 pub fn divdo(inputs: InstructionInput) -> InstructionResult {
130 let dividend = inputs.try_get_ra()? as i64;
131 let divisor = inputs.try_get_rb()? as i64;
134 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
138 result = (dividend / divisor) as u64;
141 Ok(InstructionOutput {
143 overflow: Some(OverflowFlags::from_overflow(overflow)),
144 ..InstructionOutput::default()
148 create_instr_variants_ov_cr!(divdu, divduo, divdu_, divduo_, i64);
150 pub fn divduo(inputs: InstructionInput) -> InstructionResult {
151 let dividend: u64 = inputs.try_get_ra()?;
152 let divisor: u64 = inputs.try_get_rb()?;
159 result = dividend / divisor;
162 Ok(InstructionOutput {
164 overflow: Some(OverflowFlags::from_overflow(overflow)),
165 ..InstructionOutput::default()
169 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
170 create_instr_variants_ov_cr!(divwe, divweo, divwe_, divweo_, i64);
172 pub fn divweo(inputs: InstructionInput) -> InstructionResult {
173 let dividend = i64::from(inputs.try_get_ra()? as i32) << 32;
174 let divisor = i64::from(inputs.try_get_rb()? as i32);
177 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
181 let result64 = dividend / divisor;
182 if result64 as i32 as i64 != result64 {
186 result = result64 as u32 as u64;
190 Ok(InstructionOutput {
192 overflow: Some(OverflowFlags::from_overflow(overflow)),
193 ..InstructionOutput::default()
197 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
198 create_instr_variants_ov_cr!(divweu, divweuo, divweu_, divweuo_, i64);
200 pub fn divweuo(inputs: InstructionInput) -> InstructionResult {
201 let dividend = u64::from(inputs.try_get_ra()? as u32) << 32;
202 let divisor = u64::from(inputs.try_get_rb()? as u32);
209 let resultu64 = dividend / divisor;
210 if resultu64 > u64::from(u32::max_value()) {
214 result = resultu64 as u32 as u64;
218 Ok(InstructionOutput {
220 overflow: Some(OverflowFlags::from_overflow(overflow)),
221 ..InstructionOutput::default()
225 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
226 create_instr_variants_ov_cr!(divw, divwo, divw_, divwo_, i64);
228 pub fn divwo(inputs: InstructionInput) -> InstructionResult {
229 let dividend = inputs.try_get_ra()? as i32;
230 let divisor = inputs.try_get_rb()? as i32;
233 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
237 result = (dividend / divisor) as u32 as u64;
240 Ok(InstructionOutput {
242 overflow: Some(OverflowFlags::from_overflow(overflow)),
243 ..InstructionOutput::default()
247 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
248 create_instr_variants_ov_cr!(divwu, divwuo, divwu_, divwuo_, i64);
250 pub fn divwuo(inputs: InstructionInput) -> InstructionResult {
251 let dividend = inputs.try_get_ra()? as u32;
252 let divisor = inputs.try_get_rb()? as u32;
259 result = (dividend / divisor) as u64;
262 Ok(InstructionOutput {
264 overflow: Some(OverflowFlags::from_overflow(overflow)),
265 ..InstructionOutput::default()
269 pub fn modsd(inputs: InstructionInput) -> InstructionResult {
270 let dividend = inputs.try_get_ra()? as i64;
271 let divisor = inputs.try_get_rb()? as i64;
273 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
276 result = (dividend % divisor) as u64;
278 Ok(InstructionOutput {
280 ..InstructionOutput::default()
284 pub fn modud(inputs: InstructionInput) -> InstructionResult {
285 let dividend: u64 = inputs.try_get_ra()?;
286 let divisor: u64 = inputs.try_get_rb()?;
291 result = dividend % divisor;
293 Ok(InstructionOutput {
295 ..InstructionOutput::default()
299 pub fn modsw(inputs: InstructionInput) -> InstructionResult {
300 let dividend = inputs.try_get_ra()? as i32;
301 let divisor = inputs.try_get_rb()? as i32;
303 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
306 result = (dividend % divisor) as u64;
308 Ok(InstructionOutput {
310 ..InstructionOutput::default()
314 pub fn moduw(inputs: InstructionInput) -> InstructionResult {
315 let dividend = inputs.try_get_ra()? as u32;
316 let divisor = inputs.try_get_rb()? as u32;
321 result = (dividend % divisor) as u64;
323 Ok(InstructionOutput {
325 ..InstructionOutput::default()
329 create_instr_variants_ov_cr!(mullw, mullwo, mullw_, mullwo_, i64);
331 pub fn mullwo(inputs: InstructionInput) -> InstructionResult {
332 let ra = inputs.try_get_ra()? as i32 as i64;
333 let rb = inputs.try_get_rb()? as i32 as i64;
334 let result = ra.wrapping_mul(rb) as u64;
335 let overflow = result as i32 as i64 != result as i64;
336 Ok(InstructionOutput {
338 overflow: Some(OverflowFlags::from_overflow(overflow)),
339 ..InstructionOutput::default()
343 create_instr_variants_cr!(mulhw, mulhw_, i32);
345 pub fn mulhw(inputs: InstructionInput) -> InstructionResult {
346 let ra = inputs.try_get_ra()? as i32 as i64;
347 let rb = inputs.try_get_rb()? as i32 as i64;
348 let result = (ra * rb) >> 32;
349 let mut result = result as u32 as u64;
350 result |= result << 32;
351 Ok(InstructionOutput {
353 ..InstructionOutput::default()
357 create_instr_variants_cr!(mulhwu, mulhwu_, i32);
359 pub fn mulhwu(inputs: InstructionInput) -> InstructionResult {
360 let ra = inputs.try_get_ra()? as u32 as u64;
361 let rb = inputs.try_get_rb()? as u32 as u64;
362 let result = (ra * rb) >> 32;
363 let mut result = result as u32 as u64;
364 result |= result << 32;
365 Ok(InstructionOutput {
367 ..InstructionOutput::default()
371 create_instr_variants_ov_cr!(mulld, mulldo, mulld_, mulldo_, i64);
373 pub fn mulldo(inputs: InstructionInput) -> InstructionResult {
374 let ra = inputs.try_get_ra()? as i64;
375 let rb = inputs.try_get_rb()? as i64;
376 let result = ra.wrapping_mul(rb) as u64;
377 let overflow = ra.checked_mul(rb).is_none();
378 Ok(InstructionOutput {
380 overflow: Some(OverflowFlags::from_overflow(overflow)),
381 ..InstructionOutput::default()
385 create_instr_variants_cr!(mulhd, mulhd_, i64);
387 pub fn mulhd(inputs: InstructionInput) -> InstructionResult {
388 let ra = inputs.try_get_ra()? as i64 as i128;
389 let rb = inputs.try_get_rb()? as i64 as i128;
390 let result = ((ra * rb) >> 64) as i64;
391 let result = result as u64;
392 Ok(InstructionOutput {
394 ..InstructionOutput::default()
398 create_instr_variants_cr!(mulhdu, mulhdu_, i64);
400 pub fn mulhdu(inputs: InstructionInput) -> InstructionResult {
401 let ra = inputs.try_get_ra()? as u128;
402 let rb = inputs.try_get_rb()? as u128;
403 let result = ((ra * rb) >> 64) as u64;
404 Ok(InstructionOutput {
406 ..InstructionOutput::default()
410 pub fn maddhd(inputs: InstructionInput) -> InstructionResult {
411 let ra = inputs.try_get_ra()? as i64 as i128;
412 let rb = inputs.try_get_rb()? as i64 as i128;
413 let rc = inputs.try_get_rc()? as i64 as i128;
414 let result = ((ra * rb + rc) >> 64) as u64;
415 Ok(InstructionOutput {
417 ..InstructionOutput::default()
421 pub fn maddhdu(inputs: InstructionInput) -> InstructionResult {
422 let ra = inputs.try_get_ra()? as u128;
423 let rb = inputs.try_get_rb()? as u128;
424 let rc = inputs.try_get_rc()? as u128;
425 let result = ((ra * rb + rc) >> 64) as u64;
426 Ok(InstructionOutput {
428 ..InstructionOutput::default()
432 pub fn maddld(inputs: InstructionInput) -> InstructionResult {
433 let ra = inputs.try_get_ra()? as i64;
434 let rb = inputs.try_get_rb()? as i64;
435 let rc = inputs.try_get_rc()? as i64;
436 let result = ra.wrapping_mul(rb).wrapping_add(rc) as u64;
437 Ok(InstructionOutput {
439 ..InstructionOutput::default()