diff options
-rw-r--r-- | binutils/NEWS | 2 | ||||
-rw-r--r-- | include/opcode/s390.h | 25 | ||||
-rw-r--r-- | opcodes/s390-dis.c | 36 | ||||
-rw-r--r-- | opcodes/s390-mkopc.c | 12 | ||||
-rw-r--r-- | opcodes/s390-opc.txt | 82 |
5 files changed, 112 insertions, 45 deletions
diff --git a/binutils/NEWS b/binutils/NEWS index 3bf3b56..73df705 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -17,6 +17,8 @@ * objcopy --set-section-flags now supports "large" to set SHF_X86_64_LARGE for ELF x86-64 objects. +* objdump --visualize-jumps is now supported on s390 architecture. + Changes in 2.41: * The MIPS port now supports the Sony Interactive Entertainment Allegrex diff --git a/include/opcode/s390.h b/include/opcode/s390.h index f787b90..d540e1d 100644 --- a/include/opcode/s390.h +++ b/include/opcode/s390.h @@ -48,14 +48,35 @@ enum s390_opcode_cpu_val S390_OPCODE_MAXCPU }; -/* Instruction specific flags. */ +/* Values defined for the flags field of a struct s390_opcode. */ + +/* Last one or two instruction operands are optional. */ #define S390_INSTR_FLAG_OPTPARM 0x1 #define S390_INSTR_FLAG_OPTPARM2 0x2 +/* Instruction requires a specific facility. */ #define S390_INSTR_FLAG_HTM 0x4 #define S390_INSTR_FLAG_VX 0x8 #define S390_INSTR_FLAG_FACILITY_MASK 0xc +/* Instruction annotations for jump visualization. */ +#define S390_INSTR_FLAG_CLASS_BRANCH 0x10 +#define S390_INSTR_FLAG_CLASS_RELATIVE 0x20 +#define S390_INSTR_FLAG_CLASS_CONDITIONAL 0x40 +#define S390_INSTR_FLAG_CLASS_SUBROUTINE 0x80 +#define S390_INSTR_FLAG_CLASS_MASK 0xf0 + +#define S390_INSTR_FLAGS_CLASS_JUMP \ + (S390_INSTR_FLAG_CLASS_BRANCH | S390_INSTR_FLAG_CLASS_RELATIVE) + +#define S390_INSTR_FLAGS_CLASS_CONDJUMP \ + (S390_INSTR_FLAG_CLASS_BRANCH | S390_INSTR_FLAG_CLASS_RELATIVE \ + | S390_INSTR_FLAG_CLASS_CONDITIONAL) + +#define S390_INSTR_FLAGS_CLASS_JUMPSR \ + (S390_INSTR_FLAG_CLASS_BRANCH | S390_INSTR_FLAG_CLASS_RELATIVE \ + | S390_INSTR_FLAG_CLASS_SUBROUTINE) + /* The opcode table is an array of struct s390_opcode. */ struct s390_opcode @@ -101,8 +122,6 @@ extern const int s390_num_opcodes; extern const struct s390_opcode s390_opformats[]; extern const int s390_num_opformats; -/* Values defined for the flags field of a struct s390_opcode. */ - /* The operands table is an array of struct s390_operand. */ struct s390_operand diff --git a/opcodes/s390-dis.c b/opcodes/s390-dis.c index 2a3b4c2..8c8a98c 100644 --- a/opcodes/s390-dis.c +++ b/opcodes/s390-dis.c @@ -26,6 +26,7 @@ #include "opintl.h" #include "opcode/s390.h" #include "libiberty.h" +#include "dis-asm.h" static int opc_index[256]; static int current_arch_mask = 0; @@ -259,9 +260,14 @@ s390_print_insn_with_opcode (bfd_vma memaddr, } else if (flags & S390_OPERAND_PCREL) { + bfd_vma target = memaddr + val.i + val.i; + + /* Provide info for jump visualization. May be evaluated by p_a_f(). */ + info->target = target; + info->fprintf_styled_func (info->stream, dis_style_text, "%c", separator); - info->print_address_func (memaddr + val.i + val.i, info); + info->print_address_func (target, info); } else if (flags & S390_OPERAND_SIGNED) { @@ -332,6 +338,14 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info) /* The output looks better if we put 6 bytes on a line. */ info->bytes_per_line = 6; + /* Set some defaults for the insn info. */ + info->insn_info_valid = 0; + info->branch_delay_insns = 0; + info->data_size = 0; + info->insn_type = dis_nonbranch; + info->target = 0; + info->target2 = 0; + /* Every S390 instruction is max 6 bytes long. */ memset (buffer, 0, 6); status = info->read_memory_func (memaddr, buffer, 6, info); @@ -373,6 +387,23 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info) if (opcode != NULL) { + /* Provide info for jump visualization. Must be done before print. */ + switch (opcode->flags & S390_INSTR_FLAG_CLASS_MASK) + { + case S390_INSTR_FLAGS_CLASS_JUMP: + info->insn_type = dis_branch; + break; + case S390_INSTR_FLAGS_CLASS_CONDJUMP: + info->insn_type = dis_condbranch; + break; + case S390_INSTR_FLAGS_CLASS_JUMPSR: + info->insn_type = dis_jsr; + break; + default: + info->insn_type = dis_nonbranch; + } + info->insn_info_valid = 1; + /* The instruction is valid. Print it and return its size. */ s390_print_insn_with_opcode (memaddr, info, buffer, opcode); return opsize; @@ -394,6 +425,9 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info) if (bytes_to_dump == 0) return 0; + info->insn_type = dis_noninsn; + info->insn_info_valid = 1; + /* Fall back to hex print. */ switch (bytes_to_dump) { diff --git a/opcodes/s390-mkopc.c b/opcodes/s390-mkopc.c index 48b1c1e..5f921ee 100644 --- a/opcodes/s390-mkopc.c +++ b/opcodes/s390-mkopc.c @@ -431,6 +431,18 @@ main (void) && (str[2] == 0 || str[2] == ',')) { flag_bits |= S390_INSTR_FLAG_VX; str += 2; + } else if (strncmp (str, "jump", 7) == 0 + && (str[4] == 0 || str[4] == ',')) { + flag_bits |= S390_INSTR_FLAGS_CLASS_JUMP; + str += 4; + } else if (strncmp (str, "condjump", 7) == 0 + && (str[8] == 0 || str[8] == ',')) { + flag_bits |= S390_INSTR_FLAGS_CLASS_CONDJUMP; + str += 8; + } else if (strncmp (str, "jumpsr", 7) == 0 + && (str[6] == 0 || str[6] == ',')) { + flag_bits |= S390_INSTR_FLAGS_CLASS_JUMPSR; + str += 6; } else { fprintf (stderr, "Couldn't parse flags string %s\n", flags_string); diff --git a/opcodes/s390-opc.txt b/opcodes/s390-opc.txt index 853758b..0fd04ee 100644 --- a/opcodes/s390-opc.txt +++ b/opcodes/s390-opc.txt @@ -245,15 +245,15 @@ d7 xc SS_L0RDRD "exclusive OR" g5 esa,zarch 17 xr RR_RR "exclusive OR" g5 esa,zarch f8 zap SS_LLRDRD "zero and add" g5 esa,zarch a70a ahi RI_RI "add halfword immediate" g5 esa,zarch -84 brxh RSI_RRP "branch relative on index high" g5 esa,zarch -84 jxh RSI_RRP "branch relative on index high" g5 esa,zarch -85 brxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch -85 jxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch -a705 bras RI_RP "branch relative and save" g5 esa,zarch -a705 jas RI_RP "branch relative and save" g5 esa,zarch -a704 brc RI_UP "branch relative on condition" g5 esa,zarch -a706 brct RI_RP "branch relative on count" g5 esa,zarch -a706 jct RI_RP "branch relative on count" g5 esa,zarch +84 brxh RSI_RRP "branch relative on index high" g5 esa,zarch condjump +84 jxh RSI_RRP "branch relative on index high" g5 esa,zarch condjump +85 brxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch condjump +85 jxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch condjump +a705 bras RI_RP "branch relative and save" g5 esa,zarch jumpsr +a705 jas RI_RP "branch relative and save" g5 esa,zarch jumpsr +a704 brc RI_UP "branch relative on condition" g5 esa,zarch condjump +a706 brct RI_RP "branch relative on count" g5 esa,zarch condjump +a706 jct RI_RP "branch relative on count" g5 esa,zarch condjump b241 cksm RRE_RR "checksum" g5 esa,zarch a70e chi RI_RI "compare halfword immediate" g5 esa,zarch a9 clcle RS_RRRD "compare logical long extended" g5 esa,zarch @@ -272,12 +272,12 @@ a701 tml RI_RU "test under mask low" g5 esa,zarch 4700 nop RX_0RRD "no operation" g5 esa,zarch optparm 4700 b*8 RX_0RRD "conditional branch" g5 esa,zarch 47f0 b RX_0RRD "unconditional branch" g5 esa,zarch -a704 jc RI_UP "conditional jump" g5 esa,zarch +a704 jc RI_UP "conditional jump" g5 esa,zarch condjump a704 jnop RI_0P "nop jump" g5 esa,zarch -a704 j*8 RI_0P "conditional jump" g5 esa,zarch -a704 br*8 RI_0P "conditional jump" g5 esa,zarch -a7f4 j RI_0P "unconditional jump" g5 esa,zarch -a7f4 bru RI_0P "unconditional jump" g5 esa,zarch +a704 j*8 RI_0P "conditional jump" g5 esa,zarch condjump +a704 br*8 RI_0P "conditional jump" g5 esa,zarch condjump +a7f4 j RI_0P "unconditional jump" g5 esa,zarch jump +a7f4 bru RI_0P "unconditional jump" g5 esa,zarch jump b34a axbr RRE_FEFE "add extended bfp" g5 esa,zarch b31a adbr RRE_FF "add long bfp" g5 esa,zarch ed000000001a adb RXE_FRRD "add long bfp" g5 esa,zarch @@ -446,10 +446,10 @@ e3000000000b slg RXE_RRRD "subtract logical 64" z900 zarch e3000000001b slgf RXE_RRRD "subtract logical 64<32" z900 zarch e3000000000c msg RXE_RRRD "multiply single 64" z900 zarch e3000000001c msgf RXE_RRRD "multiply single 64<32" z900 zarch -ec0000000044 brxhg RIE_RRP "branch relative on index high 64" z900 zarch -ec0000000044 jxhg RIE_RRP "branch relative on index high 64" z900 zarch -ec0000000045 brxlg RIE_RRP "branch relative on index low or equal 64" z900 zarch -ec0000000045 jxleg RIE_RRP "branch relative on index low or equal 64" z900 zarch +ec0000000044 brxhg RIE_RRP "branch relative on index high 64" z900 zarch condjump +ec0000000044 jxhg RIE_RRP "branch relative on index high 64" z900 zarch condjump +ec0000000045 brxlg RIE_RRP "branch relative on index low or equal 64" z900 zarch condjump +ec0000000045 jxleg RIE_RRP "branch relative on index low or equal 64" z900 zarch condjump eb0000000044 bxhg RSE_RRRD "branch on index high 64" z900 zarch eb0000000045 bxleg RSE_RRRD "branch on index low or equal 64" z900 zarch eb000000000c srlg RSE_RRRD "shift right single logical 64" z900 zarch @@ -473,18 +473,18 @@ eb000000002c stcmh RSE_RURD "store characters under mask high" z900 zarch eb0000000080 icmh RSE_RURD "insert characters under mask high" z900 zarch a702 tmhh RI_RU "test under mask high high" z900 zarch a703 tmhl RI_RU "test under mask high low" z900 zarch -c004 brcl RIL_UP "branch relative on condition long" z900 esa,zarch +c004 brcl RIL_UP "branch relative on condition long" z900 esa,zarch condjump # jlc omitted due to missing jl* (see jl*8) and not added as non-standard jgc c004 jgnop RIL_0P "nop jump long" z900 esa,zarch -c004 jg*8 RIL_0P "conditional jump long" z900 esa,zarch +c004 jg*8 RIL_0P "conditional jump long" z900 esa,zarch condjump # jl*8 omitted due to clash with non-standard j*8 flavors jle and jlh; exists as non-standard jg*8 instead -c004 br*8l RIL_0P "conditional jump long" z900 esa,zarch -c0f4 jg RIL_0P "unconditional jump long" z900 esa,zarch -c0f4 brul RIL_0P "unconditional jump long" z900 esa,zarch -c005 brasl RIL_RP "branch relative and save long" z900 esa,zarch -c005 jasl RIL_RP "branch relative and save long" z900 esa,zarch -a707 brctg RI_RP "branch relative on count 64" z900 zarch -a707 jctg RI_RP "branch relative on count 64" z900 zarch +c004 br*8l RIL_0P "conditional jump long" z900 esa,zarch condjump +c0f4 jg RIL_0P "unconditional jump long" z900 esa,zarch jump +c0f4 brul RIL_0P "unconditional jump long" z900 esa,zarch jump +c005 brasl RIL_RP "branch relative and save long" z900 esa,zarch jumpsr +c005 jasl RIL_RP "branch relative and save long" z900 esa,zarch jumpsr +a707 brctg RI_RP "branch relative on count 64" z900 zarch condjump +a707 jctg RI_RP "branch relative on count 64" z900 zarch condjump a709 lghi RI_RI "load halfword immediate 64" z900 zarch a70b aghi RI_RI "add halfword immediate 64" z900 zarch a70d mghi RI_RI "multiply halfword immediate 64" z900 zarch @@ -896,18 +896,18 @@ ec00000000f6 crb$32 RRS_RRRD0 "compare and branch (32)" z10 zarch ec00000000f6 crb RRS_RRRDU "compare and branch (32)" z10 zarch ec00000000e4 cgrb$32 RRS_RRRD0 "compare and branch (64)" z10 zarch ec00000000e4 cgrb RRS_RRRDU "compare and branch (64)" z10 zarch -ec0000000076 crj$32 RIE_RRP0 "compare and branch relative (32)" z10 zarch -ec0000000076 crj RIE_RRPU "compare and branch relative (32)" z10 zarch -ec0000000064 cgrj$32 RIE_RRP0 "compare and branch relative (64)" z10 zarch -ec0000000064 cgrj RIE_RRPU "compare and branch relative (64)" z10 zarch +ec0000000076 crj$32 RIE_RRP0 "compare and branch relative (32)" z10 zarch condjump +ec0000000076 crj RIE_RRPU "compare and branch relative (32)" z10 zarch condjump +ec0000000064 cgrj$32 RIE_RRP0 "compare and branch relative (64)" z10 zarch condjump +ec0000000064 cgrj RIE_RRPU "compare and branch relative (64)" z10 zarch condjump ec00000000fe cib$12 RIS_R0RDI "compare immediate and branch (32<8)" z10 zarch ec00000000fe cib RIS_RURDI "compare immediate and branch (32<8)" z10 zarch ec00000000fc cgib$12 RIS_R0RDI "compare immediate and branch (64<8)" z10 zarch ec00000000fc cgib RIS_RURDI "compare immediate and branch (64<8)" z10 zarch -ec000000007e cij$12 RIE_R0PI "compare immediate and branch relative (32<8)" z10 zarch -ec000000007e cij RIE_RUPI "compare immediate and branch relative (32<8)" z10 zarch -ec000000007c cgij$12 RIE_R0PI "compare immediate and branch relative (64<8)" z10 zarch -ec000000007c cgij RIE_RUPI "compare immediate and branch relative (64<8)" z10 zarch +ec000000007e cij$12 RIE_R0PI "compare immediate and branch relative (32<8)" z10 zarch condjump +ec000000007e cij RIE_RUPI "compare immediate and branch relative (32<8)" z10 zarch condjump +ec000000007c cgij$12 RIE_R0PI "compare immediate and branch relative (64<8)" z10 zarch condjump +ec000000007c cgij RIE_RUPI "compare immediate and branch relative (64<8)" z10 zarch condjump b9720000 crt$16 RRF_00RR "compare and trap" z10 zarch b972 crt RRF_U0RR "compare and trap" z10 zarch b9600000 cgrt$16 RRF_00RR "compare and trap 64" z10 zarch @@ -934,10 +934,10 @@ ec00000000f7 clrb$32 RRS_RRRD0 "compare logical and branch (32)" z10 zarch ec00000000f7 clrb RRS_RRRDU "compare logical and branch (32)" z10 zarch ec00000000e5 clgrb$32 RRS_RRRD0 "compare logical and branch (64)" z10 zarch ec00000000e5 clgrb RRS_RRRDU "compare logical and branch (64)" z10 zarch -ec0000000077 clrj$32 RIE_RRP0 "compare logical and branch relative (32)" z10 zarch -ec0000000077 clrj RIE_RRPU "compare logical and branch relative (32)" z10 zarch -ec0000000065 clgrj$32 RIE_RRP0 "compare logical and branch relative (64)" z10 zarch -ec0000000065 clgrj RIE_RRPU "compare logical and branch relative (64)" z10 zarch +ec0000000077 clrj$32 RIE_RRP0 "compare logical and branch relative (32)" z10 zarch condjump +ec0000000077 clrj RIE_RRPU "compare logical and branch relative (32)" z10 zarch condjump +ec0000000065 clgrj$32 RIE_RRP0 "compare logical and branch relative (64)" z10 zarch condjump +ec0000000065 clgrj RIE_RRPU "compare logical and branch relative (64)" z10 zarch condjump ec00000000ff clib$12 RIS_R0RDU "compare logical immediate and branch (32<8)" z10 zarch ec00000000ff clib RIS_RURDU "compare logical immediate and branch (32<8)" z10 zarch ec00000000fd clgib$12 RIS_R0RDU "compare logical immediate and branch (64<8)" z10 zarch @@ -1011,8 +1011,8 @@ b9ca alhhhr RRF_R0RR2 "add logical high high" z196 zarch b9da alhhlr RRF_R0RR2 "add logical high low" z196 zarch cc0a alsih RIL_RI "add logical with signed immediate high with cc" z196 zarch cc0b alsihn RIL_RI "add logical with signed immediate high no cc" z196 zarch -cc06 brcth RIL_RP "branch relative on count high" z196 zarch -cc06 jcth RIL_RP "jump on count high" z196 zarch +cc06 brcth RIL_RP "branch relative on count high" z196 zarch condjump +cc06 jcth RIL_RP "jump on count high" z196 zarch condjump b9cd chhr RRE_RR "compare high high" z196 zarch b9dd chlr RRE_RR "compare high low" z196 zarch e300000000cd chf RXY_RRRD "compare high" z196 zarch |