diff --git a/harm/src/instructions/control/testbranch.rs b/harm/src/instructions/control/testbranch.rs index e79b539b..4d51c41b 100644 --- a/harm/src/instructions/control/testbranch.rs +++ b/harm/src/instructions/control/testbranch.rs @@ -15,23 +15,28 @@ use crate::{ sealed::Sealed, }; -pub struct TestBranch { +pub type TestBranchBit64 = UBitValue<6>; +pub type TestBranchBit32 = UBitValue<5>; +pub type TestBranchOffset = SBitValue<14, 2>; + +pub struct TestBranch { op: bool, reg: Reg, bit: Bit, - offset: SBitValue<14, 2>, + offset: Offset, } -impl Sealed for TestBranch {} +impl Sealed for TestBranch {} +impl Sealed for TestBranch {} -pub trait MakeTestBranch: Sealed { - fn new(op: bool, reg: Reg, bit: Bit, offset: SBitValue<14, 2>) -> Self; +pub trait MakeTestBranch: Sealed { + fn new(op: bool, reg: Reg, bit: Bit, offset: Offset) -> Self; } -impl> MakeTestBranch> - for TestBranch> +impl> MakeTestBranch + for TestBranch { - fn new(op: bool, reg: R, bit: UBitValue<6>, offset: SBitValue<14, 2>) -> Self { + fn new(op: bool, reg: R, bit: TestBranchBit64, offset: TestBranchOffset) -> Self { Self { op, reg: reg.into_reg(), @@ -41,20 +46,20 @@ impl> MakeTestBranch> } } -impl> MakeTestBranch> - for TestBranch> +impl> MakeTestBranch + for TestBranch { - fn new(op: bool, reg: R, bit: UBitValue<5>, offset: SBitValue<14, 2>) -> Self { + fn new(op: bool, reg: R, bit: TestBranchBit32, offset: TestBranchOffset) -> Self { Self { op, - reg: reg.into(), + reg: reg.into_reg(), bit, offset, } } } -impl RawInstruction for TestBranch> { +impl RawInstruction for TestBranch { #[inline] fn to_code(&self) -> InstructionCode { let bit = self.bit.bits(); @@ -64,17 +69,12 @@ impl RawInstruction for TestBranch> { if self.op { TBNZ_only_testbranch(b5.into(), b40.into(), self.offset.into(), self.reg.index()) } else { - TBZ_only_testbranch( - (bit >> 5).into(), - (bit & 0b11111).into(), - self.offset.into(), - self.reg.index(), - ) + TBZ_only_testbranch(b5.into(), b40.into(), self.offset.into(), self.reg.index()) } } } -impl RawInstruction for TestBranch> { +impl RawInstruction for TestBranch { #[inline] fn to_code(&self) -> InstructionCode { let bit = self.bit.bits(); @@ -89,20 +89,20 @@ impl RawInstruction for TestBranch> { } } -pub fn tbnz( +pub fn tbnz( reg: InpReg, bit: Bit, - offset: SBitValue<14, 2>, -) -> TestBranch + offset: Offset, +) -> TestBranch where - TestBranch: MakeTestBranch, + TestBranch: MakeTestBranch, { TestBranch::new(true, reg, bit, offset) } -pub fn tbz(reg: Reg, bit: Bit, offset: SBitValue<14, 2>) -> TestBranch +pub fn tbz(reg: Reg, bit: Bit, offset: Offset) -> TestBranch where - TestBranch: MakeTestBranch, + TestBranch: MakeTestBranch, { TestBranch::new(false, reg, bit, offset) } @@ -122,57 +122,133 @@ mod tests { #[test] fn test_tbz_64_big_pos() { - let offset = SBitValue::new(76).unwrap(); - let bit = UBitValue::new(42).unwrap(); + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit64::new(42).unwrap(); let it = tbz(X2, bit, offset); let words: Vec<_> = it.encode().collect(); // tbz x2, 42, 76 - assert_eq!(words, inst!([0x62, 0x02, 0x50, 0xb6])); // 0xb6500262 + assert_eq!(words, inst!(0xb6500262)); } #[test] fn test_tbz_64_small_pos() { - let offset = SBitValue::new(76).unwrap(); - let bit = UBitValue::new(29).unwrap(); + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit64::new(29).unwrap(); let it = tbz(X2, bit, offset); let words: Vec<_> = it.encode().collect(); - assert_eq!(words, inst!([0x62, 0x02, 0xe8, 0x36])); // 0x36e80262 + assert_eq!(words, inst!(0x36e80262)); } #[test] fn test_tbz_xzr_big_pos() { - let offset = SBitValue::new(76).unwrap(); - let bit = UBitValue::new(42).unwrap(); + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit64::new(42).unwrap(); let it = tbz(XZR, bit, offset); let words: Vec<_> = it.encode().collect(); - assert_eq!(words, inst!([0x7f, 0x02, 0x50, 0xb6])); // 0xb650027f + assert_eq!(words, inst!(0xb650027f)); + } + + #[test] + fn test_tbz_64_neg_pos() { + let offset = TestBranchOffset::new(-76).unwrap(); + let bit = TestBranchBit64::new(29).unwrap(); + let it = tbz(X2, bit, offset); + let words: Vec<_> = it.encode().collect(); + + assert_eq!(words, inst!(0x36effda2)); } #[test] fn test_tbz_xzr_small_pos() { - let offset = SBitValue::new(76).unwrap(); - let bit = UBitValue::new(29).unwrap(); + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit64::new(29).unwrap(); let it = tbz(XZR, bit, offset); let words: Vec<_> = it.encode().collect(); - assert_eq!(words, inst!([0x7f, 0x02, 0xe8, 0x36])); // 0x36e8027f + assert_eq!(words, inst!(0x36e8027f)); } #[test] fn test_tbz_32_pos() { - let offset = SBitValue::new(76).unwrap(); - let bit = UBitValue::new(29).unwrap(); + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit32::new(29).unwrap(); let it = tbz(W2, bit, offset); let words: Vec<_> = it.encode().collect(); - assert_eq!(words, inst!([0x62, 0x02, 0xe8, 0x36])); // 0x36e80262 + assert_eq!(words, inst!(0x36e80262)); } #[test] fn test_tbz_wzr_pos() { - let offset = SBitValue::new(76).unwrap(); - let bit = UBitValue::new(29).unwrap(); + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit32::new(29).unwrap(); let it = tbz(WZR, bit, offset); let words: Vec<_> = it.encode().collect(); - assert_eq!(words, inst!([0x7f, 0x02, 0xe8, 0x36])); // 0x36e8027f + assert_eq!(words, inst!(0x36e8027f)); + } + + #[test] + fn test_tbnz_64_big_pos() { + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit64::new(42).unwrap(); + let it = tbnz(X2, bit, offset); + let words: Vec<_> = it.encode().collect(); + // tbnz x2, 42, 76 + assert_eq!(words, inst!(0xb7500262)); + } + + #[test] + fn test_tbnz_64_small_pos() { + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit64::new(29).unwrap(); + let it = tbnz(X2, bit, offset); + let words: Vec<_> = it.encode().collect(); + + assert_eq!(words, inst!(0x37e80262)); + } + + #[test] + fn test_tbnz_xzr_big_pos() { + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit64::new(42).unwrap(); + let it = tbnz(XZR, bit, offset); + let words: Vec<_> = it.encode().collect(); + assert_eq!(words, inst!(0xb750027f)); + } + + #[test] + fn test_tbnz_64_neg_pos() { + let offset = TestBranchOffset::new(-76).unwrap(); + let bit = TestBranchBit64::new(29).unwrap(); + let it = tbnz(X2, bit, offset); + let words: Vec<_> = it.encode().collect(); + + assert_eq!(words, inst!(0x37effda2)); + } + + #[test] + fn test_tbnz_xzr_small_pos() { + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit64::new(29).unwrap(); + let it = tbnz(XZR, bit, offset); + let words: Vec<_> = it.encode().collect(); + assert_eq!(words, inst!(0x37e8027f)); + } + + #[test] + fn test_tbnz_32_pos() { + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit32::new(29).unwrap(); + let it = tbnz(W2, bit, offset); + let words: Vec<_> = it.encode().collect(); + assert_eq!(words, inst!(0x37e80262)); + } + + #[test] + fn test_tbnz_wzr_pos() { + let offset = TestBranchOffset::new(76).unwrap(); + let bit = TestBranchBit32::new(29).unwrap(); + let it = tbnz(WZR, bit, offset); + let words: Vec<_> = it.encode().collect(); + assert_eq!(words, inst!(0x37e8027f)); } }