/* s390-dis.c -- Disassemble S390 instructions
- Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 2000-2017 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU opcodes library.
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. */
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);
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);
|| 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
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"));
}