* ld-cris/expdyn1.d, ld-cris/expdyn5.d, ld-cris/expdyn6.d,
[binutils.git] / cpu / iq2000.opc
blob3b7620f328befd8c83372be4433d1a1e86d26631
1 /* IQ2000 opcode support.  -*- C -*-
3    Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
5    Contributed by Red Hat Inc; developed under contract from Fujitsu.
7    This file is part of the GNU Binutils.
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 /* This file is an addendum to iq2000.cpu.  Heavy use of C code isn't
26    appropriate in .cpu files, so it resides here.  This especially applies
27    to assembly/disassembly where parsing/printing can be quite involved.
28    Such things aren't really part of the specification of the cpu, per se,
29    so .cpu files provide the general framework and .opc files handle the
30    nitty-gritty details as necessary.
32    Each section is delimited with start and end markers.
34    <arch>-opc.h additions use: "-- opc.h"
35    <arch>-opc.c additions use: "-- opc.c"
36    <arch>-asm.c additions use: "-- asm.c"
37    <arch>-dis.c additions use: "-- dis.c"
38    <arch>-ibd.h additions use: "-- ibd.h"
41 /* -- opc.h */
43 /* Allows reason codes to be output when assembler errors occur.  */
44 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
46 /* Override disassembly hashing - there are variable bits in the top
47    byte of these instructions.  */
48 #define CGEN_DIS_HASH_SIZE 8
49 #define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 6) % CGEN_DIS_HASH_SIZE)
51 /* following activates check beyond hashing since some iq2000 and iq10
52    instructions have same mnemonics but different functionality. */
53 #define CGEN_VALIDATE_INSN_SUPPORTED
55 extern int iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn);
57 /* -- asm.c */
58 static const char * parse_mimm PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
59 static const char * parse_imm  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
60 static const char * parse_hi16 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
61 static const char * parse_lo16 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
63 /* Special check to ensure that instruction exists for given machine.  */
64 int
65 iq2000_cgen_insn_supported (cd, insn)
66      CGEN_CPU_DESC cd;
67      const CGEN_INSN *insn;
69   int machs = cd->machs;
71   return ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0);
74 static int iq2000_cgen_isa_register (strp)
75      const char **strp;
77   int len;
78   int ch1, ch2;
79   if (**strp == 'r' || **strp == 'R') 
80     {
81       len = strlen (*strp);
82       if (len == 2) 
83         {
84           ch1 = (*strp)[1];
85           if ('0' <= ch1 && ch1 <= '9')
86             return 1;
87         } 
88       else if (len == 3) 
89         {
90           ch1 = (*strp)[1];
91           ch2 = (*strp)[2];
92           if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
93             return 1;
94           if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
95             return 1;
96         }
97     }
98   if (**strp == '%' && tolower((*strp)[1]) != 'l' && tolower((*strp)[1]) != 'h')
99     return 1;
100   return 0;
103 /* Handle negated literal.  */
105 static const char *
106 parse_mimm (cd, strp, opindex, valuep)
107      CGEN_CPU_DESC cd;
108      const char **strp;
109      int opindex;
110      long *valuep;
112   const char *errmsg;
113   long value;
115   /* Verify this isn't a register */
116   if (iq2000_cgen_isa_register (strp))
117     errmsg = _("immediate value cannot be register");
118   else
119     {
120       long value;
121       
122       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
123       if (errmsg == NULL)
124         {
125           long x = (-value) & 0xFFFF0000;
126           if (x != 0 && x != 0xFFFF0000)
127             errmsg = _("immediate value out of range");
128           else
129             *valuep = (-value & 0xFFFF);
130         }
131     }
132   return errmsg;
135 /* Handle signed/unsigned literal.  */
137 static const char *
138 parse_imm (cd, strp, opindex, valuep)
139      CGEN_CPU_DESC cd;
140      const char **strp;
141      int opindex;
142      unsigned long *valuep;
144   const char *errmsg;
145   long value;
147   if (iq2000_cgen_isa_register (strp))
148     errmsg = _("immediate value cannot be register");
149   else
150     {
151       long value;
153       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
154       if (errmsg == NULL)
155         {
156           long x = value & 0xFFFF0000;
157           if (x != 0 && x != 0xFFFF0000)
158             errmsg = _("immediate value out of range");
159           else
160             *valuep = (value & 0xFFFF);
161         }
162     }
163   return errmsg;
166 /* Handle iq10 21-bit jmp offset.  */
168 static const char *
169 parse_jtargq10 (cd, strp, opindex, reloc, type_addr, valuep)
170      CGEN_CPU_DESC cd;
171      const char **strp;
172      int opindex;
173      int reloc;
174      enum cgen_parse_operand_result *type_addr;
175      unsigned long *valuep;
177   const char *errmsg;
178   bfd_vma value;
179   enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
181   errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
182                                &result_type, &value);
183   if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
184     {
185       /* check value is within 23-bits (remembering that 2-bit shift right will occur) */
186       if (value > 0x7fffff)
187         return _("21-bit offset out of range");
188     }
189   *valuep = (value & 0x7FFFFF);
190   return errmsg;
193 /* Handle high().  */
195 static const char *
196 parse_hi16 (cd, strp, opindex, valuep)
197      CGEN_CPU_DESC cd;
198      const char **strp;
199      int opindex;
200      unsigned long *valuep;
202   if (strncasecmp (*strp, "%hi(", 4) == 0)
203     {
204       enum cgen_parse_operand_result result_type;
205       bfd_vma value;
206       const char *errmsg;
208       *strp += 4;
209       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
210                                    &result_type, &value);
211       if (**strp != ')')
212         return _("missing `)'");
214       ++*strp;
215       if (errmsg == NULL
216           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
217         {
218           /* if value has top-bit of %lo on, then it will
219              sign-propagate and so we compensate by adding
220              1 to the resultant %hi value */
221           if (value & 0x8000)
222             value += 0x10000;
223           value >>= 16;
224         }
225       *valuep = value;
227       return errmsg;
228     }
230   /* we add %uhi in case a user just wants the high 16-bits or is using
231      an insn like ori for %lo which does not sign-propagate */
232   if (strncasecmp (*strp, "%uhi(", 5) == 0)
233     {
234       enum cgen_parse_operand_result result_type;
235       bfd_vma value;
236       const char *errmsg;
238       *strp += 5;
239       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
240                                    &result_type, &value);
241       if (**strp != ')')
242         return _("missing `)'");
244       ++*strp;
245       if (errmsg == NULL
246           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
247         {
248           value >>= 16;
249         }
250       *valuep = value;
252       return errmsg;
253     }
255   return parse_imm (cd, strp, opindex, valuep);
258 /* Handle %lo in a signed context.
259    The signedness of the value doesn't matter to %lo(), but this also
260    handles the case where %lo() isn't present.  */
262 static const char *
263 parse_lo16 (cd, strp, opindex, valuep)
264      CGEN_CPU_DESC cd;
265      const char **strp;
266      int opindex;
267      long *valuep;
269   if (strncasecmp (*strp, "%lo(", 4) == 0)
270     {
271       const char *errmsg;
272       enum cgen_parse_operand_result result_type;
273       bfd_vma value;
275       *strp += 4;
276       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
277                                    &result_type, &value);
278       if (**strp != ')')
279         return _("missing `)'");
280       ++*strp;
281       if (errmsg == NULL
282           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
283         value &= 0xffff;
284       *valuep = value;
285       return errmsg;
286     }
288   return parse_imm (cd, strp, opindex, valuep);
291 /* Handle %lo in a negated signed context.
292    The signedness of the value doesn't matter to %lo(), but this also
293    handles the case where %lo() isn't present.  */
295 static const char *
296 parse_mlo16 (cd, strp, opindex, valuep)
297      CGEN_CPU_DESC cd;
298      const char **strp;
299      int opindex;
300      long *valuep;
302   if (strncasecmp (*strp, "%lo(", 4) == 0)
303     {
304       const char *errmsg;
305       enum cgen_parse_operand_result result_type;
306       bfd_vma value;
308       *strp += 4;
309       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
310                                    &result_type, &value);
311       if (**strp != ')')
312         return _("missing `)'");
313       ++*strp;
314       if (errmsg == NULL
315           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
316         value = (-value) & 0xffff;
317       *valuep = value;
318       return errmsg;
319     }
321   return parse_mimm (cd, strp, opindex, valuep);
324 /* -- */