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