xref: /netbsd-src/external/gpl3/binutils/dist/cpu/iq2000.opc (revision be12b8bcaf6171e22ce54bb82a70fb1a78be9ab5)
12a6b7db3Sskrll/* IQ2000 opcode support.  -*- C -*-
22a6b7db3Sskrll
3*be12b8bcSchristos   Copyright 2000, 2001, 2002, 2005, 2007, 2009 Free Software Foundation, Inc.
42a6b7db3Sskrll
52a6b7db3Sskrll   Contributed by Red Hat Inc; developed under contract from Fujitsu.
62a6b7db3Sskrll
72a6b7db3Sskrll   This file is part of the GNU Binutils.
82a6b7db3Sskrll
92a6b7db3Sskrll   This program is free software; you can redistribute it and/or modify
102a6b7db3Sskrll   it under the terms of the GNU General Public License as published by
112a6b7db3Sskrll   the Free Software Foundation; either version 3 of the License, or
122a6b7db3Sskrll   (at your option) any later version.
132a6b7db3Sskrll
142a6b7db3Sskrll   This program is distributed in the hope that it will be useful,
152a6b7db3Sskrll   but WITHOUT ANY WARRANTY; without even the implied warranty of
162a6b7db3Sskrll   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
172a6b7db3Sskrll   GNU General Public License for more details.
182a6b7db3Sskrll
192a6b7db3Sskrll   You should have received a copy of the GNU General Public License
202a6b7db3Sskrll   along with this program; if not, write to the Free Software
212a6b7db3Sskrll   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
222a6b7db3Sskrll   MA 02110-1301, USA.  */
232a6b7db3Sskrll
242a6b7db3Sskrll/* This file is an addendum to iq2000.cpu.  Heavy use of C code isn't
252a6b7db3Sskrll   appropriate in .cpu files, so it resides here.  This especially applies
262a6b7db3Sskrll   to assembly/disassembly where parsing/printing can be quite involved.
272a6b7db3Sskrll   Such things aren't really part of the specification of the cpu, per se,
282a6b7db3Sskrll   so .cpu files provide the general framework and .opc files handle the
292a6b7db3Sskrll   nitty-gritty details as necessary.
302a6b7db3Sskrll
312a6b7db3Sskrll   Each section is delimited with start and end markers.
322a6b7db3Sskrll
332a6b7db3Sskrll   <arch>-opc.h additions use: "-- opc.h"
342a6b7db3Sskrll   <arch>-opc.c additions use: "-- opc.c"
352a6b7db3Sskrll   <arch>-asm.c additions use: "-- asm.c"
362a6b7db3Sskrll   <arch>-dis.c additions use: "-- dis.c"
372a6b7db3Sskrll   <arch>-ibd.h additions use: "-- ibd.h".  */
382a6b7db3Sskrll
392a6b7db3Sskrll/* -- opc.h */
402a6b7db3Sskrll
412a6b7db3Sskrll/* Allows reason codes to be output when assembler errors occur.  */
422a6b7db3Sskrll#define CGEN_VERBOSE_ASSEMBLER_ERRORS
432a6b7db3Sskrll
442a6b7db3Sskrll/* Override disassembly hashing - there are variable bits in the top
452a6b7db3Sskrll   byte of these instructions.  */
462a6b7db3Sskrll#define CGEN_DIS_HASH_SIZE 8
472a6b7db3Sskrll#define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 6) % CGEN_DIS_HASH_SIZE)
482a6b7db3Sskrll
492a6b7db3Sskrll/* following activates check beyond hashing since some iq2000 and iq10
502a6b7db3Sskrll   instructions have same mnemonics but different functionality. */
512a6b7db3Sskrll#define CGEN_VALIDATE_INSN_SUPPORTED
522a6b7db3Sskrll
532a6b7db3Sskrllextern int iq2000_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
542a6b7db3Sskrll
552a6b7db3Sskrll/* -- asm.c */
562a6b7db3Sskrll
572a6b7db3Sskrll#include "safe-ctype.h"
582a6b7db3Sskrll
592a6b7db3Sskrllstatic const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
602a6b7db3Sskrll
612a6b7db3Sskrll/* Special check to ensure that instruction exists for given machine.  */
622a6b7db3Sskrll
632a6b7db3Sskrllint
642a6b7db3Sskrlliq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
652a6b7db3Sskrll{
662a6b7db3Sskrll  int machs = cd->machs;
672a6b7db3Sskrll
682a6b7db3Sskrll  return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0;
692a6b7db3Sskrll}
702a6b7db3Sskrll
712a6b7db3Sskrllstatic int
722a6b7db3Sskrlliq2000_cgen_isa_register (const char **strp)
732a6b7db3Sskrll{
742a6b7db3Sskrll  int len;
752a6b7db3Sskrll  int ch1, ch2;
762a6b7db3Sskrll
772a6b7db3Sskrll  if (**strp == 'r' || **strp == 'R')
782a6b7db3Sskrll    {
792a6b7db3Sskrll      len = strlen (*strp);
802a6b7db3Sskrll      if (len == 2)
812a6b7db3Sskrll        {
822a6b7db3Sskrll          ch1 = (*strp)[1];
832a6b7db3Sskrll          if ('0' <= ch1 && ch1 <= '9')
842a6b7db3Sskrll            return 1;
852a6b7db3Sskrll        }
862a6b7db3Sskrll      else if (len == 3)
872a6b7db3Sskrll        {
882a6b7db3Sskrll	  ch1 = (*strp)[1];
892a6b7db3Sskrll          ch2 = (*strp)[2];
902a6b7db3Sskrll          if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
912a6b7db3Sskrll            return 1;
922a6b7db3Sskrll          if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
932a6b7db3Sskrll            return 1;
942a6b7db3Sskrll        }
952a6b7db3Sskrll    }
962a6b7db3Sskrll  if (**strp == '%'
972a6b7db3Sskrll      && TOLOWER ((*strp)[1]) != 'l'
982a6b7db3Sskrll      && TOLOWER ((*strp)[1]) != 'h')
992a6b7db3Sskrll    return 1;
1002a6b7db3Sskrll  return 0;
1012a6b7db3Sskrll}
1022a6b7db3Sskrll
1032a6b7db3Sskrll/* Handle negated literal.  */
1042a6b7db3Sskrll
1052a6b7db3Sskrllstatic const char *
1062a6b7db3Sskrllparse_mimm (CGEN_CPU_DESC cd,
1072a6b7db3Sskrll	    const char **strp,
1082a6b7db3Sskrll	    int opindex,
1092a6b7db3Sskrll	    unsigned long *valuep)
1102a6b7db3Sskrll{
1112a6b7db3Sskrll  const char *errmsg;
1122a6b7db3Sskrll
1132a6b7db3Sskrll  /* Verify this isn't a register.  */
1142a6b7db3Sskrll  if (iq2000_cgen_isa_register (strp))
1152a6b7db3Sskrll    errmsg = _("immediate value cannot be register");
1162a6b7db3Sskrll  else
1172a6b7db3Sskrll    {
1182a6b7db3Sskrll      long value;
1192a6b7db3Sskrll
1202a6b7db3Sskrll      errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
1212a6b7db3Sskrll      if (errmsg == NULL)
1222a6b7db3Sskrll	{
1232a6b7db3Sskrll	  long x = (-value) & 0xFFFF0000;
1242a6b7db3Sskrll
1252a6b7db3Sskrll	  if (x != 0 && x != (long) 0xFFFF0000)
1262a6b7db3Sskrll	    errmsg = _("immediate value out of range");
1272a6b7db3Sskrll	  else
1282a6b7db3Sskrll	    *valuep = (-value & 0xFFFF);
1292a6b7db3Sskrll	}
1302a6b7db3Sskrll    }
1312a6b7db3Sskrll  return errmsg;
1322a6b7db3Sskrll}
1332a6b7db3Sskrll
1342a6b7db3Sskrll/* Handle signed/unsigned literal.  */
1352a6b7db3Sskrll
1362a6b7db3Sskrllstatic const char *
1372a6b7db3Sskrllparse_imm (CGEN_CPU_DESC cd,
1382a6b7db3Sskrll	   const char **strp,
1392a6b7db3Sskrll	   int opindex,
1402a6b7db3Sskrll	   unsigned long *valuep)
1412a6b7db3Sskrll{
1422a6b7db3Sskrll  const char *errmsg;
1432a6b7db3Sskrll
1442a6b7db3Sskrll  if (iq2000_cgen_isa_register (strp))
1452a6b7db3Sskrll    errmsg = _("immediate value cannot be register");
1462a6b7db3Sskrll  else
1472a6b7db3Sskrll    {
1482a6b7db3Sskrll      long value;
1492a6b7db3Sskrll
1502a6b7db3Sskrll      errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
1512a6b7db3Sskrll      if (errmsg == NULL)
1522a6b7db3Sskrll	{
1532a6b7db3Sskrll	  long x = value & 0xFFFF0000;
1542a6b7db3Sskrll
1552a6b7db3Sskrll	  if (x != 0 && x != (long) 0xFFFF0000)
1562a6b7db3Sskrll	    errmsg = _("immediate value out of range");
1572a6b7db3Sskrll	  else
1582a6b7db3Sskrll	    *valuep = (value & 0xFFFF);
1592a6b7db3Sskrll	}
1602a6b7db3Sskrll    }
1612a6b7db3Sskrll  return errmsg;
1622a6b7db3Sskrll}
1632a6b7db3Sskrll
1642a6b7db3Sskrll/* Handle iq10 21-bit jmp offset.  */
1652a6b7db3Sskrll
1662a6b7db3Sskrllstatic const char *
1672a6b7db3Sskrllparse_jtargq10 (CGEN_CPU_DESC cd,
1682a6b7db3Sskrll		const char **strp,
1692a6b7db3Sskrll		int opindex,
1702a6b7db3Sskrll		int reloc ATTRIBUTE_UNUSED,
1712a6b7db3Sskrll		enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED,
1722a6b7db3Sskrll		bfd_vma *valuep)
1732a6b7db3Sskrll{
1742a6b7db3Sskrll  const char *errmsg;
1752a6b7db3Sskrll  bfd_vma value;
1762a6b7db3Sskrll  enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
1772a6b7db3Sskrll
1782a6b7db3Sskrll  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
1792a6b7db3Sskrll			       & result_type, & value);
1802a6b7db3Sskrll  if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1812a6b7db3Sskrll    {
1822a6b7db3Sskrll      /* Check value is within 23-bits
1832a6b7db3Sskrll	 (remembering that 2-bit shift right will occur).  */
1842a6b7db3Sskrll      if (value > 0x7fffff)
1852a6b7db3Sskrll        return _("21-bit offset out of range");
1862a6b7db3Sskrll    }
1872a6b7db3Sskrll  *valuep = (value & 0x7FFFFF);
1882a6b7db3Sskrll  return errmsg;
1892a6b7db3Sskrll}
1902a6b7db3Sskrll
1912a6b7db3Sskrll/* Handle high().  */
1922a6b7db3Sskrll
1932a6b7db3Sskrllstatic const char *
1942a6b7db3Sskrllparse_hi16 (CGEN_CPU_DESC cd,
1952a6b7db3Sskrll	    const char **strp,
1962a6b7db3Sskrll	    int opindex,
1972a6b7db3Sskrll	    unsigned long *valuep)
1982a6b7db3Sskrll{
1992a6b7db3Sskrll  if (strncasecmp (*strp, "%hi(", 4) == 0)
2002a6b7db3Sskrll    {
2012a6b7db3Sskrll      enum cgen_parse_operand_result result_type;
2022a6b7db3Sskrll      bfd_vma value;
2032a6b7db3Sskrll      const char *errmsg;
2042a6b7db3Sskrll
2052a6b7db3Sskrll      *strp += 4;
2062a6b7db3Sskrll      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
2072a6b7db3Sskrll				   & result_type, & value);
2082a6b7db3Sskrll      if (**strp != ')')
2092a6b7db3Sskrll	return MISSING_CLOSING_PARENTHESIS;
2102a6b7db3Sskrll
2112a6b7db3Sskrll      ++*strp;
2122a6b7db3Sskrll      if (errmsg == NULL
2132a6b7db3Sskrll  	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
2142a6b7db3Sskrll	{
2152a6b7db3Sskrll	  /* If value has top-bit of %lo on, then it will
2162a6b7db3Sskrll	     sign-propagate and so we compensate by adding
2172a6b7db3Sskrll	     1 to the resultant %hi value.  */
2182a6b7db3Sskrll	  if (value & 0x8000)
2192a6b7db3Sskrll	    value += 0x10000;
2202a6b7db3Sskrll	  value >>= 16;
2212a6b7db3Sskrll	  value &= 0xffff;
2222a6b7db3Sskrll	}
2232a6b7db3Sskrll      *valuep = value;
2242a6b7db3Sskrll
2252a6b7db3Sskrll      return errmsg;
2262a6b7db3Sskrll    }
2272a6b7db3Sskrll
2282a6b7db3Sskrll  /* We add %uhi in case a user just wants the high 16-bits or is using
2292a6b7db3Sskrll     an insn like ori for %lo which does not sign-propagate.  */
2302a6b7db3Sskrll  if (strncasecmp (*strp, "%uhi(", 5) == 0)
2312a6b7db3Sskrll    {
2322a6b7db3Sskrll      enum cgen_parse_operand_result result_type;
2332a6b7db3Sskrll      bfd_vma value;
2342a6b7db3Sskrll      const char *errmsg;
2352a6b7db3Sskrll
2362a6b7db3Sskrll      *strp += 5;
2372a6b7db3Sskrll      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
2382a6b7db3Sskrll				   & result_type, & value);
2392a6b7db3Sskrll      if (**strp != ')')
2402a6b7db3Sskrll	return MISSING_CLOSING_PARENTHESIS;
2412a6b7db3Sskrll
2422a6b7db3Sskrll      ++*strp;
2432a6b7db3Sskrll      if (errmsg == NULL
2442a6b7db3Sskrll  	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
2452a6b7db3Sskrll	value >>= 16;
2462a6b7db3Sskrll
2472a6b7db3Sskrll      value &= 0xffff;
2482a6b7db3Sskrll      *valuep = value;
2492a6b7db3Sskrll
2502a6b7db3Sskrll      return errmsg;
2512a6b7db3Sskrll    }
2522a6b7db3Sskrll
2532a6b7db3Sskrll  return parse_imm (cd, strp, opindex, valuep);
2542a6b7db3Sskrll}
2552a6b7db3Sskrll
2562a6b7db3Sskrll/* Handle %lo in a signed context.
2572a6b7db3Sskrll   The signedness of the value doesn't matter to %lo(), but this also
2582a6b7db3Sskrll   handles the case where %lo() isn't present.  */
2592a6b7db3Sskrll
2602a6b7db3Sskrllstatic const char *
2612a6b7db3Sskrllparse_lo16 (CGEN_CPU_DESC cd,
2622a6b7db3Sskrll	    const char **strp,
2632a6b7db3Sskrll	    int opindex,
2642a6b7db3Sskrll	    unsigned long *valuep)
2652a6b7db3Sskrll{
2662a6b7db3Sskrll  if (strncasecmp (*strp, "%lo(", 4) == 0)
2672a6b7db3Sskrll    {
2682a6b7db3Sskrll      const char *errmsg;
2692a6b7db3Sskrll      enum cgen_parse_operand_result result_type;
2702a6b7db3Sskrll      bfd_vma value;
2712a6b7db3Sskrll
2722a6b7db3Sskrll      *strp += 4;
2732a6b7db3Sskrll      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
2742a6b7db3Sskrll				   & result_type, & value);
2752a6b7db3Sskrll      if (**strp != ')')
2762a6b7db3Sskrll	return MISSING_CLOSING_PARENTHESIS;
2772a6b7db3Sskrll      ++*strp;
2782a6b7db3Sskrll      if (errmsg == NULL
2792a6b7db3Sskrll	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
2802a6b7db3Sskrll	value &= 0xffff;
2812a6b7db3Sskrll      *valuep = value;
2822a6b7db3Sskrll      return errmsg;
2832a6b7db3Sskrll    }
2842a6b7db3Sskrll
2852a6b7db3Sskrll  return parse_imm (cd, strp, opindex, valuep);
2862a6b7db3Sskrll}
2872a6b7db3Sskrll
2882a6b7db3Sskrll/* Handle %lo in a negated signed context.
2892a6b7db3Sskrll   The signedness of the value doesn't matter to %lo(), but this also
2902a6b7db3Sskrll   handles the case where %lo() isn't present.  */
2912a6b7db3Sskrll
2922a6b7db3Sskrllstatic const char *
2932a6b7db3Sskrllparse_mlo16 (CGEN_CPU_DESC cd,
2942a6b7db3Sskrll	     const char **strp,
2952a6b7db3Sskrll	     int opindex,
2962a6b7db3Sskrll	     unsigned long *valuep)
2972a6b7db3Sskrll{
2982a6b7db3Sskrll  if (strncasecmp (*strp, "%lo(", 4) == 0)
2992a6b7db3Sskrll    {
3002a6b7db3Sskrll      const char *errmsg;
3012a6b7db3Sskrll      enum cgen_parse_operand_result result_type;
3022a6b7db3Sskrll      bfd_vma value;
3032a6b7db3Sskrll
3042a6b7db3Sskrll      *strp += 4;
3052a6b7db3Sskrll      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
3062a6b7db3Sskrll				   & result_type, & value);
3072a6b7db3Sskrll      if (**strp != ')')
3082a6b7db3Sskrll	return MISSING_CLOSING_PARENTHESIS;
3092a6b7db3Sskrll      ++*strp;
3102a6b7db3Sskrll      if (errmsg == NULL
3112a6b7db3Sskrll	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
3122a6b7db3Sskrll	value = (-value) & 0xffff;
3132a6b7db3Sskrll      *valuep = value;
3142a6b7db3Sskrll      return errmsg;
3152a6b7db3Sskrll    }
3162a6b7db3Sskrll
3172a6b7db3Sskrll  return parse_mimm (cd, strp, opindex, valuep);
3182a6b7db3Sskrll}
3192a6b7db3Sskrll
3202a6b7db3Sskrll/* -- */
321