add addc* and subfc* instructions
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 3 Sep 2020 23:18:34 +0000 (16:18 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 3 Sep 2020 23:18:34 +0000 (16:18 -0700)
src/instr_models.rs
src/lib.rs

index 1b56cad3c21172757dae91496cf2ff1afa9c3b34..e56e4fb1ffd117ce4c77405dee867c38af5dabd5 100644 (file)
@@ -1,5 +1,5 @@
 use crate::{
-    ConditionRegister, InstructionInput, InstructionOutput, InstructionResult,
+    CarryFlags, ConditionRegister, InstructionInput, InstructionOutput, InstructionResult,
     MissingInstructionInput, OverflowFlags,
 };
 
@@ -85,6 +85,42 @@ pub fn subfo(inputs: InstructionInput) -> InstructionResult {
     })
 }
 
+create_instr_variants_ov_cr!(addc, addco, addc_, addco_, i64);
+
+pub fn addco(inputs: InstructionInput) -> InstructionResult {
+    let ra = inputs.try_get_ra()? as i64;
+    let rb = inputs.try_get_rb()? as i64;
+    let (result, ov) = ra.overflowing_add(rb);
+    let result = result as u64;
+    let ov32 = (ra as i32).overflowing_add(rb as i32).1;
+    let ca = (ra as u64).overflowing_add(rb as u64).1;
+    let ca32 = (ra as u32).overflowing_add(rb as u32).1;
+    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!(subfc, subfco, subfc_, subfco_, i64);
+
+pub fn subfco(inputs: InstructionInput) -> InstructionResult {
+    let ra = inputs.try_get_ra()? as i64;
+    let rb = inputs.try_get_rb()? as i64;
+    let (result, ov) = rb.overflowing_sub(ra);
+    let result = result as u64;
+    let ov32 = (rb as i32).overflowing_sub(ra as i32).1;
+    let ca = (rb as u64).overflowing_sub(ra as u64).1;
+    let ca32 = (rb as u32).overflowing_sub(ra as u32).1;
+    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 f0ac587f293ff6ad601f80492184be3afca11d58..085d6c06d77b811837720bdb994ee2eed9b7ac25 100644 (file)
@@ -315,6 +315,42 @@ instructions! {
         "subfo."
     }
 
+    // addc
+    #[enumerant = AddC]
+    fn addc(Ra, Rb) -> (Rt, Carry) {
+        "addc"
+    }
+    #[enumerant = AddCO]
+    fn addco(Ra, Rb, Overflow) -> (Rt, Carry, Overflow) {
+        "addco"
+    }
+    #[enumerant = AddC_]
+    fn addc_(Ra, Rb, Overflow) -> (Rt, Carry, CR0) {
+        "addc."
+    }
+    #[enumerant = AddCO_]
+    fn addco_(Ra, Rb, Overflow) -> (Rt, Carry, Overflow, CR0) {
+        "addco."
+    }
+
+    // subfc
+    #[enumerant = SubFC]
+    fn subfc(Ra, Rb) -> (Rt, Carry) {
+        "subfc"
+    }
+    #[enumerant = SubFCO]
+    fn subfco(Ra, Rb, Overflow) -> (Rt, Carry, Overflow) {
+        "subfco"
+    }
+    #[enumerant = SubFC_]
+    fn subfc_(Ra, Rb, Overflow) -> (Rt, Carry, CR0) {
+        "subfc."
+    }
+    #[enumerant = SubFCO_]
+    fn subfco_(Ra, Rb, Overflow) -> (Rt, Carry, Overflow, CR0) {
+        "subfco."
+    }
+
     // divde
     #[enumerant = DivDE]
     fn divde(Ra, Rb) -> (Rt) {