2004-02-20 Andrew Cagney <cagney@redhat.com>
* m32r.opc, m32r.cpu: New files. Written by , Doug Evans, Nick Clifton, Ben Elliston, Matthew Green, and Andrew Haley.
This commit is contained in:
parent
299d901ce6
commit
e866a2571a
3 changed files with 2432 additions and 0 deletions
|
@ -1,5 +1,8 @@
|
|||
2004-02-20 Andrew Cagney <cagney@redhat.com>
|
||||
|
||||
* m32r.opc, m32r.cpu: New files. Written by , Doug Evans, Nick
|
||||
Clifton, Ben Elliston, Matthew Green, and Andrew Haley.
|
||||
|
||||
* sh.cpu, sh.opc, sh64-compact.cpu, sh64-media.cpu: New files, all
|
||||
written by Ben Elliston.
|
||||
|
||||
|
|
2127
cpu/m32r.cpu
Normal file
2127
cpu/m32r.cpu
Normal file
File diff suppressed because it is too large
Load diff
302
cpu/m32r.opc
Normal file
302
cpu/m32r.opc
Normal file
|
@ -0,0 +1,302 @@
|
|||
/* M32R opcode support. -*- C -*-
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
Contributed by Red Hat Inc; developed under contract from
|
||||
Mitsubishi Electric Corporation.
|
||||
|
||||
This file is part of the GNU Binutils.
|
||||
|
||||
Contributed by Red Hat Inc; developed under contract from Fujitsu.
|
||||
|
||||
This file is part of the GNU Binutils.
|
||||
|
||||
This program 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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* This file is an addendum to m32r.cpu. Heavy use of C code isn't
|
||||
appropriate in .cpu files, so it resides here. This especially applies
|
||||
to assembly/disassembly where parsing/printing can be quite involved.
|
||||
Such things aren't really part of the specification of the cpu, per se,
|
||||
so .cpu files provide the general framework and .opc files handle the
|
||||
nitty-gritty details as necessary.
|
||||
|
||||
Each section is delimited with start and end markers.
|
||||
|
||||
<arch>-opc.h additions use: "-- opc.h"
|
||||
<arch>-opc.c additions use: "-- opc.c"
|
||||
<arch>-asm.c additions use: "-- asm.c"
|
||||
<arch>-dis.c additions use: "-- dis.c"
|
||||
<arch>-ibd.h additions use: "-- ibd.h"
|
||||
*/
|
||||
|
||||
/* -- opc.h */
|
||||
|
||||
#undef CGEN_DIS_HASH_SIZE
|
||||
#define CGEN_DIS_HASH_SIZE 256
|
||||
#undef CGEN_DIS_HASH
|
||||
#define X(b) (((unsigned char *) (b))[0] & 0xf0)
|
||||
#define CGEN_DIS_HASH(buffer, value) \
|
||||
(X (buffer) | \
|
||||
(X (buffer) == 0x40 || X (buffer) == 0xe0 || X (buffer) == 0x60 || X (buffer) == 0x50 ? 0 \
|
||||
: X (buffer) == 0x70 || X (buffer) == 0xf0 ? (((unsigned char *) (buffer))[0] & 0xf) \
|
||||
: X (buffer) == 0x30 ? ((((unsigned char *) (buffer))[1] & 0x70) >> 4) \
|
||||
: ((((unsigned char *) (buffer))[1] & 0xf0) >> 4)))
|
||||
|
||||
/* -- */
|
||||
|
||||
/* -- asm.c */
|
||||
static const char * parse_hash
|
||||
PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
|
||||
static const char * parse_hi16
|
||||
PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
|
||||
static const char * parse_slo16
|
||||
PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
|
||||
static const char * parse_ulo16
|
||||
PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
|
||||
|
||||
/* Handle '#' prefixes (i.e. skip over them). */
|
||||
|
||||
static const char *
|
||||
parse_hash (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
const char **strp;
|
||||
int opindex ATTRIBUTE_UNUSED;
|
||||
unsigned long *valuep ATTRIBUTE_UNUSED;
|
||||
{
|
||||
if (**strp == '#')
|
||||
++*strp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle shigh(), high(). */
|
||||
|
||||
static const char *
|
||||
parse_hi16 (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char **strp;
|
||||
int opindex;
|
||||
unsigned long *valuep;
|
||||
{
|
||||
const char *errmsg;
|
||||
enum cgen_parse_operand_result result_type;
|
||||
bfd_vma value;
|
||||
|
||||
if (**strp == '#')
|
||||
++*strp;
|
||||
|
||||
if (strncasecmp (*strp, "high(", 5) == 0)
|
||||
{
|
||||
*strp += 5;
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
|
||||
&result_type, &value);
|
||||
if (**strp != ')')
|
||||
return "missing `)'";
|
||||
++*strp;
|
||||
if (errmsg == NULL
|
||||
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
|
||||
value >>= 16;
|
||||
*valuep = value;
|
||||
return errmsg;
|
||||
}
|
||||
else if (strncasecmp (*strp, "shigh(", 6) == 0)
|
||||
{
|
||||
*strp += 6;
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
|
||||
&result_type, &value);
|
||||
if (**strp != ')')
|
||||
return "missing `)'";
|
||||
++*strp;
|
||||
if (errmsg == NULL
|
||||
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
|
||||
value = (value >> 16) + (value & 0x8000 ? 1 : 0);
|
||||
*valuep = value;
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
|
||||
}
|
||||
|
||||
/* Handle low() in a signed context. Also handle sda().
|
||||
The signedness of the value doesn't matter to low(), but this also
|
||||
handles the case where low() isn't present. */
|
||||
|
||||
static const char *
|
||||
parse_slo16 (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char **strp;
|
||||
int opindex;
|
||||
long *valuep;
|
||||
{
|
||||
const char *errmsg;
|
||||
enum cgen_parse_operand_result result_type;
|
||||
bfd_vma value;
|
||||
|
||||
if (**strp == '#')
|
||||
++*strp;
|
||||
|
||||
if (strncasecmp (*strp, "low(", 4) == 0)
|
||||
{
|
||||
*strp += 4;
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
|
||||
&result_type, &value);
|
||||
if (**strp != ')')
|
||||
return "missing `)'";
|
||||
++*strp;
|
||||
if (errmsg == NULL
|
||||
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
|
||||
value &= 0xffff;
|
||||
*valuep = value;
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
if (strncasecmp (*strp, "sda(", 4) == 0)
|
||||
{
|
||||
*strp += 4;
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
|
||||
NULL, &value);
|
||||
if (**strp != ')')
|
||||
return "missing `)'";
|
||||
++*strp;
|
||||
*valuep = value;
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
return cgen_parse_signed_integer (cd, strp, opindex, valuep);
|
||||
}
|
||||
|
||||
/* Handle low() in an unsigned context.
|
||||
The signedness of the value doesn't matter to low(), but this also
|
||||
handles the case where low() isn't present. */
|
||||
|
||||
static const char *
|
||||
parse_ulo16 (cd, strp, opindex, valuep)
|
||||
CGEN_CPU_DESC cd;
|
||||
const char **strp;
|
||||
int opindex;
|
||||
unsigned long *valuep;
|
||||
{
|
||||
const char *errmsg;
|
||||
enum cgen_parse_operand_result result_type;
|
||||
bfd_vma value;
|
||||
|
||||
if (**strp == '#')
|
||||
++*strp;
|
||||
|
||||
if (strncasecmp (*strp, "low(", 4) == 0)
|
||||
{
|
||||
*strp += 4;
|
||||
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
|
||||
&result_type, &value);
|
||||
if (**strp != ')')
|
||||
return "missing `)'";
|
||||
++*strp;
|
||||
if (errmsg == NULL
|
||||
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
|
||||
value &= 0xffff;
|
||||
*valuep = value;
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
|
||||
}
|
||||
|
||||
/* -- */
|
||||
|
||||
/* -- dis.c */
|
||||
static void print_hash PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
|
||||
static int my_print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
|
||||
|
||||
/* Immediate values are prefixed with '#'. */
|
||||
|
||||
#define CGEN_PRINT_NORMAL(cd, info, value, attrs, pc, length) \
|
||||
do \
|
||||
{ \
|
||||
if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_HASH_PREFIX)) \
|
||||
(*info->fprintf_func) (info->stream, "#"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Handle '#' prefixes as operands. */
|
||||
|
||||
static void
|
||||
print_hash (cd, dis_info, value, attrs, pc, length)
|
||||
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
|
||||
PTR dis_info;
|
||||
long value ATTRIBUTE_UNUSED;
|
||||
unsigned int attrs ATTRIBUTE_UNUSED;
|
||||
bfd_vma pc ATTRIBUTE_UNUSED;
|
||||
int length ATTRIBUTE_UNUSED;
|
||||
{
|
||||
disassemble_info *info = (disassemble_info *) dis_info;
|
||||
(*info->fprintf_func) (info->stream, "#");
|
||||
}
|
||||
|
||||
#undef CGEN_PRINT_INSN
|
||||
#define CGEN_PRINT_INSN my_print_insn
|
||||
|
||||
static int
|
||||
my_print_insn (cd, pc, info)
|
||||
CGEN_CPU_DESC cd;
|
||||
bfd_vma pc;
|
||||
disassemble_info *info;
|
||||
{
|
||||
char buffer[CGEN_MAX_INSN_SIZE];
|
||||
char *buf = buffer;
|
||||
int status;
|
||||
int buflen = (pc & 3) == 0 ? 4 : 2;
|
||||
|
||||
/* Read the base part of the insn. */
|
||||
|
||||
status = (*info->read_memory_func) (pc, buf, buflen, info);
|
||||
if (status != 0)
|
||||
{
|
||||
(*info->memory_error_func) (status, pc, info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 32 bit insn? */
|
||||
if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
|
||||
return print_insn (cd, pc, info, buf, buflen);
|
||||
|
||||
/* Print the first insn. */
|
||||
if ((pc & 3) == 0)
|
||||
{
|
||||
if (print_insn (cd, pc, info, buf, 2) == 0)
|
||||
(*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
|
||||
buf += 2;
|
||||
}
|
||||
|
||||
if (buf[0] & 0x80)
|
||||
{
|
||||
/* Parallel. */
|
||||
(*info->fprintf_func) (info->stream, " || ");
|
||||
buf[0] &= 0x7f;
|
||||
}
|
||||
else
|
||||
(*info->fprintf_func) (info->stream, " -> ");
|
||||
|
||||
/* The "& 3" is to pass a consistent address.
|
||||
Parallel insns arguably both begin on the word boundary.
|
||||
Also, branch insns are calculated relative to the word boundary. */
|
||||
if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
|
||||
(*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
|
||||
|
||||
return (pc & 3) ? 2 : 4;
|
||||
}
|
||||
|
||||
/* -- */
|
Loading…
Reference in a new issue