use crate::{ConditionRegister, InstructionInput, InstructionResult, OverflowFlags};
-macro_rules! create_instr_variants {
+macro_rules! create_instr_variants_ov_cr {
($fn:ident, $fno:ident, $fn_:ident, $fno_:ident, $iwidth:ident) => {
pub fn $fn(inputs: InstructionInput) -> InstructionResult {
InstructionResult {
};
}
-create_instr_variants!(divde, divdeo, divde_, divdeo_, i64);
+macro_rules! create_instr_variants_cr {
+ ($fn:ident, $fn_:ident, $iwidth:ident) => {
+ pub fn $fn_(inputs: InstructionInput) -> InstructionResult {
+ let mut retval = $fn(inputs);
+ let result = retval.rt.expect("expected rt to be set");
+ let cr0 = ConditionRegister::from_signed_int(result as $iwidth, false);
+ retval.cr0 = Some(cr0);
+ retval
+ }
+ };
+}
+
+create_instr_variants_ov_cr!(divde, divdeo, divde_, divdeo_, i64);
pub fn divdeo(inputs: InstructionInput) -> InstructionResult {
let dividend = i128::from(inputs.ra as i64) << 64;
}
}
-create_instr_variants!(divdeu, divdeuo, divdeu_, divdeuo_, i64);
+create_instr_variants_ov_cr!(divdeu, divdeuo, divdeu_, divdeuo_, i64);
pub fn divdeuo(inputs: InstructionInput) -> InstructionResult {
let dividend = u128::from(inputs.ra) << 64;
}
}
-create_instr_variants!(divd, divdo, divd_, divdo_, i64);
+create_instr_variants_ov_cr!(divd, divdo, divd_, divdo_, i64);
pub fn divdo(inputs: InstructionInput) -> InstructionResult {
let dividend = inputs.ra as i64;
}
}
-create_instr_variants!(divdu, divduo, divdu_, divduo_, i64);
+create_instr_variants_ov_cr!(divdu, divduo, divdu_, divduo_, i64);
pub fn divduo(inputs: InstructionInput) -> InstructionResult {
let dividend: u64 = inputs.ra;
}
}
-create_instr_variants!(divwe, divweo, divwe_, divweo_, i32);
+create_instr_variants_ov_cr!(divwe, divweo, divwe_, divweo_, i32);
pub fn divweo(inputs: InstructionInput) -> InstructionResult {
let dividend = i64::from(inputs.ra as i32) << 32;
}
}
-create_instr_variants!(divweu, divweuo, divweu_, divweuo_, i32);
+create_instr_variants_ov_cr!(divweu, divweuo, divweu_, divweuo_, i32);
pub fn divweuo(inputs: InstructionInput) -> InstructionResult {
let dividend = u64::from(inputs.ra as u32) << 32;
}
}
-create_instr_variants!(divw, divwo, divw_, divwo_, i32);
+create_instr_variants_ov_cr!(divw, divwo, divw_, divwo_, i32);
pub fn divwo(inputs: InstructionInput) -> InstructionResult {
let dividend = inputs.ra as i32;
}
}
-create_instr_variants!(divwu, divwuo, divwu_, divwuo_, i32);
+create_instr_variants_ov_cr!(divwu, divwuo, divwu_, divwuo_, i32);
pub fn divwuo(inputs: InstructionInput) -> InstructionResult {
let dividend = inputs.ra as u32;
..InstructionResult::default()
}
}
+
+create_instr_variants_ov_cr!(mullw, mullwo, mullw_, mullwo_, i32);
+
+pub fn mullwo(inputs: InstructionInput) -> InstructionResult {
+ let ra = inputs.ra as i32;
+ let rb = inputs.rb as i32;
+ let result = ra.wrapping_mul(rb) as u64;
+ let overflow = ra.checked_mul(rb).is_none();
+ InstructionResult {
+ rt: Some(result),
+ overflow: Some(OverflowFlags::from_overflow(overflow)),
+ ..InstructionResult::default()
+ }
+}
+
+create_instr_variants_cr!(mulhw, mulhw_, i32);
+
+pub fn mulhw(inputs: InstructionInput) -> InstructionResult {
+ let ra = inputs.ra as i32 as i64;
+ let rb = inputs.rb as i32 as i64;
+ let result = ((ra * rb) >> 32) as i32;
+ let result = result as u64;
+ InstructionResult {
+ rt: Some(result),
+ ..InstructionResult::default()
+ }
+}
+
+create_instr_variants_cr!(mulhwu, mulhwu_, i32);
+
+pub fn mulhwu(inputs: InstructionInput) -> InstructionResult {
+ let ra = inputs.ra as u32 as u64;
+ let rb = inputs.rb as u32 as u64;
+ let result = ((ra * rb) >> 32) as u32;
+ let result = result as u64;
+ InstructionResult {
+ rt: Some(result),
+ ..InstructionResult::default()
+ }
+}
+
+create_instr_variants_ov_cr!(mulld, mulldo, mulld_, mulldo_, i64);
+
+pub fn mulldo(inputs: InstructionInput) -> InstructionResult {
+ let ra = inputs.ra as i64;
+ let rb = inputs.rb as i64;
+ let result = ra.wrapping_mul(rb) as u64;
+ let overflow = ra.checked_mul(rb).is_none();
+ InstructionResult {
+ rt: Some(result),
+ overflow: Some(OverflowFlags::from_overflow(overflow)),
+ ..InstructionResult::default()
+ }
+}
+
+create_instr_variants_cr!(mulhd, mulhd_, i64);
+
+pub fn mulhd(inputs: InstructionInput) -> InstructionResult {
+ let ra = inputs.ra as i64 as i128;
+ let rb = inputs.rb as i64 as i128;
+ let result = ((ra * rb) >> 64) as i64;
+ let result = result as u64;
+ InstructionResult {
+ rt: Some(result),
+ ..InstructionResult::default()
+ }
+}
+
+create_instr_variants_cr!(mulhdu, mulhdu_, i64);
+
+pub fn mulhdu(inputs: InstructionInput) -> InstructionResult {
+ let ra = inputs.ra as u128;
+ let rb = inputs.rb as u128;
+ let result = ((ra * rb) >> 64) as u64;
+ InstructionResult {
+ rt: Some(result),
+ ..InstructionResult::default()
+ }
+}
+
+pub fn maddhd(inputs: InstructionInput) -> InstructionResult {
+ let ra = inputs.ra as i64 as i128;
+ let rb = inputs.rb as i64 as i128;
+ let rc = inputs.rc as i64 as i128;
+ let result = ((ra * rb + rc) >> 64) as u64;
+ InstructionResult {
+ rt: Some(result),
+ ..InstructionResult::default()
+ }
+}
+
+pub fn maddhdu(inputs: InstructionInput) -> InstructionResult {
+ let ra = inputs.ra as u128;
+ let rb = inputs.rb as u128;
+ let rc = inputs.rc as u128;
+ let result = ((ra * rb + rc) >> 64) as u64;
+ InstructionResult {
+ rt: Some(result),
+ ..InstructionResult::default()
+ }
+}
+
+pub fn maddld(inputs: InstructionInput) -> InstructionResult {
+ let ra = inputs.ra as i64;
+ let rb = inputs.rb as i64;
+ let rc = inputs.rc as i64;
+ let result = ra.wrapping_mul(rb).wrapping_add(rc) as u64;
+ InstructionResult {
+ rt: Some(result),
+ ..InstructionResult::default()
+ }
+}
fn moduw(ra, rb) -> (rt) {
"moduw"
}
+
+ // mullw
+ #[enumerant = MulLW]
+ fn mullw(ra, rb) -> (rt) {
+ "mullw"
+ }
+ #[enumerant = MulLWO]
+ fn mullwo(ra, rb) -> (rt, ov) {
+ "mullwo"
+ }
+ #[enumerant = MulLW_]
+ fn mullw_(ra, rb) -> (rt, cr0) {
+ "mullw."
+ }
+ #[enumerant = MulLWO_]
+ fn mullwo_(ra, rb) -> (rt, ov, cr0) {
+ "mullwo."
+ }
+
+ // mulhw
+ #[enumerant = MulHW]
+ fn mulhw(ra, rb) -> (rt) {
+ "mulhw"
+ }
+ #[enumerant = MulHW_]
+ fn mulhw_(ra, rb) -> (rt, cr0) {
+ "mulhw."
+ }
+
+ // mulhwu
+ #[enumerant = MulHWU]
+ fn mulhwu(ra, rb) -> (rt) {
+ "mulhwu"
+ }
+ #[enumerant = MulHWU_]
+ fn mulhwu_(ra, rb) -> (rt, cr0) {
+ "mulhwu."
+ }
+
+ // mulld
+ #[enumerant = MulLD]
+ fn mulld(ra, rb) -> (rt) {
+ "mulld"
+ }
+ #[enumerant = MulLDO]
+ fn mulldo(ra, rb) -> (rt, ov) {
+ "mulldo"
+ }
+ #[enumerant = MulLD_]
+ fn mulld_(ra, rb) -> (rt, cr0) {
+ "mulld."
+ }
+ #[enumerant = MulLDO_]
+ fn mulldo_(ra, rb) -> (rt, ov, cr0) {
+ "mulldo."
+ }
+
+ // mulhd
+ #[enumerant = MulHD]
+ fn mulhd(ra, rb) -> (rt) {
+ "mulhd"
+ }
+ #[enumerant = MulHD_]
+ fn mulhd_(ra, rb) -> (rt, cr0) {
+ "mulhd."
+ }
+
+ // mulhdu
+ #[enumerant = MulHDU]
+ fn mulhdu(ra, rb) -> (rt) {
+ "mulhdu"
+ }
+ #[enumerant = MulHDU_]
+ fn mulhdu_(ra, rb) -> (rt, cr0) {
+ "mulhdu."
+ }
+
+ // madd*
+ #[enumerant = MAddHD]
+ fn maddhd(ra, rb, rc) -> (rt) {
+ "maddhd"
+ }
+ #[enumerant = MAddHDU]
+ fn maddhdu(ra, rb, rc) -> (rt) {
+ "maddhdu"
+ }
+ #[enumerant = MAddLD]
+ fn maddld(ra, rb, rc) -> (rt) {
+ "maddld"
+ }
}
// must be after instrs macro call since it uses a macro definition