From: Jacob Lifshay Date: Thu, 3 Sep 2020 23:43:45 +0000 (-0700) Subject: add adde* and subfe* X-Git-Tag: v0.2.0~22 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=245952fd4ca7d93d610292aea168fa85d91e5b7b;p=power-instruction-analyzer.git add adde* and subfe* --- diff --git a/src/instr_models.rs b/src/instr_models.rs index d140ea5..aa025c1 100644 --- a/src/instr_models.rs +++ b/src/instr_models.rs @@ -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 { diff --git a/src/lib.rs b/src/lib.rs index 085d6c0..4c205d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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) {