aboutsummaryrefslogtreecommitdiff
path: root/opcodes/s390-dis.c
diff options
context:
space:
mode:
Diffstat (limited to 'opcodes/s390-dis.c')
-rw-r--r--opcodes/s390-dis.c55
1 files changed, 38 insertions, 17 deletions
diff --git a/opcodes/s390-dis.c b/opcodes/s390-dis.c
index eeaeaf8..8134073 100644
--- a/opcodes/s390-dis.c
+++ b/opcodes/s390-dis.c
@@ -29,6 +29,7 @@
static int init_flag = 0;
static int opc_index[256];
static int current_arch_mask = 0;
+static int option_use_insn_len_bits_p = 0;
/* Set up index table for first opcode byte. */
@@ -51,6 +52,8 @@ init_disasm (struct disassemble_info *info)
current_arch_mask = 1 << S390_OPCODE_ESA;
else if (CONST_STRNEQ (p, "zarch"))
current_arch_mask = 1 << S390_OPCODE_ZARCH;
+ else if (CONST_STRNEQ (p, "insnlength"))
+ option_use_insn_len_bits_p = 1;
else
fprintf (stderr, "Unknown S/390 disassembler option: %s\n", p);
@@ -261,7 +264,7 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
bfd_byte buffer[6];
const struct s390_opcode *opcode = NULL;
unsigned int value;
- int status, opsize, bufsize;
+ int status, opsize, bufsize, bytes_to_dump, i;
if (init_flag == 0)
init_disasm (info);
@@ -307,38 +310,54 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
|| opcode_mask_more_specific (op, opcode)))
opcode = op;
}
- }
- if (opcode != NULL)
- {
- /* The instruction is valid. Print it and return its size. */
- s390_print_insn_with_opcode (memaddr, info, buffer, opcode);
- return opsize;
+ if (opcode != NULL)
+ {
+ /* The instruction is valid. Print it and return its size. */
+ s390_print_insn_with_opcode (memaddr, info, buffer, opcode);
+ return opsize;
+ }
}
+ /* For code sections it makes sense to skip unknown instructions
+ according to their length bits. */
+ if (status == 0
+ && option_use_insn_len_bits_p
+ && info->section != NULL
+ && (info->section->flags & SEC_CODE))
+ bytes_to_dump = opsize;
+ else
+ /* By default unknown instructions are printed as .long's/.short'
+ depending on how many bytes are available. */
+ bytes_to_dump = bufsize >= 4 ? 4 : bufsize;
+
+ if (bytes_to_dump == 0)
+ return 0;
+
/* Fall back to hex print. */
- if (bufsize >= 4)
+ switch (bytes_to_dump)
{
+ case 4:
value = (unsigned int) buffer[0];
value = (value << 8) + (unsigned int) buffer[1];
value = (value << 8) + (unsigned int) buffer[2];
value = (value << 8) + (unsigned int) buffer[3];
info->fprintf_func (info->stream, ".long\t0x%08x", value);
return 4;
- }
- else if (bufsize >= 2)
- {
+ case 2:
value = (unsigned int) buffer[0];
value = (value << 8) + (unsigned int) buffer[1];
info->fprintf_func (info->stream, ".short\t0x%04x", value);
return 2;
+ default:
+ info->fprintf_func (info->stream, ".byte\t0x%02x",
+ (unsigned int) buffer[0]);
+ for (i = 1; i < bytes_to_dump; i++)
+ info->fprintf_func (info->stream, ",0x%02x",
+ (unsigned int) buffer[i]);
+ return bytes_to_dump;
}
- else
- {
- value = (unsigned int) buffer[0];
- info->fprintf_func (info->stream, ".byte\t0x%02x", value);
- return 1;
- }
+ return 0;
}
void
@@ -350,4 +369,6 @@ with the -M switch (multiple options should be separated by commas):\n"));
fprintf (stream, _(" esa Disassemble in ESA architecture mode\n"));
fprintf (stream, _(" zarch Disassemble in z/Architecture mode\n"));
+ fprintf (stream, _(" insnlength Print unknown instructions according "
+ "to length from first two bits\n"));
}