/* s390-dis.c -- Disassemble S390 instructions
- Copyright 2000, 2001 Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
- This file is part of GDB, GAS and the GNU binutils.
+ This file is part of the GNU opcodes library.
- This program is free software; you can redistribute it and/or modify
+ This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ along with this file; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#include <stdio.h>
#include "ansidecl.h"
#include "sysdep.h"
#include "dis-asm.h"
+#include "opintl.h"
#include "opcode/s390.h"
static int init_flag = 0;
static int opc_index[256];
static int current_arch_mask = 0;
-static void init_disasm PARAMS ((struct disassemble_info *));
-static unsigned int s390_extract_operand
- PARAMS ((unsigned char *, const struct s390_operand *));
-
/* Set up index table for first opcode byte. */
static void
-init_disasm (info)
- struct disassemble_info *info;
+init_disasm (struct disassemble_info *info)
{
const struct s390_opcode *opcode;
const struct s390_opcode *opcode_end;
+ const char *p;
memset (opc_index, 0, sizeof (opc_index));
opcode_end = s390_opcodes + s390_num_opcodes;
(opcode[1].opcode[0] == opcode->opcode[0]))
opcode++;
}
- switch (info->mach)
+
+ for (p = info->disassembler_options; p != NULL; )
{
- case bfd_mach_s390_31:
- current_arch_mask = 1 << S390_OPCODE_ESA;
- break;
- case bfd_mach_s390_64:
- current_arch_mask = 1 << S390_OPCODE_ESAME;
- break;
- default:
- abort ();
+ if (CONST_STRNEQ (p, "esa"))
+ current_arch_mask = 1 << S390_OPCODE_ESA;
+ else if (CONST_STRNEQ (p, "zarch"))
+ current_arch_mask = 1 << S390_OPCODE_ZARCH;
+ else
+ fprintf (stderr, "Unknown S/390 disassembler option: %s\n", p);
+
+ p = strchr (p, ',');
+ if (p != NULL)
+ p++;
}
+
+ if (!current_arch_mask)
+ switch (info->mach)
+ {
+ case bfd_mach_s390_31:
+ current_arch_mask = 1 << S390_OPCODE_ESA;
+ break;
+ case bfd_mach_s390_64:
+ current_arch_mask = 1 << S390_OPCODE_ZARCH;
+ break;
+ default:
+ abort ();
+ }
+
init_flag = 1;
}
/* Extracts an operand value from an instruction. */
static inline unsigned int
-s390_extract_operand (insn, operand)
- unsigned char *insn;
- const struct s390_operand *operand;
+s390_extract_operand (unsigned char *insn, const struct s390_operand *operand)
{
unsigned int val;
int bits;
val >>= -bits;
val &= ((1U << (operand->bits - 1)) << 1) - 1;
+ /* Check for special long displacement case. */
+ if (operand->bits == 20 && operand->shift == 20)
+ val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
+
/* Sign extend value if the operand is signed or pc relative. */
if ((operand->flags & (S390_OPERAND_SIGNED | S390_OPERAND_PCREL))
&& (val & (1U << (operand->bits - 1))))
if (operand->flags & S390_OPERAND_PCREL)
val <<= 1;
- /* Length x in an instructions has real length x+1. */
+ /* Length x in an instructions has real length x + 1. */
if (operand->flags & S390_OPERAND_LENGTH)
val++;
return val;
/* Print a S390 instruction. */
int
-print_insn_s390 (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
+print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
{
bfd_byte buffer[6];
const struct s390_opcode *opcode;
const unsigned char *opindex;
/* Check architecture. */
- if (!(opcode->architecture & current_arch_mask))
+ if (!(opcode->modes & current_arch_mask))
continue;
/* Check signature of the opcode. */
if ((buffer[1] & opcode->mask[1]) != opcode->opcode[1]
else if (operand->flags & S390_OPERAND_SIGNED)
(*info->fprintf_func) (info->stream, "%i", (int) value);
else
- (*info->fprintf_func) (info->stream, "%i", value);
+ (*info->fprintf_func) (info->stream, "%u", value);
if (operand->flags & S390_OPERAND_DISP)
{
return 1;
}
}
+
+void
+print_s390_disassembler_options (FILE *stream)
+{
+ fprintf (stream, _("\n\
+The following S/390 specific disassembler options are supported for use\n\
+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"));
+}