1
- use super :: {
2
- super :: opnd:: * ,
3
- family:: Family ,
4
- sf:: Sf
5
- } ;
1
+ use super :: { family:: Family , sf:: Sf } ;
6
2
7
3
/// The operation being performed by this instruction.
8
4
enum Op {
@@ -33,127 +29,106 @@ enum Shift {
33
29
/// +-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
34
30
///
35
31
pub struct DataProcessingImmediate {
36
- /// Whether or not this instruction is operating on 64-bit operands .
37
- sf : Sf ,
32
+ /// The register number of the destination register .
33
+ rd : u8 ,
38
34
39
- /// The opcode for this instruction .
40
- op : Op ,
35
+ /// The register number of the first operand register .
36
+ rn : u8 ,
41
37
42
- /// Whether or not to update the flags when this instruction is performed .
43
- s : S ,
38
+ /// The value of the immediate .
39
+ imm12 : u16 ,
44
40
45
41
/// How much to shift the immediate by.
46
42
shift : Shift ,
47
43
48
- /// The value of the immediate .
49
- imm12 : u16 ,
44
+ /// Whether or not to update the flags when this instruction is performed .
45
+ s : S ,
50
46
51
- /// The register number of the first operand register .
52
- rn : u8 ,
47
+ /// The opcode for this instruction .
48
+ op : Op ,
53
49
54
- /// The register number of the destination register .
55
- rd : u8
50
+ /// Whether or not this instruction is operating on 64-bit operands .
51
+ sf : Sf
56
52
}
57
53
58
54
impl DataProcessingImmediate {
59
55
/// ADD (immediate)
60
56
/// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADD--immediate---Add--immediate--?lang=en
61
- pub fn add ( rd : & A64Opnd , rn : & A64Opnd , imm12 : & A64Opnd ) -> Self {
62
- let ( rd, rn, imm12) = Self :: unwrap ( rd, rn, imm12) ;
63
-
57
+ pub fn add ( rd : u8 , rn : u8 , imm12 : u16 , num_bits : u8 ) -> Self {
64
58
Self {
65
- sf : rd . num_bits . into ( ) ,
66
- op : Op :: Add ,
67
- s : S :: LeaveFlags ,
59
+ rd ,
60
+ rn ,
61
+ imm12 ,
68
62
shift : Shift :: LSL0 ,
69
- imm12 : imm12 . value as u16 ,
70
- rn : rn . reg_no ,
71
- rd : rd . reg_no
63
+ s : S :: LeaveFlags ,
64
+ op : Op :: Add ,
65
+ sf : num_bits . into ( )
72
66
}
73
67
}
74
68
75
69
/// ADDS (immediate, set flags)
76
70
/// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADDS--immediate---Add--immediate---setting-flags-?lang=en
77
- pub fn adds ( rd : & A64Opnd , rn : & A64Opnd , imm12 : & A64Opnd ) -> Self {
78
- let ( rd, rn, imm12) = Self :: unwrap ( rd, rn, imm12) ;
79
-
71
+ pub fn adds ( rd : u8 , rn : u8 , imm12 : u16 , num_bits : u8 ) -> Self {
80
72
Self {
81
- sf : rd . num_bits . into ( ) ,
82
- op : Op :: Add ,
83
- s : S :: UpdateFlags ,
73
+ rd ,
74
+ rn ,
75
+ imm12 ,
84
76
shift : Shift :: LSL0 ,
85
- imm12 : imm12 . value as u16 ,
86
- rn : rn . reg_no ,
87
- rd : rd . reg_no
77
+ s : S :: UpdateFlags ,
78
+ op : Op :: Add ,
79
+ sf : num_bits . into ( )
88
80
}
89
81
}
90
82
91
83
/// SUB (immediate)
92
84
/// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/SUB--immediate---Subtract--immediate--?lang=en
93
- pub fn sub ( rd : & A64Opnd , rn : & A64Opnd , imm12 : & A64Opnd ) -> Self {
94
- let ( rd, rn, imm12) = Self :: unwrap ( rd, rn, imm12) ;
95
-
85
+ pub fn sub ( rd : u8 , rn : u8 , imm12 : u16 , num_bits : u8 ) -> Self {
96
86
Self {
97
- sf : rd . num_bits . into ( ) ,
98
- op : Op :: Sub ,
99
- s : S :: LeaveFlags ,
87
+ rd ,
88
+ rn ,
89
+ imm12 ,
100
90
shift : Shift :: LSL0 ,
101
- imm12 : imm12 . value as u16 ,
102
- rn : rn . reg_no ,
103
- rd : rd . reg_no
91
+ s : S :: LeaveFlags ,
92
+ op : Op :: Sub ,
93
+ sf : num_bits . into ( )
104
94
}
105
95
}
106
96
107
97
/// SUBS (immediate, set flags)
108
98
/// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/SUBS--immediate---Subtract--immediate---setting-flags-?lang=en
109
- pub fn subs ( rd : & A64Opnd , rn : & A64Opnd , imm12 : & A64Opnd ) -> Self {
110
- let ( rd, rn, imm12) = Self :: unwrap ( rd, rn, imm12) ;
111
-
99
+ pub fn subs ( rd : u8 , rn : u8 , imm12 : u16 , num_bits : u8 ) -> Self {
112
100
Self {
113
- sf : rd . num_bits . into ( ) ,
114
- op : Op :: Sub ,
115
- s : S :: UpdateFlags ,
101
+ rd ,
102
+ rn ,
103
+ imm12 ,
116
104
shift : Shift :: LSL0 ,
117
- imm12 : imm12. value as u16 ,
118
- rn : rn. reg_no ,
119
- rd : rd. reg_no
120
- }
121
- }
122
-
123
- /// Extract out two registers and an immediate from the given operands.
124
- /// Panic if any of the operands do not match the expected type or size.
125
- fn unwrap < ' a > ( rd : & ' a A64Opnd , rn : & ' a A64Opnd , imm12 : & ' a A64Opnd ) -> ( & ' a A64Reg , & ' a A64Reg , & ' a A64UImm ) {
126
- match ( rd, rn, imm12) {
127
- ( A64Opnd :: Reg ( rd) , A64Opnd :: Reg ( rn) , A64Opnd :: UImm ( imm12) ) => {
128
- assert ! ( rd. num_bits == rn. num_bits, "Both rd and rn operands to a data processing immediate instruction must be of the same size." ) ;
129
- assert ! ( imm12. num_bits <= 12 , "The immediate operand to a data processing immediate instruction must be 12 bits or less." ) ;
130
- ( rd, rn, imm12)
131
- } ,
132
- _ => {
133
- panic ! ( "Expected 2 register operands and an immediate operand for a data processing immediate instruction." ) ;
134
- }
105
+ s : S :: UpdateFlags ,
106
+ op : Op :: Sub ,
107
+ sf : num_bits. into ( )
135
108
}
136
109
}
137
110
}
138
111
139
112
impl From < DataProcessingImmediate > for u32 {
140
- /// Convert a data processing instruction into a 32-bit value.
113
+ /// Convert an instruction into a 32-bit value.
141
114
fn from ( inst : DataProcessingImmediate ) -> Self {
115
+ let imm12 = ( inst. imm12 as u32 ) & ( ( 1 << 12 ) - 1 ) ;
116
+
142
117
0
143
- | ( inst. sf as u32 ) . wrapping_shl ( 31 )
144
- | ( inst. op as u32 ) . wrapping_shl ( 30 )
145
- | ( inst. s as u32 ) . wrapping_shl ( 29 )
146
- | ( Family :: DataProcessingImmediate as u32 ) . wrapping_shl ( 25 )
147
- | ( 0b1 << 24 )
148
- | ( inst. shift as u32 ) . wrapping_shl ( 22 )
149
- | ( inst . imm12 as u32 ) . wrapping_shl ( 10 )
150
- | ( inst. rn as u32 ) . wrapping_shl ( 5 )
118
+ | ( ( inst. sf as u32 ) << 31 )
119
+ | ( ( inst. op as u32 ) << 30 )
120
+ | ( ( inst. s as u32 ) << 29 )
121
+ | ( ( Family :: DataProcessingImmediate as u32 ) << 25 )
122
+ | ( 1 << 24 )
123
+ | ( ( inst. shift as u32 ) << 22 )
124
+ | ( imm12 << 10 )
125
+ | ( ( inst. rn as u32 ) << 5 )
151
126
| inst. rd as u32
152
127
}
153
128
}
154
129
155
130
impl From < DataProcessingImmediate > for [ u8 ; 4 ] {
156
- /// Convert a data processing instruction into a 4 byte array.
131
+ /// Convert an instruction into a 4 byte array.
157
132
fn from ( inst : DataProcessingImmediate ) -> [ u8 ; 4 ] {
158
133
let result: u32 = inst. into ( ) ;
159
134
result. to_le_bytes ( )
@@ -166,32 +141,28 @@ mod tests {
166
141
167
142
#[ test]
168
143
fn test_add ( ) {
169
- let uimm12 = A64Opnd :: new_uimm ( 7 ) ;
170
- let inst = DataProcessingImmediate :: add ( & X0 , & X1 , & uimm12) ;
144
+ let inst = DataProcessingImmediate :: add ( 0 , 1 , 7 , 64 ) ;
171
145
let result: u32 = inst. into ( ) ;
172
146
assert_eq ! ( 0x91001c20 , result) ;
173
147
}
174
148
175
149
#[ test]
176
150
fn test_adds ( ) {
177
- let uimm12 = A64Opnd :: new_uimm ( 7 ) ;
178
- let inst = DataProcessingImmediate :: adds ( & X0 , & X1 , & uimm12) ;
151
+ let inst = DataProcessingImmediate :: adds ( 0 , 1 , 7 , 64 ) ;
179
152
let result: u32 = inst. into ( ) ;
180
153
assert_eq ! ( 0xb1001c20 , result) ;
181
154
}
182
155
183
156
#[ test]
184
157
fn test_sub ( ) {
185
- let uimm12 = A64Opnd :: new_uimm ( 7 ) ;
186
- let inst = DataProcessingImmediate :: sub ( & X0 , & X1 , & uimm12) ;
158
+ let inst = DataProcessingImmediate :: sub ( 0 , 1 , 7 , 64 ) ;
187
159
let result: u32 = inst. into ( ) ;
188
160
assert_eq ! ( 0xd1001c20 , result) ;
189
161
}
190
162
191
163
#[ test]
192
164
fn test_subs ( ) {
193
- let uimm12 = A64Opnd :: new_uimm ( 7 ) ;
194
- let inst = DataProcessingImmediate :: subs ( & X0 , & X1 , & uimm12) ;
165
+ let inst = DataProcessingImmediate :: subs ( 0 , 1 , 7 , 64 ) ;
195
166
let result: u32 = inst. into ( ) ;
196
167
assert_eq ! ( 0xf1001c20 , result) ;
197
168
}
0 commit comments