123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- /* Morpho Technologies mRISC opcode support, for GNU Binutils. -*- C -*-
- Copyright 2001, 2007, 2008, 2009, 2012 Free Software Foundation, Inc.
- Contributed by Red Hat Inc; developed under contract from
- Morpho Technologies.
- 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 3 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. */
- /* 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 */
- /* Check applicability of instructions against machines. */
- #define CGEN_VALIDATE_INSN_SUPPORTED
- /* Allows reason codes to be output when assembler errors occur. */
- #define CGEN_VERBOSE_ASSEMBLER_ERRORS
- /* Override disassembly hashing - there are variable bits in the top
- byte of these instructions. */
- #define CGEN_DIS_HASH_SIZE 8
- #define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
- #define CGEN_ASM_HASH_SIZE 127
- #define CGEN_ASM_HASH(insn) mt_asm_hash (insn)
- extern unsigned int mt_asm_hash (const char *);
- extern int mt_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
- /* -- opc.c */
- #include "safe-ctype.h"
- /* Special check to ensure that instruction exists for given machine. */
- int
- mt_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
- {
- int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
- /* No mach attribute? Assume it's supported for all machs. */
- if (machs == 0)
- return 1;
-
- return ((machs & cd->machs) != 0);
- }
- /* A better hash function for instruction mnemonics. */
- unsigned int
- mt_asm_hash (const char* insn)
- {
- unsigned int hash;
- const char* m = insn;
- for (hash = 0; *m && ! ISSPACE (*m); m++)
- hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
- /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
- return hash % CGEN_ASM_HASH_SIZE;
- }
- /* -- asm.c */
- /* Range checking for signed numbers. Returns 0 if acceptable
- and 1 if the value is out of bounds for a signed quantity. */
- static int
- signed_out_of_bounds (long val)
- {
- if ((val < -32768) || (val > 32767))
- return 1;
- return 0;
- }
- static const char *
- parse_loopsize (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- void *arg)
- {
- signed long * valuep = (signed long *) arg;
- const char *errmsg;
- bfd_reloc_code_real_type code = BFD_RELOC_NONE;
- enum cgen_parse_operand_result result_type;
- bfd_vma value;
- /* Is it a control transfer instructions? */
- if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_LOOPSIZE)
- {
- code = BFD_RELOC_MT_PCINSN8;
- errmsg = cgen_parse_address (cd, strp, opindex, code,
- & result_type, & value);
- *valuep = value;
- return errmsg;
- }
- abort ();
- }
- static const char *
- parse_imm16 (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- void *arg)
- {
- signed long * valuep = (signed long *) arg;
- const char *errmsg;
- enum cgen_parse_operand_result result_type;
- bfd_reloc_code_real_type code = BFD_RELOC_NONE;
- bfd_vma value;
- /* Is it a control transfer instructions? */
- if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16O)
- {
- code = BFD_RELOC_16_PCREL;
- errmsg = cgen_parse_address (cd, strp, opindex, code,
- & result_type, & value);
- if (errmsg == NULL)
- {
- if (signed_out_of_bounds (value))
- errmsg = _("Operand out of range. Must be between -32768 and 32767.");
- }
- *valuep = value;
- return errmsg;
- }
- /* If it's not a control transfer instruction, then
- we have to check for %OP relocating operators. */
- if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16L)
- ;
- else if (strncmp (*strp, "%hi16", 5) == 0)
- {
- *strp += 5;
- code = BFD_RELOC_HI16;
- }
- else if (strncmp (*strp, "%lo16", 5) == 0)
- {
- *strp += 5;
- code = BFD_RELOC_LO16;
- }
- /* If we found a %OP relocating operator, then parse it as an address.
- If not, we need to parse it as an integer, either signed or unsigned
- depending on which operand type we have. */
- if (code != BFD_RELOC_NONE)
- {
- /* %OP relocating operator found. */
- errmsg = cgen_parse_address (cd, strp, opindex, code,
- & result_type, & value);
- if (errmsg == NULL)
- {
- switch (result_type)
- {
- case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
- if (code == BFD_RELOC_HI16)
- value = (value >> 16) & 0xFFFF;
- else if (code == BFD_RELOC_LO16)
- value = value & 0xFFFF;
- else
- errmsg = _("Biiiig Trouble in parse_imm16!");
- break;
- case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
- /* No special processing for this case. */
- break;
- default:
- errmsg = _("The percent-operator's operand is not a symbol");
- break;
- }
- }
- *valuep = value;
- }
- else
- {
- /* Parse hex values like 0xffff as unsigned, and sign extend
- them manually. */
- int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MT_OPERAND_IMM16);
- if ((*strp)[0] == '0'
- && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
- parse_signed = 0;
- /* No relocating operator. Parse as an number. */
- if (parse_signed)
- {
- /* Parse as as signed integer. */
-
- errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
- if (errmsg == NULL)
- {
- #if 0
- /* Manual range checking is needed for the signed case. */
- if (*valuep & 0x8000)
- value = 0xffff0000 | *valuep;
- else
- value = *valuep;
- if (signed_out_of_bounds (value))
- errmsg = _("Operand out of range. Must be between -32768 and 32767.");
- /* Truncate to 16 bits. This is necessary
- because cgen will have sign extended *valuep. */
- *valuep &= 0xFFFF;
- #endif
- }
- }
- else
- {
- /* MT_OPERAND_IMM16Z. Parse as an unsigned integer. */
- errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
- if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16
- && *valuep >= 0x8000
- && *valuep <= 0xffff)
- *valuep -= 0x10000;
- }
- }
- return errmsg;
- }
- static const char *
- parse_dup (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- unsigned long *valuep)
- {
- const char *errmsg = NULL;
- if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
- {
- *strp += 3;
- *valuep = 1;
- }
- else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
- {
- *strp += 2;
- *valuep = 0;
- }
- else
- errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
- return errmsg;
- }
- static const char *
- parse_ball (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- unsigned long *valuep)
- {
- const char *errmsg = NULL;
- if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
- {
- *strp += 3;
- *valuep = 1;
- }
- else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
- {
- *strp += 3;
- *valuep = 0;
- }
- else
- errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
- return errmsg;
- }
- static const char *
- parse_xmode (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- unsigned long *valuep)
- {
- const char *errmsg = NULL;
- if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
- {
- *strp += 2;
- *valuep = 1;
- }
- else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
- {
- *strp += 2;
- *valuep = 0;
- }
- else
- errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
- return errmsg;
- }
- static const char *
- parse_rc (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- unsigned long *valuep)
- {
- const char *errmsg = NULL;
- if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
- {
- *strp += 1;
- *valuep = 1;
- }
- else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
- {
- *strp += 1;
- *valuep = 0;
- }
- else
- errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
- return errmsg;
- }
- static const char *
- parse_cbrb (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- unsigned long *valuep)
- {
- const char *errmsg = NULL;
- if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
- {
- *strp += 2;
- *valuep = 1;
- }
- else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
- {
- *strp += 2;
- *valuep = 0;
- }
- else
- errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
- return errmsg;
- }
- static const char *
- parse_rbbc (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- unsigned long *valuep)
- {
- const char *errmsg = NULL;
- if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
- {
- *strp += 2;
- *valuep = 0;
- }
- else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
- {
- *strp += 3;
- *valuep = 1;
- }
- else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
- {
- *strp += 3;
- *valuep = 2;
- }
- else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
- {
- *strp += 2;
- *valuep = 3;
- }
- else
- errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
- return errmsg;
- }
- static const char *
- parse_type (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- unsigned long *valuep)
- {
- const char *errmsg = NULL;
- if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
- {
- *strp += 3;
- *valuep = 0;
- }
- else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
- {
- *strp += 4;
- *valuep = 1;
- }
- else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
- {
- *strp += 2;
- *valuep = 2;
- }
- else
- errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
- if ((errmsg == NULL) && (*valuep == 3))
- errmsg = _("invalid operand. type may have values 0,1,2 only.");
- return errmsg;
- }
- /* -- dis.c */
- static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
- static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
- static void
- print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
- void * dis_info,
- long value,
- 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, "$%lx", value & 0xffffffff);
- if (0)
- print_normal (cd, dis_info, value, attrs, pc, length);
- }
- static void
- print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
- void * dis_info,
- long value,
- unsigned int attrs ATTRIBUTE_UNUSED,
- bfd_vma pc ATTRIBUTE_UNUSED,
- int length ATTRIBUTE_UNUSED)
- {
- print_address (cd, dis_info, value + pc, attrs, pc, length);
- }
- /* -- */
|