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