summaryrefslogtreecommitdiff
path: root/cpu/iq2000.opc
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2003-06-06 21:49:30 +0000
committerAndrew Cagney <cagney@redhat.com>2003-06-06 21:49:30 +0000
commit046f06292e126ec9e2a342b08beda9230b614501 (patch)
tree58f5381a28d4cbc289d7508c7e045b7d9c90937b /cpu/iq2000.opc
parentb8433b4c03dbe0ce37f388e7aced93b29d15b2ce (diff)
downloadbinutils-redhat-046f06292e126ec9e2a342b08beda9230b614501.tar.gz
2003-06-06 Andrew Cagney <cagney@redhat.com>
Contributed by Red Hat. * iq2000.cpu: New file. Written by Ben Elliston, Jeff Johnston, Stan Cox, and Frank Ch. Eigler. * iq2000.opc: New file. Written by Ben Elliston, Frank Ch. Eigler, Chris Moller, Jeff Johnston, and Stan Cox. * iq2000m.cpu: New file. Written by Jeff Johnston. * iq10.cpu: New file. Written by Jeff Johnston.
Diffstat (limited to 'cpu/iq2000.opc')
-rw-r--r--cpu/iq2000.opc324
1 files changed, 324 insertions, 0 deletions
diff --git a/cpu/iq2000.opc b/cpu/iq2000.opc
new file mode 100644
index 0000000000..06600ec793
--- /dev/null
+++ b/cpu/iq2000.opc
@@ -0,0 +1,324 @@
+/* IQ2000 opcode support. -*- C -*-
+
+ Copyright 2000, 2001, 2002 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 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 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 cd, CGEN_INSN *insn);
+
+/* -- asm.c */
+static const char * parse_mimm PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
+static const char * parse_imm 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_lo16 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
+
+/* Special check to ensure that instruction exists for given machine */
+int
+iq2000_cgen_insn_supported (cd, insn)
+ CGEN_CPU_DESC cd;
+ CGEN_INSN *insn;
+{
+ int machs = cd->machs;
+
+ return ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0);
+}
+
+static int iq2000_cgen_isa_register (strp)
+ 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 (cd, strp, opindex, valuep)
+ CGEN_CPU_DESC cd;
+ const char **strp;
+ int opindex;
+ long *valuep;
+{
+ const char *errmsg;
+ long value;
+
+ /* 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 != 0xFFFF0000)
+ errmsg = _("immediate value out of range");
+ else
+ *valuep = (-value & 0xFFFF);
+ }
+ }
+ return errmsg;
+}
+
+/* Handle signed/unsigned literal. */
+
+static const char *
+parse_imm (cd, strp, opindex, valuep)
+ CGEN_CPU_DESC cd;
+ const char **strp;
+ int opindex;
+ unsigned long *valuep;
+{
+ const char *errmsg;
+ long value;
+
+ 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 != 0xFFFF0000)
+ errmsg = _("immediate value out of range");
+ else
+ *valuep = (value & 0xFFFF);
+ }
+ }
+ return errmsg;
+}
+
+/* Handle iq10 21-bit jmp offset. */
+
+static const char *
+parse_jtargq10 (cd, strp, opindex, reloc, type_addr, valuep)
+ CGEN_CPU_DESC cd;
+ const char **strp;
+ int opindex;
+ int reloc;
+ enum cgen_parse_operand_result *type_addr;
+ unsigned long *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 (cd, strp, opindex, valuep)
+ 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 `)'");
+
+ ++*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;
+ }
+ *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 `)'");
+
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ {
+ value >>= 16;
+ }
+ *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 (cd, strp, opindex, valuep)
+ CGEN_CPU_DESC cd;
+ const char **strp;
+ int opindex;
+ 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 `)'");
+ ++*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 (cd, strp, opindex, valuep)
+ CGEN_CPU_DESC cd;
+ const char **strp;
+ int opindex;
+ 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 `)'");
+ ++*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);
+}
+
+/* -- */