add addme*, subfme*, addze*, and subfze*
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 4 Sep 2020 00:17:06 +0000 (17:17 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Fri, 4 Sep 2020 00:17:06 +0000 (17:17 -0700)
src/instr_models.rs
src/lib.rs

index aa025c1c7307f3ee5820123a90bdea429443510e..059f1ce2195ab31c6f204cd71bb0c0dbe1a927b3 100644 (file)
@@ -148,8 +148,55 @@ pub fn addeo(inputs: InstructionInput) -> InstructionResult {
 create_instr_variants_ov_cr!(subfe, subfeo, subfe_, subfeo_, i64);
 
 pub fn subfeo(inputs: InstructionInput) -> InstructionResult {
-    let ra = inputs.try_get_ra()?;
-    let rb = inputs.try_get_rb()?;
+    let ra: u64 = inputs.try_get_ra()?;
+    let rb: u64 = inputs.try_get_rb()?;
+    let carry_in = inputs.try_get_carry()?.ca;
+    let not_ra = !ra;
+    let result_i128 = not_ra as i64 as i128 + rb as i64 as i128 + carry_in as i128;
+    let result_u128 = not_ra as u128 + rb as u128 + carry_in as u128;
+    let result32_i128 = not_ra as i32 as i128 + rb as i32 as i128 + carry_in as i128;
+    let result32_u128 = not_ra as u32 as u128 + rb as u32 as u128 + carry_in as u128;
+    let result = result_u128 as u64;
+    let ov = i64::try_from(result_i128).is_err();
+    let ov32 = i32::try_from(result32_i128).is_err();
+    let ca = u64::try_from(result_u128).is_err();
+    let ca32 = u32::try_from(result32_u128).is_err();
+    Ok(InstructionOutput {
+        rt: Some(result),
+        overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
+        carry: Some(CarryFlags { ca, ca32 }),
+        ..InstructionOutput::default()
+    })
+}
+
+create_instr_variants_ov_cr!(addme, addmeo, addme_, addmeo_, i64);
+
+pub fn addmeo(inputs: InstructionInput) -> InstructionResult {
+    let ra: u64 = inputs.try_get_ra()?;
+    let rb: u64 = !0;
+    let carry_in = inputs.try_get_carry()?.ca;
+    let result_i128 = ra as i64 as i128 + rb as i64 as i128 + carry_in as i128;
+    let result_u128 = ra as u128 + rb as u128 + carry_in as u128;
+    let result32_i128 = ra as i32 as i128 + rb as i32 as i128 + carry_in as i128;
+    let result32_u128 = ra as u32 as u128 + rb as u32 as u128 + carry_in as u128;
+    let result = result_u128 as u64;
+    let ov = i64::try_from(result_i128).is_err();
+    let ov32 = i32::try_from(result32_i128).is_err();
+    let ca = u64::try_from(result_u128).is_err();
+    let ca32 = u32::try_from(result32_u128).is_err();
+    Ok(InstructionOutput {
+        rt: Some(result),
+        overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
+        carry: Some(CarryFlags { ca, ca32 }),
+        ..InstructionOutput::default()
+    })
+}
+
+create_instr_variants_ov_cr!(subfme, subfmeo, subfme_, subfmeo_, i64);
+
+pub fn subfmeo(inputs: InstructionInput) -> InstructionResult {
+    let ra: u64 = inputs.try_get_ra()?;
+    let rb: u64 = !0;
     let carry_in = inputs.try_get_carry()?.ca;
     let not_ra = !ra;
     let result_i128 = not_ra as i64 as i128 + rb as i64 as i128 + carry_in as i128;
@@ -169,6 +216,51 @@ pub fn subfeo(inputs: InstructionInput) -> InstructionResult {
     })
 }
 
+create_instr_variants_ov_cr!(addze, addzeo, addze_, addzeo_, i64);
+
+pub fn addzeo(inputs: InstructionInput) -> InstructionResult {
+    let ra: u64 = inputs.try_get_ra()?;
+    let carry_in = inputs.try_get_carry()?.ca;
+    let result_i128 = ra as i64 as i128 + carry_in as i128;
+    let result_u128 = ra as u128 + carry_in as u128;
+    let result32_i128 = ra as i32 as i128 + carry_in as i128;
+    let result32_u128 = ra as u32 as u128 + carry_in as u128;
+    let result = result_u128 as u64;
+    let ov = i64::try_from(result_i128).is_err();
+    let ov32 = i32::try_from(result32_i128).is_err();
+    let ca = u64::try_from(result_u128).is_err();
+    let ca32 = u32::try_from(result32_u128).is_err();
+    Ok(InstructionOutput {
+        rt: Some(result),
+        overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
+        carry: Some(CarryFlags { ca, ca32 }),
+        ..InstructionOutput::default()
+    })
+}
+
+create_instr_variants_ov_cr!(subfze, subfzeo, subfze_, subfzeo_, i64);
+
+pub fn subfzeo(inputs: InstructionInput) -> InstructionResult {
+    let ra: u64 = inputs.try_get_ra()?;
+    let carry_in = inputs.try_get_carry()?.ca;
+    let not_ra = !ra;
+    let result_i128 = not_ra as i64 as i128 + carry_in as i128;
+    let result_u128 = not_ra as u128 + carry_in as u128;
+    let result32_i128 = not_ra as i32 as i128 + carry_in as i128;
+    let result32_u128 = not_ra as u32 as u128 + carry_in as u128;
+    let result = result_u128 as u64;
+    let ov = i64::try_from(result_i128).is_err();
+    let ov32 = i32::try_from(result32_i128).is_err();
+    let ca = u64::try_from(result_u128).is_err();
+    let ca32 = u32::try_from(result32_u128).is_err();
+    Ok(InstructionOutput {
+        rt: Some(result),
+        overflow: Some(propagate_so(OverflowFlags { so: ov, ov, ov32 }, inputs)?),
+        carry: Some(CarryFlags { ca, ca32 }),
+        ..InstructionOutput::default()
+    })
+}
+
 create_instr_variants_ov_cr!(divde, divdeo, divde_, divdeo_, i64);
 
 pub fn divdeo(inputs: InstructionInput) -> InstructionResult {
index 4c205d0072beaf6c212bc2ff4562a4bb8c9f03e7..3c7c9bd149632475f83aefc6dc05bb2fed6bb152 100644 (file)
@@ -387,6 +387,78 @@ instructions! {
         "subfeo."
     }
 
+    // addme
+    #[enumerant = AddME]
+    fn addme(Ra, Carry) -> (Rt, Carry) {
+        "addme"
+    }
+    #[enumerant = AddMEO]
+    fn addmeo(Ra, Overflow, Carry) -> (Rt, Carry, Overflow) {
+        "addmeo"
+    }
+    #[enumerant = AddME_]
+    fn addme_(Ra, Overflow, Carry) -> (Rt, Carry, CR0) {
+        "addme."
+    }
+    #[enumerant = AddMEO_]
+    fn addmeo_(Ra, Overflow, Carry) -> (Rt, Carry, Overflow, CR0) {
+        "addmeo."
+    }
+
+    // subfme
+    #[enumerant = SubFME]
+    fn subfme(Ra, Carry) -> (Rt, Carry) {
+        "subfme"
+    }
+    #[enumerant = SubFMEO]
+    fn subfmeo(Ra, Overflow, Carry) -> (Rt, Carry, Overflow) {
+        "subfmeo"
+    }
+    #[enumerant = SubFME_]
+    fn subfme_(Ra, Overflow, Carry) -> (Rt, Carry, CR0) {
+        "subfme."
+    }
+    #[enumerant = SubFMEO_]
+    fn subfmeo_(Ra, Overflow, Carry) -> (Rt, Carry, Overflow, CR0) {
+        "subfmeo."
+    }
+
+    // addze
+    #[enumerant = AddZE]
+    fn addze(Ra, Carry) -> (Rt, Carry) {
+        "addze"
+    }
+    #[enumerant = AddZEO]
+    fn addzeo(Ra, Overflow, Carry) -> (Rt, Carry, Overflow) {
+        "addzeo"
+    }
+    #[enumerant = AddZE_]
+    fn addze_(Ra, Overflow, Carry) -> (Rt, Carry, CR0) {
+        "addze."
+    }
+    #[enumerant = AddZEO_]
+    fn addzeo_(Ra, Overflow, Carry) -> (Rt, Carry, Overflow, CR0) {
+        "addzeo."
+    }
+
+    // subfze
+    #[enumerant = SubFZE]
+    fn subfze(Ra, Carry) -> (Rt, Carry) {
+        "subfze"
+    }
+    #[enumerant = SubFZEO]
+    fn subfzeo(Ra, Overflow, Carry) -> (Rt, Carry, Overflow) {
+        "subfzeo"
+    }
+    #[enumerant = SubFZE_]
+    fn subfze_(Ra, Overflow, Carry) -> (Rt, Carry, CR0) {
+        "subfze."
+    }
+    #[enumerant = SubFZEO_]
+    fn subfzeo_(Ra, Overflow, Carry) -> (Rt, Carry, Overflow, CR0) {
+        "subfzeo."
+    }
+
     // divde
     #[enumerant = DivDE]
     fn divde(Ra, Rb) -> (Rt) {