From f96fe7f454bdd077abec2acc415f546bb5646189 Mon Sep 17 00:00:00 2001 From: Jens Remus Date: Wed, 20 Dec 2023 11:34:15 +0100 Subject: s390: Optionally print instruction description in disassembly Print instruction description as comment in disassembly with s390 architecture specific option "insndesc": - For objdump it can be enabled with option "-M insndesc" - In gdb it can be enabled with "set disassembler-options insndesc" Since comments are not column aligned the output can enhanced for readability by postprocessing using a filter such as "expand": ... | expand -t 8,16,24,32,40,80 Or when using in combination with objdump option --visualize-jumps: ... | expand | sed -e 's/ *#/\t#/' | expand -t 1,80 Note that the instruction descriptions add about 128 KB to s390-opc.o: s390-opc.o without instruction descriptions: 216368 bytes s390-opc.o with instruction descriptions : 348432 bytes binutils/ * NEWS: Mention new s390-specific disassembler option "insndesc". include/ * opcode/s390.h (struct s390_opcode): Add field to hold instruction description. opcodes/ * s390-mkopc.c: Copy instruction description from s390-opc.txt into generated operation code table s390-opc.tab. * s390-opc.c (s390_opformats): Provide NULL as description in .insn pseudo-mnemonics opcode table. * s390-dis.c: Add s390-specific disassembler option "insndesc" and optionally print the instruction description as comment in the disassembly when it is specified. gas/ * testsuite/gas/s390/s390.exp: Add new test disassembly test case "zarch-insndesc". * testsuite/gas/s390/zarch-insndesc.s: New test case for s390- specific disassembler option "insndesc". * testsuite/gas/s390/zarch-insndesc.d: Likewise. Signed-off-by: Jens Remus Reviewed-by: Andreas Krebbel --- binutils/NEWS | 5 +++ gas/testsuite/gas/s390/s390.exp | 1 + gas/testsuite/gas/s390/zarch-insndesc.d | 17 +++++++++ gas/testsuite/gas/s390/zarch-insndesc.s | 10 ++++++ include/opcode/s390.h | 5 ++- opcodes/s390-dis.c | 13 ++++++- opcodes/s390-mkopc.c | 19 ++++++---- opcodes/s390-opc.c | 62 ++++++++++++++++----------------- 8 files changed, 92 insertions(+), 40 deletions(-) create mode 100644 gas/testsuite/gas/s390/zarch-insndesc.d create mode 100644 gas/testsuite/gas/s390/zarch-insndesc.s diff --git a/binutils/NEWS b/binutils/NEWS index 73df705..35b84e6 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -19,6 +19,11 @@ * objdump --visualize-jumps is now supported on s390 architecture. +* The s390 disassembly now optionally includes the instruction description as + comment with the s390-specific disassembler option "insndesc": + - For objdump it can be enabled with "objdump -M insndesc ...". + - In gdb it can be enabled with "set disassembler-options insndesc". + Changes in 2.41: * The MIPS port now supports the Sony Interactive Entertainment Allegrex diff --git a/gas/testsuite/gas/s390/s390.exp b/gas/testsuite/gas/s390/s390.exp index 356fba9..86e2dd4 100644 --- a/gas/testsuite/gas/s390/s390.exp +++ b/gas/testsuite/gas/s390/s390.exp @@ -37,6 +37,7 @@ if [expr [istarget "s390-*-*"] || [istarget "s390x-*-*"]] then { run_dump_test "zarch-operands" "{as -m64} {as -march=z9-109}" run_dump_test "zarch-machine" "{as -m64} {as -march=z900}" run_dump_test "zarch-optargs" "{as -m64} {as -march=arch12}" + run_dump_test "zarch-insndesc" "{as -m64}" run_list_test "machine-parsing-1" "" run_list_test "machine-parsing-2" "" run_list_test "machine-parsing-3" "" diff --git a/gas/testsuite/gas/s390/zarch-insndesc.d b/gas/testsuite/gas/s390/zarch-insndesc.d new file mode 100644 index 0000000..9a121fb --- /dev/null +++ b/gas/testsuite/gas/s390/zarch-insndesc.d @@ -0,0 +1,17 @@ +#name: s390x insndesc +#objdump: -dr -M insndesc + +.*: +file format .* + +Disassembly of section .text: + +.* : +.*: b3 95 00 69 [ ]*cdfbr %f6,%r9 # convert from fixed 32 to long bfp + *([\da-f]+): 84 69 00 00 [ ]*brxh %r6,%r9,\1 # branch relative on index high +.*: b2 99 5f ff [ ]*srnm 4095\(%r5\) # set rounding mode +.*: b9 11 00 96 [ ]*lngfr %r9,%r6 # load negative 64<32 +.*: ec 67 92 1c 26 54 [ ]*rnsbgt %r6,%r7,18,28,38 # rotate then and selected bits and test results +.*: ec 67 0c 8d 0e 5d [ ]*risbhgz %r6,%r7,12,13,14 # rotate then insert selected bits high and zero remaining bits +.*: b3 96 37 59 [ ]*cxfbra %f5,3,%r9,7 # convert from 32 bit fixed to extended bfp with rounding mode +.*: ec 67 0c 94 0e 59 [ ]*risbgnz %r6,%r7,12,20,14 # rotate then insert selected bits and zero remaining bits nocc +.*: 07 07 [ ]*nopr %r7 # no operation diff --git a/gas/testsuite/gas/s390/zarch-insndesc.s b/gas/testsuite/gas/s390/zarch-insndesc.s new file mode 100644 index 0000000..e964315 --- /dev/null +++ b/gas/testsuite/gas/s390/zarch-insndesc.s @@ -0,0 +1,10 @@ +.text +foo: + cdfbr %f6,%r9 + brxh %r6,%r9,. + srnm 4095(%r5) + lngfr %r9,%r6 + rnsbgt %r6,%r7,18,28,38 + risbhgz %r6,%r7,12,13,14 + cxfbra %f5,3,%r9,7 + risbgnz %r6,%r7,12,20,14 diff --git a/include/opcode/s390.h b/include/opcode/s390.h index d540e1d..319bfe2 100644 --- a/include/opcode/s390.h +++ b/include/opcode/s390.h @@ -81,7 +81,7 @@ enum s390_opcode_cpu_val struct s390_opcode { - /* The opcode name. */ + /* The opcode name (mnemonic). */ const char * name; /* The opcode itself. Those bits which will be filled in with @@ -110,6 +110,9 @@ struct s390_opcode /* Instruction specific flags. */ unsigned int flags; + + /* Instruction description. */ + const char * description; }; /* The table itself is sorted by major opcode number, and is otherwise diff --git a/opcodes/s390-dis.c b/opcodes/s390-dis.c index 8c8a98c..fca965f 100644 --- a/opcodes/s390-dis.c +++ b/opcodes/s390-dis.c @@ -31,6 +31,7 @@ static int opc_index[256]; static int current_arch_mask = 0; static int option_use_insn_len_bits_p = 0; +static int option_print_insn_desc = 0; typedef struct { @@ -43,7 +44,8 @@ static const s390_options_t options[] = { "esa" , N_("Disassemble in ESA architecture mode") }, { "zarch", N_("Disassemble in z/Architecture mode") }, { "insnlength", N_("Print unknown instructions according to " - "length from first two bits") } + "length from first two bits") }, + { "insndesc", N_("Print instruction description as comment") }, }; /* Set up index table for first opcode byte. */ @@ -63,6 +65,7 @@ disassemble_init_s390 (struct disassemble_info *info) current_arch_mask = 1 << S390_OPCODE_ZARCH; option_use_insn_len_bits_p = 0; + option_print_insn_desc = 0; for (p = info->disassembler_options; p != NULL; ) { @@ -72,6 +75,8 @@ disassemble_init_s390 (struct disassemble_info *info) current_arch_mask = 1 << S390_OPCODE_ZARCH; else if (startswith (p, "insnlength")) option_use_insn_len_bits_p = 1; + else if (startswith (p, "insndesc")) + option_print_insn_desc = 1; else /* xgettext:c-format */ opcodes_error_handler (_("unknown S/390 disassembler option: %s"), p); @@ -311,6 +316,12 @@ s390_print_insn_with_opcode (bfd_vma memaddr, else separator = ','; } + + /* Optional: instruction name. */ + if (option_print_insn_desc && opcode->description + && opcode->description[0] != '\0') + info->fprintf_styled_func (info->stream, dis_style_comment_start, "\t# %s", + opcode->description); } /* Check whether opcode A's mask is more specific than that of B. */ diff --git a/opcodes/s390-mkopc.c b/opcodes/s390-mkopc.c index eae0397..c6930a3 100644 --- a/opcodes/s390-mkopc.c +++ b/opcodes/s390-mkopc.c @@ -63,6 +63,7 @@ struct op_struct int mode_bits; int min_cpu; int flags; + char description[MAX_DESCRIPTION_LEN + 1]; unsigned long long sort_value; int no_nibbles; @@ -84,7 +85,7 @@ createTable (void) static void insertOpcode (char *opcode, char *mnemonic, char *format, - int min_cpu, int mode_bits, int flags) + int min_cpu, int mode_bits, int flags, char* description) { char *str; unsigned long long sort_value; @@ -132,6 +133,8 @@ insertOpcode (char *opcode, char *mnemonic, char *format, op_array[ix].min_cpu = min_cpu; op_array[ix].mode_bits = mode_bits; op_array[ix].flags = flags; + strncpy (op_array[ix].description, description, MAX_DESCRIPTION_LEN); + op_array[ix].description[MAX_DESCRIPTION_LEN] = '\0'; no_ops++; } @@ -193,7 +196,7 @@ const struct s390_cond_ext_format s390_crb_extensions[NUM_CRB_EXTENSIONS] = static void insertExpandedMnemonic (char *opcode, char *mnemonic, char *format, - int min_cpu, int mode_bits, int flags) + int min_cpu, int mode_bits, int flags, char *description) { char *tag; char prefix[MAX_MNEMONIC_LEN + 1]; @@ -206,7 +209,7 @@ insertExpandedMnemonic (char *opcode, char *mnemonic, char *format, if (!(tag = strpbrk (mnemonic, "*$"))) { - insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits, flags); + insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits, flags, description); return; } @@ -290,7 +293,7 @@ insertExpandedMnemonic (char *opcode, char *mnemonic, char *format, return; } - insertOpcode (opcode, new_mnemonic, format, min_cpu, mode_bits, flags); + insertOpcode (opcode, new_mnemonic, format, min_cpu, mode_bits, flags, description); } return; @@ -311,7 +314,8 @@ static const char file_header[] = " instruction which matches.\n" " MODE_BITS - zarch or esa\n" " MIN_CPU - number of the min cpu level required\n" - " FLAGS - instruction flags. */\n\n" + " FLAGS - instruction flags.\n" + " DESCRIPTION - description of the instruction. */\n\n" "const struct s390_opcode s390_opcodes[] =\n {\n"; /* `dumpTable': write opcode table. */ @@ -337,7 +341,8 @@ dumpTable (void) op_array[ix].format, op_array[ix].format); printf ("%i, ", op_array[ix].mode_bits); printf ("%i, ", op_array[ix].min_cpu); - printf ("%i}", op_array[ix].flags); + printf ("%i, ", op_array[ix].flags); + printf ("\"%s\" }", op_array[ix].description); if (ix < no_ops-1) printf (",\n"); else @@ -497,7 +502,7 @@ main (void) str++; } while (*str != 0); } - insertExpandedMnemonic (opcode, mnemonic, format, min_cpu, mode_bits, flag_bits); + insertExpandedMnemonic (opcode, mnemonic, format, min_cpu, mode_bits, flag_bits, description); continue_loop: ; diff --git a/opcodes/s390-opc.c b/opcodes/s390-opc.c index cbfdb3d..e44621a 100644 --- a/opcodes/s390-opc.c +++ b/opcodes/s390-opc.c @@ -774,37 +774,37 @@ unused_s390_operands_static_asserts (void) const struct s390_opcode s390_opformats[] = { - { "e", OP8(0x00LL), MASK_E, INSTR_E, 3, 0 ,0 }, - { "ri", OP8(0x00LL), MASK_RI_RI, INSTR_RI_RI, 3, 0 ,0 }, - { "rie", OP8(0x00LL), MASK_RIE_RRP, INSTR_RIE_RRP, 3, 0 ,0 }, - { "ril", OP8(0x00LL), MASK_RIL_RP, INSTR_RIL_RP, 3, 0 ,0 }, - { "rilu", OP8(0x00LL), MASK_RIL_RU, INSTR_RIL_RU, 3, 0 ,0 }, - { "ris", OP8(0x00LL), MASK_RIS_RURDI, INSTR_RIS_RURDI, 3, 6 ,0 }, - { "rr", OP8(0x00LL), MASK_RR_RR, INSTR_RR_RR, 3, 0 ,0 }, - { "rre", OP8(0x00LL), MASK_RRE_RR, INSTR_RRE_RR, 3, 0 ,0 }, - { "rrf", OP8(0x00LL), MASK_RRF_RURR, INSTR_RRF_RURR, 3, 0 ,0 }, - { "rrs", OP8(0x00LL), MASK_RRS_RRRDU, INSTR_RRS_RRRDU, 3, 6 ,0 }, - { "rs", OP8(0x00LL), MASK_RS_RRRD, INSTR_RS_RRRD, 3, 0 ,0 }, - { "rse", OP8(0x00LL), MASK_RSE_RRRD, INSTR_RSE_RRRD, 3, 0 ,0 }, - { "rsi", OP8(0x00LL), MASK_RSI_RRP, INSTR_RSI_RRP, 3, 0 ,0 }, - { "rsy", OP8(0x00LL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 3 ,0 }, - { "rx", OP8(0x00LL), MASK_RX_RRRD, INSTR_RX_RRRD, 3, 0 ,0 }, - { "rxe", OP8(0x00LL), MASK_RXE_RRRD, INSTR_RXE_RRRD, 3, 0 ,0 }, - { "rxf", OP8(0x00LL), MASK_RXF_RRRDR, INSTR_RXF_RRRDR, 3, 0 ,0 }, - { "rxy", OP8(0x00LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 3, 3 ,0 }, - { "s", OP8(0x00LL), MASK_S_RD, INSTR_S_RD, 3, 0 ,0 }, - { "si", OP8(0x00LL), MASK_SI_URD, INSTR_SI_URD, 3, 0 ,0 }, - { "siy", OP8(0x00LL), MASK_SIY_URD, INSTR_SIY_URD, 3, 3 ,0 }, - { "sil", OP8(0x00LL), MASK_SIL_RDI, INSTR_SIL_RDI, 3, 6 ,0 }, - { "ss", OP8(0x00LL), MASK_SS_RRRDRD, INSTR_SS_RRRDRD, 3, 0 ,0 }, - { "sse", OP8(0x00LL), MASK_SSE_RDRD, INSTR_SSE_RDRD, 3, 0 ,0 }, - { "ssf", OP8(0x00LL), MASK_SSF_RRDRD, INSTR_SSF_RRDRD, 3, 0 ,0 }, - { "vrv", OP8(0x00LL), MASK_VRV_VVXRDU, INSTR_VRV_VVXRDU, 3, 9 ,0 }, - { "vri", OP8(0x00LL), MASK_VRI_VVUUU, INSTR_VRI_VVUUU, 3, 9 ,0 }, - { "vrx", OP8(0x00LL), MASK_VRX_VRRDU, INSTR_VRX_VRRDU, 3, 9 ,0 }, - { "vrs", OP8(0x00LL), MASK_VRS_RVRDU, INSTR_VRS_RVRDU, 3, 9 ,0 }, - { "vrr", OP8(0x00LL), MASK_VRR_VVV0UUU, INSTR_VRR_VVV0UUU, 3, 9 ,0 }, - { "vsi", OP8(0x00LL), MASK_VSI_URDV, INSTR_VSI_URDV, 3, 10 ,0 }, + { "e", OP8(0x00LL), MASK_E, INSTR_E, 3, 0, 0, NULL }, + { "ri", OP8(0x00LL), MASK_RI_RI, INSTR_RI_RI, 3, 0, 0, NULL }, + { "rie", OP8(0x00LL), MASK_RIE_RRP, INSTR_RIE_RRP, 3, 0, 0, NULL }, + { "ril", OP8(0x00LL), MASK_RIL_RP, INSTR_RIL_RP, 3, 0, 0, NULL }, + { "rilu", OP8(0x00LL), MASK_RIL_RU, INSTR_RIL_RU, 3, 0, 0, NULL }, + { "ris", OP8(0x00LL), MASK_RIS_RURDI, INSTR_RIS_RURDI, 3, 6, 0, NULL }, + { "rr", OP8(0x00LL), MASK_RR_RR, INSTR_RR_RR, 3, 0, 0, NULL }, + { "rre", OP8(0x00LL), MASK_RRE_RR, INSTR_RRE_RR, 3, 0, 0, NULL }, + { "rrf", OP8(0x00LL), MASK_RRF_RURR, INSTR_RRF_RURR, 3, 0, 0, NULL }, + { "rrs", OP8(0x00LL), MASK_RRS_RRRDU, INSTR_RRS_RRRDU, 3, 6, 0, NULL }, + { "rs", OP8(0x00LL), MASK_RS_RRRD, INSTR_RS_RRRD, 3, 0, 0, NULL }, + { "rse", OP8(0x00LL), MASK_RSE_RRRD, INSTR_RSE_RRRD, 3, 0, 0, NULL }, + { "rsi", OP8(0x00LL), MASK_RSI_RRP, INSTR_RSI_RRP, 3, 0, 0, NULL }, + { "rsy", OP8(0x00LL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 3, 0, NULL }, + { "rx", OP8(0x00LL), MASK_RX_RRRD, INSTR_RX_RRRD, 3, 0, 0, NULL }, + { "rxe", OP8(0x00LL), MASK_RXE_RRRD, INSTR_RXE_RRRD, 3, 0, 0, NULL }, + { "rxf", OP8(0x00LL), MASK_RXF_RRRDR, INSTR_RXF_RRRDR, 3, 0, 0, NULL }, + { "rxy", OP8(0x00LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 3, 3, 0, NULL }, + { "s", OP8(0x00LL), MASK_S_RD, INSTR_S_RD, 3, 0, 0, NULL }, + { "si", OP8(0x00LL), MASK_SI_URD, INSTR_SI_URD, 3, 0, 0, NULL }, + { "siy", OP8(0x00LL), MASK_SIY_URD, INSTR_SIY_URD, 3, 3, 0, NULL }, + { "sil", OP8(0x00LL), MASK_SIL_RDI, INSTR_SIL_RDI, 3, 6, 0, NULL }, + { "ss", OP8(0x00LL), MASK_SS_RRRDRD, INSTR_SS_RRRDRD, 3, 0, 0, NULL }, + { "sse", OP8(0x00LL), MASK_SSE_RDRD, INSTR_SSE_RDRD, 3, 0, 0, NULL }, + { "ssf", OP8(0x00LL), MASK_SSF_RRDRD, INSTR_SSF_RRDRD, 3, 0, 0, NULL }, + { "vrv", OP8(0x00LL), MASK_VRV_VVXRDU, INSTR_VRV_VVXRDU, 3, 9, 0, NULL }, + { "vri", OP8(0x00LL), MASK_VRI_VVUUU, INSTR_VRI_VVUUU, 3, 9, 0, NULL }, + { "vrx", OP8(0x00LL), MASK_VRX_VRRDU, INSTR_VRX_VRRDU, 3, 9, 0, NULL }, + { "vrs", OP8(0x00LL), MASK_VRS_RVRDU, INSTR_VRS_RVRDU, 3, 9, 0, NULL }, + { "vrr", OP8(0x00LL), MASK_VRR_VVV0UUU, INSTR_VRR_VVV0UUU, 3, 9, 0, NULL }, + { "vsi", OP8(0x00LL), MASK_VSI_URDV, INSTR_VSI_URDV, 3, 10, 0, NULL }, }; const int s390_num_opformats = -- cgit v1.1