* Copyright (c) 2014-2022 Google, Inc. All rights reserved.
* **********************************************************/
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Goole, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#ifndef DECODE_PRIVATE_H
#define DECODE_PRIVATE_H
enum {
INVALID = OP_LAST + 1,
* specify the bottom for multi-bit sets for A32, but list which halfword (A vs
* B) and the range for bitsets for T32. We could normalize the two but having
* them different is a feature.
*/
EXT_OPC4,
EXT_OPC4X,
EXT_OPC4Y,
EXT_IMM1916,
EXT_IMM5,
EXT_BITS0,
EXT_BITS8,
EXT_BIT4,
EXT_BIT5,
EXT_BIT9,
EXT_FP,
EXT_FPA,
EXT_FPB,
EXT_BITS16,
EXT_RAPC,
EXT_RBPC,
EXT_RDPC,
EXT_BIT6,
EXT_BIT7,
EXT_BIT19,
EXT_BIT22,
EXT_BITS20,
EXT_IMM1816,
EXT_IMM2016,
EXT_SIMD6,
EXT_SIMD5,
EXT_SIMD5B,
EXT_SIMD8,
EXT_SIMD6B,
EXT_SIMD2,
EXT_IMM6L,
EXT_VLDA,
EXT_VLDB,
EXT_VLDC,
EXT_VLDD,
EXT_VTB,
EXT_A10_6_4,
EXT_A9_7_eq1,
EXT_B10_8,
EXT_B2_0,
EXT_B5_4,
EXT_B6_4,
EXT_B7_4,
EXT_B7_4_eq1,
EXT_B4,
EXT_B5,
EXT_B7,
EXT_B11,
EXT_B13,
EXT_FOPC8,
EXT_IMM126,
EXT_OPCBX,
EXT_RCPC,
EXT_11,
EXT_11_10,
EXT_11_9,
EXT_11_8,
EXT_10_9,
EXT_10_8,
EXT_10_6,
EXT_9_6,
EXT_7_6,
EXT_7,
EXT_5_4,
EXT_6_4,
EXT_3_0,
};
* We set it first, so we don't need to store 0's explicitly.
*/
* for ARM-style disasm.
*/
* we are free to reorder them. We pick the asm order.
*/
enum {
DECODE_EXTRA_OPERANDS = 0x0001,
DECODE_EXTRA_SHIFT = 0x0002,
DECODE_EXTRA_WRITEBACK = 0x0004,
DECODE_EXTRA_WRITEBACK2 = 0x0008,
DECODE_4_SRCS = 0x0010,
DECODE_3_DSTS = 0x0020,
DECODE_PREDICATE_28 = 0x0040,
DECODE_PREDICATE_28_AL = 0x0080,
DECODE_PREDICATE_22 = 0x0100,
DECODE_PREDICATE_8 = 0x0200,
DECODE_UNPREDICTABLE = 0x0400,
DECODE_ARM_V8 = 0x0800,
DECODE_ARM_VFP = 0x1000,
* bits as we're only using through 0x00000800 now.
*/
};
* we need a way to keep track of IT block state and avoid using stale state
* on encode/decode.
* For decoding, we added pc information in addition to it_block_info_t,
* to only continue if the pc match.
* For encoding, we store the instr pointer to ensure we're still encoding
* in the same block. We briefly tried requiring a call to enable tracking,
* only used during full instrlist encoding, but too many cases perform
* individual encoding (e.g., instr_length()) for that to easily work.
*/
typedef struct _it_block_info_t {
byte num_instrs;
byte firstcond;
byte preds;
* work around it in encode_in_it_block(), where we assume 4 bits.
*/
char cur_instr : 4;
} it_block_info_t;
typedef struct _encode_state_t {
it_block_info_t itb_info;
instr_t *instr;
} encode_state_t;
typedef struct _decode_state_t {
it_block_info_t itb_info;
app_pc pc;
} decode_state_t;
* + for EXTENSION and *_EXT: index into extensions table
* + for OP_: pointer to next entry of that opcode
* + may also point to extra operand table
*/
struct _decode_info_t {
dr_isa_mode_t isa_mode;
* (to match our table opcodes, for easier human reading, and to enable
* sharing the A32 bit position labels). This does NOT match the little-endian
* encoding of both halfwords as one doubleword: this matches big-endian.
*/
uint instr_word;
ushort halfwordA;
ushort halfwordB;
bool T32_16;
uint opcode;
uint predicate;
bool check_reachable;
byte *start_pc;
byte *final_pc;
byte *orig_pc;
byte *decorated_pc;
ptr_int_t cur_offs;
bool has_instr_opnds;
decode_state_t decode_state;
encode_state_t encode_state;
* The rest of the fields are zeroed when encoding each template
*/
const char *errmsg;
int errmsg_param;
* decode_debug_checks_arch()).
*/
int reglist_sz;
opnd_t *mem_needs_reglist_sz;
bool mem_adjust_disp_for_reglist;
uint reglist_start;
uint reglist_stop;
bool reglist_simd;
opnd_size_t reglist_itemsz;
uint reglist_min_num;
int memop_sz;
* adjacent immediates. This is set to point at the first one.
*/
bool shift_has_type;
uint shift_type_idx;
bool shift_uses_immed;
dr_shift_type_t shift_type;
bool shift_1bit;
* the memory operand, but also have the same elements separate for writeback
* or post-indexed addressing. We need to make sure they match.
* We assume that the writeback/postindex args are sources that are later
* in the src array than memop, if memop is a source.
*/
reg_id_t check_wb_base;
reg_id_t check_wb_index;
opnd_size_t check_wb_disp_sz;
int check_wb_disp;
bool check_wb_shift;
uint check_wb_shift_type;
uint check_wb_shift_amount;
uint mod_imm_enc;
};
typedef struct _op_to_instr_info_t {
const instr_info_t *const A32;
const instr_info_t *const T32;
const instr_info_t *const T32_it;
} op_to_instr_info_t;
* them, kept in encode.c
*/
* the operand is encoded, and the type of operand.
* For T32.32, we share the A32 bit labels by considering halfwordA to be
* placed above halfwordB to form a big-endian doubleword.
*/
enum {
TYPE_NONE,
* XXX: Rd is T32-11:8; T32.16-2:0; A64-4:0 so not always "C"
*
* XXX: record which registers are "unpredictable" if PC (or SP, or LR) is
* passed? Many are, for many different opcodes.
*/
TYPE_R_A,
TYPE_R_B,
TYPE_R_C,
TYPE_R_D,
TYPE_R_U,
TYPE_R_V,
TYPE_R_W,
TYPE_R_X,
TYPE_R_Y,
TYPE_R_Z,
TYPE_R_V_DUP,
TYPE_R_W_DUP,
TYPE_R_Z_DUP,
TYPE_R_A_TOP,
TYPE_R_B_TOP,
TYPE_R_C_TOP,
TYPE_R_D_TOP,
TYPE_R_D_NEGATED,
TYPE_R_B_EVEN,
TYPE_R_B_PLUS1,
TYPE_R_D_EVEN,
TYPE_R_D_PLUS1,
TYPE_R_A_EQ_D,
TYPE_CR_A,
TYPE_CR_B,
TYPE_CR_C,
TYPE_CR_D,
TYPE_V_A,
TYPE_V_B,
TYPE_V_C,
TYPE_V_C_3b,
TYPE_V_C_4b,
TYPE_W_A,
TYPE_W_B,
TYPE_W_C,
TYPE_W_C_PLUS1,
TYPE_SPSR,
TYPE_CPSR,
TYPE_FPSCR,
TYPE_LR,
TYPE_SP,
TYPE_PC,
* need to add handling for that.
*/
* different sizes. We considered storing a bitmask to cover any type
* of immediate, but there are few enough that we are enumerating them.
* For split types, our type + the size does not specify how many bits are at
* each bit location: we rely on the decoder and encoder enumerating all the
* possibilities.
*/
TYPE_I_b0,
TYPE_I_x4_b0,
TYPE_I_SHIFTED_b0,
TYPE_NI_b0,
TYPE_NI_x4_b0,
TYPE_I_b3,
TYPE_I_b4,
TYPE_I_b5,
TYPE_I_b6,
TYPE_I_b7,
TYPE_I_b8,
TYPE_I_b9,
TYPE_I_b10,
TYPE_I_b16,
TYPE_I_b17,
TYPE_I_b18,
TYPE_I_b19,
TYPE_I_b20,
TYPE_I_b21,
TYPE_I_b0_b5,
TYPE_I_b4_b8,
TYPE_I_b4_b16,
TYPE_I_b5_b3,
TYPE_I_b8_b0,
TYPE_NI_b8_b0,
TYPE_I_b8_b16,
TYPE_I_b8_b24_b16_b0,
TYPE_I_b8_b28_b16_b0,
TYPE_I_b12_b6,
TYPE_I_b16_b0,
TYPE_I_b16_b26_b12_b0,
TYPE_I_b21_b5,
TYPE_I_b21_b6,
TYPE_I_b26_b12_b0,
TYPE_I_b26_b12_b0_z,
TYPE_J_b0,
TYPE_J_x4_b0,
TYPE_J_b0_b24,
TYPE_J_b9_b3,
TYPE_J_b26_b11_b13_b16_b0,
TYPE_J_b26_b13_b11_b16_b0,
TYPE_SHIFT_b4,
TYPE_SHIFT_b5,
TYPE_SHIFT_b6,
TYPE_SHIFT_b21,
TYPE_SHIFT_LSL,
TYPE_SHIFT_ASR,
TYPE_L_8b,
TYPE_L_9b_LR,
TYPE_L_9b_PC,
TYPE_L_16b,
TYPE_L_16b_NO_SP,
TYPE_L_16b_NO_SP_PC,
TYPE_L_CONSEC,
* count in immed 7:0
*/
TYPE_L_VBx2,
TYPE_L_VBx3,
TYPE_L_VBx4,
TYPE_L_VBx2D,
TYPE_L_VBx3D,
TYPE_L_VBx4D,
TYPE_L_VAx2,
TYPE_L_VAx3,
TYPE_L_VAx4,
* A32: base = RA 19:16 ("Rn" in manual)
* index = RD 3:0 ("Rm" in manual)
* T32.32: base = RA 19:16 ("Rn" in manual)
* index = RD 3:0 ("Rm" in manual)
*
* T32.16 may use fixed register for index but different register for base.
* T32.16: base = RY 5:3 ("Rn" in manual)
* RW 10:8 ("Rn" in manual) for ldm/stm
* index = RX 8:6 ("Rm" in manual)
*
* A64: base =
* index =
*
* Shifted registers always use sh2, i5.
*
* To be compatible w/ x86, we don't want to list the index, offset, or shift
* operands separately for regular offset addressing: we want to hide them
* inside the memref. So we have to record exactly how to decode and encode
* each piece.
*
* We don't encode in the memref whether it has writeback ("[Rn + Rm]!") or
* is post-indexed ("[Rn], Rm"): the disassembler has to look at the other
* opnds to figure out how to write down the memref, and single-memref-opnd
* disasm will NOT contain writeback or post-index info.
*/
TYPE_M,
TYPE_M_SP,
TYPE_M_POS_REG,
TYPE_M_NEG_REG,
TYPE_M_POS_SHREG,
TYPE_M_NEG_SHREG,
TYPE_M_POS_LSHREG,
TYPE_M_POS_LSH1REG,
TYPE_M_POS_I12,
TYPE_M_NEG_I12,
TYPE_M_SI9,
TYPE_M_POS_I8,
TYPE_M_NEG_I8,
TYPE_M_POS_I8x4,
TYPE_M_NEG_I8x4,
TYPE_M_SP_POS_I8x4,
TYPE_M_POS_I4_4,
TYPE_M_NEG_I4_4,
TYPE_M_SI7,
TYPE_M_POS_I5,
TYPE_M_POS_I5x2,
TYPE_M_POS_I5x4,
TYPE_M_PCREL_POS_I8x4,
TYPE_M_PCREL_POS_I12,
TYPE_M_PCREL_NEG_I12,
TYPE_M_PCREL_S9,
TYPE_M_PCREL_U9,
TYPE_M_UP_OFFS,
TYPE_M_DOWN,
TYPE_M_DOWN_OFFS,
TYPE_M_SP_DOWN_OFFS,
TYPE_K,
TYPE_BEYOND_LAST_ENUM,
DECODE_INDEX_SHIFT_TYPE_BITPOS_A32 = 5,
DECODE_INDEX_SHIFT_TYPE_SIZE = OPSZ_2b,
DECODE_INDEX_SHIFT_AMOUNT_BITPOS_A32 = 7,
DECODE_INDEX_SHIFT_AMOUNT_SIZE_A32 = OPSZ_5b,
DECODE_INDEX_SHIFT_AMOUNT_BITPOS_T32 = 4,
DECODE_INDEX_SHIFT_AMOUNT_SIZE_T32 = OPSZ_2b,
SHIFT_ENCODING_DECODE = -1,
SHIFT_ENCODING_LSL = 0,
SHIFT_ENCODING_LSR = 1,
SHIFT_ENCODING_ASR = 2,
SHIFT_ENCODING_ROR = 3,
SHIFT_ENCODING_RRX = 3,
};
extern const instr_info_t A32_pred_opc8[];
extern const instr_info_t A32_ext_opc4x[][6];
extern const instr_info_t A32_ext_opc4y[][9];
extern const instr_info_t A32_ext_opc4[][16];
extern const instr_info_t A32_ext_imm1916[][3];
extern const instr_info_t A32_ext_bits0[][8];
extern const instr_info_t A32_ext_bits8[][4];
extern const instr_info_t A32_ext_bit9[][2];
extern const instr_info_t A32_ext_bit5[][2];
extern const instr_info_t A32_ext_bit4[][2];
extern const instr_info_t A32_ext_fp[][3];
extern const instr_info_t A32_ext_opc4fpA[][3];
extern const instr_info_t A32_ext_opc4fpB[][8];
extern const instr_info_t A32_ext_bits16[][16];
extern const instr_info_t A32_ext_RAPC[][2];
extern const instr_info_t A32_ext_RBPC[][2];
extern const instr_info_t A32_ext_RDPC[][2];
extern const instr_info_t A32_ext_imm5[][2];
extern const instr_info_t A32_extra_operands[];
extern const instr_info_t A32_unpred_opc7[];
extern const instr_info_t A32_ext_bits20[][16];
extern const instr_info_t A32_ext_imm2016[][2];
extern const instr_info_t A32_ext_imm1816[][2];
extern const instr_info_t A32_ext_bit7[][2];
extern const instr_info_t A32_ext_bit6[][2];
extern const instr_info_t A32_ext_bit19[][2];
extern const instr_info_t A32_ext_bit22[][2];
extern const instr_info_t A32_ext_simd6[][64];
extern const instr_info_t A32_ext_simd5[][32];
extern const instr_info_t A32_ext_simd5b[][32];
extern const instr_info_t A32_ext_simd8[][80];
extern const instr_info_t A32_ext_simd6b[][36];
extern const instr_info_t A32_ext_simd2[][4];
extern const instr_info_t A32_ext_imm6L[][16];
extern const instr_info_t A32_ext_vldA[][132];
extern const instr_info_t A32_ext_vldB[][96];
extern const instr_info_t A32_ext_vldC[][24];
extern const instr_info_t A32_ext_vldD[][48];
extern const instr_info_t A32_ext_vtb[][9];
extern const instr_info_t T32_base_e[];
extern const instr_info_t T32_base_f[];
extern const instr_info_t T32_ext_fopc8[][192];
extern const instr_info_t T32_ext_A9_7_eq1[][2];
extern const instr_info_t T32_ext_bits_A10_6_4[][16];
extern const instr_info_t T32_ext_opcBX[][9];
extern const instr_info_t T32_ext_bits_B10_8[][8];
extern const instr_info_t T32_ext_bits_B7_4[][16];
extern const instr_info_t T32_ext_B7_4_eq1[][8];
extern const instr_info_t T32_ext_bits_B6_4[][8];
extern const instr_info_t T32_ext_bits_B5_4[][4];
extern const instr_info_t T32_ext_bits_B2_0[][8];
extern const instr_info_t T32_ext_bit_B4[][2];
extern const instr_info_t T32_ext_bit_B5[][2];
extern const instr_info_t T32_ext_bit_B7[][2];
extern const instr_info_t T32_ext_bit_B11[][2];
extern const instr_info_t T32_ext_bit_B13[][2];
extern const instr_info_t T32_ext_RAPC[][2];
extern const instr_info_t T32_ext_RBPC[][2];
extern const instr_info_t T32_ext_RCPC[][2];
extern const instr_info_t T32_ext_imm126[][2];
extern const instr_info_t T32_extra_operands[];
extern const instr_info_t T32_coproc_e[];
extern const instr_info_t T32_coproc_f[];
extern const instr_info_t T32_ext_fp[][3];
extern const instr_info_t T32_ext_opc4[][16];
extern const instr_info_t T32_ext_imm1916[][3];
extern const instr_info_t T32_ext_opc4fpA[][3];
extern const instr_info_t T32_ext_opc4fpB[][8];
extern const instr_info_t T32_ext_bits16[][16];
extern const instr_info_t T32_ext_bits20[][16];
extern const instr_info_t T32_ext_imm2016[][2];
extern const instr_info_t T32_ext_imm1816[][2];
extern const instr_info_t T32_ext_bit6[][2];
extern const instr_info_t T32_ext_bit19[][2];
extern const instr_info_t T32_ext_simd6[][64];
extern const instr_info_t T32_ext_simd5[][32];
extern const instr_info_t T32_ext_simd5b[][32];
extern const instr_info_t T32_ext_simd8[][80];
extern const instr_info_t T32_ext_simd6b[][36];
extern const instr_info_t T32_ext_simd2[][4];
extern const instr_info_t T32_ext_imm6L[][16];
extern const instr_info_t T32_ext_vldA[][132];
extern const instr_info_t T32_ext_vldB[][96];
extern const instr_info_t T32_ext_vldC[][24];
extern const instr_info_t T32_ext_vldD[][48];
extern const instr_info_t T32_ext_vtb[][9];
extern const instr_info_t T32_16_opc4[];
extern const instr_info_t T32_16_ext_bit_11[][2];
extern const instr_info_t T32_16_ext_bits_11_10[][4];
extern const instr_info_t T32_16_ext_bits_11_9[][8];
extern const instr_info_t T32_16_ext_bits_11_8[][16];
extern const instr_info_t T32_16_ext_bits_9_6[][16];
extern const instr_info_t T32_16_ext_bit_7[][2];
extern const instr_info_t T32_16_ext_bits_5_4[][4];
extern const instr_info_t T32_16_ext_bits_10_9[][4];
extern const instr_info_t T32_16_ext_bits_10_8[][2];
extern const instr_info_t T32_16_ext_bits_7_6[][4];
extern const instr_info_t T32_16_ext_bits_6_4[][8];
extern const instr_info_t T32_16_ext_imm_10_6[][2];
extern const instr_info_t T32_16_ext_imm_3_0[][2];
extern const instr_info_t T32_16_it_opc4[];
extern const instr_info_t T32_16_it_ext_bit_11[][2];
extern const instr_info_t T32_16_it_ext_bits_11_10[][4];
extern const instr_info_t T32_16_it_ext_bits_11_9[][8];
extern const instr_info_t T32_16_it_ext_bits_11_8[][16];
extern const instr_info_t T32_16_it_ext_bits_9_6[][16];
extern const instr_info_t T32_16_it_ext_bit_7[][2];
extern const instr_info_t T32_16_it_ext_bits_10_9[][4];
extern const instr_info_t T32_16_it_ext_bits_10_8[][2];
extern const instr_info_t T32_16_it_ext_bits_7_6[][4];
extern const instr_info_t T32_16_it_ext_bits_6_4[][8];
extern const instr_info_t T32_16_it_ext_imm_10_6[][2];
extern const op_to_instr_info_t op_instr[];
opnd_size_t
resolve_size_upward(opnd_size_t size);
opnd_size_t
resolve_size_downward(opnd_size_t size);
bool
optype_is_reg(int optype);
bool
optype_is_gpr(int optype);
uint
gpr_list_num_bits(byte optype);
void
it_block_info_init_immeds(it_block_info_t *info, byte mask, byte firstcond);
void
it_block_info_init(it_block_info_t *info, decode_info_t *di);
static inline void
it_block_info_reset(it_block_info_t *info)
{
*(uint *)info = 0;
}
* - return true if still in the IT block,
* - return false if finish current IT block
*/
static inline bool
it_block_info_advance(it_block_info_t *info)
{
ASSERT(info->num_instrs != 0);
if (++info->cur_instr == info->num_instrs)
return false;
return true;
}
static inline dr_pred_type_t
it_block_instr_predicate(it_block_info_t info, uint index)
{
return (
DR_PRED_EQ +
(TEST(BITMAP_MASK(index), info.preds) ? info.firstcond : (info.firstcond ^ 0x1)));
}
#endif