binutils-gdb/cpu/m32c.opc

1176 lines
30 KiB
Plaintext
Raw Normal View History

ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> * configure.in: Add cases for Renesas m32c. * configure: Regenerated. bfd/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for m32c-*-elf (Renesas m32c and m16c). * Makefile.am (ALL_MACHINES): Add cpu-m32c.lo. (ALL_MACHINES_CFILES): Add cpu-m32c.c. (BFD32_BACKENDS): Add elf32-m32c.lo. (BFD32_BACKENDS_CFILES): Add elf32-m32c.c. (cpu-m32c.lo, elf32-m32c.lo): New rules, generated by 'make dep-am'. * Makefile.in: Regenerated. * archures.c (bfd_arch_m32c, bfd_mach_m16c, bfd_mach_m32c): New arch and mach codes. (bfd_m32c_arch): New arch info object. (bfd_archures_list): List bfd_m32c_arch. * bfd-in2.h: Regenerated. * config.bfd: Add case for the m32c. * configure.in: Add case for the m32c. * configure: Regenerated. * cpu-m32c.c, elf32-m32c.c: New files. * libbfd.h: Regenerated. * targets.c (bfd_elf32_m32c_vec): Declare. (_bfd_target_vector): List bfd_elf32_m32c_vec. binutils/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> * readelf.c: #include "elf/m32c.h" (guess_is_rela, dump_relocations, get_machine_name): Add cases for EM_M32C. * Makefile.am (readelf.o): Update dependencies. * Makefile.in: Regenerated. cpu/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> * m32c.cpu, m32c.opc: Machine description for the Renesas M32C. gas/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for the Renesas M32C. * Makefile.am (CPU_TYPES): List m32c. (TARGET_CPU_CFILES): List config/tc-m32c.c. (TARGET_CPU_HFILES): List config/tc-m32c.h. * configure.in: Add case for m32c. * configure.tgt: Add cases for m32c and m32c-*-elf. * configure: Regenerated. * config/tc-m32c.c, config/tc-m32c.h: New files. * doc/Makefile.am (CPU_DOCS): Add c-m32c.texi. * doc/Makefile.in: Regenerated. * doc/all.texi: Set M32C. * doc/as.texinfo: Add text for the M32C-specific options and line comment characters, and refer to c-m32c.texi. * doc/c-m32c.texi: New file. include/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> * dis-asm.h (print_insn_m32c): New declaration. include/elf/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for Renesas M32C and M16C. * common.h (EM_M32C): New machine number. * m32c.h: New file. ld/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for the Renesas M32C and M16C. * Makefile.am (ALL_EMULATIONS): Add eelf32m32c.o. (eelf32m32c.c): New target. * Makefile.in: Regenerated. * configure.tgt: Add case for m32c-*-elf. * emulparams/elf32m32c.sh: New file. opcodes/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for the Renesas M32C and M16C. * m32c-asm.c, m32c-desc.c, m32c-dis.c, m32c-ibld.c, m32c-opc.c: New. * m32c-desc.h, m32c-opc.h: New. * Makefile.am (HFILES): List m32c-desc.h and m32c-opc.h. (CFILES): List m32c-asm.c, m32c-desc.c, m32c-dis.c, m32c-ibld.c, m32c-opc.c. (ALL_MACHINES): List m32c-asm.lo, m32c-desc.lo, m32c-dis.lo, m32c-ibld.lo, m32c-opc.lo. (CLEANFILES): List stamp-m32c. (M32C_DEPS): List stamp-m32c, if CGEN_MAINT. (CGEN_CPUS): Add m32c. (m32c-asm.c, m32c-desc.c, m32c-dis.c, m32c-ibld.c, m32c-opc.c) (m32c-desc.h, m32c-opc.h): Depend on M32C_DEPS. (m32c_opc_h): New variable. (stamp-m32c, m32c-asm.lo, m32c-desc.lo, m32c-dis.lo, m32c-ibld.lo) (m32c-opc.lo): New rules. * Makefile.in: Regenerated. * configure.in: Add case for bfd_m32c_arch. * configure: Regenerated. * disassemble.c (ARCH_m32c): New. [ARCH_m32c]: #include "m32c-desc.h". (disassembler) [ARCH_m32c]: Add case for bfd_arch_m32c. (disassemble_init_for_target) [ARCH_m32c]: Same. * cgen-ops.h, cgen-types.h: New files. * Makefile.am (HFILES): List them. * Makefile.in: Regenerated.
2005-07-15 00:52:28 +02:00
/* m32c opcode support. -*- C -*-
2005-07-15 22:31:17 +02:00
Copyright 2005 Free Software Foundation, Inc.
Contributed by Red Hat Inc; developed under contract from Renesas
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> * configure.in: Add cases for Renesas m32c. * configure: Regenerated. bfd/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for m32c-*-elf (Renesas m32c and m16c). * Makefile.am (ALL_MACHINES): Add cpu-m32c.lo. (ALL_MACHINES_CFILES): Add cpu-m32c.c. (BFD32_BACKENDS): Add elf32-m32c.lo. (BFD32_BACKENDS_CFILES): Add elf32-m32c.c. (cpu-m32c.lo, elf32-m32c.lo): New rules, generated by 'make dep-am'. * Makefile.in: Regenerated. * archures.c (bfd_arch_m32c, bfd_mach_m16c, bfd_mach_m32c): New arch and mach codes. (bfd_m32c_arch): New arch info object. (bfd_archures_list): List bfd_m32c_arch. * bfd-in2.h: Regenerated. * config.bfd: Add case for the m32c. * configure.in: Add case for the m32c. * configure: Regenerated. * cpu-m32c.c, elf32-m32c.c: New files. * libbfd.h: Regenerated. * targets.c (bfd_elf32_m32c_vec): Declare. (_bfd_target_vector): List bfd_elf32_m32c_vec. binutils/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> * readelf.c: #include "elf/m32c.h" (guess_is_rela, dump_relocations, get_machine_name): Add cases for EM_M32C. * Makefile.am (readelf.o): Update dependencies. * Makefile.in: Regenerated. cpu/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> * m32c.cpu, m32c.opc: Machine description for the Renesas M32C. gas/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for the Renesas M32C. * Makefile.am (CPU_TYPES): List m32c. (TARGET_CPU_CFILES): List config/tc-m32c.c. (TARGET_CPU_HFILES): List config/tc-m32c.h. * configure.in: Add case for m32c. * configure.tgt: Add cases for m32c and m32c-*-elf. * configure: Regenerated. * config/tc-m32c.c, config/tc-m32c.h: New files. * doc/Makefile.am (CPU_DOCS): Add c-m32c.texi. * doc/Makefile.in: Regenerated. * doc/all.texi: Set M32C. * doc/as.texinfo: Add text for the M32C-specific options and line comment characters, and refer to c-m32c.texi. * doc/c-m32c.texi: New file. include/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> * dis-asm.h (print_insn_m32c): New declaration. include/elf/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for Renesas M32C and M16C. * common.h (EM_M32C): New machine number. * m32c.h: New file. ld/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for the Renesas M32C and M16C. * Makefile.am (ALL_EMULATIONS): Add eelf32m32c.o. (eelf32m32c.c): New target. * Makefile.in: Regenerated. * configure.tgt: Add case for m32c-*-elf. * emulparams/elf32m32c.sh: New file. opcodes/ChangeLog: 2005-07-14 Jim Blandy <jimb@redhat.com> Add support for the Renesas M32C and M16C. * m32c-asm.c, m32c-desc.c, m32c-dis.c, m32c-ibld.c, m32c-opc.c: New. * m32c-desc.h, m32c-opc.h: New. * Makefile.am (HFILES): List m32c-desc.h and m32c-opc.h. (CFILES): List m32c-asm.c, m32c-desc.c, m32c-dis.c, m32c-ibld.c, m32c-opc.c. (ALL_MACHINES): List m32c-asm.lo, m32c-desc.lo, m32c-dis.lo, m32c-ibld.lo, m32c-opc.lo. (CLEANFILES): List stamp-m32c. (M32C_DEPS): List stamp-m32c, if CGEN_MAINT. (CGEN_CPUS): Add m32c. (m32c-asm.c, m32c-desc.c, m32c-dis.c, m32c-ibld.c, m32c-opc.c) (m32c-desc.h, m32c-opc.h): Depend on M32C_DEPS. (m32c_opc_h): New variable. (stamp-m32c, m32c-asm.lo, m32c-desc.lo, m32c-dis.lo, m32c-ibld.lo) (m32c-opc.lo): New rules. * Makefile.in: Regenerated. * configure.in: Add case for bfd_m32c_arch. * configure: Regenerated. * disassemble.c (ARCH_m32c): New. [ARCH_m32c]: #include "m32c-desc.h". (disassembler) [ARCH_m32c]: Add case for bfd_arch_m32c. (disassemble_init_for_target) [ARCH_m32c]: Same. * cgen-ops.h, cgen-types.h: New files. * Makefile.am (HFILES): List them. * Makefile.in: Regenerated.
2005-07-15 00:52:28 +02:00
/* This file is an addendum to m32c.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 */
/* Needed for RTL's 'ext' and 'trunc' operators. */
#include "cgen-types.h"
#include "cgen-ops.h"
/* We can't use the default hash size because many bits are used by
operands. */
#define CGEN_DIS_HASH_SIZE 1
#define CGEN_DIS_HASH(buf, value) 0
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
#define CGEN_VALIDATE_INSN_SUPPORTED
extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
#define CGEN_ASM_HASH_SIZE 0xffff
#define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem))
/* -- */
/* -- opc.c */
static unsigned int
m32c_asm_hash (const char *mnem)
{
unsigned int h;
/* The length of the mnemonic for the Jcnd insns is 1. Hash jsri. */
if (mnem[0] == 'j' && mnem[1] != 's')
return 'j';
/* Don't hash scCND */
if (mnem[0] == 's' && mnem[1] == 'c')
return 's';
for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem)
h += *mnem;
return h % CGEN_ASM_HASH_SIZE;
}
/* -- asm.c */
#include <ctype.h>
#define MACH_M32C 5 /* Must match md_begin. */
static int
m32c_cgen_isa_register (const char **strp)
{
int u;
const char *s = *strp;
static char * m32c_register_names [] =
{
"r0", "r1", "r2", "r3", "r0l", "r0h", "r1l", "r1h",
"a0", "a1", "r2r0", "r3r1", "sp", "fb", "dct0", "dct1", "flg", "svf",
"drc0", "drc1", "dmd0", "dmd1", "intb", "svp", "vct", "isp", "dma0",
"dma1", "dra0", "dra1", "dsa0", "dsa1", 0
};
for (u = 0; m32c_register_names[u]; u++)
{
int len = strlen (m32c_register_names[u]);
if (memcmp (m32c_register_names[u], s, len) == 0
&& (s[len] == 0 || ! ISALNUM (s[len])))
return 1;
}
return 0;
}
static const char *
parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
const char *errmsg = 0;
unsigned long value;
long have_zero = 0;
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
if (strncmp (*strp, "0x0", 3) == 0
|| (**strp == '0' && *(*strp + 1) != 'x'))
have_zero = 1;
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value > 0x3f)
return _("imm:6 immediate is out of range");
*valuep = value;
return 0;
}
static const char *
parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
const char *errmsg = 0;
unsigned long value;
long have_zero = 0;
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
if (strncmp (*strp, "0x0", 3) == 0
|| (**strp == '0' && *(*strp + 1) != 'x'))
have_zero = 1;
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value > 0xff)
return _("dsp:8 immediate is out of range");
/* If this field may require a relocation then use larger dsp16. */
if (! have_zero && value == 0)
return _("dsp:8 immediate is out of range");
*valuep = value;
return 0;
}
static const char *
parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep)
{
const char *errmsg = 0;
signed long value;
long have_zero = 0;
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
if (strncmp (*strp, "0x0", 3) == 0
|| (**strp == '0' && *(*strp + 1) != 'x'))
have_zero = 1;
errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value < -8 || value > 7)
return _("Immediate is out of range -8 to 7");
/* If this field may require a relocation then use larger dsp16. */
if (! have_zero && value == 0)
return _("Immediate is out of range -8 to 7");
*valuep = value;
return 0;
}
static const char *
parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep)
{
const char *errmsg = 0;
signed long value;
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value <= 255 && value > 127)
value -= 0x100;
if (value < -128 || value > 127)
return _("dsp:8 immediate is out of range");
*valuep = value;
return 0;
}
static const char *
parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
const char *errmsg = 0;
unsigned long value;
long have_zero = 0;
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
/* Don't successfully parse register names */
if (m32c_cgen_isa_register (strp))
return "Invalid literal"; /* anything -- will not be seen */
if (strncmp (*strp, "0x0", 3) == 0
|| (**strp == '0' && *(*strp + 1) != 'x'))
have_zero = 1;
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value > 0xffff)
return _("dsp:16 immediate is out of range");
/* If this field may require a relocation then use larger dsp24. */
if (cd->machs == MACH_M32C && ! have_zero && value == 0
&& (strncmp (*strp, "[a", 2) == 0
|| **strp == ','
|| **strp == 0))
return _("dsp:16 immediate is out of range");
*valuep = value;
return 0;
}
static const char *
parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep)
{
const char *errmsg = 0;
signed long value;
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value <= 65535 && value > 32767)
value -= 0x10000;
if (value < -32768 || value > 32767)
return _("dsp:16 immediate is out of range");
*valuep = value;
return 0;
}
static const char *
parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
const char *errmsg = 0;
unsigned long value;
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
/* Don't successfully parse register names */
if (m32c_cgen_isa_register (strp))
return "Invalid literal"; /* anything -- will not be seen */
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value > 0xfffff)
return _("dsp:20 immediate is out of range");
*valuep = value;
return 0;
}
static const char *
parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
const char *errmsg = 0;
unsigned long value;
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
/* Don't successfully parse register names */
if (m32c_cgen_isa_register (strp))
return "Invalid literal"; /* anything -- will not be seen */
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value > 0xffffff)
return _("dsp:24 immediate is out of range");
*valuep = value;
return 0;
}
static const char *
parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep)
{
const char *errmsg = 0;
signed long value;
#if 0
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
/* Don't successfully parse register names */
if (m32c_cgen_isa_register (strp))
return "Invalid literal"; /* anything -- will not be seen */
#endif
errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
*valuep = value;
return 0;
}
static const char *
parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep)
{
const char *errmsg = 0;
signed long value;
#if 0
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
/* Don't successfully parse register names */
if (m32c_cgen_isa_register (strp))
return "Invalid literal"; /* anything -- will not be seen */
#endif
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value < 1 || value > 2)
return _("immediate is out of range 1-2");
*valuep = value;
return 0;
}
static const char *
parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep)
{
const char *errmsg = 0;
signed long value;
#if 0
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
/* Don't successfully parse register names */
if (m32c_cgen_isa_register (strp))
return "Invalid literal"; /* anything -- will not be seen */
#endif
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value < 1 || value > 8)
return _("immediate is out of range 1-8");
*valuep = value;
return 0;
}
static const char *
parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
const char *errmsg = 0;
unsigned long value;
#if 0
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
#endif
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
if (errmsg)
return errmsg;
if (value > 15)
return _("Bit number for indexing general register is out of range 0-15");
*valuep = value;
return 0;
}
static const char *
parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep,
unsigned bits)
{
const char *errmsg = 0;
unsigned long bit;
unsigned long base;
const char *newp = *strp;
unsigned long long bitbase;
#if 0
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
#endif
errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
if (errmsg)
return errmsg;
if (*newp != ',')
return "Missing base for bit,base:8";
++newp;
errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
if (errmsg)
return errmsg;
bitbase = (unsigned long long)bit + ((unsigned long long)base * 8);
if (bitbase >= (1ull << bits))
return _("bit,base is out of range");
*valuep = bitbase;
*strp = newp;
return 0;
}
static const char *
parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep,
unsigned bits)
{
const char *errmsg = 0;
unsigned long bit;
signed long base;
const char *newp = *strp;
long long bitbase;
long long limit;
#if 0
/* Don't successfully parse literals beginning with '[' */
if (**strp == '[')
return "Invalid literal"; /* anything -- will not be seen */
#endif
errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
if (errmsg)
return errmsg;
if (*newp != ',')
return "Missing base for bit,base:8";
++newp;
errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
if (errmsg)
return errmsg;
bitbase = (long long)bit + ((long long)base * 8);
limit = 1ll << (bits - 1);
if (bitbase < -limit || bitbase >= limit)
return _("bit,base is out of range");
*valuep = bitbase;
*strp = newp;
return 0;
}
static const char *
parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8);
}
static const char *
parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11);
}
static const char *
parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16);
}
static const char *
parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19);
}
static const char *
parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
int opindex, unsigned long *valuep)
{
return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27);
}
static const char *
parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep)
{
return parse_signed_bitbase (cd, strp, opindex, valuep, 8);
}
static const char *
parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep)
{
return parse_signed_bitbase (cd, strp, opindex, valuep, 11);
}
static const char *
parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
int opindex, signed long *valuep)
{
return parse_signed_bitbase (cd, strp, opindex, valuep, 19);
}
/* Parse the suffix as :<char> or as nothing followed by a whitespace. */
static const char *
parse_suffix (const char **strp, char suffix)
{
const char *newp = *strp;
if (**strp == ':' && tolower (*(*strp + 1)) == suffix)
newp = *strp + 2;
if (isspace (*newp))
{
*strp = newp;
return 0;
}
return "Invalid suffix"; /* anything -- will not be seen */
}
static const char *
parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
{
return parse_suffix (strp, 's');
}
static const char *
parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
{
return parse_suffix (strp, 'g');
}
static const char *
parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
{
return parse_suffix (strp, 'q');
}
static const char *
parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
{
return parse_suffix (strp, 'z');
}
/* Parse an empty suffix. Fail if the next char is ':'. */
static const char *
parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
{
if (**strp == ':')
return "Unexpected suffix";
return 0;
}
static const char *
parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
int opindex ATTRIBUTE_UNUSED, signed long *valuep)
{
const char *errmsg;
signed long value;
signed long junk;
const char *newp = *strp;
/* Parse r0[hl] */
errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
if (errmsg)
return errmsg;
if (*newp != ',')
return "not a valid r0l/r0h pair";
++newp;
/* Parse the second register in the pair */
if (value == 0) /* r0l */
errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
else
errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
if (errmsg)
return errmsg;
*strp = newp;
*valuep = ! value;
return 0;
}
/* Accept .b or .w in any case */
static const char *
parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
{
if (**strp == '.'
&& (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
|| *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
{
*strp += 2;
return 0;
}
return "Invalid size specifier";
}
/* static const char * parse_abs (CGEN_CPU_DESC, const char **, int, */
/* unsigned long *, unsigned long); */
/* static const char * parse_abs16 (CGEN_CPU_DESC, const char **, int, */
/* int ATTRIBUTE_UNUSED, */
/* enum cgen_parse_operand_result * ATTRIBUTE_UNUSED, */
/* unsigned long * ); */
/* static const char * parse_abs24 (CGEN_CPU_DESC, const char **, int, */
/* int ATTRIBUTE_UNUSED, */
/* enum cgen_parse_operand_result * ATTRIBUTE_UNUSED, */
/* unsigned long *); */
/* /\* Parse absolute *\/ */
/* static const char * */
/* parse_abs16 (CGEN_CPU_DESC cd, const char **strp, int opindex, */
/* int reloc ATTRIBUTE_UNUSED, */
/* enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED, */
/* unsigned long *valuep) */
/* { */
/* return parse_abs (cd, strp, opindex, valuep, 16); */
/* } */
/* static const char * */
/* parse_abs24 (CGEN_CPU_DESC cd, const char **strp, int opindex, */
/* int reloc ATTRIBUTE_UNUSED, */
/* enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED, */
/* unsigned long *valuep) */
/* { */
/* return parse_abs (cd, strp, opindex, valuep, 24); */
/* } */
/* static const char * */
/* parse_abs (CGEN_CPU_DESC cd, const char **strp, int opindex, */
/* unsigned long *valuep, */
/* unsigned long length) */
/* { */
/* const char *errmsg = 0; */
/* const char *op; */
/* int has_register = 0; */
/* for (op = *strp; *op != '\0'; op++) */
/* { */
/* if (*op == '[') */
/* { */
/* has_register = 1; */
/* break; */
/* } */
/* else if (*op == ',') */
/* break; */
/* } */
/* if (has_register || m32c_cgen_isa_register (strp)) */
/* errmsg = _("immediate value cannot be register"); */
/* else */
/* { */
/* enum cgen_parse_operand_result result_type; */
/* bfd_vma value; */
/* const char *errmsg; */
/* errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16, */
/* &result_type, &value); */
/* *valuep = value; */
/* } */
/* return errmsg; */
/* } */
/* /\* Handle signed/unsigned literal. *\/ */
/* static const char * */
/* parse_imm8 (cd, strp, opindex, valuep) */
/* CGEN_CPU_DESC cd; */
/* const char **strp; */
/* int opindex; */
/* unsigned long *valuep; */
/* { */
/* const char *errmsg = 0; */
/* long value; */
/* long have_zero = 0; */
/* if (strncmp (*strp, "0x0", 3) == 0 */
/* || (**strp == '0' && *(*strp + 1) != 'x')) */
/* have_zero = 1; */
/* errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); */
/* *valuep = value; */
/* /\* If this field may require a relocation then use larger dsp16. *\/ */
/* if (! have_zero && value == 0) */
/* errmsg = _("immediate value may not fit in dsp8 field"); */
/* return errmsg; */
/* } */
/* static const char * */
/* parse_imm16 (cd, strp, opindex, valuep) */
/* CGEN_CPU_DESC cd; */
/* const char **strp; */
/* int opindex; */
/* unsigned long *valuep; */
/* { */
/* const char *errmsg; */
/* long value; */
/* errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); */
/* *valuep = value; */
/* return errmsg; */
/* } */
/* static const char * */
/* parse_imm24 (cd, strp, opindex, valuep) */
/* CGEN_CPU_DESC cd; */
/* const char **strp; */
/* int opindex; */
/* unsigned long *valuep; */
/* { */
/* const char *errmsg; */
/* long value; */
/* errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); */
/* *valuep = value; */
/* return errmsg; */
/* } */
/* static const char * */
/* parse_imm32 (cd, strp, opindex, valuep) */
/* CGEN_CPU_DESC cd; */
/* const char **strp; */
/* int opindex; */
/* unsigned long *valuep; */
/* { */
/* const char *errmsg; */
/* long value; */
/* errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); */
/* *valuep = value; */
/* return errmsg; */
/* } */
/* /\* Handle bitfields. *\/ */
/* static const char * */
/* parse_boff8 (cd, strp, opindex, valuep) */
/* CGEN_CPU_DESC cd; */
/* const char **strp; */
/* int opindex; */
/* unsigned long *valuep; */
/* { */
/* const char *errmsg; */
/* long bit_value, value; */
/* errmsg = cgen_parse_signed_integer (cd, strp, opindex, & bit_value); */
/* if (errmsg == 0) */
/* { */
/* *strp = *strp + 1; */
/* errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); */
/* } */
/* value = value * 8 + bit_value; */
/* *valuep = value; */
/* if (value > 0x100) */
/* errmsg = _("Operand out of range. Must be between 0 and 255."); */
/* return errmsg; */
/* } */
/* static const char * */
/* parse_boff16 (cd, strp, opindex, valuep) */
/* CGEN_CPU_DESC cd; */
/* const char **strp; */
/* int opindex; */
/* unsigned long *valuep; */
/* { */
/* const char *errmsg; */
/* long bit_value, value; */
/* errmsg = cgen_parse_signed_integer (cd, strp, opindex, & bit_value); */
/* if (errmsg == 0) */
/* { */
/* *strp = *strp + 1; */
/* errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); */
/* } */
/* value = value * 8 + bit_value; */
/* *valuep = value; */
/* if (value > 0x1000) */
/* errmsg = _("Operand out of range. Must be between 0 and 65535."); */
/* return errmsg; */
/* } */
/* Special check to ensure that instruction exists for given machine */
int
m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
const CGEN_INSN *insn)
{
int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
/* If attributes are absent, assume no restriction. */
if (machs == 0)
machs = ~0;
return (machs & cd->machs)
&& cgen_bitset_intersect_p (& isas, cd->isas);
}
/* Parse a set of registers, R0,R1,A0,A1,SB,FB. */
static const char *
parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
const char **strp,
int opindex ATTRIBUTE_UNUSED,
unsigned long *valuep,
int push
)
{
const char *errmsg = 0;
int regno = 0;
*valuep = 0;
while (**strp && **strp != ')')
{
if (**strp == 'r' || **strp == 'R')
{
++*strp;
regno = **strp - '0';
if (regno > 4)
errmsg = _("Register number is not valid");
}
else if (**strp == 'a' || **strp == 'A')
{
++*strp;
regno = **strp - '0';
if (regno > 2)
errmsg = _("Register number is not valid");
regno = **strp - '0' + 4;
}
else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
{
regno = 6;
++*strp;
}
else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
{
regno = 7;
++*strp;
}
if (push) /* Mask is reversed for push. */
*valuep |= 0x80 >> regno;
else
*valuep |= 1 << regno;
++*strp;
if (**strp == ',')
{
if (*(*strp + 1) == ')')
break;
++*strp;
}
}
if (!*strp)
errmsg = _("Register list is not valid");
return errmsg;
}
#define POP 0
#define PUSH 1
static const char *
parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
const char **strp,
int opindex ATTRIBUTE_UNUSED,
unsigned long *valuep)
{
return parse_regset (cd, strp, opindex, valuep, POP);
}
static const char *
parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
const char **strp,
int opindex ATTRIBUTE_UNUSED,
unsigned long *valuep)
{
return parse_regset (cd, strp, opindex, valuep, PUSH);
}
/* -- dis.c */
#include "elf/m32c.h"
#include "elf-bfd.h"
/* Always print the short insn format suffix as ':<char>' */
static void
print_suffix (PTR dis_info, char suffix)
{
disassemble_info *info = dis_info;
(*info->fprintf_func) (info->stream, ":%c", suffix);
}
static void
print_S (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)
{
print_suffix (dis_info, 's');
}
static void
print_G (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)
{
print_suffix (dis_info, 'g');
}
static void
print_Q (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)
{
print_suffix (dis_info, 'q');
}
static void
print_Z (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)
{
print_suffix (dis_info, 'z');
}
/* Print the empty suffix */
static void
print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
PTR dis_info ATTRIBUTE_UNUSED,
long value ATTRIBUTE_UNUSED,
unsigned int attrs ATTRIBUTE_UNUSED,
bfd_vma pc ATTRIBUTE_UNUSED,
int length ATTRIBUTE_UNUSED)
{
return;
}
static void
print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
PTR dis_info,
long value,
unsigned int attrs ATTRIBUTE_UNUSED,
bfd_vma pc ATTRIBUTE_UNUSED,
int length ATTRIBUTE_UNUSED)
{
disassemble_info *info = dis_info;
if (value == 0)
(*info->fprintf_func) (info->stream, "r0h,r0l");
else
(*info->fprintf_func) (info->stream, "r0l,r0h");
}
static void
print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
PTR dis_info,
unsigned long value,
unsigned int attrs ATTRIBUTE_UNUSED,
bfd_vma pc ATTRIBUTE_UNUSED,
int length ATTRIBUTE_UNUSED)
{
disassemble_info *info = dis_info;
(*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
}
static void
print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
PTR dis_info,
signed long value,
unsigned int attrs ATTRIBUTE_UNUSED,
bfd_vma pc ATTRIBUTE_UNUSED,
int length ATTRIBUTE_UNUSED)
{
disassemble_info *info = dis_info;
(*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
}
static void
print_size (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)
{
/* Always print the size as '.w' */
disassemble_info *info = dis_info;
(*info->fprintf_func) (info->stream, ".w");
}
#define POP 0
#define PUSH 1
static void print_pop_regset (CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int);
static void print_push_regset (CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int);
/* Print a set of registers, R0,R1,A0,A1,SB,FB. */
static void
print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
PTR dis_info,
long value,
unsigned int attrs ATTRIBUTE_UNUSED,
bfd_vma pc ATTRIBUTE_UNUSED,
int length ATTRIBUTE_UNUSED,
int push)
{
static char * m16c_register_names [] =
{
"r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
};
disassemble_info *info = dis_info;
int mask;
int index = 0;
char* comma = "";
if (push)
mask = 0x80;
else
mask = 1;
if (value & mask)
{
(*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
comma = ",";
}
for (index = 1; index <= 7; ++index)
{
if (push)
mask >>= 1;
else
mask <<= 1;
if (value & mask)
{
(*info->fprintf_func) (info->stream, "%s%s", comma,
m16c_register_names [index]);
comma = ",";
}
}
}
static void
print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
PTR dis_info,
long value,
unsigned int attrs ATTRIBUTE_UNUSED,
bfd_vma pc ATTRIBUTE_UNUSED,
int length ATTRIBUTE_UNUSED)
{
print_regset (cd, dis_info, value, attrs, pc, length, POP);
}
static void
print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
PTR dis_info,
long value,
unsigned int attrs ATTRIBUTE_UNUSED,
bfd_vma pc ATTRIBUTE_UNUSED,
int length ATTRIBUTE_UNUSED)
{
print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
}
#if 0 /* not used? */
static void
print_boff (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
PTR dis_info,
long value,
unsigned int attrs ATTRIBUTE_UNUSED,
bfd_vma pc ATTRIBUTE_UNUSED,
int length ATTRIBUTE_UNUSED)
{
disassemble_info *info = dis_info;
if (value)
info->fprintf_func (info->stream, "%d,%d", value % 16,
(value / 16) * 2);
}
#endif /* not used? */