/* mmix-dis.c -- Disassemble MMIX instructions.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000-2020 Free Software Foundation, Inc.
Written by Hans-Peter Nilsson (hp@bitrange.com)
-This file is part of GDB and the GNU binutils.
+ This file is part of the GNU opcodes library.
-GDB and the GNU binutils are free software; you can redistribute
-them and/or modify them under the terms of the GNU General Public
-License as published by the Free Software Foundation; either version 2,
-or (at your option) any later version.
+ 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 3, or (at your option)
+ any later version.
-GDB and the GNU binutils are distributed in the hope that they
-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 file; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ 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 "sysdep.h"
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
#include "opcode/mmix.h"
-#include "dis-asm.h"
+#include "disassemble.h"
#include "libiberty.h"
#include "bfd.h"
#include "opintl.h"
-#define BAD_CASE(x) \
- do \
- { \
- fprintf (stderr, \
- _("Bad case %d (%s) in %s:%d\n"), \
- x, #x, __FILE__, __LINE__); \
- abort (); \
- } \
+#define BAD_CASE(x) \
+ do \
+ { \
+ opcodes_error_handler (_("bad case %d (%s) in %s:%d"), \
+ x, #x, __FILE__, __LINE__); \
+ abort (); \
+ } \
while (0)
-#define FATAL_DEBUG \
- do \
- { \
- fprintf (stderr, \
- _("Internal: Non-debugged code (test-case missing): %s:%d"), \
- __FILE__, __LINE__); \
- abort (); \
- } \
+#define FATAL_DEBUG \
+ do \
+ { \
+ opcodes_error_handler (_("internal: non-debugged code " \
+ "(test-case missing): %s:%d"), \
+ __FILE__, __LINE__); \
+ abort (); \
+ } \
while (0)
#define ROUND_MODE(n) \
#define INSN_IMMEDIATE_BIT (IMM_OFFSET_BIT << 24)
#define INSN_BACKWARD_OFFSET_BIT (1 << 24)
+#define MAX_REG_NAME_LEN 256
+#define MAX_SPEC_REG_NAME_LEN 32
struct mmix_dis_info
{
- const char *reg_name[256];
- const char *spec_reg_name[32];
+ const char *reg_name[MAX_REG_NAME_LEN];
+ const char *spec_reg_name[MAX_SPEC_REG_NAME_LEN];
/* Waste a little memory so we don't have to allocate each separately.
We could have an array with static contents for these, but on the
other hand, we don't have to. */
- char basic_reg_name[256][sizeof ("$255")];
+ char basic_reg_name[MAX_REG_NAME_LEN][sizeof ("$255")];
};
-static boolean initialize_mmix_dis_info PARAMS ((struct disassemble_info *));
-static const struct mmix_opcode *get_opcode PARAMS ((unsigned long));
-
-
/* Initialize a target-specific array in INFO. */
-static boolean
-initialize_mmix_dis_info (info)
- struct disassemble_info *info;
+static bfd_boolean
+initialize_mmix_dis_info (struct disassemble_info *info)
{
struct mmix_dis_info *minfop = malloc (sizeof (struct mmix_dis_info));
- int i;
+ long i;
if (minfop == NULL)
- return false;
+ return FALSE;
memset (minfop, 0, sizeof (*minfop));
long symsize = bfd_get_symtab_upper_bound (abfd);
asymbol **syms = malloc (symsize);
long nsyms;
- long i;
if (syms == NULL)
- { FATAL_DEBUG;
+ {
+ FATAL_DEBUG;
free (minfop);
- return false;
+ return FALSE;
}
nsyms = bfd_canonicalize_symtab (abfd, syms);
for (i = 0; i < nsyms && syms[i] != NULL; i++)
{
if (syms[i]->section == reg_section
- && syms[i]->value < 256
+ && syms[i]->value < MAX_REG_NAME_LEN
&& minfop->reg_name[syms[i]->value] == NULL)
minfop->reg_name[syms[i]->value] = syms[i]->name;
}
}
/* Fill in the rest with the canonical names. */
- for (i = 0; i < 256; i++)
+ for (i = 0; i < MAX_REG_NAME_LEN; i++)
if (minfop->reg_name[i] == NULL)
{
- sprintf (minfop->basic_reg_name[i], "$%d", i);
+ sprintf (minfop->basic_reg_name[i], "$%ld", i);
minfop->reg_name[i] = minfop->basic_reg_name[i];
}
for (i = 0; mmix_spec_regs[i].name != NULL; i++)
minfop->spec_reg_name[mmix_spec_regs[i].number] = mmix_spec_regs[i].name;
- info->private_data = (PTR) minfop;
- return true;
+ info->private_data = (void *) minfop;
+ return TRUE;
}
/* A table indexed by the first byte is constructed as we disassemble each
"further entry" will just show that there was no other match. */
static const struct mmix_opcode *
-get_opcode (insn)
- unsigned long insn;
+get_opcode (unsigned long insn)
{
static const struct mmix_opcode **opcodes = NULL;
const struct mmix_opcode *opcodep = mmix_opcodes;
unsigned int opcode_part = (insn >> 24) & 255;
+
if (opcodes == NULL)
opcodes = xcalloc (256, sizeof (struct mmix_opcode *));
case mmix_operands_roundregs:
{
int midbyte = (insn >> 8) & 255;
+
if (midbyte <= 4)
return opcodep;
}
return NULL;
}
+static inline const char *
+get_reg_name (const struct mmix_dis_info * minfop, unsigned int x)
+{
+ if (x >= MAX_REG_NAME_LEN)
+ return _("*illegal*");
+ return minfop->reg_name[x];
+}
+
+static inline const char *
+get_spec_reg_name (const struct mmix_dis_info * minfop, unsigned int x)
+{
+ if (x >= MAX_SPEC_REG_NAME_LEN)
+ return _("*illegal*");
+ return minfop->spec_reg_name[x];
+}
+
/* The main disassembly function. */
int
-print_insn_mmix (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
+print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info)
{
unsigned char buffer[4];
unsigned long insn;
case mmix_operands_regs:
/* All registers: "$X,$Y,$Z". */
(*info->fprintf_func) (info->stream, "%s,%s,%s",
- minfop->reg_name[x],
- minfop->reg_name[y],
- minfop->reg_name[z]);
+ get_reg_name (minfop, x),
+ get_reg_name (minfop, y),
+ get_reg_name (minfop, z));
break;
case mmix_operands_reg_yz:
/* Like SETH - "$X,YZ". */
(*info->fprintf_func) (info->stream, "%s,0x%x",
- minfop->reg_name[x], y * 256 + z);
+ get_reg_name (minfop, x), y * 256 + z);
break;
case mmix_operands_regs_z_opt:
/* The regular "$X,$Y,$Z|Z". */
if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%s,%d",
- minfop->reg_name[x], minfop->reg_name[y], z);
+ get_reg_name (minfop, x),
+ get_reg_name (minfop, y), z);
else
(*info->fprintf_func) (info->stream, "%s,%s,%s",
- minfop->reg_name[x],
- minfop->reg_name[y],
- minfop->reg_name[z]);
+ get_reg_name (minfop, x),
+ get_reg_name (minfop, y),
+ get_reg_name (minfop, z));
break;
case mmix_operands_jmp:
{
if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%s,%d",
- minfop->reg_name[x],
+ get_reg_name (minfop, x),
ROUND_MODE (y), z);
else
(*info->fprintf_func) (info->stream, "%s,%s,%s",
- minfop->reg_name[x],
+ get_reg_name (minfop, x),
ROUND_MODE (y),
- minfop->reg_name[z]);
+ get_reg_name (minfop, z));
}
else
{
if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%d",
- minfop->reg_name[x], z);
+ get_reg_name (minfop, x), z);
else
(*info->fprintf_func) (info->stream, "%s,%s",
- minfop->reg_name[x],
- minfop->reg_name[z]);
+ get_reg_name (minfop, x),
+ get_reg_name (minfop, z));
}
break;
"$X,ROUND_MODE,$Z". */
if (y != 0)
(*info->fprintf_func) (info->stream, "%s,%s,%s",
- minfop->reg_name[x],
+ get_reg_name (minfop, x),
ROUND_MODE (y),
- minfop->reg_name[z]);
+ get_reg_name (minfop, z));
else
(*info->fprintf_func) (info->stream, "%s,%s",
- minfop->reg_name[x],
- minfop->reg_name[z]);
+ get_reg_name (minfop, x),
+ get_reg_name (minfop, z));
break;
case mmix_operands_sync:
/* Like SYNCD - "X,$Y,$Z|Z". */
if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%d,%s,%d",
- x, minfop->reg_name[y], z);
+ x, get_reg_name (minfop, y), z);
else
(*info->fprintf_func) (info->stream, "%d,%s,%s",
- x, minfop->reg_name[y],
- minfop->reg_name[z]);
+ x, get_reg_name (minfop, y),
+ get_reg_name (minfop, z));
break;
case mmix_operands_neg:
/* Like NEG and NEGU - "$X,Y,$Z|Z". */
if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%d,%d",
- minfop->reg_name[x], y, z);
+ get_reg_name (minfop, x), y, z);
else
(*info->fprintf_func) (info->stream, "%s,%d,%s",
- minfop->reg_name[x], y,
- minfop->reg_name[z]);
+ get_reg_name (minfop, x), y,
+ get_reg_name (minfop, z));
break;
case mmix_operands_pushj:
info->target = memaddr + offset;
- (*info->fprintf_func) (info->stream, "%s,", minfop->reg_name[x]);
+ (*info->fprintf_func) (info->stream, "%s,", get_reg_name (minfop, x));
(*info->print_address_func) (memaddr + offset, info);
}
break;
case mmix_operands_get:
/* GET - "X,spec_reg". */
(*info->fprintf_func) (info->stream, "%s,%s",
- minfop->reg_name[x],
- minfop->spec_reg_name[z]);
+ get_reg_name (minfop, x),
+ get_spec_reg_name (minfop, z));
break;
case mmix_operands_put:
/* PUT - "spec_reg,$Z|Z". */
if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%d",
- minfop->spec_reg_name[x], z);
+ get_spec_reg_name (minfop, x), z);
else
(*info->fprintf_func) (info->stream, "%s,%s",
- minfop->spec_reg_name[x],
- minfop->reg_name[z]);
+ get_spec_reg_name (minfop, x),
+ get_reg_name (minfop, z));
break;
case mmix_operands_set:
/* Two registers, "$X,$Y". */
(*info->fprintf_func) (info->stream, "%s,%s",
- minfop->reg_name[x],
- minfop->reg_name[y]);
+ get_reg_name (minfop, x),
+ get_reg_name (minfop, y));
break;
case mmix_operands_save: