summaryrefslogtreecommitdiffstats
path: root/binutils-2.25/cpu/iq2000.opc
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-2.25/cpu/iq2000.opc')
-rw-r--r--binutils-2.25/cpu/iq2000.opc320
1 files changed, 320 insertions, 0 deletions
diff --git a/binutils-2.25/cpu/iq2000.opc b/binutils-2.25/cpu/iq2000.opc
new file mode 100644
index 00000000..f1803737
--- /dev/null
+++ b/binutils-2.25/cpu/iq2000.opc
@@ -0,0 +1,320 @@
+/* IQ2000 opcode support. -*- C -*-
+
+ Copyright 2000, 2001, 2002, 2005, 2007, 2009 Free Software Foundation, Inc.
+
+ 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 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. */
+
+/* This file is an addendum to iq2000.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 */
+
+/* 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)) >> 6) % CGEN_DIS_HASH_SIZE)
+
+/* following activates check beyond hashing since some iq2000 and iq10
+ instructions have same mnemonics but different functionality. */
+#define CGEN_VALIDATE_INSN_SUPPORTED
+
+extern int iq2000_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
+
+/* -- asm.c */
+
+#include "safe-ctype.h"
+
+static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
+
+/* Special check to ensure that instruction exists for given machine. */
+
+int
+iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
+{
+ int machs = cd->machs;
+
+ return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0;
+}
+
+static int
+iq2000_cgen_isa_register (const char **strp)
+{
+ int len;
+ int ch1, ch2;
+
+ if (**strp == 'r' || **strp == 'R')
+ {
+ len = strlen (*strp);
+ if (len == 2)
+ {
+ ch1 = (*strp)[1];
+ if ('0' <= ch1 && ch1 <= '9')
+ return 1;
+ }
+ else if (len == 3)
+ {
+ ch1 = (*strp)[1];
+ ch2 = (*strp)[2];
+ if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
+ return 1;
+ if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
+ return 1;
+ }
+ }
+ if (**strp == '%'
+ && TOLOWER ((*strp)[1]) != 'l'
+ && TOLOWER ((*strp)[1]) != 'h')
+ return 1;
+ return 0;
+}
+
+/* Handle negated literal. */
+
+static const char *
+parse_mimm (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ unsigned long *valuep)
+{
+ const char *errmsg;
+
+ /* Verify this isn't a register. */
+ if (iq2000_cgen_isa_register (strp))
+ errmsg = _("immediate value cannot be register");
+ else
+ {
+ long value;
+
+ errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
+ if (errmsg == NULL)
+ {
+ long x = (-value) & 0xFFFF0000;
+
+ if (x != 0 && x != (long) 0xFFFF0000)
+ errmsg = _("immediate value out of range");
+ else
+ *valuep = (-value & 0xFFFF);
+ }
+ }
+ return errmsg;
+}
+
+/* Handle signed/unsigned literal. */
+
+static const char *
+parse_imm (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ unsigned long *valuep)
+{
+ const char *errmsg;
+
+ if (iq2000_cgen_isa_register (strp))
+ errmsg = _("immediate value cannot be register");
+ else
+ {
+ long value;
+
+ errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
+ if (errmsg == NULL)
+ {
+ long x = value & 0xFFFF0000;
+
+ if (x != 0 && x != (long) 0xFFFF0000)
+ errmsg = _("immediate value out of range");
+ else
+ *valuep = (value & 0xFFFF);
+ }
+ }
+ return errmsg;
+}
+
+/* Handle iq10 21-bit jmp offset. */
+
+static const char *
+parse_jtargq10 (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ int reloc ATTRIBUTE_UNUSED,
+ enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED,
+ bfd_vma *valuep)
+{
+ const char *errmsg;
+ bfd_vma value;
+ enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
+
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
+ & result_type, & value);
+ if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ {
+ /* Check value is within 23-bits
+ (remembering that 2-bit shift right will occur). */
+ if (value > 0x7fffff)
+ return _("21-bit offset out of range");
+ }
+ *valuep = (value & 0x7FFFFF);
+ return errmsg;
+}
+
+/* Handle high(). */
+
+static const char *
+parse_hi16 (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ unsigned long *valuep)
+{
+ if (strncasecmp (*strp, "%hi(", 4) == 0)
+ {
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+ const char *errmsg;
+
+ *strp += 4;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
+ & result_type, & value);
+ if (**strp != ')')
+ return MISSING_CLOSING_PARENTHESIS;
+
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ {
+ /* If value has top-bit of %lo on, then it will
+ sign-propagate and so we compensate by adding
+ 1 to the resultant %hi value. */
+ if (value & 0x8000)
+ value += 0x10000;
+ value >>= 16;
+ value &= 0xffff;
+ }
+ *valuep = value;
+
+ return errmsg;
+ }
+
+ /* We add %uhi in case a user just wants the high 16-bits or is using
+ an insn like ori for %lo which does not sign-propagate. */
+ if (strncasecmp (*strp, "%uhi(", 5) == 0)
+ {
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+ const char *errmsg;
+
+ *strp += 5;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
+ & result_type, & value);
+ if (**strp != ')')
+ return MISSING_CLOSING_PARENTHESIS;
+
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ value >>= 16;
+
+ value &= 0xffff;
+ *valuep = value;
+
+ return errmsg;
+ }
+
+ return parse_imm (cd, strp, opindex, valuep);
+}
+
+/* Handle %lo in a signed context.
+ The signedness of the value doesn't matter to %lo(), but this also
+ handles the case where %lo() isn't present. */
+
+static const char *
+parse_lo16 (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ unsigned long *valuep)
+{
+ if (strncasecmp (*strp, "%lo(", 4) == 0)
+ {
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ *strp += 4;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
+ & result_type, & value);
+ if (**strp != ')')
+ return MISSING_CLOSING_PARENTHESIS;
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ value &= 0xffff;
+ *valuep = value;
+ return errmsg;
+ }
+
+ return parse_imm (cd, strp, opindex, valuep);
+}
+
+/* Handle %lo in a negated signed context.
+ The signedness of the value doesn't matter to %lo(), but this also
+ handles the case where %lo() isn't present. */
+
+static const char *
+parse_mlo16 (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ unsigned long *valuep)
+{
+ if (strncasecmp (*strp, "%lo(", 4) == 0)
+ {
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ *strp += 4;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
+ & result_type, & value);
+ if (**strp != ')')
+ return MISSING_CLOSING_PARENTHESIS;
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ value = (-value) & 0xffff;
+ *valuep = value;
+ return errmsg;
+ }
+
+ return parse_mimm (cd, strp, opindex, valuep);
+}
+
+/* -- */