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