X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Faarch64-dis.c;h=6567880efbaaeea5e1f2aa026df99059e9bb7471;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=e7bece9c1ac4b444dfcd7a35a18d1809d94c734d;hpb=b3ac5c6c286c5b5c1909628e85754edfb403cf1a;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index e7bece9c1a..6567880efb 100644 --- a/opcodes/aarch64-dis.c +++ b/opcodes/aarch64-dis.c @@ -1,5 +1,5 @@ /* aarch64-dis.c -- AArch64 disassembler. - Copyright (C) 2009-2018 Free Software Foundation, Inc. + Copyright (C) 2009-2020 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of the GNU opcodes library. @@ -26,11 +26,6 @@ #include "aarch64-dis.h" #include "elf-bfd.h" -#define ERR_OK 0 -#define ERR_UND -1 -#define ERR_UNP -3 -#define ERR_NYI -5 - #define INSNLEN 4 /* Cached mapping symbol state. */ @@ -42,11 +37,16 @@ enum map_type static enum map_type last_type; static int last_mapping_sym = -1; +static bfd_vma last_stop_offset = 0; static bfd_vma last_mapping_addr = 0; /* Other options */ static int no_aliases = 0; /* If set disassemble as most general inst. */ - + static int no_notes = 1; /* If set do not print disassemble notes in the + output as comments. */ + +/* Currently active instruction sequence. */ +static aarch64_instr_sequence insn_sequence; static void set_default_aarch64_dis_options (struct disassemble_info *info ATTRIBUTE_UNUSED) @@ -69,6 +69,18 @@ parse_aarch64_dis_option (const char *option, unsigned int len ATTRIBUTE_UNUSED) return; } + if (CONST_STRNEQ (option, "no-notes")) + { + no_notes = 1; + return; + } + + if (CONST_STRNEQ (option, "notes")) + { + no_notes = 0; + return; + } + #ifdef DEBUG_AARCH64 if (CONST_STRNEQ (option, "debug_dump")) { @@ -166,18 +178,15 @@ extract_all_fields (const aarch64_operand *self, aarch64_insn code) } /* Sign-extend bit I of VALUE. */ -static inline int32_t +static inline uint64_t sign_extend (aarch64_insn value, unsigned i) { - uint32_t ret = value; + uint64_t ret, sign; assert (i < 32); - if ((value >> i) & 0x1) - { - uint32_t val = (uint32_t)(-1) << i; - ret = ret | val; - } - return (int32_t) ret; + ret = value; + sign = (uint64_t) 1 << i; + return ((ret & (sign + sign - 1)) ^ sign) - sign; } /* N.B. the following inline helpfer functions create a dependency on the @@ -242,31 +251,44 @@ get_expected_qualifier (const aarch64_inst *inst, int i) /* Operand extractors. */ -int +bfd_boolean +aarch64_ext_none (const aarch64_operand *self ATTRIBUTE_UNUSED, + aarch64_opnd_info *info ATTRIBUTE_UNUSED, + const aarch64_insn code ATTRIBUTE_UNUSED, + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) +{ + return TRUE; +} + +bfd_boolean aarch64_ext_regno (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { info->reg.regno = extract_field (self->fields[0], code, 0); - return 1; + return TRUE; } -int +bfd_boolean aarch64_ext_regno_pair (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, const aarch64_insn code ATTRIBUTE_UNUSED, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { assert (info->idx == 1 || info->idx ==3); info->reg.regno = inst->operands[info->idx - 1].reg.regno + 1; - return 1; + return TRUE; } /* e.g. IC {, }. */ -int +bfd_boolean aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { info->reg.regno = extract_field (self->fields[0], code, 0); assert (info->idx == 1 @@ -277,14 +299,15 @@ aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info, not. */ info->present = aarch64_sys_ins_reg_has_xt (inst->operands[0].sysins_op); - return 1; + return TRUE; } /* e.g. SQDMLAL , , .[]. */ -int +bfd_boolean aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { /* regno */ info->reglane.regno = extract_field (self->fields[0], code, @@ -320,7 +343,7 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, while (++pos <= 3 && (value & 0x1) == 0) value >>= 1; if (pos > 3) - return 0; + return FALSE; info->qualifier = get_sreg_qualifier_from_value (pos); info->reglane.index = (unsigned) (value >> 1); } @@ -332,12 +355,13 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, switch (info->qualifier) { case AARCH64_OPND_QLF_S_4B: + case AARCH64_OPND_QLF_S_2H: /* L:H */ info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L); info->reglane.regno &= 0x1f; break; default: - return 0; + return FALSE; } } else if (inst->opcode->iclass == cryptosm3) @@ -355,10 +379,18 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, switch (info->qualifier) { case AARCH64_OPND_QLF_S_H: - /* h:l:m */ - info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L, - FLD_M); - info->reglane.regno &= 0xf; + if (info->type == AARCH64_OPND_Em16) + { + /* h:l:m */ + info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L, + FLD_M); + info->reglane.regno &= 0xf; + } + else + { + /* h:l */ + info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L); + } break; case AARCH64_OPND_QLF_S_S: /* h:l */ @@ -369,38 +401,41 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, info->reglane.index = extract_field (FLD_H, code, 0); break; default: - return 0; + return FALSE; } - if (inst->opcode->op == OP_FCMLA_ELEM) + if (inst->opcode->op == OP_FCMLA_ELEM + && info->qualifier != AARCH64_OPND_QLF_S_H) { /* Complex operand takes two elements. */ if (info->reglane.index & 1) - return 0; + return FALSE; info->reglane.index /= 2; } } - return 1; + return TRUE; } -int +bfd_boolean aarch64_ext_reglist (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { /* R */ info->reglist.first_regno = extract_field (self->fields[0], code, 0); /* len */ info->reglist.num_regs = extract_field (FLD_len, code, 0) + 1; - return 1; + return TRUE; } /* Decode Rt and opcode fields of Vt in AdvSIMD load/store instructions. */ -int +bfd_boolean aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst) + const aarch64_inst *inst, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { aarch64_insn value; /* Number of elements in each structure to be loaded/stored. */ @@ -431,20 +466,21 @@ aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED, value = extract_field (FLD_opcode, code, 0); /* PR 21595: Check for a bogus value. */ if (value >= ARRAY_SIZE (data)) - return 0; + return FALSE; if (expected_num != data[value].num_elements || data[value].is_reserved) - return 0; + return FALSE; info->reglist.num_regs = data[value].num_regs; - return 1; + return TRUE; } /* Decode Rt and S fields of Vt in AdvSIMD load single structure to all lanes instructions. */ -int +bfd_boolean aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst) + const aarch64_inst *inst, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { aarch64_insn value; @@ -462,15 +498,16 @@ aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED, if (info->reglist.num_regs == 1 && value == (aarch64_insn) 1) info->reglist.num_regs = 2; - return 1; + return TRUE; } /* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD load/store single element instructions. */ -int +bfd_boolean aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { aarch64_field field = {0, 0}; aarch64_insn QSsize; /* fields Q:S:size. */ @@ -493,7 +530,7 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED, case 0x1: if (QSsize & 0x1) /* UND. */ - return 0; + return FALSE; info->qualifier = AARCH64_OPND_QLF_S_H; /* Index encoded in "Q:S:size<1>". */ info->reglist.index = QSsize >> 1; @@ -501,7 +538,7 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED, case 0x2: if ((QSsize >> 1) & 0x1) /* UND. */ - return 0; + return FALSE; if ((QSsize & 0x1) == 0) { info->qualifier = AARCH64_OPND_QLF_S_S; @@ -512,14 +549,14 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED, { if (extract_field (FLD_S, code, 0)) /* UND */ - return 0; + return FALSE; info->qualifier = AARCH64_OPND_QLF_S_D; /* Index encoded in "Q". */ info->reglist.index = QSsize >> 3; } break; default: - return 0; + return FALSE; } info->reglist.has_index = 1; @@ -529,17 +566,18 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED, info->reglist.num_regs = get_opcode_dependent_value (inst->opcode); assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4); - return 1; + return TRUE; } /* Decode fields immh:immb and/or Q for e.g. SSHR ., ., # or SSHR , , #. */ -int +bfd_boolean aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst) + const aarch64_inst *inst, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { int pos; aarch64_insn Q, imm, immh; @@ -547,7 +585,7 @@ aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED, immh = extract_field (FLD_immh, code, 0); if (immh == 0) - return 0; + return FALSE; imm = extract_fields (code, 0, 2, FLD_immh, FLD_immb); pos = 4; /* Get highest set bit in immh. */ @@ -595,14 +633,15 @@ aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED, 1xxx (UInt(immh:immb)-64) */ info->imm.value = imm - (8 << pos); - return 1; + return TRUE; } /* Decode shift immediate for e.g. sshr (imm). */ -int +bfd_boolean aarch64_ext_shll_imm (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { int64_t imm; aarch64_insn val; @@ -612,20 +651,21 @@ aarch64_ext_shll_imm (const aarch64_operand *self ATTRIBUTE_UNUSED, case 0: imm = 8; break; case 1: imm = 16; break; case 2: imm = 32; break; - default: return 0; + default: return FALSE; } info->imm.value = imm; - return 1; + return TRUE; } /* Decode imm for e.g. BFM , , #, #. value in the field(s) will be extracted as unsigned immediate value. */ -int +bfd_boolean aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { - int64_t imm; + uint64_t imm; imm = extract_all_fields (self, code); @@ -634,33 +674,37 @@ aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info, if (operand_need_shift_by_two (self)) imm <<= 2; + else if (operand_need_shift_by_four (self)) + imm <<= 4; if (info->type == AARCH64_OPND_ADDR_ADRP) imm <<= 12; info->imm.value = imm; - return 1; + return TRUE; } /* Decode imm and its shifter for e.g. MOVZ , #{, LSL #}. */ -int +bfd_boolean aarch64_ext_imm_half (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors) { - aarch64_ext_imm (self, info, code, inst); + aarch64_ext_imm (self, info, code, inst, errors); info->shifter.kind = AARCH64_MOD_LSL; info->shifter.amount = extract_field (FLD_hw, code, 0) << 4; - return 1; + return TRUE; } /* Decode cmode and "a:b:c:d:e:f:g:h" for e.g. MOVI ., # {, LSL #}. */ -int +bfd_boolean aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { uint64_t imm; enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier; @@ -704,7 +748,7 @@ aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED, case 4: gen_sub_field (FLD_cmode, 1, 2, &field); break; /* per word */ case 2: gen_sub_field (FLD_cmode, 1, 1, &field); break; /* per half */ case 1: gen_sub_field (FLD_cmode, 1, 0, &field); break; /* per byte */ - default: assert (0); return 0; + default: assert (0); return FALSE; } /* 00: 0; 01: 8; 10:16; 11:24. */ info->shifter.amount = extract_field_2 (&field, code, 0) << 3; @@ -717,63 +761,68 @@ aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED, break; default: assert (0); - return 0; + return FALSE; } - return 1; + return TRUE; } /* Decode an 8-bit floating-point immediate. */ -int +bfd_boolean aarch64_ext_fpimm (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { info->imm.value = extract_all_fields (self, code); info->imm.is_fp = 1; - return 1; + return TRUE; } /* Decode a 1-bit rotate immediate (#90 or #270). */ -int +bfd_boolean aarch64_ext_imm_rotate1 (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { uint64_t rot = extract_field (self->fields[0], code, 0); assert (rot < 2U); info->imm.value = rot * 180 + 90; - return 1; + return TRUE; } /* Decode a 2-bit rotate immediate (#0, #90, #180 or #270). */ -int +bfd_boolean aarch64_ext_imm_rotate2 (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { uint64_t rot = extract_field (self->fields[0], code, 0); assert (rot < 4U); info->imm.value = rot * 90; - return 1; + return TRUE; } /* Decode scale for e.g. SCVTF
, , #. */ -int +bfd_boolean aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { info->imm.value = 64- extract_field (FLD_scale, code, 0); - return 1; + return TRUE; } /* Decode arithmetic immediate for e.g. SUBS , , # {, }. */ -int +bfd_boolean aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { aarch64_insn value; @@ -781,18 +830,18 @@ aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED, /* shift */ value = extract_field (FLD_shift, code, 0); if (value >= 2) - return 0; + return FALSE; info->shifter.amount = value ? 12 : 0; /* imm12 (unsigned) */ info->imm.value = extract_field (FLD_imm12, code, 0); - return 1; + return TRUE; } /* Return true if VALUE is a valid logical immediate encoding, storing the decoded value in *RESULT if so. ESIZE is the number of bytes in the decoded immediate. */ -static int +static bfd_boolean decode_limm (uint32_t esize, aarch64_insn value, int64_t *result) { uint64_t imm, mask; @@ -820,7 +869,7 @@ decode_limm (uint32_t esize, aarch64_insn value, int64_t *result) case 0x30 ... 0x37: /* 110xxx */ simd_size = 8; S &= 0x7; break; case 0x38 ... 0x3b: /* 1110xx */ simd_size = 4; S &= 0x3; break; case 0x3c ... 0x3d: /* 11110x */ simd_size = 2; S &= 0x1; break; - default: return 0; + default: return FALSE; } mask = (1ull << simd_size) - 1; /* Top bits are IGNORED. */ @@ -828,11 +877,11 @@ decode_limm (uint32_t esize, aarch64_insn value, int64_t *result) } if (simd_size > esize * 8) - return 0; + return FALSE; /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */ if (S == simd_size - 1) - return 0; + return FALSE; /* S+1 consecutive bits to 1. */ /* NOTE: S can't be 63 due to detection above. */ imm = (1ull << (S + 1)) - 1; @@ -858,14 +907,15 @@ decode_limm (uint32_t esize, aarch64_insn value, int64_t *result) *result = imm & ~((uint64_t) -1 << (esize * 4) << (esize * 4)); - return 1; + return TRUE; } /* Decode a logical immediate for e.g. ORR , , #. */ -int +bfd_boolean aarch64_ext_limm (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst) + const aarch64_inst *inst, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { uint32_t esize; aarch64_insn value; @@ -877,23 +927,25 @@ aarch64_ext_limm (const aarch64_operand *self, } /* Decode a logical immediate for the BIC alias of AND (etc.). */ -int +bfd_boolean aarch64_ext_inv_limm (const aarch64_operand *self, aarch64_opnd_info *info, const aarch64_insn code, - const aarch64_inst *inst) + const aarch64_inst *inst, + aarch64_operand_error *errors) { - if (!aarch64_ext_limm (self, info, code, inst)) - return 0; + if (!aarch64_ext_limm (self, info, code, inst, errors)) + return FALSE; info->imm.value = ~info->imm.value; - return 1; + return TRUE; } /* Decode Ft for e.g. STR , [, {, {}}] or LDP , , [], #. */ -int +bfd_boolean aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, - const aarch64_insn code, const aarch64_inst *inst) + const aarch64_insn code, const aarch64_inst *inst, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { aarch64_insn value; @@ -913,7 +965,7 @@ aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED, case 0: qualifier = AARCH64_OPND_QLF_S_S; break; case 1: qualifier = AARCH64_OPND_QLF_S_D; break; case 2: qualifier = AARCH64_OPND_QLF_S_Q; break; - default: return 0; + default: return FALSE; } info->qualifier = qualifier; } @@ -922,31 +974,33 @@ aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED, /* opc1:size */ value = extract_fields (code, 0, 2, FLD_opc1, FLD_ldst_size); if (value > 0x4) - return 0; + return FALSE; info->qualifier = get_sreg_qualifier_from_value (value); } - return 1; + return TRUE; } /* Decode the address operand for e.g. STXRB , , [{,#0}]. */ -int +bfd_boolean aarch64_ext_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { /* Rn */ info->addr.base_regno = extract_field (FLD_Rn, code, 0); - return 1; + return TRUE; } /* Decode the address operand for e.g. stlur , [{, }]. */ -int +bfd_boolean aarch64_ext_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, - aarch64_insn code, const aarch64_inst *inst) + aarch64_insn code, const aarch64_inst *inst, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { info->qualifier = get_expected_qualifier (inst, info->idx); @@ -960,15 +1014,16 @@ aarch64_ext_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED, info->addr.writeback = 1; info->addr.preind = 1; } - return 1; + return TRUE; } /* Decode the address operand for e.g. STR , [, {, {}}]. */ -int +bfd_boolean aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, - aarch64_insn code, const aarch64_inst *inst) + aarch64_insn code, const aarch64_inst *inst, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { aarch64_insn S, value; @@ -1004,13 +1059,14 @@ aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED, info->shifter.amount_present = 1; } - return 1; + return TRUE; } /* Decode the address operand for e.g. LDRSW , [], #. */ -int +bfd_boolean aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info, - aarch64_insn code, const aarch64_inst *inst) + aarch64_insn code, const aarch64_inst *inst, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { aarch64_insn imm; info->qualifier = get_expected_qualifier (inst, info->idx); @@ -1020,7 +1076,8 @@ aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info, /* simm (imm9 or imm7) */ imm = extract_field (self->fields[0], code, 0); info->addr.offset.imm = sign_extend (imm, fields[self->fields[0]].width - 1); - if (self->fields[0] == FLD_imm7) + if (self->fields[0] == FLD_imm7 + || info->qualifier == AARCH64_OPND_QLF_imm_tag) /* scaled immediate in ld/st pair instructions. */ info->addr.offset.imm *= aarch64_get_qualifier_esize (info->qualifier); /* qualifier */ @@ -1039,14 +1096,15 @@ aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info, info->addr.postind = 1; } - return 1; + return TRUE; } /* Decode the address operand for e.g. LDRSW , [{, #}]. */ -int +bfd_boolean aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info, aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { int shift; info->qualifier = get_expected_qualifier (inst, info->idx); @@ -1055,14 +1113,15 @@ aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info, info->addr.base_regno = extract_field (self->fields[0], code, 0); /* uimm12 */ info->addr.offset.imm = extract_field (self->fields[1], code, 0) << shift; - return 1; + return TRUE; } /* Decode the address operand for e.g. LDRAA , [{, #}]. */ -int +bfd_boolean aarch64_ext_addr_simm10 (const aarch64_operand *self, aarch64_opnd_info *info, aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { aarch64_insn imm; @@ -1076,15 +1135,16 @@ aarch64_ext_addr_simm10 (const aarch64_operand *self, aarch64_opnd_info *info, info->addr.writeback = 1; info->addr.preind = 1; } - return 1; + return TRUE; } /* Decode the address operand for e.g. LD1 {., ., .}, [], >. */ -int +bfd_boolean aarch64_ext_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, - aarch64_insn code, const aarch64_inst *inst) + aarch64_insn code, const aarch64_inst *inst, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { /* The opcode dependent area stores the number of elements in each structure to be loaded/stored. */ @@ -1110,57 +1170,76 @@ aarch64_ext_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED, info->addr.offset.is_reg = 1; info->addr.writeback = 1; - return 1; + return TRUE; } /* Decode the condition operand for e.g. CSEL , , , . */ -int +bfd_boolean aarch64_ext_cond (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, - aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED) + aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { aarch64_insn value; /* cond */ value = extract_field (FLD_cond, code, 0); info->cond = get_cond_from_value (value); - return 1; + return TRUE; } /* Decode the system register operand for e.g. MRS , . */ -int +bfd_boolean aarch64_ext_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { /* op0:op1:CRn:CRm:op2 */ - info->sysreg = extract_fields (code, 0, 5, FLD_op0, FLD_op1, FLD_CRn, - FLD_CRm, FLD_op2); - return 1; + info->sysreg.value = extract_fields (code, 0, 5, FLD_op0, FLD_op1, FLD_CRn, + FLD_CRm, FLD_op2); + info->sysreg.flags = 0; + + /* If a system instruction, check which restrictions should be on the register + value during decoding, these will be enforced then. */ + if (inst->opcode->iclass == ic_system) + { + /* Check to see if it's read-only, else check if it's write only. + if it's both or unspecified don't care. */ + if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE)) == F_SYS_READ) + info->sysreg.flags = F_REG_READ; + else if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE)) + == F_SYS_WRITE) + info->sysreg.flags = F_REG_WRITE; + } + + return TRUE; } /* Decode the PSTATE field operand for e.g. MSR , #. */ -int +bfd_boolean aarch64_ext_pstatefield (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { int i; /* op1:op2 */ info->pstatefield = extract_fields (code, 0, 2, FLD_op1, FLD_op2); for (i = 0; aarch64_pstatefields[i].name != NULL; ++i) if (aarch64_pstatefields[i].value == (aarch64_insn)info->pstatefield) - return 1; + return TRUE; /* Reserved value in . */ - return 0; + return FALSE; } /* Decode the system instruction op operand for e.g. AT , . */ -int +bfd_boolean aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, aarch64_insn code, - const aarch64_inst *inst ATTRIBUTE_UNUSED) + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) { int i; aarch64_insn value; @@ -1176,7 +1255,13 @@ aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED, case AARCH64_OPND_SYSREG_DC: sysins_ops = aarch64_sys_regs_dc; break; case AARCH64_OPND_SYSREG_IC: sysins_ops = aarch64_sys_regs_ic; break; case AARCH64_OPND_SYSREG_TLBI: sysins_ops = aarch64_sys_regs_tlbi; break; - default: assert (0); return 0; + case AARCH64_OPND_SYSREG_SR: + sysins_ops = aarch64_sys_regs_sr; + /* Let's remove op2 for rctx. Refer to comments in the definition of + aarch64_sys_regs_sr[]. */ + value = value & ~(0x7); + break; + default: assert (0); return FALSE; } for (i = 0; sysins_ops[i].name != NULL; ++i) @@ -1187,46 +1272,49 @@ aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED, info->sysins_op->name, (unsigned)info->sysins_op->value, aarch64_sys_ins_reg_has_xt (info->sysins_op), i); - return 1; + return TRUE; } - return 0; + return FALSE; } /* Decode the memory barrier option operand for e.g. DMB