Update function declarations to ISO C90 formatting
[external/binutils.git] / cpu / iq2000.opc
1 /* IQ2000 opcode support.  -*- C -*-
2
3    Copyright 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
4
5    Contributed by Red Hat Inc; developed under contract from Fujitsu.
6
7    This file is part of the GNU Binutils.
8
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.
13
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.
18
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.  */
23
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.
30
31    Each section is delimited with start and end markers.
32
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".  */
38 \f
39 /* -- opc.h */
40
41 /* Allows reason codes to be output when assembler errors occur.  */
42 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
43
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)
48
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
52
53 extern int iq2000_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
54
55 /* -- asm.c */
56
57 #include "safe-ctype.h"
58
59 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
60
61 /* Special check to ensure that instruction exists for given machine.  */
62
63 int
64 iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
65 {
66   int machs = cd->machs;
67
68   return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0;
69 }
70
71 static int
72 iq2000_cgen_isa_register (const char **strp)
73 {
74   int len;
75   int ch1, ch2;
76
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;
101 }
102
103 /* Handle negated literal.  */
104
105 static const char *
106 parse_mimm (CGEN_CPU_DESC cd,
107             const char **strp,
108             int opindex,
109             unsigned long *valuep)
110 {
111   const char *errmsg;
112
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;
124
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;
132 }
133
134 /* Handle signed/unsigned literal.  */
135
136 static const char *
137 parse_imm (CGEN_CPU_DESC cd,
138            const char **strp,
139            int opindex,
140            unsigned long *valuep)
141 {
142   const char *errmsg;
143
144   if (iq2000_cgen_isa_register (strp))
145     errmsg = _("immediate value cannot be register");
146   else
147     {
148       long value;
149
150       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
151       if (errmsg == NULL)
152         {
153           long x = value & 0xFFFF0000;
154
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;
162 }
163
164 /* Handle iq10 21-bit jmp offset.  */
165
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)
173 {
174   const char *errmsg;
175   bfd_vma value;
176   enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
177
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;
189 }
190
191 /* Handle high().  */
192
193 static const char *
194 parse_hi16 (CGEN_CPU_DESC cd,
195             const char **strp,
196             int opindex,
197             unsigned long *valuep)
198 {
199   if (strncasecmp (*strp, "%hi(", 4) == 0)
200     {
201       enum cgen_parse_operand_result result_type;
202       bfd_vma value;
203       const char *errmsg;
204
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;
210
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         }
222       *valuep = value;
223
224       return errmsg;
225     }
226
227   /* We add %uhi in case a user just wants the high 16-bits or is using
228      an insn like ori for %lo which does not sign-propagate.  */
229   if (strncasecmp (*strp, "%uhi(", 5) == 0)
230     {
231       enum cgen_parse_operand_result result_type;
232       bfd_vma value;
233       const char *errmsg;
234
235       *strp += 5;
236       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
237                                    & result_type, & value);
238       if (**strp != ')')
239         return MISSING_CLOSING_PARENTHESIS;
240
241       ++*strp;
242       if (errmsg == NULL
243           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
244         value >>= 16;
245
246       *valuep = value;
247
248       return errmsg;
249     }
250
251   return parse_imm (cd, strp, opindex, valuep);
252 }
253
254 /* Handle %lo in a signed context.
255    The signedness of the value doesn't matter to %lo(), but this also
256    handles the case where %lo() isn't present.  */
257
258 static const char *
259 parse_lo16 (CGEN_CPU_DESC cd,
260             const char **strp,
261             int opindex,
262             long *valuep)
263 {
264   if (strncasecmp (*strp, "%lo(", 4) == 0)
265     {
266       const char *errmsg;
267       enum cgen_parse_operand_result result_type;
268       bfd_vma value;
269
270       *strp += 4;
271       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
272                                    & result_type, & value);
273       if (**strp != ')')
274         return MISSING_CLOSING_PARENTHESIS;
275       ++*strp;
276       if (errmsg == NULL
277           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
278         value &= 0xffff;
279       *valuep = value;
280       return errmsg;
281     }
282
283   return parse_imm (cd, strp, opindex, valuep);
284 }
285
286 /* Handle %lo in a negated signed context.
287    The signedness of the value doesn't matter to %lo(), but this also
288    handles the case where %lo() isn't present.  */
289
290 static const char *
291 parse_mlo16 (CGEN_CPU_DESC cd,
292              const char **strp,
293              int opindex,
294              long *valuep)
295 {
296   if (strncasecmp (*strp, "%lo(", 4) == 0)
297     {
298       const char *errmsg;
299       enum cgen_parse_operand_result result_type;
300       bfd_vma value;
301
302       *strp += 4;
303       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
304                                    & result_type, & value);
305       if (**strp != ')')
306         return MISSING_CLOSING_PARENTHESIS;
307       ++*strp;
308       if (errmsg == NULL
309           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
310         value = (-value) & 0xffff;
311       *valuep = value;
312       return errmsg;
313     }
314
315   return parse_mimm (cd, strp, opindex, valuep);
316 }
317
318 /* -- */