Skip to content

Commit 663fe0b

Browse files
authored
harm: refactor tbz/tbnz (#48)
+ Use type aliases. + Generalize on offsets. + Improve tests
1 parent a759507 commit 663fe0b

1 file changed

Lines changed: 120 additions & 44 deletions

File tree

harm/src/instructions/control/testbranch.rs

Lines changed: 120 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,28 @@ use crate::{
1515
sealed::Sealed,
1616
};
1717

18-
pub struct TestBranch<Reg, Bit> {
18+
pub type TestBranchBit64 = UBitValue<6>;
19+
pub type TestBranchBit32 = UBitValue<5>;
20+
pub type TestBranchOffset = SBitValue<14, 2>;
21+
22+
pub struct TestBranch<Reg, Bit, Offset> {
1923
op: bool,
2024
reg: Reg,
2125
bit: Bit,
22-
offset: SBitValue<14, 2>,
26+
offset: Offset,
2327
}
2428

25-
impl<Reg, Bit> Sealed for TestBranch<Reg, Bit> {}
29+
impl Sealed for TestBranch<RegOrZero64, TestBranchBit64, TestBranchOffset> {}
30+
impl Sealed for TestBranch<RegOrZero32, TestBranchBit32, TestBranchOffset> {}
2631

27-
pub trait MakeTestBranch<Reg, Bit>: Sealed {
28-
fn new(op: bool, reg: Reg, bit: Bit, offset: SBitValue<14, 2>) -> Self;
32+
pub trait MakeTestBranch<Reg, Bit, Offset>: Sealed {
33+
fn new(op: bool, reg: Reg, bit: Bit, offset: Offset) -> Self;
2934
}
3035

31-
impl<R: IntoReg<RegOrZero64>> MakeTestBranch<R, UBitValue<6>>
32-
for TestBranch<RegOrZero64, UBitValue<6>>
36+
impl<R: IntoReg<RegOrZero64>> MakeTestBranch<R, TestBranchBit64, TestBranchOffset>
37+
for TestBranch<RegOrZero64, TestBranchBit64, TestBranchOffset>
3338
{
34-
fn new(op: bool, reg: R, bit: UBitValue<6>, offset: SBitValue<14, 2>) -> Self {
39+
fn new(op: bool, reg: R, bit: TestBranchBit64, offset: TestBranchOffset) -> Self {
3540
Self {
3641
op,
3742
reg: reg.into_reg(),
@@ -41,20 +46,20 @@ impl<R: IntoReg<RegOrZero64>> MakeTestBranch<R, UBitValue<6>>
4146
}
4247
}
4348

44-
impl<R: Into<RegOrZero32>> MakeTestBranch<R, UBitValue<5>>
45-
for TestBranch<RegOrZero32, UBitValue<5>>
49+
impl<R: IntoReg<RegOrZero32>> MakeTestBranch<R, TestBranchBit32, TestBranchOffset>
50+
for TestBranch<RegOrZero32, TestBranchBit32, TestBranchOffset>
4651
{
47-
fn new(op: bool, reg: R, bit: UBitValue<5>, offset: SBitValue<14, 2>) -> Self {
52+
fn new(op: bool, reg: R, bit: TestBranchBit32, offset: TestBranchOffset) -> Self {
4853
Self {
4954
op,
50-
reg: reg.into(),
55+
reg: reg.into_reg(),
5156
bit,
5257
offset,
5358
}
5459
}
5560
}
5661

57-
impl RawInstruction for TestBranch<RegOrZero64, UBitValue<6>> {
62+
impl RawInstruction for TestBranch<RegOrZero64, TestBranchBit64, TestBranchOffset> {
5863
#[inline]
5964
fn to_code(&self) -> InstructionCode {
6065
let bit = self.bit.bits();
@@ -64,17 +69,12 @@ impl RawInstruction for TestBranch<RegOrZero64, UBitValue<6>> {
6469
if self.op {
6570
TBNZ_only_testbranch(b5.into(), b40.into(), self.offset.into(), self.reg.index())
6671
} else {
67-
TBZ_only_testbranch(
68-
(bit >> 5).into(),
69-
(bit & 0b11111).into(),
70-
self.offset.into(),
71-
self.reg.index(),
72-
)
72+
TBZ_only_testbranch(b5.into(), b40.into(), self.offset.into(), self.reg.index())
7373
}
7474
}
7575
}
7676

77-
impl RawInstruction for TestBranch<RegOrZero32, UBitValue<5>> {
77+
impl RawInstruction for TestBranch<RegOrZero32, TestBranchBit32, TestBranchOffset> {
7878
#[inline]
7979
fn to_code(&self) -> InstructionCode {
8080
let bit = self.bit.bits();
@@ -89,20 +89,20 @@ impl RawInstruction for TestBranch<RegOrZero32, UBitValue<5>> {
8989
}
9090
}
9191

92-
pub fn tbnz<Reg, InpReg, Bit>(
92+
pub fn tbnz<Reg, InpReg, Bit, Offset>(
9393
reg: InpReg,
9494
bit: Bit,
95-
offset: SBitValue<14, 2>,
96-
) -> TestBranch<Reg, Bit>
95+
offset: Offset,
96+
) -> TestBranch<Reg, Bit, Offset>
9797
where
98-
TestBranch<Reg, Bit>: MakeTestBranch<InpReg, Bit>,
98+
TestBranch<Reg, Bit, Offset>: MakeTestBranch<InpReg, Bit, Offset>,
9999
{
100100
TestBranch::new(true, reg, bit, offset)
101101
}
102102

103-
pub fn tbz<R, Reg, Bit>(reg: Reg, bit: Bit, offset: SBitValue<14, 2>) -> TestBranch<R, Bit>
103+
pub fn tbz<R, Reg, Bit, Offset>(reg: Reg, bit: Bit, offset: Offset) -> TestBranch<R, Bit, Offset>
104104
where
105-
TestBranch<R, Bit>: MakeTestBranch<Reg, Bit>,
105+
TestBranch<R, Bit, Offset>: MakeTestBranch<Reg, Bit, Offset>,
106106
{
107107
TestBranch::new(false, reg, bit, offset)
108108
}
@@ -122,57 +122,133 @@ mod tests {
122122

123123
#[test]
124124
fn test_tbz_64_big_pos() {
125-
let offset = SBitValue::new(76).unwrap();
126-
let bit = UBitValue::new(42).unwrap();
125+
let offset = TestBranchOffset::new(76).unwrap();
126+
let bit = TestBranchBit64::new(42).unwrap();
127127
let it = tbz(X2, bit, offset);
128128
let words: Vec<_> = it.encode().collect();
129129
// tbz x2, 42, 76
130-
assert_eq!(words, inst!([0x62, 0x02, 0x50, 0xb6])); // 0xb6500262
130+
assert_eq!(words, inst!(0xb6500262));
131131
}
132132

133133
#[test]
134134
fn test_tbz_64_small_pos() {
135-
let offset = SBitValue::new(76).unwrap();
136-
let bit = UBitValue::new(29).unwrap();
135+
let offset = TestBranchOffset::new(76).unwrap();
136+
let bit = TestBranchBit64::new(29).unwrap();
137137
let it = tbz(X2, bit, offset);
138138
let words: Vec<_> = it.encode().collect();
139139

140-
assert_eq!(words, inst!([0x62, 0x02, 0xe8, 0x36])); // 0x36e80262
140+
assert_eq!(words, inst!(0x36e80262));
141141
}
142142

143143
#[test]
144144
fn test_tbz_xzr_big_pos() {
145-
let offset = SBitValue::new(76).unwrap();
146-
let bit = UBitValue::new(42).unwrap();
145+
let offset = TestBranchOffset::new(76).unwrap();
146+
let bit = TestBranchBit64::new(42).unwrap();
147147
let it = tbz(XZR, bit, offset);
148148
let words: Vec<_> = it.encode().collect();
149-
assert_eq!(words, inst!([0x7f, 0x02, 0x50, 0xb6])); // 0xb650027f
149+
assert_eq!(words, inst!(0xb650027f));
150+
}
151+
152+
#[test]
153+
fn test_tbz_64_neg_pos() {
154+
let offset = TestBranchOffset::new(-76).unwrap();
155+
let bit = TestBranchBit64::new(29).unwrap();
156+
let it = tbz(X2, bit, offset);
157+
let words: Vec<_> = it.encode().collect();
158+
159+
assert_eq!(words, inst!(0x36effda2));
150160
}
151161

152162
#[test]
153163
fn test_tbz_xzr_small_pos() {
154-
let offset = SBitValue::new(76).unwrap();
155-
let bit = UBitValue::new(29).unwrap();
164+
let offset = TestBranchOffset::new(76).unwrap();
165+
let bit = TestBranchBit64::new(29).unwrap();
156166
let it = tbz(XZR, bit, offset);
157167
let words: Vec<_> = it.encode().collect();
158-
assert_eq!(words, inst!([0x7f, 0x02, 0xe8, 0x36])); // 0x36e8027f
168+
assert_eq!(words, inst!(0x36e8027f));
159169
}
160170

161171
#[test]
162172
fn test_tbz_32_pos() {
163-
let offset = SBitValue::new(76).unwrap();
164-
let bit = UBitValue::new(29).unwrap();
173+
let offset = TestBranchOffset::new(76).unwrap();
174+
let bit = TestBranchBit32::new(29).unwrap();
165175
let it = tbz(W2, bit, offset);
166176
let words: Vec<_> = it.encode().collect();
167-
assert_eq!(words, inst!([0x62, 0x02, 0xe8, 0x36])); // 0x36e80262
177+
assert_eq!(words, inst!(0x36e80262));
168178
}
169179

170180
#[test]
171181
fn test_tbz_wzr_pos() {
172-
let offset = SBitValue::new(76).unwrap();
173-
let bit = UBitValue::new(29).unwrap();
182+
let offset = TestBranchOffset::new(76).unwrap();
183+
let bit = TestBranchBit32::new(29).unwrap();
174184
let it = tbz(WZR, bit, offset);
175185
let words: Vec<_> = it.encode().collect();
176-
assert_eq!(words, inst!([0x7f, 0x02, 0xe8, 0x36])); // 0x36e8027f
186+
assert_eq!(words, inst!(0x36e8027f));
187+
}
188+
189+
#[test]
190+
fn test_tbnz_64_big_pos() {
191+
let offset = TestBranchOffset::new(76).unwrap();
192+
let bit = TestBranchBit64::new(42).unwrap();
193+
let it = tbnz(X2, bit, offset);
194+
let words: Vec<_> = it.encode().collect();
195+
// tbnz x2, 42, 76
196+
assert_eq!(words, inst!(0xb7500262));
197+
}
198+
199+
#[test]
200+
fn test_tbnz_64_small_pos() {
201+
let offset = TestBranchOffset::new(76).unwrap();
202+
let bit = TestBranchBit64::new(29).unwrap();
203+
let it = tbnz(X2, bit, offset);
204+
let words: Vec<_> = it.encode().collect();
205+
206+
assert_eq!(words, inst!(0x37e80262));
207+
}
208+
209+
#[test]
210+
fn test_tbnz_xzr_big_pos() {
211+
let offset = TestBranchOffset::new(76).unwrap();
212+
let bit = TestBranchBit64::new(42).unwrap();
213+
let it = tbnz(XZR, bit, offset);
214+
let words: Vec<_> = it.encode().collect();
215+
assert_eq!(words, inst!(0xb750027f));
216+
}
217+
218+
#[test]
219+
fn test_tbnz_64_neg_pos() {
220+
let offset = TestBranchOffset::new(-76).unwrap();
221+
let bit = TestBranchBit64::new(29).unwrap();
222+
let it = tbnz(X2, bit, offset);
223+
let words: Vec<_> = it.encode().collect();
224+
225+
assert_eq!(words, inst!(0x37effda2));
226+
}
227+
228+
#[test]
229+
fn test_tbnz_xzr_small_pos() {
230+
let offset = TestBranchOffset::new(76).unwrap();
231+
let bit = TestBranchBit64::new(29).unwrap();
232+
let it = tbnz(XZR, bit, offset);
233+
let words: Vec<_> = it.encode().collect();
234+
assert_eq!(words, inst!(0x37e8027f));
235+
}
236+
237+
#[test]
238+
fn test_tbnz_32_pos() {
239+
let offset = TestBranchOffset::new(76).unwrap();
240+
let bit = TestBranchBit32::new(29).unwrap();
241+
let it = tbnz(W2, bit, offset);
242+
let words: Vec<_> = it.encode().collect();
243+
assert_eq!(words, inst!(0x37e80262));
244+
}
245+
246+
#[test]
247+
fn test_tbnz_wzr_pos() {
248+
let offset = TestBranchOffset::new(76).unwrap();
249+
let bit = TestBranchBit32::new(29).unwrap();
250+
let it = tbnz(WZR, bit, offset);
251+
let words: Vec<_> = it.encode().collect();
252+
assert_eq!(words, inst!(0x37e8027f));
177253
}
178254
}

0 commit comments

Comments
 (0)