2007-06-14 Paolo Bonzini <bonzini@gnu.org>
[binutils.git] / cpu / iq2000.opc
blob528750688f43b77cf921b44bc39227743e7a99ec
1 /* IQ2000 opcode support.  -*- C -*-
3    Copyright 2000, 2001, 2002, 2005 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., 51 Franklin Street - Fifth Floor, Boston,
22    MA 02110-1301, USA.  */
24 /* This file is an addendum to iq2000.cpu.  Heavy use of C code isn't
25    appropriate in .cpu files, so it resides here.  This especially applies
26    to assembly/disassembly where parsing/printing can be quite involved.
27    Such things aren't really part of the specification of the cpu, per se,
28    so .cpu files provide the general framework and .opc files handle the
29    nitty-gritty details as necessary.
31    Each section is delimited with start and end markers.
33    <arch>-opc.h additions use: "-- opc.h"
34    <arch>-opc.c additions use: "-- opc.c"
35    <arch>-asm.c additions use: "-- asm.c"
36    <arch>-dis.c additions use: "-- dis.c"
37    <arch>-ibd.h additions use: "-- ibd.h".  */
39 /* -- opc.h */
41 /* Allows reason codes to be output when assembler errors occur.  */
42 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
44 /* Override disassembly hashing - there are variable bits in the top
45    byte of these instructions.  */
46 #define CGEN_DIS_HASH_SIZE 8
47 #define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 6) % CGEN_DIS_HASH_SIZE)
49 /* following activates check beyond hashing since some iq2000 and iq10
50    instructions have same mnemonics but different functionality. */
51 #define CGEN_VALIDATE_INSN_SUPPORTED
53 extern int iq2000_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
55 /* -- asm.c */
57 #include "safe-ctype.h"
59 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
61 /* Special check to ensure that instruction exists for given machine.  */
63 int
64 iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
66   int machs = cd->machs;
68   return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0;
71 static int
72 iq2000_cgen_isa_register (const char **strp)
74   int len;
75   int ch1, ch2;
77   if (**strp == 'r' || **strp == 'R') 
78     {
79       len = strlen (*strp);
80       if (len == 2) 
81         {
82           ch1 = (*strp)[1];
83           if ('0' <= ch1 && ch1 <= '9')
84             return 1;
85         } 
86       else if (len == 3) 
87         {
88           ch1 = (*strp)[1];
89           ch2 = (*strp)[2];
90           if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
91             return 1;
92           if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
93             return 1;
94         }
95     }
96   if (**strp == '%'
97       && TOLOWER ((*strp)[1]) != 'l'
98       && TOLOWER ((*strp)[1]) != 'h')
99     return 1;
100   return 0;
103 /* Handle negated literal.  */
105 static const char *
106 parse_mimm (CGEN_CPU_DESC cd,
107             const char **strp,
108             int opindex,
109             unsigned long *valuep)
111   const char *errmsg;
113   /* Verify this isn't a register.  */
114   if (iq2000_cgen_isa_register (strp))
115     errmsg = _("immediate value cannot be register");
116   else
117     {
118       long value;
119       
120       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
121       if (errmsg == NULL)
122         {
123           long x = (-value) & 0xFFFF0000;
125           if (x != 0 && x != (long) 0xFFFF0000)
126             errmsg = _("immediate value out of range");
127           else
128             *valuep = (-value & 0xFFFF);
129         }
130     }
131   return errmsg;
134 /* Handle signed/unsigned literal.  */
136 static const char *
137 parse_imm (CGEN_CPU_DESC cd,
138            const char **strp,
139            int opindex,
140            unsigned long *valuep)
142   const char *errmsg;
144   if (iq2000_cgen_isa_register (strp))
145     errmsg = _("immediate value cannot be register");
146   else
147     {
148       long value;
150       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
151       if (errmsg == NULL)
152         {
153           long x = value & 0xFFFF0000;
155           if (x != 0 && x != (long) 0xFFFF0000)
156             errmsg = _("immediate value out of range");
157           else
158             *valuep = (value & 0xFFFF);
159         }
160     }
161   return errmsg;
164 /* Handle iq10 21-bit jmp offset.  */
166 static const char *
167 parse_jtargq10 (CGEN_CPU_DESC cd,
168                 const char **strp,
169                 int opindex,
170                 int reloc ATTRIBUTE_UNUSED,
171                 enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED,
172                 bfd_vma *valuep)
174   const char *errmsg;
175   bfd_vma value;
176   enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
178   errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
179                                & result_type, & value);
180   if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
181     {
182       /* Check value is within 23-bits
183          (remembering that 2-bit shift right will occur).  */
184       if (value > 0x7fffff)
185         return _("21-bit offset out of range");
186     }
187   *valuep = (value & 0x7FFFFF);
188   return errmsg;
191 /* Handle high().  */
193 static const char *
194 parse_hi16 (CGEN_CPU_DESC cd,
195             const char **strp,
196             int opindex,
197             unsigned long *valuep)
199   if (strncasecmp (*strp, "%hi(", 4) == 0)
200     {
201       enum cgen_parse_operand_result result_type;
202       bfd_vma value;
203       const char *errmsg;
205       *strp += 4;
206       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
207                                    & result_type, & value);
208       if (**strp != ')')
209         return MISSING_CLOSING_PARENTHESIS;
211       ++*strp;
212       if (errmsg == NULL
213           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
214         {
215           /* If value has top-bit of %lo on, then it will
216              sign-propagate and so we compensate by adding
217              1 to the resultant %hi value.  */
218           if (value & 0x8000)
219             value += 0x10000;
220           value >>= 16;
221           value &= 0xffff;
222         }
223       *valuep = value;
225       return errmsg;
226     }
228   /* We add %uhi in case a user just wants the high 16-bits or is using
229      an insn like ori for %lo which does not sign-propagate.  */
230   if (strncasecmp (*strp, "%uhi(", 5) == 0)
231     {
232       enum cgen_parse_operand_result result_type;
233       bfd_vma value;
234       const char *errmsg;
236       *strp += 5;
237       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
238                                    & result_type, & value);
239       if (**strp != ')')
240         return MISSING_CLOSING_PARENTHESIS;
242       ++*strp;
243       if (errmsg == NULL
244           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
245         value >>= 16;
247       value &= 0xffff;
248       *valuep = value;
250       return errmsg;
251     }
253   return parse_imm (cd, strp, opindex, valuep);
256 /* Handle %lo in a signed context.
257    The signedness of the value doesn't matter to %lo(), but this also
258    handles the case where %lo() isn't present.  */
260 static const char *
261 parse_lo16 (CGEN_CPU_DESC cd,
262             const char **strp,
263             int opindex,
264             unsigned long *valuep)
266   if (strncasecmp (*strp, "%lo(", 4) == 0)
267     {
268       const char *errmsg;
269       enum cgen_parse_operand_result result_type;
270       bfd_vma value;
272       *strp += 4;
273       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
274                                    & result_type, & value);
275       if (**strp != ')')
276         return MISSING_CLOSING_PARENTHESIS;
277       ++*strp;
278       if (errmsg == NULL
279           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
280         value &= 0xffff;
281       *valuep = value;
282       return errmsg;
283     }
285   return parse_imm (cd, strp, opindex, valuep);
288 /* Handle %lo in a negated signed context.
289    The signedness of the value doesn't matter to %lo(), but this also
290    handles the case where %lo() isn't present.  */
292 static const char *
293 parse_mlo16 (CGEN_CPU_DESC cd,
294              const char **strp,
295              int opindex,
296              unsigned long *valuep)
298   if (strncasecmp (*strp, "%lo(", 4) == 0)
299     {
300       const char *errmsg;
301       enum cgen_parse_operand_result result_type;
302       bfd_vma value;
304       *strp += 4;
305       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
306                                    & result_type, & value);
307       if (**strp != ')')
308         return MISSING_CLOSING_PARENTHESIS;
309       ++*strp;
310       if (errmsg == NULL
311           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
312         value = (-value) & 0xffff;
313       *valuep = value;
314       return errmsg;
315     }
317   return parse_mimm (cd, strp, opindex, valuep);
320 /* -- */