/* * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2015, Linaro Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef _DECODE_H #define _DECODE_H #include #include "cpustate_aarch32.hpp" // bitfield immediate expansion helper extern int expandLogicalImmediate(u_int32_t immN, u_int32_t immr, u_int32_t imms, u_int64_t &bimm); /* * codes used in conditional instructions * * these are passed to conditional operations to identify which * condition to test for */ enum CondCode { EQ = 0b0000, // meaning Z == 1 NE = 0b0001, // meaning Z == 0 HS = 0b0010, // meaning C == 1 CS = HS, LO = 0b0011, // meaning C == 0 CC = LO, MI = 0b0100, // meaning N == 1 PL = 0b0101, // meaning N == 0 VS = 0b0110, // meaning V == 1 VC = 0b0111, // meaning V == 0 HI = 0b1000, // meaning C == 1 && Z == 0 LS = 0b1001, // meaning !(C == 1 && Z == 0) GE = 0b1010, // meaning N == V LT = 0b1011, // meaning N != V GT = 0b1100, // meaning Z == 0 && N == V LE = 0b1101, // meaning !(Z == 0 && N == V) AL = 0b1110, // meaning ANY NV = 0b1111 // ditto }; /* * certain addressing modes for load require pre or post writeback of * the computed address to a base register */ enum WriteBack { Post = 0, Pre = 1 }; /* * certain addressing modes for load require an offset to * be optionally scaled so the decode needs to pass that * through to the execute routine */ enum Scaling { Unscaled = 0, Scaled = 1 }; /* * when we do have to scale we do so by shifting using * log(bytes in data element - 1) as the shift count. * so we don't have to scale offsets when loading * bytes. */ enum ScaleShift { ScaleShift16 = 1, ScaleShift32 = 2, ScaleShift64 = 3, ScaleShift128 = 4 }; /* * one of the addressing modes for load requires a 32-bit register * value to be either zero- or sign-extended for these instructions * UXTW or SXTW should be passed * * arithmetic register data processing operations can optionally * extend a portion of the second register value for these * instructions the value supplied must identify the portion of the * register which is to be zero- or sign-exended */ enum Extension { UXTB = 0, UXTH = 1, UXTW = 2, UXTX = 3, SXTB = 4, SXTH = 5, SXTW = 6, SXTX = 7 }; /* * arithmetic and logical register data processing operations * optionally perform a shift on the second register value */ enum Shift { LSL = 0, LSR = 1, ASR = 2, ROR = 3 }; /* * bit twiddling helpers for instruction decode */ // 32 bit mask with bits [hi,...,lo] set static inline u_int32_t mask32(int hi = 31, int lo = 0) { int nbits = (hi + 1) - lo; return ((1 << nbits) - 1) << lo; } static inline u_int64_t mask64(int hi = 63, int lo = 0) { int nbits = (hi + 1) - lo; return ((1L << nbits) - 1) << lo; } // pick bits [hi,...,lo] from val static inline u_int32_t pick32(u_int32_t val, int hi = 31, int lo = 0) { return (val & mask32(hi, lo)); } // pick bits [hi,...,lo] from val static inline u_int64_t pick64(u_int64_t val, int hi = 31, int lo = 0) { return (val & mask64(hi, lo)); } // pick bits [hi,...,lo] from val and shift to [(hi-(newlo - lo)),newlo] static inline u_int32_t pickshift32(u_int32_t val, int hi = 31, int lo = 0, int newlo = 0) { u_int32_t bits = pick32(val, hi, lo); if (lo < newlo) { return (bits << (newlo - lo)); } else { return (bits >> (lo - newlo)); } } // mask [hi,lo] and shift down to start at bit 0 static inline u_int32_t pickbits32(u_int32_t val, int hi = 31, int lo = 0) { return (pick32(val, hi, lo) >> lo); } // mask [hi,lo] and shift down to start at bit 0 static inline u_int64_t pickbits64(u_int64_t val, int hi = 63, int lo = 0) { return (pick64(val, hi, lo) >> lo); } /* * decode registers, immediates and constants of various types */ static inline GReg greg(u_int32_t val, int lo) { return (GReg)pickbits32(val, lo + 4, lo); } static inline VReg vreg(u_int32_t val, int lo) { return (VReg)pickbits32(val, lo + 4, lo); } static inline u_int32_t uimm(u_int32_t val, int hi, int lo) { return pickbits32(val, hi, lo); } static inline int32_t simm(u_int32_t val, int hi = 31, int lo = 0) { union { u_int32_t u; int32_t n; }; u = val << (31 - hi); n = n >> (31 - hi + lo); return n; } static inline int64_t simm(u_int64_t val, int hi = 63, int lo = 0) { union { u_int64_t u; int64_t n; }; u = val << (63 - hi); n = n >> (63 - hi + lo); return n; } static inline Shift shift(u_int32_t val, int lo) { return (Shift)pickbits32(val, lo+1, lo); } static inline Extension extension(u_int32_t val, int lo) { return (Extension)pickbits32(val, lo+2, lo); } static inline Scaling scaling(u_int32_t val, int lo) { return (Scaling)pickbits32(val, lo, lo); } static inline WriteBack writeback(u_int32_t val, int lo) { return (WriteBack)pickbits32(val, lo, lo); } static inline CondCode condcode(u_int32_t val, int lo) { return (CondCode)pickbits32(val, lo+3, lo); } /* * operation decode */ // bits [28,25] are the primary dispatch vector static inline u_int32_t dispatchGroup(u_int32_t val) { return pickshift32(val, 28, 25, 0); } /* * the 16 possible values for bits [28,25] identified by tags which * map them to the 5 main instruction groups LDST, DPREG, ADVSIMD, * BREXSYS and DPIMM. * * An extra group PSEUDO is included in one of the unallocated ranges * for simulator-specific pseudo-instructions. */ enum DispatchGroup { GROUP_PSEUDO_0000, GROUP_UNALLOC_0001, GROUP_UNALLOC_0010, GROUP_UNALLOC_0011, GROUP_LDST_0100, GROUP_DPREG_0101, GROUP_LDST_0110, GROUP_ADVSIMD_0111, GROUP_DPIMM_1000, GROUP_DPIMM_1001, GROUP_BREXSYS_1010, GROUP_BREXSYS_1011, GROUP_LDST_1100, GROUP_DPREG_1101, GROUP_LDST_1110, GROUP_ADVSIMD_1111 }; // bits [31, 29] of a Pseudo are the secondary dispatch vector static inline u_int32_t dispatchPseudo(u_int32_t val) { return pickshift32(val, 31, 29, 0); } /* * the 8 possible values for bits [31,29] in a Pseudo Instruction. * Bits [28,25] are always 0000. */ enum DispatchPseudo { PSEUDO_UNALLOC_000, // unallocated PSEUDO_UNALLOC_001, // ditto PSEUDO_UNALLOC_010, // ditto PSEUDO_UNALLOC_011, // ditto PSEUDO_UNALLOC_100, // ditto PSEUDO_UNALLOC_101, // ditto PSEUDO_CALLOUT_110, // CALLOUT -- bits [24,0] identify call/ret sig PSEUDO_HALT_111 // HALT -- bits [24, 0] identify halt code }; // bits [25, 23] of a DPImm are the secondary dispatch vector static inline u_int32_t dispatchDPImm(u_int32_t instr) { return pickshift32(instr, 25, 23, 0); } /* * the 8 possible values for bits [25,23] in a Data Processing Immediate * Instruction. Bits [28,25] are always 100_. */ enum DispatchDPImm { DPIMM_PCADR_000, // PC-rel-addressing DPIMM_PCADR_001, // ditto DPIMM_ADDSUB_010, // Add/Subtract (immediate) DPIMM_ADDSUB_011, // ditto DPIMM_LOG_100, // Logical (immediate) DPIMM_MOV_101, // Move Wide (immediate) DPIMM_BITF_110, // Bitfield DPIMM_EXTR_111 // Extract }; // bits [29,28:26] of a LS are the secondary dispatch vector static inline u_int32_t dispatchLS(u_int32_t instr) { return (pickshift32(instr, 29, 28, 1) | pickshift32(instr, 26, 26, 0)); } /* * the 8 possible values for bits [29,28:26] in a Load/Store * Instruction. Bits [28,25] are always _1_0 */ enum DispatchLS { LS_EXCL_000, // Load/store exclusive (includes some unallocated) LS_ADVSIMD_001, // AdvSIMD load/store (various -- includes some unallocated) LS_LIT_010, // Load register literal (includes some unallocated) LS_LIT_011, // ditto LS_PAIR_100, // Load/store register pair (various) LS_PAIR_101, // ditto LS_OTHER_110, // other load/store formats LS_OTHER_111 // ditto }; // bits [28:24:21] of a DPReg are the secondary dispatch vector static inline u_int32_t dispatchDPReg(u_int32_t instr) { return (pickshift32(instr, 28, 28, 2) | pickshift32(instr, 24, 24, 1) | pickshift32(instr, 21, 21, 0)); } /* * the 8 possible values for bits [28:24:21] in a Data Processing * Register Instruction. Bits [28,25] are always _101 */ enum DispatchDPReg { DPREG_LOG_000, // Logical (shifted register) DPREG_LOG_001, // ditto DPREG_ADDSHF_010, // Add/subtract (shifted register) DPREG_ADDEXT_011, // Add/subtract (extended register) DPREG_ADDCOND_100, // Add/subtract (with carry) AND // Cond compare/select AND // Data Processing (1/2 source) DPREG_UNALLOC_101, // Unallocated DPREG_3SRC_110, // Data Processing (3 source) DPREG_3SRC_111 // Data Processing (3 source) }; // bits [31,29] of a BrExSys are the secondary dispatch vector static inline u_int32_t dispatchBrExSys(u_int32_t instr) { return pickbits32(instr, 31, 29); } /* * the 8 possible values for bits [31,29] in a Branch/Exception/System * Instruction. Bits [28,25] are always 101_ */ enum DispatchBr { BR_IMM_000, // Unconditional branch (immediate) BR_IMMCMP_001, // Compare & branch (immediate) AND // Test & branch (immediate) BR_IMMCOND_010, // Conditional branch (immediate) AND Unallocated BR_UNALLOC_011, // Unallocated BR_IMM_100, // Unconditional branch (immediate) BR_IMMCMP_101, // Compare & branch (immediate) AND // Test & branch (immediate) BR_REG_110, // Unconditional branch (register) AND System AND // Excn gen AND Unallocated BR_UNALLOC_111 // Unallocated }; /* * TODO still need to provide secondary decode and dispatch for * AdvSIMD Insructions with instr[28,25] = 0111 or 1111 */ #endif // ifndef DECODE_H