/* Disassemble SH64 instructions.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000-2015 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify
+ This file is part of the GNU opcodes library.
+
+ 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 "sysdep.h"
#include <stdio.h>
-
#include "dis-asm.h"
-#include "sysdep.h"
#include "sh64-opc.h"
#include "libiberty.h"
-
/* We need to refer to the ELF header structure. */
#include "elf-bfd.h"
#include "elf/sh.h"
+#include "elf32-sh64.h"
#define ELF_MODE32_CODE_LABEL_P(SYM) \
(((elf_symbol_type *) (SYM))->internal_elf_sym.st_other & STO_SH5_ISA32)
};
/* Each item in the table is a mask to indicate which bits to be set
- to determine an instruction's operator.
+ to determine an instruction's operator.
The index is as same as the instruction in the opcode table.
Note that some archs have this as a field in the opcode table. */
static unsigned long *shmedia_opcode_mask_table;
-static void initialize_shmedia_opcode_mask_table PARAMS ((void));
-static int print_insn_shmedia PARAMS ((bfd_vma, disassemble_info *));
-static int print_insn_sh64x
- PARAMS ((bfd_vma, disassemble_info *,
- int (*) PARAMS ((bfd_vma, struct disassemble_info *)),
- enum bfd_endian));
-static const char *creg_name PARAMS ((int));
-static boolean init_sh64_disasm_info PARAMS ((struct disassemble_info *));
-static enum sh64_elf_cr_type sh64_get_contents_type_disasm
- PARAMS ((bfd_vma, struct disassemble_info *));
-
/* Initialize the SH64 opcode mask table for each instruction in SHmedia
mode. */
static void
-initialize_shmedia_opcode_mask_table ()
+initialize_shmedia_opcode_mask_table (void)
{
int n_opc;
int n;
{
int offset = shmedia_table[n].nibbles[i];
int length;
-
+
switch (shmedia_table[n].arg[i])
{
case A_GREG_M:
length = 3;
break;
- case A_IMMM:
+ case A_IMMM:
abort ();
break;
/* Get a predefined control-register-name, or return NULL. */
-const char *
-creg_name (cregno)
- int cregno;
+static const char *
+creg_name (int cregno)
{
const shmedia_creg_info *cregp;
/* If control register usage is common enough, change this to search a
hash-table. */
for (cregp = shmedia_creg_table; cregp->name != NULL; cregp++)
- {
- if (cregp->cregno == cregno)
- return cregp->name;
- }
+ if (cregp->cregno == cregno)
+ return cregp->name;
return NULL;
}
/* Main function to disassemble SHmedia instructions. */
static int
-print_insn_shmedia (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
+print_insn_shmedia (bfd_vma memaddr, struct disassemble_info *info)
{
fprintf_ftype fprintf_fn = info->fprintf_func;
void *stream = info->stream;
-
unsigned char insn[4];
unsigned long instruction;
int status;
can get as .byte:s. */
if (status != 0)
{
- int i;
-
for (i = 0; i < 3; i++)
{
status = info->read_memory_func (memaddr + i, insn, 1, info);
/* FIXME: We should also check register number constraints. */
if (op->name == NULL)
{
- fprintf_fn (stream, ".long 0x%08x", instruction);
+ fprintf_fn (stream, ".long 0x%08lx", instruction);
return 4;
}
case A_CREG_J:
{
const char *name;
+
r = temp & 0x3f;
name = creg_name (r);
imm = temp & 0x3f;
if (imm & (unsigned long) 0x20)
imm |= ~(unsigned long) 0x3f;
- fprintf_fn (stream, "%d", imm);
+ fprintf_fn (stream, "%ld", imm);
break;
/* A signed 6-bit number, multiplied by 32 when used. */
imm = temp & 0x3f;
if (imm & (unsigned long) 0x20)
imm |= ~(unsigned long) 0x3f;
- fprintf_fn (stream, "%d", imm * 32);
+ fprintf_fn (stream, "%ld", imm * 32);
break;
/* A signed 10-bit number, multiplied by 8 when used. */
if (imm & (unsigned long) 0x200)
imm |= ~(unsigned long) 0x3ff;
imm <<= by_number;
- fprintf_fn (stream, "%d", imm);
+ fprintf_fn (stream, "%ld", imm);
break;
/* A signed 16-bit number. */
imm = temp & 0xffff;
if (imm & (unsigned long) 0x8000)
imm |= ~((unsigned long) 0xffff);
- fprintf_fn (stream, "%d", imm);
+ fprintf_fn (stream, "%ld", imm);
break;
/* A PC-relative signed 16-bit number, multiplied by 4 when
/* An unsigned 5-bit number. */
case A_IMMU5:
imm = temp & 0x1f;
- fprintf_fn (stream, "%d", imm);
+ fprintf_fn (stream, "%ld", imm);
break;
/* An unsigned 6-bit number. */
case A_IMMU6:
imm = temp & 0x3f;
- fprintf_fn (stream, "%d", imm);
+ fprintf_fn (stream, "%ld", imm);
break;
/* An unsigned 16-bit number. */
case A_IMMU16:
imm = temp & 0xffff;
- fprintf_fn (stream, "%d", imm);
+ fprintf_fn (stream, "%ld", imm);
break;
default:
no section is available. */
static enum sh64_elf_cr_type
-sh64_get_contents_type_disasm (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
+sh64_get_contents_type_disasm (bfd_vma memaddr, struct disassemble_info *info)
{
struct sh64_disassemble_info *sh64_infop = info->private_data;
/* Initialize static and dynamic disassembly state. */
-static boolean
-init_sh64_disasm_info (info)
- struct disassemble_info *info;
+static bfd_boolean
+init_sh64_disasm_info (struct disassemble_info *info)
{
struct sh64_disassemble_info *sh64_infop
= calloc (sizeof (*sh64_infop), 1);
if (sh64_infop == NULL)
- return false;
+ return FALSE;
info->private_data = sh64_infop;
if (shmedia_opcode_mask_table == NULL)
initialize_shmedia_opcode_mask_table ();
- return true;
+ return TRUE;
}
/* Main entry to disassemble SHmedia instructions, given an endian set in
INFO. Note that the simulator uses this as the main entry and does not
use any of the functions further below. */
-int
-print_insn_sh64x_media (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
+int
+print_insn_sh64x_media (bfd_vma memaddr, struct disassemble_info *info)
{
if (info->private_data == NULL && ! init_sh64_disasm_info (info))
return -1;
return print_insn_shmedia (memaddr, info);
}
-/* Main entry to disassemble SHcompact or SHmedia insns. */
+/* Main entry to disassemble SHmedia insns.
+ If we see an SHcompact instruction, return -2. */
-static int
-print_insn_sh64x (memaddr, info, pfun_compact, endian)
- bfd_vma memaddr;
- struct disassemble_info *info;
- int (*pfun_compact) PARAMS ((bfd_vma, struct disassemble_info *));
- enum bfd_endian endian;
+int
+print_insn_sh64 (bfd_vma memaddr, struct disassemble_info *info)
{
+ enum bfd_endian endian = info->endian;
enum sh64_elf_cr_type cr_type;
if (info->private_data == NULL && ! init_sh64_disasm_info (info))
int length = 4 - (memaddr % 4);
info->display_endian = endian;
+ /* If we got an uneven address to indicate SHmedia, adjust it. */
+ if (cr_type == CRT_SH5_ISA32 && length == 3)
+ memaddr--, length = 4;
+
/* Only disassemble on four-byte boundaries. Addresses that are not
a multiple of four can happen after a data region. */
if (cr_type == CRT_SH5_ISA32 && length == 4)
}
}
- return (*pfun_compact) (memaddr, info);
-}
-
-/* Main entry to disassemble SHcompact or SHmedia insns, big endian. */
-
-int
-print_insn_sh64 (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
-{
- return
- print_insn_sh64x (memaddr, info, print_insn_sh, BFD_ENDIAN_BIG);
-}
-
-/* Main entry to disassemble SHcompact or SHmedia insns, little endian. */
-
-int
-print_insn_sh64l (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
-{
- return
- print_insn_sh64x (memaddr, info, print_insn_shl, BFD_ENDIAN_LITTLE);
+ /* SH1 .. SH4 instruction, let caller handle it. */
+ return -2;
}