From: Jacob Lifshay Date: Thu, 3 Sep 2020 23:18:34 +0000 (-0700) Subject: add addc* and subfc* instructions X-Git-Tag: v0.2.0~24 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=93abe3fa99a1fcf56aa1ca221788d4e13a41dbce;p=power-instruction-analyzer.git add addc* and subfc* instructions --- diff --git a/src/instr_models.rs b/src/instr_models.rs index 1b56cad..e56e4fb 100644 --- a/src/instr_models.rs +++ b/src/instr_models.rs @@ -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 { diff --git a/src/lib.rs b/src/lib.rs index f0ac587..085d6c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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) {