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 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
138 create_instr_variants_ov_cr!(divwe, divweo, divwe_, divweo_, i64);
140 pub fn divweo(inputs: InstructionInput) -> InstructionResult {
141 let dividend = i64::from(inputs.ra as i32) << 32;
142 let divisor = i64::from(inputs.rb as i32);
145 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
149 let result64 = dividend / divisor;
150 if result64 as i32 as i64 != result64 {
154 result = result64 as u32 as u64;
160 overflow: Some(OverflowFlags::from_overflow(overflow)),
161 ..InstructionResult::default()
165 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
166 create_instr_variants_ov_cr!(divweu, divweuo, divweu_, divweuo_, i64);
168 pub fn divweuo(inputs: InstructionInput) -> InstructionResult {
169 let dividend = u64::from(inputs.ra as u32) << 32;
170 let divisor = u64::from(inputs.rb as u32);
177 let resultu64 = dividend / divisor;
178 if resultu64 > u64::from(u32::max_value()) {
182 result = resultu64 as u32 as u64;
188 overflow: Some(OverflowFlags::from_overflow(overflow)),
189 ..InstructionResult::default()
193 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
194 create_instr_variants_ov_cr!(divw, divwo, divw_, divwo_, i64);
196 pub fn divwo(inputs: InstructionInput) -> InstructionResult {
197 let dividend = inputs.ra as i32;
198 let divisor = inputs.rb as i32;
201 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
205 result = (dividend / divisor) as u32 as u64;
210 overflow: Some(OverflowFlags::from_overflow(overflow)),
211 ..InstructionResult::default()
215 // ISA doesn't define compare results -- POWER9 apparently uses i64 instead of i32
216 create_instr_variants_ov_cr!(divwu, divwuo, divwu_, divwuo_, i64);
218 pub fn divwuo(inputs: InstructionInput) -> InstructionResult {
219 let dividend = inputs.ra as u32;
220 let divisor = inputs.rb as u32;
227 result = (dividend / divisor) as u64;
232 overflow: Some(OverflowFlags::from_overflow(overflow)),
233 ..InstructionResult::default()
237 pub fn modsd(inputs: InstructionInput) -> InstructionResult {
238 let dividend = inputs.ra as i64;
239 let divisor = inputs.rb as i64;
241 if divisor == 0 || (divisor == -1 && dividend == i64::min_value()) {
244 result = (dividend % divisor) as u64;
248 ..InstructionResult::default()
252 pub fn modud(inputs: InstructionInput) -> InstructionResult {
253 let dividend: u64 = inputs.ra;
254 let divisor: u64 = inputs.rb;
259 result = dividend % divisor;
263 ..InstructionResult::default()
267 pub fn modsw(inputs: InstructionInput) -> InstructionResult {
268 let dividend = inputs.ra as i32;
269 let divisor = inputs.rb as i32;
271 if divisor == 0 || (divisor == -1 && dividend == i32::min_value()) {
274 result = (dividend % divisor) as u64;
278 ..InstructionResult::default()
282 pub fn moduw(inputs: InstructionInput) -> InstructionResult {
283 let dividend = inputs.ra as u32;
284 let divisor = inputs.rb as u32;
289 result = (dividend % divisor) as u64;
293 ..InstructionResult::default()
297 create_instr_variants_ov_cr!(mullw, mullwo, mullw_, mullwo_, i32);
299 pub fn mullwo(inputs: InstructionInput) -> InstructionResult {
300 let ra = inputs.ra as i32 as i64;
301 let rb = inputs.rb as i32 as i64;
302 let result = ra.wrapping_mul(rb) as u64;
303 let overflow = result as i32 as i64 != result as i64;
306 overflow: Some(OverflowFlags::from_overflow(overflow)),
307 ..InstructionResult::default()
311 create_instr_variants_cr!(mulhw, mulhw_, i32);
313 pub fn mulhw(inputs: InstructionInput) -> InstructionResult {
314 let ra = inputs.ra as i32 as i64;
315 let rb = inputs.rb as i32 as i64;
316 let result = ((ra * rb) >> 32) as i32;
317 let result = result as u64;
320 ..InstructionResult::default()
324 create_instr_variants_cr!(mulhwu, mulhwu_, i32);
326 pub fn mulhwu(inputs: InstructionInput) -> InstructionResult {
327 let ra = inputs.ra as u32 as u64;
328 let rb = inputs.rb as u32 as u64;
329 let result = ((ra * rb) >> 32) as u32;
330 let result = result as u64;
333 ..InstructionResult::default()
337 create_instr_variants_ov_cr!(mulld, mulldo, mulld_, mulldo_, i64);
339 pub fn mulldo(inputs: InstructionInput) -> InstructionResult {
340 let ra = inputs.ra as i64;
341 let rb = inputs.rb as i64;
342 let result = ra.wrapping_mul(rb) as u64;
343 let overflow = ra.checked_mul(rb).is_none();
346 overflow: Some(OverflowFlags::from_overflow(overflow)),
347 ..InstructionResult::default()
351 create_instr_variants_cr!(mulhd, mulhd_, i64);
353 pub fn mulhd(inputs: InstructionInput) -> InstructionResult {
354 let ra = inputs.ra as i64 as i128;
355 let rb = inputs.rb as i64 as i128;
356 let result = ((ra * rb) >> 64) as i64;
357 let result = result as u64;
360 ..InstructionResult::default()
364 create_instr_variants_cr!(mulhdu, mulhdu_, i64);
366 pub fn mulhdu(inputs: InstructionInput) -> InstructionResult {
367 let ra = inputs.ra as u128;
368 let rb = inputs.rb as u128;
369 let result = ((ra * rb) >> 64) as u64;
372 ..InstructionResult::default()
376 pub fn maddhd(inputs: InstructionInput) -> InstructionResult {
377 let ra = inputs.ra as i64 as i128;
378 let rb = inputs.rb as i64 as i128;
379 let rc = inputs.rc as i64 as i128;
380 let result = ((ra * rb + rc) >> 64) as u64;
383 ..InstructionResult::default()
387 pub fn maddhdu(inputs: InstructionInput) -> InstructionResult {
388 let ra = inputs.ra as u128;
389 let rb = inputs.rb as u128;
390 let rc = inputs.rc as u128;
391 let result = ((ra * rb + rc) >> 64) as u64;
394 ..InstructionResult::default()
398 pub fn maddld(inputs: InstructionInput) -> InstructionResult {
399 let ra = inputs.ra as i64;
400 let rb = inputs.rb as i64;
401 let rc = inputs.rc as i64;
402 let result = ra.wrapping_mul(rb).wrapping_add(rc) as u64;
405 ..InstructionResult::default()