* ld-elf/exclude.exp: Don't run for cris-*-elf.
[binutils.git] / cpu / frv.opc
blob46985b6110ae05376a980ace6a9b5508610cc1ae
1 /* Fujitsu FRV opcode support, for GNU Binutils.  -*- C -*-
3    Copyright 2000, 2001, 2003, 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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, unsigned 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, long *));
968 static const char * parse_A1
969   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
970 static const char * parse_A
971   PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
973 static const char *
974 parse_ulo16 (cd, strp, opindex, valuep)
975      CGEN_CPU_DESC cd;
976      const char **strp;
977      int opindex;
978      unsigned long *valuep;
980   const char *errmsg;
981   enum cgen_parse_operand_result result_type;
982   bfd_vma value;
984   if (**strp == '#' || **strp == '%')
985     {
986       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
987         {
988           *strp += 4;
989           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
990                                        &result_type, &value);
991           if (**strp != ')')
992             return "missing `)'";
993           ++*strp;
994           if (errmsg == NULL
995               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
996             value &= 0xffff;
997           *valuep = value;
998           return errmsg;
999         }
1000       if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1001         {
1002           *strp += 9;
1003           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
1004                                        &result_type, &value);
1005           if (**strp != ')')
1006             return "missing ')'";
1007           ++*strp;
1008           if (errmsg == NULL
1009               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1010             value &= 0xffff;
1011           *valuep = value;
1012           return errmsg;
1013         }
1014       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1015         {
1016           *strp += 7;
1017           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
1018                                        &result_type, &value);
1019           if (**strp != ')')
1020             return "missing ')'";
1021           ++*strp;
1022           if (errmsg == NULL
1023               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1024             value &= 0xffff;
1025           *valuep = value;
1026           return errmsg;
1027         }
1028       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1029         {
1030           *strp += 15;
1031           errmsg = cgen_parse_address (cd, strp, opindex,
1032                                        BFD_RELOC_FRV_FUNCDESC_GOTLO,
1033                                        &result_type, &value);
1034           if (**strp != ')')
1035             return "missing ')'";
1036           ++*strp;
1037           if (errmsg == NULL
1038               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1039             value &= 0xffff;
1040           *valuep = value;
1041           return errmsg;
1042         }
1043       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1044         {
1045           *strp += 10;
1046           errmsg = cgen_parse_address (cd, strp, opindex,
1047                                        BFD_RELOC_FRV_GOTOFFLO,
1048                                        &result_type, &value);
1049           if (**strp != ')')
1050             return "missing ')'";
1051           ++*strp;
1052           if (errmsg == NULL
1053               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1054             value &= 0xffff;
1055           *valuep = value;
1056           return errmsg;
1057         }
1058       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1059         {
1060           *strp += 18;
1061           errmsg = cgen_parse_address (cd, strp, opindex,
1062                                        BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1063                                        &result_type, &value);
1064           if (**strp != ')')
1065             return "missing ')'";
1066           ++*strp;
1067           if (errmsg == NULL
1068               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1069             value &= 0xffff;
1070           *valuep = value;
1071           return errmsg;
1072         }
1073     }
1074   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1077 static const char *
1078 parse_uslo16 (cd, strp, opindex, valuep)
1079      CGEN_CPU_DESC cd;
1080      const char **strp;
1081      int opindex;
1082      unsigned long *valuep;
1084   const char *errmsg;
1085   enum cgen_parse_operand_result result_type;
1086   bfd_vma value;
1088   if (**strp == '#' || **strp == '%')
1089     {
1090       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1091         {
1092           *strp += 4;
1093           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1094                                        &result_type, &value);
1095           if (**strp != ')')
1096             return "missing `)'";
1097           ++*strp;
1098           if (errmsg == NULL
1099               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1100             value &= 0xffff;
1101           *valuep = value;
1102           return errmsg;
1103         }
1104       else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1105         {
1106           *strp += 9;
1107           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
1108                                        &result_type, &value);
1109           if (**strp != ')')
1110             return "missing ')'";
1111           ++*strp;
1112           if (errmsg == NULL
1113               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1114             value &= 0xffff;
1115           *valuep = value;
1116           return errmsg;
1117         }
1118       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1119         {
1120           *strp += 7;
1121           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
1122                                        &result_type, &value);
1123           if (**strp != ')')
1124             return "missing ')'";
1125           ++*strp;
1126           if (errmsg == NULL
1127               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1128             value &= 0xffff;
1129           *valuep = value;
1130           return errmsg;
1131         }
1132       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1133         {
1134           *strp += 15;
1135           errmsg = cgen_parse_address (cd, strp, opindex,
1136                                        BFD_RELOC_FRV_FUNCDESC_GOTLO,
1137                                        &result_type, &value);
1138           if (**strp != ')')
1139             return "missing ')'";
1140           ++*strp;
1141           if (errmsg == NULL
1142               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1143             value &= 0xffff;
1144           *valuep = value;
1145           return errmsg;
1146         }
1147       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1148         {
1149           *strp += 10;
1150           errmsg = cgen_parse_address (cd, strp, opindex,
1151                                        BFD_RELOC_FRV_GOTOFFLO,
1152                                        &result_type, &value);
1153           if (**strp != ')')
1154             return "missing ')'";
1155           ++*strp;
1156           if (errmsg == NULL
1157               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1158             value &= 0xffff;
1159           *valuep = value;
1160           return errmsg;
1161         }
1162       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1163         {
1164           *strp += 18;
1165           errmsg = cgen_parse_address (cd, strp, opindex,
1166                                        BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1167                                        &result_type, &value);
1168           if (**strp != ')')
1169             return "missing ')'";
1170           ++*strp;
1171           if (errmsg == NULL
1172               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1173             value &= 0xffff;
1174           *valuep = value;
1175           return errmsg;
1176         }
1177     }
1178   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1181 static const char *
1182 parse_uhi16 (cd, strp, opindex, valuep)
1183      CGEN_CPU_DESC cd;
1184      const char **strp;
1185      int opindex;
1186      unsigned long *valuep;
1188   const char *errmsg;
1189   enum cgen_parse_operand_result result_type;
1190   bfd_vma value;
1192   if (**strp == '#' || **strp == '%')
1193     {
1194       if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1195         {
1196           *strp += 4;
1197           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1198                                        &result_type, &value);
1199           if (**strp != ')')
1200             return "missing `)'";
1201           ++*strp;
1202           if (errmsg == NULL
1203               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1204             value >>= 16;
1205           *valuep = value;
1206           return errmsg;
1207         }
1208       else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1209         {
1210           *strp += 9;
1211           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
1212                                        &result_type, &value);
1213           if (**strp != ')')
1214             return "missing ')'";
1215           ++*strp;
1216           if (errmsg == NULL
1217               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1218             value >>= 16;
1219           *valuep = value;
1220           return errmsg;
1221         }
1222       else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1223         {
1224           *strp += 7;
1225           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTHI,
1226                                        &result_type, &value);
1227           if (**strp != ')')
1228             return "missing ')'";
1229           ++*strp;
1230           if (errmsg == NULL
1231               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1232             value >>= 16;
1233           *valuep = value;
1234           return errmsg;
1235         }
1236       else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1237         {
1238           *strp += 15;
1239           errmsg = cgen_parse_address (cd, strp, opindex,
1240                                        BFD_RELOC_FRV_FUNCDESC_GOTHI,
1241                                        &result_type, &value);
1242           if (**strp != ')')
1243             return "missing ')'";
1244           ++*strp;
1245           if (errmsg == NULL
1246               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1247             value >>= 16;
1248           *valuep = value;
1249           return errmsg;
1250         }
1251       else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1252         {
1253           *strp += 10;
1254           errmsg = cgen_parse_address (cd, strp, opindex,
1255                                        BFD_RELOC_FRV_GOTOFFHI,
1256                                        &result_type, &value);
1257           if (**strp != ')')
1258             return "missing ')'";
1259           ++*strp;
1260           if (errmsg == NULL
1261               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1262             value >>= 16;
1263           *valuep = value;
1264           return errmsg;
1265         }
1266       else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1267         {
1268           *strp += 18;
1269           errmsg = cgen_parse_address (cd, strp, opindex,
1270                                        BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1271                                        &result_type, &value);
1272           if (**strp != ')')
1273             return "missing ')'";
1274           ++*strp;
1275           if (errmsg == NULL
1276               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1277             value >>= 16;
1278           *valuep = value;
1279           return errmsg;
1280         }
1281     }
1282   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1285 static long
1286 parse_register_number (strp)
1287      const char **strp;
1289   int regno;
1290   if (**strp < '0' || **strp > '9')
1291     return -1; /* error */
1293   regno = **strp - '0';
1294   for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1295     regno = regno * 10 + (**strp - '0');
1297   return regno;
1300 static const char *
1301 parse_spr (cd, strp, table, valuep)
1302      CGEN_CPU_DESC cd;
1303      const char **strp;
1304      CGEN_KEYWORD * table;
1305      long *valuep;
1307   const char *save_strp;
1308   long regno;
1310   /* Check for spr index notation.  */
1311   if (strncasecmp (*strp, "spr[", 4) == 0)
1312     {
1313       *strp += 4;
1314       regno = parse_register_number (strp);
1315       if (**strp != ']')
1316         return "missing `]'";
1317       ++*strp;
1318       if (! spr_valid (regno))
1319         return "Special purpose register number is out of range";
1320       *valuep = regno;
1321       return NULL;
1322     }
1324   save_strp = *strp;
1325   regno = parse_register_number (strp);
1326   if (regno != -1)
1327     {
1328       if (! spr_valid (regno))
1329         return "Special purpose register number is out of range";
1330       *valuep = regno;
1331       return NULL;
1332     }
1334   *strp = save_strp;
1335   return cgen_parse_keyword (cd, strp, table, valuep);
1338 static const char *
1339 parse_d12 (cd, strp, opindex, valuep)
1340      CGEN_CPU_DESC cd;
1341      const char **strp;
1342      int opindex;
1343      long *valuep;
1345   const char *errmsg;
1346   enum cgen_parse_operand_result result_type;
1347   bfd_vma value;
1349   /* Check for small data reference.  */
1350   if (**strp == '#' || **strp == '%')
1351     {
1352       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1353         {
1354           *strp += 9;
1355           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
1356                                        &result_type, &value);
1357           if (**strp != ')')
1358             return "missing `)'";
1359           ++*strp;
1360           *valuep = value;
1361           return errmsg;
1362         }
1363       else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1364         {
1365           *strp += 7;
1366           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
1367                                        &result_type, &value);
1368           if (**strp != ')')
1369             return "missing ')'";
1370           ++*strp;
1371           *valuep = value;
1372           return errmsg;
1373         }
1374       else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1375         {
1376           *strp += 15;
1377           errmsg = cgen_parse_address (cd, strp, opindex,
1378                                        BFD_RELOC_FRV_FUNCDESC_GOT12,
1379                                        &result_type, &value);
1380           if (**strp != ')')
1381             return "missing ')'";
1382           ++*strp;
1383           *valuep = value;
1384           return errmsg;
1385         }
1386       else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1387         {
1388           *strp += 10;
1389           errmsg = cgen_parse_address (cd, strp, opindex,
1390                                        BFD_RELOC_FRV_GOTOFF12,
1391                                        &result_type, &value);
1392           if (**strp != ')')
1393             return "missing ')'";
1394           ++*strp;
1395           *valuep = value;
1396           return errmsg;
1397         }
1398       else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1399         {
1400           *strp += 18;
1401           errmsg = cgen_parse_address (cd, strp, opindex,
1402                                        BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1403                                        &result_type, &value);
1404           if (**strp != ')')
1405             return "missing ')'";
1406           ++*strp;
1407           *valuep = value;
1408           return errmsg;
1409         }
1410     }
1411   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1414 static const char *
1415 parse_s12 (cd, strp, opindex, valuep)
1416      CGEN_CPU_DESC cd;
1417      const char **strp;
1418      int opindex;
1419      long *valuep;
1421   const char *errmsg;
1422   enum cgen_parse_operand_result result_type;
1423   bfd_vma value;
1425   /* Check for small data reference.  */
1426   if ((**strp == '#' || **strp == '%')
1427       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1428     {
1429       *strp += 9;
1430       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
1431                                     &result_type, &value);
1432       if (**strp != ')')
1433         return "missing `)'";
1434       ++*strp;
1435       *valuep = value;
1436       return errmsg;
1437     }
1438   else if ((**strp == '#' || **strp == '%')
1439            && strncasecmp (*strp + 1, "got12(", 6) == 0)
1440     {
1441       *strp += 7;
1442       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
1443                                    &result_type, &value);
1444       if (**strp != ')')
1445         return "missing ')'";
1446       ++*strp;
1447       *valuep = value;
1448       return errmsg;
1449     }
1450   else if ((**strp == '#' || **strp == '%')
1451            && strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1452     {
1453       *strp += 15;
1454       errmsg = cgen_parse_address (cd, strp, opindex,
1455                                    BFD_RELOC_FRV_FUNCDESC_GOT12,
1456                                    &result_type, &value);
1457       if (**strp != ')')
1458         return "missing ')'";
1459       ++*strp;
1460       *valuep = value;
1461       return errmsg;
1462     }
1463   else if ((**strp == '#' || **strp == '%')
1464            && strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1465     {
1466       *strp += 10;
1467       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTOFF12,
1468                                    &result_type, &value);
1469       if (**strp != ')')
1470         return "missing ')'";
1471       ++*strp;
1472       *valuep = value;
1473       return errmsg;
1474     }
1475   else if ((**strp == '#' || **strp == '%')
1476            && strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1477     {
1478       *strp += 18;
1479       errmsg = cgen_parse_address (cd, strp, opindex,
1480                                    BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1481                                    &result_type, &value);
1482       if (**strp != ')')
1483         return "missing ')'";
1484       ++*strp;
1485       *valuep = value;
1486       return errmsg;
1487     }
1488   else
1489     {
1490       if (**strp == '#')
1491         ++*strp;
1492       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1493     }
1496 static const char *
1497 parse_u12 (cd, strp, opindex, valuep)
1498      CGEN_CPU_DESC cd;
1499      const char **strp;
1500      int opindex;
1501      long *valuep;
1503   const char *errmsg;
1504   enum cgen_parse_operand_result result_type;
1505   bfd_vma value;
1507   /* Check for small data reference.  */
1508   if ((**strp == '#' || **strp == '%')
1509       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1510     {
1511       *strp += 9;
1512       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
1513                                     &result_type, &value);
1514       if (**strp != ')')
1515         return "missing `)'";
1516       ++*strp;
1517       *valuep = value;
1518       return errmsg;
1519     }
1520   else
1521     {
1522       if (**strp == '#')
1523         ++*strp;
1524       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1525     }
1528 static const char *
1529 parse_A (cd, strp, opindex, valuep, A)
1530      CGEN_CPU_DESC cd;
1531      const char **strp;
1532      int opindex;
1533      long *valuep;
1534      long A;
1536   const char *errmsg;
1538   if (**strp == '#')
1539     ++*strp;
1541   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1542   if (errmsg)
1543     return errmsg;
1545   if (*valuep != A)
1546     return "Value of A operand must be 0 or 1";
1548   return NULL;
1551 static const char *
1552 parse_A0 (cd, strp, opindex, valuep)
1553      CGEN_CPU_DESC cd;
1554      const char **strp;
1555      int opindex;
1556      long *valuep;
1558   return parse_A (cd, strp, opindex, valuep, 0);
1561 static const char *
1562 parse_A1 (cd, strp, opindex, valuep)
1563      CGEN_CPU_DESC cd;
1564      const char **strp;
1565      int opindex;
1566      long *valuep;
1568   return parse_A (cd, strp, opindex, valuep, 1);
1571 static const char *
1572 parse_even_register (cd, strP, tableP, valueP)
1573      CGEN_CPU_DESC  cd;
1574      const char **  strP;
1575      CGEN_KEYWORD * tableP;
1576      long *         valueP;
1578   const char * errmsg;
1579   const char * saved_star_strP = * strP;
1581   errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1583   if (errmsg == NULL && ((* valueP) & 1))
1584     {
1585       errmsg = _("register number must be even");
1586       * strP = saved_star_strP;
1587     }
1589   return errmsg;
1591 /* -- */
1593 /* -- dis.c */
1594 static void print_spr
1595   PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
1596 static void print_hi
1597   PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
1598 static void print_lo
1599   PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
1601 static void
1602 print_spr (cd, dis_info, names, regno, attrs)
1603      CGEN_CPU_DESC cd;
1604      PTR dis_info;
1605      CGEN_KEYWORD *names;
1606      long regno;
1607      unsigned int attrs;
1609   /* Use the register index format for any unnamed registers.  */
1610   if (cgen_keyword_lookup_value (names, regno) == NULL)
1611     {
1612       disassemble_info *info = (disassemble_info *) dis_info;
1613       (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1614     }
1615   else
1616     print_keyword (cd, dis_info, names, regno, attrs);
1619 static void
1620 print_hi (cd, dis_info, value, attrs, pc, length)
1621      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1622      PTR dis_info;
1623      long value;
1624      unsigned int attrs ATTRIBUTE_UNUSED;
1625      bfd_vma pc ATTRIBUTE_UNUSED;
1626      int length ATTRIBUTE_UNUSED;
1628   disassemble_info *info = (disassemble_info *) dis_info;
1629   if (value)
1630     (*info->fprintf_func) (info->stream, "0x%lx", value);
1631   else
1632     (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
1635 static void
1636 print_lo (cd, dis_info, value, attrs, pc, length)
1637      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1638      PTR dis_info;
1639      long value;
1640      unsigned int attrs ATTRIBUTE_UNUSED;
1641      bfd_vma pc ATTRIBUTE_UNUSED;
1642      int length ATTRIBUTE_UNUSED;
1644   disassemble_info *info = (disassemble_info *) dis_info;
1645   if (value)
1646     (*info->fprintf_func) (info->stream, "0x%lx", value);
1647   else
1648     (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
1651 /* -- */