From cfac6324c82fac01d8cf4f0ca238514e1420cd62 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 3 Sep 2020 17:17:06 -0700 Subject: [PATCH] add addme*, subfme*, addze*, and subfze* --- src/instr_models.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 72 ++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 2 deletions(-) diff --git a/src/instr_models.rs b/src/instr_models.rs index aa025c1..059f1ce 100644 --- a/src/instr_models.rs +++ b/src/instr_models.rs @@ -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 { diff --git a/src/lib.rs b/src/lib.rs index 4c205d0..3c7c9bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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) { -- 2.30.2