Update function declarations to ISO C90 formatting
[external/binutils.git] / cpu / frv.opc
1 /* Fujitsu FRV opcode support, for GNU Binutils.  -*- C -*-
2
3    Copyright 2000, 2001, 2003, 2004, 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 frv.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 #undef  CGEN_DIS_HASH_SIZE
42 #define CGEN_DIS_HASH_SIZE 128
43 #undef  CGEN_DIS_HASH
44 #define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
45
46 /* Allows reason codes to be output when assembler errors occur.  */
47 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
48
49 /* Vliw support.  */
50 #define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8.  */
51 #define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
52
53 typedef CGEN_ATTR_VALUE_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
54
55 typedef struct
56 {
57   int                    next_slot;
58   int                    constraint_violation;
59   unsigned long          mach;
60   unsigned long          elf_flags;
61   CGEN_ATTR_VALUE_TYPE * unit_mapping;
62   VLIW_COMBO *           current_vliw;
63   CGEN_ATTR_VALUE_TYPE   major[FRV_VLIW_SIZE];
64   const CGEN_INSN *      insn[FRV_VLIW_SIZE];
65 } FRV_VLIW;
66
67 int frv_is_branch_major (CGEN_ATTR_VALUE_TYPE, unsigned long);
68 int frv_is_float_major  (CGEN_ATTR_VALUE_TYPE, unsigned long);
69 int frv_is_media_major  (CGEN_ATTR_VALUE_TYPE, unsigned long);
70 int frv_is_branch_insn  (const CGEN_INSN *);
71 int frv_is_float_insn   (const CGEN_INSN *);
72 int frv_is_media_insn   (const CGEN_INSN *);
73 void frv_vliw_reset     (FRV_VLIW *, unsigned long, unsigned long);
74 int frv_vliw_add_insn   (FRV_VLIW *, const CGEN_INSN *);
75 int spr_valid           (long);
76 /* -- */
77 \f
78 /* -- opc.c */
79 #include "elf/frv.h"
80 #include <stdio.h>
81
82 /* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
83    development tree.  */
84
85 bfd_boolean
86 frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
87 {
88   switch (mach)
89     {
90     case bfd_mach_fr400:
91       if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
92         return TRUE;
93       break;
94     case bfd_mach_fr450:
95       if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
96         return TRUE;
97       break;
98     default:
99       if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
100         return TRUE;
101       break;
102     }
103
104   return FALSE;
105 }
106
107 /* Returns TRUE if {MAJOR,MACH} supports floating point insns.  */
108
109 bfd_boolean
110 frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
111 {
112   switch (mach)
113     {
114     case bfd_mach_fr400:
115     case bfd_mach_fr450:
116       return FALSE;
117     default:
118       if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
119         return TRUE;
120       break;
121     }
122
123   return FALSE;
124 }
125
126 /* Returns TRUE if {MAJOR,MACH} supports media insns.  */
127
128 bfd_boolean
129 frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
130 {
131   switch (mach)
132     {
133     case bfd_mach_fr400:
134       if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
135         return TRUE;
136       break;
137     case bfd_mach_fr450:
138       if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
139         return TRUE;
140       break;
141     default:
142       if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
143         return TRUE;
144       break;
145     }
146
147   return FALSE;
148 }
149
150 bfd_boolean
151 frv_is_branch_insn (const CGEN_INSN *insn)
152 {
153   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
154                            bfd_mach_fr400))
155     return TRUE;
156   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
157                            bfd_mach_fr450))
158     return TRUE;
159   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
160                            bfd_mach_fr500))
161     return TRUE;
162
163   return FALSE;
164 }
165
166 bfd_boolean
167 frv_is_float_insn (const CGEN_INSN *insn)
168 {
169   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
170                           bfd_mach_fr400))
171     return TRUE;
172   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
173                           bfd_mach_fr450))
174     return TRUE;
175   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
176                           bfd_mach_fr500))
177     return TRUE;
178
179   return FALSE;
180 }
181
182 bfd_boolean
183 frv_is_media_insn (const CGEN_INSN *insn)
184 {
185   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
186                           bfd_mach_fr400))
187     return TRUE;
188   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
189                           bfd_mach_fr450))
190     return TRUE;
191   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
192                           bfd_mach_fr500))
193     return TRUE;
194
195   return FALSE;
196 }
197
198 /* This table represents the allowable packing for vliw insns for the fr400.
199    The fr400 has only 2 vliw slots. Represent this by not allowing any insns
200    in the extra slots.
201    Subsets of any given row are also allowed.  */
202 static VLIW_COMBO fr400_allowed_vliw[] =
203 {
204   /*  slot0       slot1       slot2       slot3    */
205   {  UNIT_I0,    UNIT_I1,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
206   {  UNIT_I0,    UNIT_FM0,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
207   {  UNIT_I0,    UNIT_B0,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
208   {  UNIT_FM0,   UNIT_FM1,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
209   {  UNIT_FM0,   UNIT_B0,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
210   {  UNIT_B0,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
211   {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
212   {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO }
213 };
214
215 /* This table represents the allowable packing for vliw insns for the fr500.
216    The fr500 has only 4 vliw slots. Represent this by not allowing any insns
217    in the extra slots.
218    Subsets of any given row are also allowed.  */
219 static VLIW_COMBO fr500_allowed_vliw[] =
220 {
221   /*  slot0       slot1       slot2       slot3    */
222   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1  PAD_VLIW_COMBO },
223   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0   PAD_VLIW_COMBO },
224   {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0   PAD_VLIW_COMBO },
225   {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
226   {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
227   {  UNIT_I0,    UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
228   {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
229   {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
230   {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
231   {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
232   {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO }
233 };
234
235 /* This table represents the allowable packing for vliw insns for the fr550.
236    Subsets of any given row are also allowed.  */
237 static VLIW_COMBO fr550_allowed_vliw[] =
238 {
239   /*  slot0       slot1       slot2       slot3       slot4       slot5       slot6       slot7   */
240   {  UNIT_I0,    UNIT_I1,    UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL },
241   {  UNIT_I0,    UNIT_I1,    UNIT_I2,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
242   {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
243   {  UNIT_I0,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
244   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_I3,    UNIT_FM3 },
245   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_I3,    UNIT_B0  },
246   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_FM3,   UNIT_B0  },
247   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_B0,    UNIT_B1  },
248   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1  },
249   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_B0,    UNIT_B1,    UNIT_NIL },
250   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1  },
251   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1  },
252   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL },
253   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
254   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1,    UNIT_NIL },
255   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_I2,    UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
256   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
257   {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1,    UNIT_NIL },
258   {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
259   {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
260   {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
261   {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
262   {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
263   {  UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
264   {  UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
265   {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
266   {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
267   {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL }
268 };
269
270 /* Some insns are assigned specialized implementation units which map to
271    different actual implementation units on different machines.  These
272    tables perform that mapping.  */
273 static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
274 {
275 /* unit in insn    actual unit */
276 /* NIL      */     UNIT_NIL,
277 /* I0       */     UNIT_I0,
278 /* I1       */     UNIT_I1,
279 /* I01      */     UNIT_I01, 
280 /* I2       */     UNIT_NIL, /* no I2 or I3 unit */
281 /* I3       */     UNIT_NIL,
282 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
283 /* FM0      */     UNIT_FM0,
284 /* FM1      */     UNIT_FM1,
285 /* FM01     */     UNIT_FM01,
286 /* FM2      */     UNIT_NIL, /* no F2 or M2 units */
287 /* FM3      */     UNIT_NIL, /* no F3 or M3 units */
288 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
289 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
290 /* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
291 /* B1       */     UNIT_B0,
292 /* B01      */     UNIT_B0,
293 /* C        */     UNIT_C,
294 /* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
295 /* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
296 /* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
297 /* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
298 /* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
299 /* DCPL     */     UNIT_C,   /* dcpl                only in C   unit.  */
300 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
301 /* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
302 /* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
303 };
304
305 /* Some insns are assigned specialized implementation units which map to
306    different actual implementation units on different machines.  These
307    tables perform that mapping.  */
308 static CGEN_ATTR_VALUE_TYPE fr450_unit_mapping[] =
309 {
310 /* unit in insn    actual unit */
311 /* NIL      */     UNIT_NIL,
312 /* I0       */     UNIT_I0,
313 /* I1       */     UNIT_I1,
314 /* I01      */     UNIT_I01, 
315 /* I2       */     UNIT_NIL, /* no I2 or I3 unit */
316 /* I3       */     UNIT_NIL,
317 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
318 /* FM0      */     UNIT_FM0,
319 /* FM1      */     UNIT_FM1,
320 /* FM01     */     UNIT_FM01,
321 /* FM2      */     UNIT_NIL, /* no F2 or M2 units */
322 /* FM3      */     UNIT_NIL, /* no F3 or M3 units */
323 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
324 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
325 /* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
326 /* B1       */     UNIT_B0,
327 /* B01      */     UNIT_B0,
328 /* C        */     UNIT_C,
329 /* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
330 /* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
331 /* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
332 /* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
333 /* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
334 /* DCPL     */     UNIT_I0,  /* dcpl                only in I0  unit.  */
335 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
336 /* MDCUTSSI */     UNIT_FM01, /* mdcutssi           in FM0 or FM1.  */
337 /* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
338 };
339
340 static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
341 {
342 /* unit in insn    actual unit */
343 /* NIL      */     UNIT_NIL,
344 /* I0       */     UNIT_I0,
345 /* I1       */     UNIT_I1,
346 /* I01      */     UNIT_I01, 
347 /* I2       */     UNIT_NIL, /* no I2 or I3 unit */
348 /* I3       */     UNIT_NIL,
349 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
350 /* FM0      */     UNIT_FM0,
351 /* FM1      */     UNIT_FM1,
352 /* FM01     */     UNIT_FM01,
353 /* FM2      */     UNIT_NIL, /* no F2 or M2 units */
354 /* FM3      */     UNIT_NIL, /* no F3 or M2 units */
355 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
356 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
357 /* B0       */     UNIT_B0,
358 /* B1       */     UNIT_B1,
359 /* B01      */     UNIT_B01,
360 /* C        */     UNIT_C,
361 /* MULT-DIV */     UNIT_I01, /* multiply and divide in I0 or I1 unit.  */
362 /* IACC     */     UNIT_NIL, /* iacc multiply       not implemented */
363 /* LOAD     */     UNIT_I01, /* load                in I0 or I1 unit.  */
364 /* STORE    */     UNIT_I0,  /* store               only in I0 unit.  */
365 /* SCAN     */     UNIT_I01, /* scan                in I0 or I1 unit.  */
366 /* DCPL     */     UNIT_C,   /* dcpl                only in C unit.  */
367 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
368 /* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
369 /* MCLRACC-1*/     UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit.  */
370 };
371
372 static CGEN_ATTR_VALUE_TYPE fr550_unit_mapping[] =
373 {
374 /* unit in insn    actual unit */
375 /* NIL      */     UNIT_NIL,
376 /* I0       */     UNIT_I0,
377 /* I1       */     UNIT_I1,
378 /* I01      */     UNIT_I01, 
379 /* I2       */     UNIT_I2,
380 /* I3       */     UNIT_I3,
381 /* IALL     */     UNIT_IALL, 
382 /* FM0      */     UNIT_FM0,
383 /* FM1      */     UNIT_FM1,
384 /* FM01     */     UNIT_FM01,
385 /* FM2      */     UNIT_FM2,
386 /* FM3      */     UNIT_FM3,
387 /* FMALL    */     UNIT_FMALL,
388 /* FMLOW    */     UNIT_FM01, /* Only F0,F1,M0,M1 units */
389 /* B0       */     UNIT_B0,
390 /* B1       */     UNIT_B1,
391 /* B01      */     UNIT_B01,
392 /* C        */     UNIT_C,
393 /* MULT-DIV */     UNIT_I01,  /* multiply and divide in I0 or I1 unit.    */
394 /* IACC     */     UNIT_NIL,  /* iacc multiply       not implemented.     */
395 /* LOAD     */     UNIT_I01,  /* load                in I0 or I1 unit.    */
396 /* STORE    */     UNIT_I01,  /* store               in I0 or I1 unit.    */
397 /* SCAN     */     UNIT_IALL, /* scan                in any integer unit. */
398 /* DCPL     */     UNIT_I0,   /* dcpl                only in I0 unit.     */
399 /* MDUALACC */     UNIT_FMALL,/* media dual acc insn in all media units   */
400 /* MDCUTSSI */     UNIT_FM01, /* mdcutssi            in FM0 or FM1 unit.  */
401 /* MCLRACC-1*/     UNIT_FM01  /* mclracc,A==1 in FM0 or FM1 unit.         */
402 };
403
404 void
405 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
406 {
407   vliw->next_slot = 0;
408   vliw->constraint_violation = 0;
409   vliw->mach = mach;
410   vliw->elf_flags = elf_flags;
411
412   switch (mach)
413     {
414     case bfd_mach_fr400:
415       vliw->current_vliw = fr400_allowed_vliw;
416       vliw->unit_mapping = fr400_unit_mapping;
417       break;
418     case bfd_mach_fr450:
419       vliw->current_vliw = fr400_allowed_vliw;
420       vliw->unit_mapping = fr450_unit_mapping;
421       break;
422     case bfd_mach_fr550:
423       vliw->current_vliw = fr550_allowed_vliw;
424       vliw->unit_mapping = fr550_unit_mapping;
425       break;
426     default:
427       vliw->current_vliw = fr500_allowed_vliw;
428       vliw->unit_mapping = fr500_unit_mapping;
429       break;
430     }
431 }
432
433 /* Return TRUE if unit1 is a match for unit2.
434    Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
435    *_allowed_vliw tables above.  */
436 static bfd_boolean
437 match_unit (FRV_VLIW *vliw,
438             CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
439 {
440   /* Map any specialized implementation units to actual ones.  */
441   unit1 = vliw->unit_mapping[unit1];
442
443   if (unit1 == unit2)
444     return TRUE;
445   if (unit1 < unit2)
446     return FALSE;
447
448   switch (unit1)
449     {
450     case UNIT_I01:
451     case UNIT_FM01:
452     case UNIT_B01:
453       /* The 01 versions of these units are within 2 enums of the 0 or 1
454          versions.  */
455       if (unit1 - unit2 <= 2)
456         return TRUE;
457       break;
458     case UNIT_IALL:
459     case UNIT_FMALL:
460       /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
461          versions.  */
462       if (unit1 - unit2 <= 5)
463         return TRUE;
464       break;
465     default:
466       break;
467     }
468
469   return FALSE;
470 }
471
472 /* Return TRUE if the vliws match, FALSE otherwise.  */
473
474 static bfd_boolean
475 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
476 {
477   int i;
478
479   for (i = 0; i < vliw_size; ++i)
480     if ((*vliw1)[i] != (*vliw2)[i])
481       return FALSE;
482
483   return TRUE;
484 }
485
486 /* Find the next vliw vliw in the table that can accomodate the new insn.
487    If one is found then return it. Otherwise return NULL.  */
488
489 static VLIW_COMBO *
490 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
491 {
492   int           next    = vliw->next_slot;
493   VLIW_COMBO    *current = vliw->current_vliw;
494   VLIW_COMBO    *potential;
495
496   if (next <= 0)
497     {
498       fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
499                __LINE__);
500       abort (); /* Should never happen.  */
501     }
502
503   /* The table is sorted by units allowed within slots, so vliws with
504      identical starting sequences are together.  */
505   potential = current;
506   do
507     {
508       if (match_unit (vliw, unit, (*potential)[next]))
509         return potential;
510       ++potential;
511     }
512   while (match_vliw (potential, current, next));
513
514   return NULL;
515 }
516
517 /* Look for the given major insn type in the given vliw.
518    Returns TRUE if found, FALSE otherwise.  */
519
520 static bfd_boolean
521 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
522 {
523   int i;
524
525   for (i = 0; i < vliw->next_slot; ++i)
526     if (vliw->major[i] == major)
527       return TRUE;
528
529   return FALSE;
530 }
531
532 /* Check for constraints between the insns in the vliw due to major insn
533    types.  */
534
535 static bfd_boolean
536 fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
537 {
538   /* In the cpu file, all media insns are represented as being allowed in
539      both media units. This makes it easier since this is the case for fr500.
540      Catch the invalid combinations here.  Insns of major class FR400_MAJOR_M_2
541      cannot coexist with any other media insn in a vliw.  */
542   switch (major)
543     {
544     case FR400_MAJOR_M_2:
545       return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
546         &&   ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
547     case FR400_MAJOR_M_1:
548       return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
549     default:
550       break;
551     }
552   return TRUE;
553 }
554
555 static bfd_boolean
556 fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
557 {
558   CGEN_ATTR_VALUE_TYPE other_major;
559
560   /* Our caller guarantees there's at least one other instruction.  */
561   other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
562
563   /* (M4, M5) and (M4, M6) are allowed.  */
564   if (other_major == FR450_MAJOR_M_4)
565     if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
566       return TRUE;
567
568   /* Otherwise, instructions in even-numbered media categories cannot be
569      executed in parallel with other media instructions.  */
570   switch (major)
571     {
572     case FR450_MAJOR_M_2:
573     case FR450_MAJOR_M_4:
574     case FR450_MAJOR_M_6:
575       return !(other_major >= FR450_MAJOR_M_1
576                && other_major <= FR450_MAJOR_M_6);
577
578     case FR450_MAJOR_M_1:
579     case FR450_MAJOR_M_3:
580     case FR450_MAJOR_M_5:
581       return !(other_major == FR450_MAJOR_M_2
582                || other_major == FR450_MAJOR_M_4
583                || other_major == FR450_MAJOR_M_6);
584
585     default:
586       return TRUE;
587     }
588 }
589
590 static bfd_boolean
591 find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
592 {
593   int i;
594
595   for (i = 0; i < vliw->next_slot; ++i)
596     if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
597       return TRUE;
598
599   return FALSE; /* Not found.  */
600 }
601
602 static bfd_boolean
603 find_major_in_slot (FRV_VLIW *vliw,
604                     CGEN_ATTR_VALUE_TYPE major,
605                     CGEN_ATTR_VALUE_TYPE slot)
606 {
607   int i;
608
609   for (i = 0; i < vliw->next_slot; ++i)
610     if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
611       return TRUE;
612
613   return FALSE;
614 }
615
616 static bfd_boolean
617 fr550_find_media_in_vliw (FRV_VLIW *vliw)
618 {
619   int i;
620
621   for (i = 0; i < vliw->next_slot; ++i)
622     {
623       if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
624         continue;
625
626       /* Found a media insn, however, MNOP and MCLRACC don't count.  */
627       if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
628           || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
629           || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
630         continue;
631
632       return TRUE; /* Found one.  */
633     }
634
635   return FALSE;
636 }
637
638 static bfd_boolean
639 fr550_find_float_in_vliw (FRV_VLIW *vliw)
640 {
641   int i;
642
643   for (i = 0; i < vliw->next_slot; ++i)
644     {
645       if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
646         continue;
647
648       /* Found a floating point insn, however, FNOP doesn't count.  */
649       if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
650         continue;
651
652       return TRUE; /* Found one.  */
653     }
654
655   return FALSE;
656 }
657
658 static bfd_boolean
659 fr550_check_insn_major_constraints (FRV_VLIW *vliw,
660                                     CGEN_ATTR_VALUE_TYPE major,
661                                     const CGEN_INSN *insn)
662 {
663   CGEN_ATTR_VALUE_TYPE unit;
664   CGEN_ATTR_VALUE_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
665   switch (slot)
666     {
667     case UNIT_I2:
668       /* If it's a store, then there must be another store in I1 */
669       unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
670       if (unit == UNIT_STORE)
671         return find_unit_in_vliw (vliw, UNIT_STORE);
672       break;
673     case UNIT_FM2:
674     case UNIT_FM3:
675       /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
676          with media insns.  */
677       if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
678           && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
679         return ! fr550_find_media_in_vliw (vliw);
680       /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
681          floating point insns.  */
682       if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
683           && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
684         return ! fr550_find_float_in_vliw (vliw);
685       /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
686          respectively.  */
687       if (major == FR550_MAJOR_F_2)
688         return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
689                                      slot - (UNIT_FM2 - UNIT_FM0))
690           &&   ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
691                                      slot - (UNIT_FM2 - UNIT_FM0));
692       /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
693          respectively.  */
694       if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
695         return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
696                                      slot - (UNIT_FM2 - UNIT_FM0));
697       /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
698          respectively.  */
699       if (major == FR550_MAJOR_M_4)
700         return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
701                                      slot - (UNIT_FM2 - UNIT_FM0));
702       break;
703     default:
704       break;
705     }
706   return TRUE; /* All OK.  */
707 }
708
709 static bfd_boolean
710 fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
711 {
712   /* TODO: A table might be faster for some of the more complex instances
713      here.  */
714   switch (major)
715     {
716     case FR500_MAJOR_I_1:
717     case FR500_MAJOR_I_4:
718     case FR500_MAJOR_I_5:
719     case FR500_MAJOR_I_6:
720     case FR500_MAJOR_B_1:
721     case FR500_MAJOR_B_2:
722     case FR500_MAJOR_B_3:
723     case FR500_MAJOR_B_4:
724     case FR500_MAJOR_B_5:
725     case FR500_MAJOR_B_6:
726     case FR500_MAJOR_F_4:
727     case FR500_MAJOR_F_8:
728     case FR500_MAJOR_M_8:
729       return TRUE; /* OK */
730     case FR500_MAJOR_I_2:
731       /* Cannot coexist with I-3 insn.  */
732       return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
733     case FR500_MAJOR_I_3:
734       /* Cannot coexist with I-2 insn.  */
735       return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
736     case FR500_MAJOR_F_1:
737     case FR500_MAJOR_F_2:
738       /* Cannot coexist with F-5, F-6, or M-7 insn.  */
739       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
740         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
741         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
742     case FR500_MAJOR_F_3:
743       /* Cannot coexist with F-7, or M-7 insn.  */
744       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
745         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
746     case FR500_MAJOR_F_5:
747       /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn.  */
748       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
749         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
750         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
751         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
752         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
753     case FR500_MAJOR_F_6:
754       /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn.  */
755       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
756         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
757         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
758         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
759         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
760     case FR500_MAJOR_F_7:
761       /* Cannot coexist with F-3, F-5, F-7, or M-7 insn.  */
762       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
763         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
764         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
765         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
766     case FR500_MAJOR_M_1:
767       /* Cannot coexist with M-7 insn.  */
768       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
769     case FR500_MAJOR_M_2:
770     case FR500_MAJOR_M_3:
771       /* Cannot coexist with M-5, M-6 or M-7 insn.  */
772       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
773         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
774         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
775     case FR500_MAJOR_M_4:
776       /* Cannot coexist with M-6 insn.  */
777       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
778     case FR500_MAJOR_M_5:
779       /* Cannot coexist with M-2, M-3, M-5, M-6  or M-7 insn.  */
780       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
781         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
782         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
783         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
784         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
785     case FR500_MAJOR_M_6:
786       /* Cannot coexist with M-2, M-3, M-4, M-5, M-6  or M-7 insn.  */
787       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
788         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
789         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
790         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
791         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
792         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
793     case FR500_MAJOR_M_7:
794       /* Cannot coexist with M-1, M-2, M-3, M-5, M-6  or M-7 insn.  */
795       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
796         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
797         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
798         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
799         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
800         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
801         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
802         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
803         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
804         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
805         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
806         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
807     default:
808       fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
809                __LINE__);
810       abort ();
811       break;
812     }
813   return TRUE;
814 }
815
816 static bfd_boolean
817 check_insn_major_constraints (FRV_VLIW *vliw,
818                               CGEN_ATTR_VALUE_TYPE major,
819                               const CGEN_INSN *insn)
820 {
821   switch (vliw->mach)
822     {
823     case bfd_mach_fr400:
824       return fr400_check_insn_major_constraints (vliw, major);
825
826     case bfd_mach_fr450:
827       return fr450_check_insn_major_constraints (vliw, major);
828
829     case bfd_mach_fr550:
830       return fr550_check_insn_major_constraints (vliw, major, insn);
831
832     default:
833       return fr500_check_insn_major_constraints (vliw, major);
834     }
835 }
836
837 /* Add in insn to the VLIW vliw if possible.
838    Return 0 if successful, non-zero otherwise.  */
839
840 int
841 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
842 {
843   int index;
844   CGEN_ATTR_VALUE_TYPE major;
845   CGEN_ATTR_VALUE_TYPE unit;
846   VLIW_COMBO *new_vliw;
847
848   if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
849     return 1;
850
851   index = vliw->next_slot;
852   if (index >= FRV_VLIW_SIZE)
853     return 1;
854
855   unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
856   if (unit == UNIT_NIL)
857     {
858       fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
859                __LINE__);
860       abort (); /* No UNIT specified for this insn in frv.cpu.  */
861     }
862
863   switch (vliw->mach)
864     {
865     case bfd_mach_fr400:
866       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
867       break;
868     case bfd_mach_fr450:
869       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
870       break;
871     case bfd_mach_fr550:
872       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
873       break;
874     default:
875       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
876       break;
877     }
878
879   if (index <= 0)
880     {
881       /* Any insn can be added to slot 0.  */
882       while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
883         ++vliw->current_vliw;
884       vliw->major[0] = major;
885       vliw->insn[0] = insn;
886       vliw->next_slot = 1;
887       return 0;
888     }
889
890   /* If there are already insns in the vliw(s) check to see that
891      this one can be added.  Do this by finding an allowable vliw
892      combination that can accept the new insn.  */
893   if (! (vliw->elf_flags & EF_FRV_NOPACK))
894     {
895       new_vliw = add_next_to_vliw (vliw, unit);
896       if (new_vliw && check_insn_major_constraints (vliw, major, insn))
897         {
898           vliw->current_vliw = new_vliw;
899           vliw->major[index] = major;
900           vliw->insn[index] = insn;
901           vliw->next_slot++;
902           return 0;
903         }
904
905       /* The frv machine supports all packing conbinations.  If we fail,
906          to add the insn, then it could not be handled as if it was the fr500.
907          Just return as if it was handled ok.  */
908       if (vliw->mach == bfd_mach_frv)
909         return 0;
910     }
911
912   vliw->constraint_violation = 1;
913   return 1;
914 }
915
916 bfd_boolean
917 spr_valid (long regno)
918 {
919   if (regno < 0)     return FALSE;
920   if (regno <= 4095) return TRUE;
921   return FALSE;
922 }
923 /* -- */
924 \f
925 /* -- asm.c */
926 inline static const char *
927 parse_symbolic_address (CGEN_CPU_DESC cd,
928                         const char **strp,
929                         int opindex,
930                         int opinfo,
931                         enum cgen_parse_operand_result *resultp,
932                         bfd_vma *valuep)
933 {
934   enum cgen_parse_operand_result result_type;
935   const char *errmsg = (* cd->parse_operand_fn)
936     (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
937      &result_type, valuep);
938
939   if (errmsg == NULL
940       && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
941     return "symbolic expression required";
942
943   if (resultp)
944     *resultp = result_type;
945
946   return errmsg;
947 }
948
949 static const char *
950 parse_ldd_annotation (CGEN_CPU_DESC cd,
951                       const char **strp,
952                       int opindex,
953                       unsigned long *valuep)
954 {
955   const char *errmsg;
956   enum cgen_parse_operand_result result_type;
957   bfd_vma value;
958
959   if (**strp == '#' || **strp == '%')
960     {
961       if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
962         {
963           *strp += 9;
964           errmsg = parse_symbolic_address (cd, strp, opindex,
965                                            BFD_RELOC_FRV_TLSDESC_RELAX,
966                                            &result_type, &value);
967           if (**strp != ')')
968             return "missing ')'";
969           if (valuep)
970             *valuep = value;
971           ++*strp;
972           if (errmsg)
973             return errmsg;
974         }
975     }
976   
977   while (**strp == ' ' || **strp == '\t')
978     ++*strp;
979   
980   if (**strp != '@')
981     return "missing `@'";
982
983   ++*strp;
984
985   return NULL;
986 }
987
988 static const char *
989 parse_call_annotation (CGEN_CPU_DESC cd,
990                        const char **strp,
991                        int opindex,
992                        unsigned long *valuep)
993 {
994   const char *errmsg;
995   enum cgen_parse_operand_result result_type;
996   bfd_vma value;
997
998   if (**strp == '#' || **strp == '%')
999     {
1000       if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1001         {
1002           *strp += 11;
1003           errmsg = parse_symbolic_address (cd, strp, opindex,
1004                                            BFD_RELOC_FRV_GETTLSOFF_RELAX,
1005                                            &result_type, &value);
1006           if (**strp != ')')
1007             return "missing ')'";
1008           if (valuep)
1009             *valuep = value;
1010           ++*strp;
1011           if (errmsg)
1012             return errmsg;
1013         }
1014     }
1015   
1016   while (**strp == ' ' || **strp == '\t')
1017     ++*strp;
1018   
1019   if (**strp != '@')
1020     return "missing `@'";
1021
1022   ++*strp;
1023
1024   return NULL;
1025 }
1026
1027 static const char *
1028 parse_ld_annotation (CGEN_CPU_DESC cd,
1029                      const char **strp,
1030                      int opindex,
1031                      unsigned long *valuep)
1032 {
1033   const char *errmsg;
1034   enum cgen_parse_operand_result result_type;
1035   bfd_vma value;
1036
1037   if (**strp == '#' || **strp == '%')
1038     {
1039       if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
1040         {
1041           *strp += 8;
1042           errmsg = parse_symbolic_address (cd, strp, opindex,
1043                                            BFD_RELOC_FRV_TLSOFF_RELAX,
1044                                            &result_type, &value);
1045           if (**strp != ')')
1046             return "missing ')'";
1047           if (valuep)
1048             *valuep = value;
1049           ++*strp;
1050           if (errmsg)
1051             return errmsg;
1052         }
1053     }
1054   
1055   while (**strp == ' ' || **strp == '\t')
1056     ++*strp;
1057   
1058   if (**strp != '@')
1059     return "missing `@'";
1060
1061   ++*strp;
1062
1063   return NULL;
1064 }
1065
1066 static const char *
1067 parse_ulo16 (CGEN_CPU_DESC cd,
1068              const char **strp,
1069              int opindex,
1070              unsigned long *valuep)
1071 {
1072   const char *errmsg;
1073   enum cgen_parse_operand_result result_type;
1074   bfd_vma value;
1075  
1076   if (**strp == '#' || **strp == '%')
1077     {
1078       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1079         {
1080           *strp += 4;
1081           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1082                                        & result_type, & value);
1083           if (**strp != ')')
1084             return "missing `)'";
1085           ++*strp;
1086           if (errmsg == NULL
1087               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1088             value &= 0xffff;
1089           *valuep = value;
1090           return errmsg;
1091         }
1092       if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1093         {
1094           *strp += 9;
1095           errmsg = parse_symbolic_address (cd, strp, opindex,
1096                                            BFD_RELOC_FRV_GPRELLO,
1097                                            & result_type, & value);
1098           if (**strp != ')')
1099             return "missing ')'";
1100           ++*strp;
1101           *valuep = value;
1102           return errmsg;
1103         }
1104       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1105         {
1106           *strp += 7;
1107           errmsg = parse_symbolic_address (cd, strp, opindex,
1108                                            BFD_RELOC_FRV_GOTLO,
1109                                            & result_type, & value);
1110           if (**strp != ')')
1111             return "missing ')'";
1112           ++*strp;
1113           *valuep = value;
1114           return errmsg;
1115         }
1116       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1117         {
1118           *strp += 15;
1119           errmsg = parse_symbolic_address (cd, strp, opindex,
1120                                            BFD_RELOC_FRV_FUNCDESC_GOTLO,
1121                                            & result_type, & value);
1122           if (**strp != ')')
1123             return "missing ')'";
1124           ++*strp;
1125           *valuep = value;
1126           return errmsg;
1127         }
1128       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1129         {
1130           *strp += 10;
1131           errmsg = parse_symbolic_address (cd, strp, opindex,
1132                                            BFD_RELOC_FRV_GOTOFFLO,
1133                                            & result_type, & value);
1134           if (**strp != ')')
1135             return "missing ')'";
1136           ++*strp;
1137           *valuep = value;
1138           return errmsg;
1139         }
1140       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1141         {
1142           *strp += 18;
1143           errmsg = parse_symbolic_address (cd, strp, opindex,
1144                                            BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1145                                            & result_type, & value);
1146           if (**strp != ')')
1147             return "missing ')'";
1148           ++*strp;
1149           *valuep = value;
1150           return errmsg;
1151         }
1152       else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1153         {
1154           *strp += 14;
1155           errmsg = parse_symbolic_address (cd, strp, opindex,
1156                                            BFD_RELOC_FRV_GOTTLSDESCLO,
1157                                            & result_type, & value);
1158           if (**strp != ')')
1159             return "missing ')'";
1160           ++*strp;
1161           *valuep = value;
1162           return errmsg;
1163         }
1164       else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1165         {
1166           *strp += 11;
1167           errmsg = parse_symbolic_address (cd, strp, opindex,
1168                                            BFD_RELOC_FRV_TLSMOFFLO,
1169                                            & result_type, & value);
1170           if (**strp != ')')
1171             return "missing ')'";
1172           ++*strp;
1173           *valuep = value;
1174           return errmsg;
1175         }
1176       else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1177         {
1178           *strp += 13;
1179           errmsg = parse_symbolic_address (cd, strp, opindex,
1180                                            BFD_RELOC_FRV_GOTTLSOFFLO,
1181                                            & result_type, & value);
1182           if (**strp != ')')
1183             return "missing ')'";
1184           ++*strp;
1185           *valuep = value;
1186           return errmsg;
1187         }
1188     }
1189   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1190 }
1191
1192 static const char *
1193 parse_uslo16 (CGEN_CPU_DESC cd,
1194               const char **strp,
1195               int opindex,
1196               signed long *valuep)
1197 {
1198   const char *errmsg;
1199   enum cgen_parse_operand_result result_type;
1200   bfd_vma value;
1201  
1202   if (**strp == '#' || **strp == '%')
1203     {
1204       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1205         {
1206           *strp += 4;
1207           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1208                                        & result_type, & value);
1209           if (**strp != ')')
1210             return "missing `)'";
1211           ++*strp;
1212           if (errmsg == NULL
1213               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1214             value &= 0xffff;
1215           *valuep = value;
1216           return errmsg;
1217         }
1218       else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1219         {
1220           *strp += 9;
1221           errmsg = parse_symbolic_address (cd, strp, opindex,
1222                                            BFD_RELOC_FRV_GPRELLO,
1223                                            & result_type, & value);
1224           if (**strp != ')')
1225             return "missing ')'";
1226           ++*strp;
1227           *valuep = value;
1228           return errmsg;
1229         }
1230       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1231         {
1232           *strp += 7;
1233           errmsg = parse_symbolic_address (cd, strp, opindex,
1234                                            BFD_RELOC_FRV_GOTLO,
1235                                            & result_type, & value);
1236           if (**strp != ')')
1237             return "missing ')'";
1238           ++*strp;
1239           *valuep = value;
1240           return errmsg;
1241         }
1242       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1243         {
1244           *strp += 15;
1245           errmsg = parse_symbolic_address (cd, strp, opindex,
1246                                            BFD_RELOC_FRV_FUNCDESC_GOTLO,
1247                                            & result_type, & value);
1248           if (**strp != ')')
1249             return "missing ')'";
1250           ++*strp;
1251           *valuep = value;
1252           return errmsg;
1253         }
1254       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1255         {
1256           *strp += 10;
1257           errmsg = parse_symbolic_address (cd, strp, opindex,
1258                                            BFD_RELOC_FRV_GOTOFFLO,
1259                                            & result_type, & value);
1260           if (**strp != ')')
1261             return "missing ')'";
1262           ++*strp;
1263           *valuep = value;
1264           return errmsg;
1265         }
1266       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1267         {
1268           *strp += 18;
1269           errmsg = parse_symbolic_address (cd, strp, opindex,
1270                                            BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1271                                            & result_type, & value);
1272           if (**strp != ')')
1273             return "missing ')'";
1274           ++*strp;
1275           *valuep = value;
1276           return errmsg;
1277         }
1278       else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1279         {
1280           *strp += 14;
1281           errmsg = parse_symbolic_address (cd, strp, opindex,
1282                                            BFD_RELOC_FRV_GOTTLSDESCLO,
1283                                            & result_type, & value);
1284           if (**strp != ')')
1285             return "missing ')'";
1286           ++*strp;
1287           *valuep = value;
1288           return errmsg;
1289         }
1290       else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1291         {
1292           *strp += 11;
1293           errmsg = parse_symbolic_address (cd, strp, opindex,
1294                                            BFD_RELOC_FRV_TLSMOFFLO,
1295                                            & result_type, & value);
1296           if (**strp != ')')
1297             return "missing ')'";
1298           ++*strp;
1299           *valuep = value;
1300           return errmsg;
1301         }
1302       else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1303         {
1304           *strp += 13;
1305           errmsg = parse_symbolic_address (cd, strp, opindex,
1306                                            BFD_RELOC_FRV_GOTTLSOFFLO,
1307                                            & result_type, & value);
1308           if (**strp != ')')
1309             return "missing ')'";
1310           ++*strp;
1311           *valuep = value;
1312           return errmsg;
1313         }
1314     }
1315   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1316 }
1317
1318 static const char *
1319 parse_uhi16 (CGEN_CPU_DESC cd,
1320              const char **strp,
1321              int opindex,
1322              unsigned long *valuep)
1323 {
1324   const char *errmsg;
1325   enum cgen_parse_operand_result result_type;
1326   bfd_vma value;
1327  
1328   if (**strp == '#' || **strp == '%')
1329     {
1330       if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1331         {
1332           *strp += 4;
1333           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1334                                        & result_type, & value);
1335           if (**strp != ')')
1336             return "missing `)'";
1337           ++*strp;
1338           if (errmsg == NULL
1339               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1340             {
1341               /* If bfd_vma is wider than 32 bits, but we have a sign-
1342                  or zero-extension, truncate it.  */
1343               if (value >= - ((bfd_vma)1 << 31)
1344                   || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
1345                 value &= (((bfd_vma)1 << 16) << 16) - 1;
1346               value >>= 16;
1347             }
1348           *valuep = value;
1349           return errmsg;
1350         }
1351       else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1352         {
1353           *strp += 9;
1354           errmsg = parse_symbolic_address (cd, strp, opindex,
1355                                            BFD_RELOC_FRV_GPRELHI,
1356                                            & result_type, & value);
1357           if (**strp != ')')
1358             return "missing ')'";
1359           ++*strp;
1360           *valuep = value;
1361           return errmsg;
1362         }
1363       else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1364         {
1365           *strp += 7;
1366           errmsg = parse_symbolic_address (cd, strp, opindex,
1367                                            BFD_RELOC_FRV_GOTHI,
1368                                            & result_type, & value);
1369           if (**strp != ')')
1370             return "missing ')'";
1371           ++*strp;
1372           *valuep = value;
1373           return errmsg;
1374         }
1375       else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1376         {
1377           *strp += 15;
1378           errmsg = parse_symbolic_address (cd, strp, opindex,
1379                                            BFD_RELOC_FRV_FUNCDESC_GOTHI,
1380                                            & result_type, & value);
1381           if (**strp != ')')
1382             return "missing ')'";
1383           ++*strp;
1384           *valuep = value;
1385           return errmsg;
1386         }
1387       else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1388         {
1389           *strp += 10;
1390           errmsg = parse_symbolic_address (cd, strp, opindex,
1391                                            BFD_RELOC_FRV_GOTOFFHI,
1392                                            & result_type, & value);
1393           if (**strp != ')')
1394             return "missing ')'";
1395           ++*strp;
1396           *valuep = value;
1397           return errmsg;
1398         }
1399       else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1400         {
1401           *strp += 18;
1402           errmsg = parse_symbolic_address (cd, strp, opindex,
1403                                            BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1404                                            & result_type, & value);
1405           if (**strp != ')')
1406             return "missing ')'";
1407           ++*strp;
1408           *valuep = value;
1409           return errmsg;
1410         }
1411       else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
1412         {
1413           *strp += 14;
1414           errmsg = parse_symbolic_address (cd, strp, opindex,
1415                                            BFD_RELOC_FRV_GOTTLSDESCHI,
1416                                            &result_type, &value);
1417           if (**strp != ')')
1418             return "missing ')'";
1419           ++*strp;
1420           *valuep = value;
1421           return errmsg;
1422         }
1423       else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
1424         {
1425           *strp += 11;
1426           errmsg = parse_symbolic_address (cd, strp, opindex,
1427                                            BFD_RELOC_FRV_TLSMOFFHI,
1428                                            & result_type, & value);
1429           if (**strp != ')')
1430             return "missing ')'";
1431           ++*strp;
1432           *valuep = value;
1433           return errmsg;
1434         }
1435       else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
1436         {
1437           *strp += 13;
1438           errmsg = parse_symbolic_address (cd, strp, opindex,
1439                                            BFD_RELOC_FRV_GOTTLSOFFHI,
1440                                            & result_type, & value);
1441           if (**strp != ')')
1442             return "missing ')'";
1443           ++*strp;
1444           *valuep = value;
1445           return errmsg;
1446         }
1447     }
1448   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1449 }
1450
1451 static long
1452 parse_register_number (const char **strp)
1453 {
1454   int regno;
1455
1456   if (**strp < '0' || **strp > '9')
1457     return -1; /* error */
1458
1459   regno = **strp - '0';
1460   for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1461     regno = regno * 10 + (**strp - '0');
1462
1463   return regno;
1464 }
1465
1466 static const char *
1467 parse_spr (CGEN_CPU_DESC cd,
1468            const char **strp,
1469            CGEN_KEYWORD * table,
1470            long *valuep)
1471 {
1472   const char *save_strp;
1473   long regno;
1474
1475   /* Check for spr index notation.  */
1476   if (strncasecmp (*strp, "spr[", 4) == 0)
1477     {
1478       *strp += 4;
1479       regno = parse_register_number (strp);
1480       if (**strp != ']')
1481         return _("missing `]'");
1482       ++*strp;
1483       if (! spr_valid (regno))
1484         return _("Special purpose register number is out of range");
1485       *valuep = regno;
1486       return NULL;
1487     }
1488
1489   save_strp = *strp;
1490   regno = parse_register_number (strp);
1491   if (regno != -1)
1492     {
1493       if (! spr_valid (regno))
1494         return _("Special purpose register number is out of range");
1495       *valuep = regno;
1496       return NULL;
1497     }
1498
1499   *strp = save_strp;
1500   return cgen_parse_keyword (cd, strp, table, valuep);
1501 }
1502
1503 static const char *
1504 parse_d12 (CGEN_CPU_DESC cd,
1505            const char **strp,
1506            int opindex,
1507            long *valuep)
1508 {
1509   const char *errmsg;
1510   enum cgen_parse_operand_result result_type;
1511   bfd_vma value;
1512  
1513   /* Check for small data reference.  */
1514   if (**strp == '#' || **strp == '%')
1515     {
1516       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1517         {
1518           *strp += 9;
1519           errmsg = parse_symbolic_address (cd, strp, opindex,
1520                                            BFD_RELOC_FRV_GPREL12,
1521                                            & result_type, & value);
1522           if (**strp != ')')
1523             return "missing `)'";
1524           ++*strp;
1525           *valuep = value;
1526           return errmsg;
1527         }
1528       else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1529         {
1530           *strp += 7;
1531           errmsg = parse_symbolic_address (cd, strp, opindex,
1532                                            BFD_RELOC_FRV_GOT12,
1533                                            & result_type, & value);
1534           if (**strp != ')')
1535             return "missing ')'";
1536           ++*strp;
1537           *valuep = value;
1538           return errmsg;
1539         }
1540       else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1541         {
1542           *strp += 15;
1543           errmsg = parse_symbolic_address (cd, strp, opindex,
1544                                            BFD_RELOC_FRV_FUNCDESC_GOT12,
1545                                            & result_type, & value);
1546           if (**strp != ')')
1547             return "missing ')'";
1548           ++*strp;
1549           *valuep = value;
1550           return errmsg;
1551         }
1552       else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1553         {
1554           *strp += 10;
1555           errmsg = parse_symbolic_address (cd, strp, opindex,
1556                                            BFD_RELOC_FRV_GOTOFF12,
1557                                            & result_type, & value);
1558           if (**strp != ')')
1559             return "missing ')'";
1560           ++*strp;
1561           *valuep = value;
1562           return errmsg;
1563         }
1564       else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1565         {
1566           *strp += 18;
1567           errmsg = parse_symbolic_address (cd, strp, opindex,
1568                                            BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1569                                            & result_type, & value);
1570           if (**strp != ')')
1571             return "missing ')'";
1572           ++*strp;
1573           *valuep = value;
1574           return errmsg;
1575         }
1576       else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1577         {
1578           *strp += 14;
1579           errmsg = parse_symbolic_address (cd, strp, opindex,
1580                                            BFD_RELOC_FRV_GOTTLSDESC12,
1581                                            & result_type, & value);
1582           if (**strp != ')')
1583             return "missing ')'";
1584           ++*strp;
1585           *valuep = value;
1586           return errmsg;
1587         }
1588       else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1589         {
1590           *strp += 11;
1591           errmsg = parse_symbolic_address (cd, strp, opindex,
1592                                            BFD_RELOC_FRV_TLSMOFF12,
1593                                            & result_type, & value);
1594           if (**strp != ')')
1595             return "missing ')'";
1596           ++*strp;
1597           *valuep = value;
1598           return errmsg;
1599         }
1600       else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1601         {
1602           *strp += 13;
1603           errmsg = parse_symbolic_address (cd, strp, opindex,
1604                                            BFD_RELOC_FRV_GOTTLSOFF12,
1605                                            & result_type, & value);
1606           if (**strp != ')')
1607             return "missing ')'";
1608           ++*strp;
1609           *valuep = value;
1610           return errmsg;
1611         }
1612     }
1613   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1614 }
1615
1616 static const char *
1617 parse_s12 (CGEN_CPU_DESC cd,
1618            const char **strp,
1619            int opindex,
1620            long *valuep)
1621 {
1622   const char *errmsg;
1623   enum cgen_parse_operand_result result_type;
1624   bfd_vma value;
1625  
1626   /* Check for small data reference.  */
1627   if (**strp == '#' || **strp == '%')
1628     {
1629       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1630         {
1631           *strp += 9;
1632           errmsg = parse_symbolic_address (cd, strp, opindex,
1633                                            BFD_RELOC_FRV_GPREL12,
1634                                            & result_type, & value);
1635           if (**strp != ')')
1636             return "missing `)'";
1637           ++*strp;
1638           *valuep = value;
1639           return errmsg;
1640         }
1641       else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1642         {
1643           *strp += 7;
1644           errmsg = parse_symbolic_address (cd, strp, opindex,
1645                                            BFD_RELOC_FRV_GOT12,
1646                                            & result_type, & value);
1647           if (**strp != ')')
1648             return "missing ')'";
1649           ++*strp;
1650           *valuep = value;
1651           return errmsg;
1652         }
1653       else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1654         {
1655           *strp += 15;
1656           errmsg = parse_symbolic_address (cd, strp, opindex,
1657                                            BFD_RELOC_FRV_FUNCDESC_GOT12,
1658                                            & result_type, & value);
1659           if (**strp != ')')
1660             return "missing ')'";
1661           ++*strp;
1662           *valuep = value;
1663           return errmsg;
1664         }
1665       else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1666         {
1667           *strp += 10;
1668           errmsg = parse_symbolic_address (cd, strp, opindex,
1669                                            BFD_RELOC_FRV_GOTOFF12,
1670                                            & result_type, & value);
1671           if (**strp != ')')
1672             return "missing ')'";
1673           ++*strp;
1674           *valuep = value;
1675           return errmsg;
1676         }
1677       else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1678         {
1679           *strp += 18;
1680           errmsg = parse_symbolic_address (cd, strp, opindex,
1681                                            BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1682                                            & result_type, & value);
1683           if (**strp != ')')
1684             return "missing ')'";
1685           ++*strp;
1686           *valuep = value;
1687           return errmsg;
1688         }
1689       else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1690         {
1691           *strp += 14;
1692           errmsg = parse_symbolic_address (cd, strp, opindex,
1693                                            BFD_RELOC_FRV_GOTTLSDESC12,
1694                                            & result_type, & value);
1695           if (**strp != ')')
1696             return "missing ')'";
1697           ++*strp;
1698           *valuep = value;
1699           return errmsg;
1700         }
1701       else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1702         {
1703           *strp += 11;
1704           errmsg = parse_symbolic_address (cd, strp, opindex,
1705                                            BFD_RELOC_FRV_TLSMOFF12,
1706                                            & result_type, & value);
1707           if (**strp != ')')
1708             return "missing ')'";
1709           ++*strp;
1710           *valuep = value;
1711           return errmsg;
1712         }
1713       else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1714         {
1715           *strp += 13;
1716           errmsg = parse_symbolic_address (cd, strp, opindex,
1717                                            BFD_RELOC_FRV_GOTTLSOFF12,
1718                                            & result_type, & value);
1719           if (**strp != ')')
1720             return "missing ')'";
1721           ++*strp;
1722           *valuep = value;
1723           return errmsg;
1724         }
1725     }
1726
1727   if (**strp == '#')
1728     ++*strp;
1729   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1730 }
1731
1732 static const char *
1733 parse_u12 (CGEN_CPU_DESC cd,
1734            const char **strp,
1735            int opindex,
1736            long *valuep)
1737 {
1738   const char *errmsg;
1739   enum cgen_parse_operand_result result_type;
1740   bfd_vma value;
1741  
1742   /* Check for small data reference.  */
1743   if ((**strp == '#' || **strp == '%')
1744       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1745     {
1746       *strp += 9;
1747       errmsg = parse_symbolic_address (cd, strp, opindex,
1748                                        BFD_RELOC_FRV_GPRELU12,
1749                                        & result_type, & value);
1750       if (**strp != ')')
1751         return "missing `)'";
1752       ++*strp;
1753       *valuep = value;
1754       return errmsg;
1755     }
1756   else
1757     {
1758       if (**strp == '#')
1759         ++*strp;
1760       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1761     }
1762 }
1763
1764 static const char *
1765 parse_A (CGEN_CPU_DESC cd,
1766          const char **strp,
1767          int opindex,
1768          unsigned long *valuep,
1769          unsigned long A)
1770 {
1771   const char *errmsg;
1772  
1773   if (**strp == '#')
1774     ++*strp;
1775
1776   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1777   if (errmsg)
1778     return errmsg;
1779
1780   if (*valuep != A)
1781     return _("Value of A operand must be 0 or 1");
1782
1783   return NULL;
1784 }
1785
1786 static const char *
1787 parse_A0 (CGEN_CPU_DESC cd,
1788           const char **strp,
1789           int opindex,
1790           unsigned long *valuep)
1791 {
1792   return parse_A (cd, strp, opindex, valuep, 0);
1793 }
1794
1795 static const char *
1796 parse_A1 (CGEN_CPU_DESC cd,
1797           const char **strp,
1798           int opindex,
1799           unsigned long *valuep)
1800 {
1801   return parse_A (cd, strp, opindex, valuep, 1);
1802 }
1803
1804 static const char *
1805 parse_even_register (CGEN_CPU_DESC  cd,
1806                      const char **  strP,
1807                      CGEN_KEYWORD * tableP,
1808                      long *         valueP)
1809 {
1810   const char * errmsg;
1811   const char * saved_star_strP = * strP;
1812
1813   errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1814
1815   if (errmsg == NULL && ((* valueP) & 1))
1816     {
1817       errmsg = _("register number must be even");
1818       * strP = saved_star_strP;
1819     }
1820
1821   return errmsg;
1822 }
1823
1824 static const char *
1825 parse_call_label (CGEN_CPU_DESC cd,
1826                   const char **strp,
1827                   int opindex,
1828                   int opinfo,
1829                   enum cgen_parse_operand_result *resultp,
1830                   bfd_vma *valuep)
1831 {
1832   const char *errmsg;
1833   bfd_vma value;
1834  
1835   /* Check for small data reference.  */
1836   if (opinfo == 0 && (**strp == '#' || **strp == '%'))
1837     {
1838       if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1839         {
1840           *strp += 11;
1841           errmsg = parse_symbolic_address (cd, strp, opindex,
1842                                            BFD_RELOC_FRV_GETTLSOFF,
1843                                            resultp, &value);
1844           if (**strp != ')')
1845             return _("missing `)'");
1846           ++*strp;
1847           *valuep = value;
1848           return errmsg;
1849         }
1850     }
1851
1852   return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
1853 }
1854
1855 /* -- */
1856 \f
1857 /* -- dis.c */
1858 static void
1859 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1860           void * dis_info,
1861           long reloc_ann ATTRIBUTE_UNUSED,
1862           long value ATTRIBUTE_UNUSED,
1863           bfd_vma pc ATTRIBUTE_UNUSED,
1864           int length ATTRIBUTE_UNUSED)
1865 {
1866   disassemble_info *info = (disassemble_info *) dis_info;
1867
1868   (*info->fprintf_func) (info->stream, "@");
1869 }  
1870
1871 static void
1872 print_spr (CGEN_CPU_DESC cd,
1873            void * dis_info,
1874            CGEN_KEYWORD *names,
1875            long regno,
1876            unsigned int attrs)
1877 {
1878   /* Use the register index format for any unnamed registers.  */
1879   if (cgen_keyword_lookup_value (names, regno) == NULL)
1880     {
1881       disassemble_info *info = (disassemble_info *) dis_info;
1882       (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1883     }
1884   else
1885     print_keyword (cd, dis_info, names, regno, attrs);
1886 }
1887
1888 static void
1889 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1890           void * dis_info,
1891           long value,
1892           unsigned int attrs ATTRIBUTE_UNUSED,
1893           bfd_vma pc ATTRIBUTE_UNUSED,
1894           int length ATTRIBUTE_UNUSED)
1895 {
1896   disassemble_info *info = (disassemble_info *) dis_info;
1897
1898   (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
1899 }
1900
1901 static void
1902 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1903           void * dis_info,
1904           long value,
1905           unsigned int attrs ATTRIBUTE_UNUSED,
1906           bfd_vma pc ATTRIBUTE_UNUSED,
1907           int length ATTRIBUTE_UNUSED)
1908 {
1909   disassemble_info *info = (disassemble_info *) dis_info;
1910   if (value)
1911     (*info->fprintf_func) (info->stream, "0x%lx", value);
1912   else
1913     (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
1914 }
1915
1916 /* -- */