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
33extern 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 */
43enum 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 */
68enum 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 */
78enum 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 */
89enum 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 */
106enum 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 */
121enum 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
134static 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
140static 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
147static 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
153static 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]
159static 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
170static 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
176static 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
185static inline GReg greg(u_int32_t val, int lo)
186{
187  return (GReg)pickbits32(val, lo + 4, lo);
188}
189
190static inline VReg vreg(u_int32_t val, int lo)
191{
192  return (VReg)pickbits32(val, lo + 4, lo);
193}
194
195static inline u_int32_t uimm(u_int32_t val, int hi, int lo)
196{
197  return pickbits32(val, hi, lo);
198}
199
200static 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
211static 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
222static inline Shift shift(u_int32_t val, int lo)
223{
224  return (Shift)pickbits32(val, lo+1, lo);
225}
226
227static inline Extension extension(u_int32_t val, int lo)
228{
229  return (Extension)pickbits32(val, lo+2, lo);
230}
231
232static inline Scaling scaling(u_int32_t val, int lo)
233{
234  return (Scaling)pickbits32(val, lo, lo);
235}
236
237static inline WriteBack writeback(u_int32_t val, int lo)
238{
239  return (WriteBack)pickbits32(val, lo, lo);
240}
241
242static 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
252static 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 */
265enum 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
286static 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
296enum 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
309static 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
319enum 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
332static 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
343enum 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
356static 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
368enum 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
383static 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
393enum 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
413