1 /* |
|
2 * Copyright (c) 2014, Red Hat Inc. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 #ifndef _DECODE_H |
|
26 #define _DECODE_H |
|
27 |
|
28 #include <sys/types.h> |
|
29 #include "cpustate_aarch64.hpp" |
|
30 |
|
31 // bitfield immediate expansion helper |
|
32 |
|
33 extern int expandLogicalImmediate(u_int32_t immN, u_int32_t immr, |
|
34 u_int32_t imms, u_int64_t &bimm); |
|
35 |
|
36 |
|
37 /* |
|
38 * codes used in conditional instructions |
|
39 * |
|
40 * these are passed to conditional operations to identify which |
|
41 * condition to test for |
|
42 */ |
|
43 enum CondCode { |
|
44 EQ = 0b0000, // meaning Z == 1 |
|
45 NE = 0b0001, // meaning Z == 0 |
|
46 HS = 0b0010, // meaning C == 1 |
|
47 CS = HS, |
|
48 LO = 0b0011, // meaning C == 0 |
|
49 CC = LO, |
|
50 MI = 0b0100, // meaning N == 1 |
|
51 PL = 0b0101, // meaning N == 0 |
|
52 VS = 0b0110, // meaning V == 1 |
|
53 VC = 0b0111, // meaning V == 0 |
|
54 HI = 0b1000, // meaning C == 1 && Z == 0 |
|
55 LS = 0b1001, // meaning !(C == 1 && Z == 0) |
|
56 GE = 0b1010, // meaning N == V |
|
57 LT = 0b1011, // meaning N != V |
|
58 GT = 0b1100, // meaning Z == 0 && N == V |
|
59 LE = 0b1101, // meaning !(Z == 0 && N == V) |
|
60 AL = 0b1110, // meaning ANY |
|
61 NV = 0b1111 // ditto |
|
62 }; |
|
63 |
|
64 /* |
|
65 * certain addressing modes for load require pre or post writeback of |
|
66 * the computed address to a base register |
|
67 */ |
|
68 enum WriteBack { |
|
69 Post = 0, |
|
70 Pre = 1 |
|
71 }; |
|
72 |
|
73 /* |
|
74 * certain addressing modes for load require an offset to |
|
75 * be optionally scaled so the decode needs to pass that |
|
76 * through to the execute routine |
|
77 */ |
|
78 enum Scaling { |
|
79 Unscaled = 0, |
|
80 Scaled = 1 |
|
81 }; |
|
82 |
|
83 /* |
|
84 * when we do have to scale we do so by shifting using |
|
85 * log(bytes in data element - 1) as the shift count. |
|
86 * so we don't have to scale offsets when loading |
|
87 * bytes. |
|
88 */ |
|
89 enum ScaleShift { |
|
90 ScaleShift16 = 1, |
|
91 ScaleShift32 = 2, |
|
92 ScaleShift64 = 3, |
|
93 ScaleShift128 = 4 |
|
94 }; |
|
95 |
|
96 /* |
|
97 * one of the addressing modes for load requires a 32-bit register |
|
98 * value to be either zero- or sign-extended for these instructions |
|
99 * UXTW or SXTW should be passed |
|
100 * |
|
101 * arithmetic register data processing operations can optionally |
|
102 * extend a portion of the second register value for these |
|
103 * instructions the value supplied must identify the portion of the |
|
104 * register which is to be zero- or sign-exended |
|
105 */ |
|
106 enum Extension { |
|
107 UXTB = 0, |
|
108 UXTH = 1, |
|
109 UXTW = 2, |
|
110 UXTX = 3, |
|
111 SXTB = 4, |
|
112 SXTH = 5, |
|
113 SXTW = 6, |
|
114 SXTX = 7 |
|
115 }; |
|
116 |
|
117 /* |
|
118 * arithmetic and logical register data processing operations |
|
119 * optionally perform a shift on the second register value |
|
120 */ |
|
121 enum Shift { |
|
122 LSL = 0, |
|
123 LSR = 1, |
|
124 ASR = 2, |
|
125 ROR = 3 |
|
126 }; |
|
127 |
|
128 /* |
|
129 * bit twiddling helpers for instruction decode |
|
130 */ |
|
131 |
|
132 // 32 bit mask with bits [hi,...,lo] set |
|
133 |
|
134 static inline u_int32_t mask32(int hi = 31, int lo = 0) |
|
135 { |
|
136 int nbits = (hi + 1) - lo; |
|
137 return ((1 << nbits) - 1) << lo; |
|
138 } |
|
139 |
|
140 static inline u_int64_t mask64(int hi = 63, int lo = 0) |
|
141 { |
|
142 int nbits = (hi + 1) - lo; |
|
143 return ((1L << nbits) - 1) << lo; |
|
144 } |
|
145 |
|
146 // pick bits [hi,...,lo] from val |
|
147 static inline u_int32_t pick32(u_int32_t val, int hi = 31, int lo = 0) |
|
148 { |
|
149 return (val & mask32(hi, lo)); |
|
150 } |
|
151 |
|
152 // pick bits [hi,...,lo] from val |
|
153 static inline u_int64_t pick64(u_int64_t val, int hi = 31, int lo = 0) |
|
154 { |
|
155 return (val & mask64(hi, lo)); |
|
156 } |
|
157 |
|
158 // pick bits [hi,...,lo] from val and shift to [(hi-(newlo - lo)),newlo] |
|
159 static inline u_int32_t pickshift32(u_int32_t val, int hi = 31, |
|
160 int lo = 0, int newlo = 0) |
|
161 { |
|
162 u_int32_t bits = pick32(val, hi, lo); |
|
163 if (lo < newlo) { |
|
164 return (bits << (newlo - lo)); |
|
165 } else { |
|
166 return (bits >> (lo - newlo)); |
|
167 } |
|
168 } |
|
169 // mask [hi,lo] and shift down to start at bit 0 |
|
170 static inline u_int32_t pickbits32(u_int32_t val, int hi = 31, int lo = 0) |
|
171 { |
|
172 return (pick32(val, hi, lo) >> lo); |
|
173 } |
|
174 |
|
175 // mask [hi,lo] and shift down to start at bit 0 |
|
176 static inline u_int64_t pickbits64(u_int64_t val, int hi = 63, int lo = 0) |
|
177 { |
|
178 return (pick64(val, hi, lo) >> lo); |
|
179 } |
|
180 |
|
181 /* |
|
182 * decode registers, immediates and constants of various types |
|
183 */ |
|
184 |
|
185 static inline GReg greg(u_int32_t val, int lo) |
|
186 { |
|
187 return (GReg)pickbits32(val, lo + 4, lo); |
|
188 } |
|
189 |
|
190 static inline VReg vreg(u_int32_t val, int lo) |
|
191 { |
|
192 return (VReg)pickbits32(val, lo + 4, lo); |
|
193 } |
|
194 |
|
195 static inline u_int32_t uimm(u_int32_t val, int hi, int lo) |
|
196 { |
|
197 return pickbits32(val, hi, lo); |
|
198 } |
|
199 |
|
200 static inline int32_t simm(u_int32_t val, int hi = 31, int lo = 0) { |
|
201 union { |
|
202 u_int32_t u; |
|
203 int32_t n; |
|
204 }; |
|
205 |
|
206 u = val << (31 - hi); |
|
207 n = n >> (31 - hi + lo); |
|
208 return n; |
|
209 } |
|
210 |
|
211 static inline int64_t simm(u_int64_t val, int hi = 63, int lo = 0) { |
|
212 union { |
|
213 u_int64_t u; |
|
214 int64_t n; |
|
215 }; |
|
216 |
|
217 u = val << (63 - hi); |
|
218 n = n >> (63 - hi + lo); |
|
219 return n; |
|
220 } |
|
221 |
|
222 static inline Shift shift(u_int32_t val, int lo) |
|
223 { |
|
224 return (Shift)pickbits32(val, lo+1, lo); |
|
225 } |
|
226 |
|
227 static inline Extension extension(u_int32_t val, int lo) |
|
228 { |
|
229 return (Extension)pickbits32(val, lo+2, lo); |
|
230 } |
|
231 |
|
232 static inline Scaling scaling(u_int32_t val, int lo) |
|
233 { |
|
234 return (Scaling)pickbits32(val, lo, lo); |
|
235 } |
|
236 |
|
237 static inline WriteBack writeback(u_int32_t val, int lo) |
|
238 { |
|
239 return (WriteBack)pickbits32(val, lo, lo); |
|
240 } |
|
241 |
|
242 static inline CondCode condcode(u_int32_t val, int lo) |
|
243 { |
|
244 return (CondCode)pickbits32(val, lo+3, lo); |
|
245 } |
|
246 |
|
247 /* |
|
248 * operation decode |
|
249 */ |
|
250 // bits [28,25] are the primary dispatch vector |
|
251 |
|
252 static inline u_int32_t dispatchGroup(u_int32_t val) |
|
253 { |
|
254 return pickshift32(val, 28, 25, 0); |
|
255 } |
|
256 |
|
257 /* |
|
258 * the 16 possible values for bits [28,25] identified by tags which |
|
259 * map them to the 5 main instruction groups LDST, DPREG, ADVSIMD, |
|
260 * BREXSYS and DPIMM. |
|
261 * |
|
262 * An extra group PSEUDO is included in one of the unallocated ranges |
|
263 * for simulator-specific pseudo-instructions. |
|
264 */ |
|
265 enum DispatchGroup { |
|
266 GROUP_PSEUDO_0000, |
|
267 GROUP_UNALLOC_0001, |
|
268 GROUP_UNALLOC_0010, |
|
269 GROUP_UNALLOC_0011, |
|
270 GROUP_LDST_0100, |
|
271 GROUP_DPREG_0101, |
|
272 GROUP_LDST_0110, |
|
273 GROUP_ADVSIMD_0111, |
|
274 GROUP_DPIMM_1000, |
|
275 GROUP_DPIMM_1001, |
|
276 GROUP_BREXSYS_1010, |
|
277 GROUP_BREXSYS_1011, |
|
278 GROUP_LDST_1100, |
|
279 GROUP_DPREG_1101, |
|
280 GROUP_LDST_1110, |
|
281 GROUP_ADVSIMD_1111 |
|
282 }; |
|
283 |
|
284 // bits [31, 29] of a Pseudo are the secondary dispatch vector |
|
285 |
|
286 static inline u_int32_t dispatchPseudo(u_int32_t val) |
|
287 { |
|
288 return pickshift32(val, 31, 29, 0); |
|
289 } |
|
290 |
|
291 /* |
|
292 * the 8 possible values for bits [31,29] in a Pseudo Instruction. |
|
293 * Bits [28,25] are always 0000. |
|
294 */ |
|
295 |
|
296 enum DispatchPseudo { |
|
297 PSEUDO_UNALLOC_000, // unallocated |
|
298 PSEUDO_UNALLOC_001, // ditto |
|
299 PSEUDO_UNALLOC_010, // ditto |
|
300 PSEUDO_UNALLOC_011, // ditto |
|
301 PSEUDO_UNALLOC_100, // ditto |
|
302 PSEUDO_UNALLOC_101, // ditto |
|
303 PSEUDO_CALLOUT_110, // CALLOUT -- bits [24,0] identify call/ret sig |
|
304 PSEUDO_HALT_111 // HALT -- bits [24, 0] identify halt code |
|
305 }; |
|
306 |
|
307 // bits [25, 23] of a DPImm are the secondary dispatch vector |
|
308 |
|
309 static inline u_int32_t dispatchDPImm(u_int32_t instr) |
|
310 { |
|
311 return pickshift32(instr, 25, 23, 0); |
|
312 } |
|
313 |
|
314 /* |
|
315 * the 8 possible values for bits [25,23] in a Data Processing Immediate |
|
316 * Instruction. Bits [28,25] are always 100_. |
|
317 */ |
|
318 |
|
319 enum DispatchDPImm { |
|
320 DPIMM_PCADR_000, // PC-rel-addressing |
|
321 DPIMM_PCADR_001, // ditto |
|
322 DPIMM_ADDSUB_010, // Add/Subtract (immediate) |
|
323 DPIMM_ADDSUB_011, // ditto |
|
324 DPIMM_LOG_100, // Logical (immediate) |
|
325 DPIMM_MOV_101, // Move Wide (immediate) |
|
326 DPIMM_BITF_110, // Bitfield |
|
327 DPIMM_EXTR_111 // Extract |
|
328 }; |
|
329 |
|
330 // bits [29,28:26] of a LS are the secondary dispatch vector |
|
331 |
|
332 static inline u_int32_t dispatchLS(u_int32_t instr) |
|
333 { |
|
334 return (pickshift32(instr, 29, 28, 1) | |
|
335 pickshift32(instr, 26, 26, 0)); |
|
336 } |
|
337 |
|
338 /* |
|
339 * the 8 possible values for bits [29,28:26] in a Load/Store |
|
340 * Instruction. Bits [28,25] are always _1_0 |
|
341 */ |
|
342 |
|
343 enum DispatchLS { |
|
344 LS_EXCL_000, // Load/store exclusive (includes some unallocated) |
|
345 LS_ADVSIMD_001, // AdvSIMD load/store (various -- includes some unallocated) |
|
346 LS_LIT_010, // Load register literal (includes some unallocated) |
|
347 LS_LIT_011, // ditto |
|
348 LS_PAIR_100, // Load/store register pair (various) |
|
349 LS_PAIR_101, // ditto |
|
350 LS_OTHER_110, // other load/store formats |
|
351 LS_OTHER_111 // ditto |
|
352 }; |
|
353 |
|
354 // bits [28:24:21] of a DPReg are the secondary dispatch vector |
|
355 |
|
356 static inline u_int32_t dispatchDPReg(u_int32_t instr) |
|
357 { |
|
358 return (pickshift32(instr, 28, 28, 2) | |
|
359 pickshift32(instr, 24, 24, 1) | |
|
360 pickshift32(instr, 21, 21, 0)); |
|
361 } |
|
362 |
|
363 /* |
|
364 * the 8 possible values for bits [28:24:21] in a Data Processing |
|
365 * Register Instruction. Bits [28,25] are always _101 |
|
366 */ |
|
367 |
|
368 enum DispatchDPReg { |
|
369 DPREG_LOG_000, // Logical (shifted register) |
|
370 DPREG_LOG_001, // ditto |
|
371 DPREG_ADDSHF_010, // Add/subtract (shifted register) |
|
372 DPREG_ADDEXT_011, // Add/subtract (extended register) |
|
373 DPREG_ADDCOND_100, // Add/subtract (with carry) AND |
|
374 // Cond compare/select AND |
|
375 // Data Processing (1/2 source) |
|
376 DPREG_UNALLOC_101, // Unallocated |
|
377 DPREG_3SRC_110, // Data Processing (3 source) |
|
378 DPREG_3SRC_111 // Data Processing (3 source) |
|
379 }; |
|
380 |
|
381 // bits [31,29] of a BrExSys are the secondary dispatch vector |
|
382 |
|
383 static inline u_int32_t dispatchBrExSys(u_int32_t instr) |
|
384 { |
|
385 return pickbits32(instr, 31, 29); |
|
386 } |
|
387 |
|
388 /* |
|
389 * the 8 possible values for bits [31,29] in a Branch/Exception/System |
|
390 * Instruction. Bits [28,25] are always 101_ |
|
391 */ |
|
392 |
|
393 enum DispatchBr { |
|
394 BR_IMM_000, // Unconditional branch (immediate) |
|
395 BR_IMMCMP_001, // Compare & branch (immediate) AND |
|
396 // Test & branch (immediate) |
|
397 BR_IMMCOND_010, // Conditional branch (immediate) AND Unallocated |
|
398 BR_UNALLOC_011, // Unallocated |
|
399 BR_IMM_100, // Unconditional branch (immediate) |
|
400 BR_IMMCMP_101, // Compare & branch (immediate) AND |
|
401 // Test & branch (immediate) |
|
402 BR_REG_110, // Unconditional branch (register) AND System AND |
|
403 // Excn gen AND Unallocated |
|
404 BR_UNALLOC_111 // Unallocated |
|
405 }; |
|
406 |
|
407 /* |
|
408 * TODO still need to provide secondary decode and dispatch for |
|
409 * AdvSIMD Insructions with instr[28,25] = 0111 or 1111 |
|
410 */ |
|
411 |
|
412 #endif // ifndef DECODE_H |
|