aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/NEWS2
-rw-r--r--include/opcode/s390.h25
-rw-r--r--opcodes/s390-dis.c36
-rw-r--r--opcodes/s390-mkopc.c12
-rw-r--r--opcodes/s390-opc.txt82
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