add adde* and subfe*
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 3 Sep 2020 23:43:45 +0000 (16:43 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 3 Sep 2020 23:43:45 +0000 (16:43 -0700)
src/instr_models.rs
src/lib.rs

index d140ea5d213587f13fec60af7cda7329fed7ceca..aa025c1c7307f3ee5820123a90bdea429443510e 100644 (file)
@@ -2,6 +2,7 @@ use crate::{
     CarryFlags, ConditionRegister, InstructionInput, InstructionOutput, InstructionResult,
     MissingInstructionInput, OverflowFlags,
 };
+use std::convert::TryFrom;
 
 fn propagate_so(
     mut overflow: OverflowFlags,
@@ -121,6 +122,53 @@ pub fn subfco(inputs: InstructionInput) -> InstructionResult {
     })
 }
 
+create_instr_variants_ov_cr!(adde, addeo, adde_, addeo_, i64);
+
+pub fn addeo(inputs: InstructionInput) -> InstructionResult {
+    let ra: u64 = inputs.try_get_ra()?;
+    let rb: u64 = inputs.try_get_rb()?;
+    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!(subfe, subfeo, subfe_, subfeo_, i64);
+
+pub fn subfeo(inputs: InstructionInput) -> InstructionResult {
+    let ra = inputs.try_get_ra()?;
+    let rb = 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!(divde, divdeo, divde_, divdeo_, i64);
 
 pub fn divdeo(inputs: InstructionInput) -> InstructionResult {
index 085d6c06d77b811837720bdb994ee2eed9b7ac25..4c205d0072beaf6c212bc2ff4562a4bb8c9f03e7 100644 (file)
@@ -351,6 +351,42 @@ instructions! {
         "subfco."
     }
 
+    // adde
+    #[enumerant = AddE]
+    fn adde(Ra, Rb, Carry) -> (Rt, Carry) {
+        "adde"
+    }
+    #[enumerant = AddEO]
+    fn addeo(Ra, Rb, Overflow, Carry) -> (Rt, Carry, Overflow) {
+        "addeo"
+    }
+    #[enumerant = AddE_]
+    fn adde_(Ra, Rb, Overflow, Carry) -> (Rt, Carry, CR0) {
+        "adde."
+    }
+    #[enumerant = AddEO_]
+    fn addeo_(Ra, Rb, Overflow, Carry) -> (Rt, Carry, Overflow, CR0) {
+        "addeo."
+    }
+
+    // subfe
+    #[enumerant = SubFE]
+    fn subfe(Ra, Rb, Carry) -> (Rt, Carry) {
+        "subfe"
+    }
+    #[enumerant = SubFEO]
+    fn subfeo(Ra, Rb, Overflow, Carry) -> (Rt, Carry, Overflow) {
+        "subfeo"
+    }
+    #[enumerant = SubFE_]
+    fn subfe_(Ra, Rb, Overflow, Carry) -> (Rt, Carry, CR0) {
+        "subfe."
+    }
+    #[enumerant = SubFEO_]
+    fn subfeo_(Ra, Rb, Overflow, Carry) -> (Rt, Carry, Overflow, CR0) {
+        "subfeo."
+    }
+
     // divde
     #[enumerant = DivDE]
     fn divde(Ra, Rb) -> (Rt) {