X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Faarch64-dis.c;h=4e44f527603e64afe0500e1dd8eecf2912f98a6d;hb=2ac435d46608be7ef90f80aaf9ff48443aea571e;hp=f7092b061f39cf5c9d999673593c001b2af6a5d7;hpb=369c9167d47e69aad2e260cc1db17f8c894c138b;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index f7092b061f..4e44f52760 100644 --- a/opcodes/aarch64-dis.c +++ b/opcodes/aarch64-dis.c @@ -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. */ @@ -49,6 +44,9 @@ 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) { @@ -1245,6 +1243,12 @@ 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; + 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; } @@ -2887,7 +2891,8 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code, } /* If the opcode has a verifier, then check it now. */ - if (opcode->verifier && ! opcode->verifier (opcode, code)) + if (opcode->verifier + && opcode->verifier (inst, code, 0, FALSE, errors, NULL) != ERR_OK) { DEBUG_TRACE ("operand verifier FAIL"); goto decode_fail; @@ -2942,7 +2947,7 @@ user_friendly_fixup (aarch64_inst *inst) opcode may be filled in *INSN if NOALIASES_P is FALSE. Return zero on success. */ -int +enum err_type aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst, bfd_boolean noaliases_p, aarch64_operand_error *errors) @@ -2984,10 +2989,11 @@ aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst, static void print_operands (bfd_vma pc, const aarch64_opcode *opcode, - const aarch64_opnd_info *opnds, struct disassemble_info *info) + const aarch64_opnd_info *opnds, struct disassemble_info *info, + bfd_boolean *has_notes) { - int i, pcrel_p, num_printed; char *notes = NULL; + int i, pcrel_p, num_printed; for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i) { char str[128]; @@ -3017,7 +3023,10 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode, } if (notes && !no_notes) - (*info->fprintf_func) (info->stream, "\t; note: %s", notes); + { + *has_notes = TRUE; + (*info->fprintf_func) (info->stream, " // note: %s", notes); + } } /* Set NAME to a copy of INST's mnemonic with the "." suffix removed. */ @@ -3075,15 +3084,63 @@ print_comment (const aarch64_inst *inst, struct disassemble_info *info) } } +/* Build notes from verifiers into a string for printing. */ + +static void +print_verifier_notes (aarch64_operand_error *detail, + struct disassemble_info *info) +{ + if (no_notes) + return; + + /* The output of the verifier cannot be a fatal error, otherwise the assembly + would not have succeeded. We can safely ignore these. */ + assert (detail->non_fatal); + assert (detail->error); + + /* If there are multiple verifier messages, concat them up to 1k. */ + (*info->fprintf_func) (info->stream, " // note: %s", detail->error); + if (detail->index >= 0) + (*info->fprintf_func) (info->stream, " at operand %d", detail->index + 1); +} + /* Print the instruction according to *INST. */ static void print_aarch64_insn (bfd_vma pc, const aarch64_inst *inst, - struct disassemble_info *info) + const aarch64_insn code, + struct disassemble_info *info, + aarch64_operand_error *mismatch_details) { + bfd_boolean has_notes = FALSE; + print_mnemonic_name (inst, info); - print_operands (pc, inst->opcode, inst->operands, info); + print_operands (pc, inst->opcode, inst->operands, info, &has_notes); print_comment (inst, info); + + /* We've already printed a note, not enough space to print more so exit. + Usually notes shouldn't overlap so it shouldn't happen that we have a note + from a register and instruction at the same time. */ + if (has_notes) + return; + + /* Always run constraint verifiers, this is needed because constraints need to + maintain a global state regardless of whether the instruction has the flag + set or not. */ + enum err_type result = verify_constraints (inst, code, pc, FALSE, + mismatch_details, &insn_sequence); + switch (result) + { + case ERR_UND: + case ERR_UNP: + case ERR_NYI: + assert (0); + case ERR_VFI: + print_verifier_notes (mismatch_details, info); + break; + default: + break; + } } /* Entry-point of the instruction disassembler and printer. */ @@ -3094,15 +3151,15 @@ print_insn_aarch64_word (bfd_vma pc, struct disassemble_info *info, aarch64_operand_error *errors) { - static const char *err_msg[6] = + static const char *err_msg[ERR_NR_ENTRIES+1] = { - [ERR_OK] = "_", - [-ERR_UND] = "undefined", - [-ERR_UNP] = "unpredictable", - [-ERR_NYI] = "NYI" + [ERR_OK] = "_", + [ERR_UND] = "undefined", + [ERR_UNP] = "unpredictable", + [ERR_NYI] = "NYI" }; - int ret; + enum err_type ret; aarch64_inst inst; info->insn_info_valid = 1; @@ -3136,11 +3193,11 @@ print_insn_aarch64_word (bfd_vma pc, /* Handle undefined instructions. */ info->insn_type = dis_noninsn; (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s", - word, err_msg[-ret]); + word, err_msg[ret]); break; case ERR_OK: user_friendly_fixup (&inst); - print_aarch64_insn (pc, &inst, info); + print_aarch64_insn (pc, &inst, word, info, errors); break; default: abort ();