2003-09-11 Michael Snyder <msnyder@redhat.com>
[external/binutils.git] / cpu / frv.opc
1 /* Fujitsu FRV opcode support, for GNU Binutils.  -*- C -*-
2
3    Copyright 2003 Free Software Foundation, Inc.
4
5    Contributed by Red Hat Inc; developed under contract from Fujitsu.
6
7    This file is part of the GNU Binutils.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 */
24
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.
31
32    Each section is delimited with start and end markers.
33
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"
39 */
40 \f
41 /* -- opc.h */
42
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)
47
48 /* Allows reason codes to be output when assembler errors occur.  */
49 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
50
51 /* Vliw support.  */
52 #define FRV_VLIW_SIZE 4 /* fr500 has largest vliw size of 4.  */
53 typedef CGEN_ATTR_VALUE_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
54
55 typedef struct
56 {
57   int                   next_slot;
58   int                   constraint_violation;
59   unsigned long         mach;
60   unsigned long         elf_flags;
61   CGEN_ATTR_VALUE_TYPE *unit_mapping;
62   VLIW_COMBO           *current_vliw;
63   CGEN_ATTR_VALUE_TYPE  major[FRV_VLIW_SIZE];
64 } FRV_VLIW;
65
66 int frv_is_branch_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
67 int frv_is_float_major  PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
68 int frv_is_media_major  PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
69 int frv_is_branch_insn  PARAMS ((const CGEN_INSN *));
70 int frv_is_float_insn   PARAMS ((const CGEN_INSN *));
71 int frv_is_media_insn   PARAMS ((const CGEN_INSN *));
72 void frv_vliw_reset     PARAMS ((FRV_VLIW *, unsigned long mach, unsigned long elf_flags));
73 int frv_vliw_add_insn   PARAMS ((FRV_VLIW *, const CGEN_INSN *));
74 int spr_valid           PARAMS ((long));
75 /* -- */
76 \f
77 /* -- opc.c */
78 #include "elf/frv.h"
79
80 static int match_unit
81   PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, CGEN_ATTR_VALUE_TYPE));
82 static int match_vliw
83   PARAMS ((VLIW_COMBO *, VLIW_COMBO *, int));
84 static VLIW_COMBO * add_next_to_vliw
85   PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
86 static int find_major_in_vliw
87   PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
88 static int fr400_check_insn_major_constraints
89   PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
90 static int fr500_check_insn_major_constraints
91   PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
92 static int check_insn_major_constraints
93   PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
94
95 int
96 frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
97 {
98   switch (mach)
99     {
100     case bfd_mach_fr400:
101       if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
102         return 1; /* is a branch */
103       break;
104     default:
105       if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
106         return 1; /* is a branch */
107       break;
108     }
109
110   return 0; /* not a branch */
111 }
112
113 int
114 frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
115 {
116   switch (mach)
117     {
118     case bfd_mach_fr400:
119       return 0; /* No float insns */
120     default:
121       if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
122         return 1; /* is a float insn */
123       break;
124     }
125
126   return 0; /* not a branch */
127 }
128
129 int
130 frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
131 {
132   switch (mach)
133     {
134     case bfd_mach_fr400:
135       if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
136         return 1; /* is a media insn */
137       break;
138     default:
139       if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
140         return 1; /* is a media insn */
141       break;
142     }
143
144   return 0; /* not a branch */
145 }
146
147 int
148 frv_is_branch_insn (const CGEN_INSN *insn)
149 {
150   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
151                            bfd_mach_fr400))
152     return 1;
153   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
154                            bfd_mach_fr500))
155     return 1;
156
157   return 0;
158 }
159
160 int
161 frv_is_float_insn (const CGEN_INSN *insn)
162 {
163   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
164                           bfd_mach_fr400))
165     return 1;
166   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
167                           bfd_mach_fr500))
168     return 1;
169
170   return 0;
171 }
172
173 int
174 frv_is_media_insn (const CGEN_INSN *insn)
175 {
176   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
177                           bfd_mach_fr400))
178     return 1;
179   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
180                           bfd_mach_fr500))
181     return 1;
182
183   return 0;
184 }
185
186 /* This table represents the allowable packing for vliw insns for the fr400.
187    The fr400 has only 2 vliw slots. Represent this by not allowing any insns
188    in the extra slots.
189    Subsets of any given row are also allowed.  */
190 static VLIW_COMBO fr400_allowed_vliw[] =
191 {
192   /*  slot0       slot1       slot2       slot3    */
193   {  UNIT_I0,    UNIT_I1,    UNIT_NIL,   UNIT_NIL  },
194   {  UNIT_I0,    UNIT_FM0,   UNIT_NIL,   UNIT_NIL  },
195   {  UNIT_I0,    UNIT_B0,    UNIT_NIL,   UNIT_NIL  },
196   {  UNIT_FM0,   UNIT_FM1,   UNIT_NIL,   UNIT_NIL  },
197   {  UNIT_FM0,   UNIT_B0,    UNIT_NIL,   UNIT_NIL  },
198   {  UNIT_B0,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL  },
199   {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  },
200   {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  }
201 };
202
203 /* This table represents the allowable packing for vliw insns for the fr500.
204    Subsets of any given row are also allowed.  */
205 static VLIW_COMBO fr500_allowed_vliw[] =
206 {
207   /*  slot0       slot1       slot2       slot3    */
208   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1  },
209   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0   },
210   {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0   },
211   {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1   },
212   {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1   },
213   {  UNIT_I0,    UNIT_B0,    UNIT_B1,    UNIT_NIL  },
214   {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1   },
215   {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL  },
216   {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL  },
217   {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  },
218   {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  }
219 };
220
221 /* Some insns are assigned specialized implementation units which map to
222    different actual implementation units on different machines.  These
223    tables perform that mapping.  */
224 static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
225 {
226 /* unit in insn    actual unit */
227 /* NIL      */     UNIT_NIL,
228 /* I0       */     UNIT_I0,
229 /* I1       */     UNIT_I1,
230 /* I01      */     UNIT_I01, 
231 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
232 /* FM0      */     UNIT_FM0,
233 /* FM1      */     UNIT_FM1,
234 /* FM01     */     UNIT_FM01,
235 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
236 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
237 /* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
238 /* B1       */     UNIT_B0,
239 /* B01      */     UNIT_B0,
240 /* C        */     UNIT_C,
241 /* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
242 /* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
243 /* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
244 /* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
245 /* DCPL     */     UNIT_C,   /* dcpl                only in C   unit.  */
246 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
247 /* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
248 };
249
250 static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
251 {
252 /* unit in insn    actual unit */
253 /* NIL      */     UNIT_NIL,
254 /* I0       */     UNIT_I0,
255 /* I1       */     UNIT_I1,
256 /* I01      */     UNIT_I01, 
257 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
258 /* FM0      */     UNIT_FM0,
259 /* FM1      */     UNIT_FM1,
260 /* FM01     */     UNIT_FM01,
261 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
262 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
263 /* B0       */     UNIT_B0,
264 /* B1       */     UNIT_B1,
265 /* B01      */     UNIT_B01,
266 /* C        */     UNIT_C,
267 /* MULT-DIV */     UNIT_I01, /* multiply and divide in I0 or I1 unit.  */
268 /* LOAD     */     UNIT_I01, /* load                in I0 or I1 unit.  */
269 /* STORE    */     UNIT_I0,  /* store               only in I0 unit.  */
270 /* SCAN     */     UNIT_I01, /* scan                in I0 or I1 unit.  */
271 /* DCPL     */     UNIT_C,   /* dcpl                only in C unit.  */
272 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
273 /* MCLRACC-1*/     UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit.  */
274 };
275
276 void
277 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
278 {
279   vliw->next_slot = 0;
280   vliw->constraint_violation = 0;
281   vliw->mach = mach;
282   vliw->elf_flags = elf_flags;
283
284   switch (mach)
285     {
286     case bfd_mach_fr400:
287       vliw->current_vliw = fr400_allowed_vliw;
288       vliw->unit_mapping = fr400_unit_mapping;
289       break;
290     default:
291       vliw->current_vliw = fr500_allowed_vliw;
292       vliw->unit_mapping = fr500_unit_mapping;
293       break;
294     }
295 }
296
297 /* Return 1 if unit1 is a match for unit2.
298    Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
299    *_allowed_vliw tables above.  */
300 static int
301 match_unit (FRV_VLIW *vliw,
302             CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
303 {
304   /* Map any specialized implementation units to actual ones.  */
305   unit1 = vliw->unit_mapping[unit1];
306
307   if (unit1 == unit2)
308     return 1;
309   if (unit1 < unit2)
310     return 0;
311
312   switch (unit1)
313     {
314     case UNIT_I01:
315     case UNIT_FM01:
316     case UNIT_B01:
317       /* The 01 versions of these units are within 2 enums of the 0 or 1
318          versions.  */
319       if (unit1 - unit2 <= 2)
320         return 1;
321       break;
322     default:
323       break;
324     }
325
326   return 0;
327 }
328
329 /* Return 1 if the vliws match, 0 otherwise.  */
330
331 static int
332 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
333 {
334   int i;
335
336   for (i = 0; i < vliw_size; ++i)
337     {
338       if ((*vliw1)[i] != (*vliw2)[i])
339         return 0;
340     }
341
342   return 1;
343 }
344
345 /* Find the next vliw vliw in the table that can accomodate the new insn.
346    If one is found then return it. Otherwise return NULL.  */
347
348 static VLIW_COMBO *
349 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
350 {
351   int           next    = vliw->next_slot;
352   VLIW_COMBO    *current = vliw->current_vliw;
353   VLIW_COMBO    *potential;
354
355   if (next <= 0)
356     abort (); /* Should never happen */
357
358   /* The table is sorted by units allowed within slots, so vliws with
359      identical starting sequences are together.  */
360   potential = current;
361   do
362     {
363       if (match_unit (vliw, unit, (*potential)[next]))
364         return potential;
365       ++potential;
366     }
367   while (match_vliw (potential, current, next));
368
369   return NULL;
370 }
371
372 /* Look for the given major insn type in the given vliw. Return 1 if found,
373    return 0 otherwise.  */
374
375 static int
376 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
377 {
378   int i;
379
380   for (i = 0; i < vliw->next_slot; ++i)
381     if (vliw->major[i] == major)
382       return 1;
383
384   return 0;
385 }
386
387 /* Check for constraints between the insns in the vliw due to major insn
388    types.  */
389
390 static int
391 fr400_check_insn_major_constraints (
392   FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
393 )
394 {
395   /* In the cpu file, all media insns are represented as being allowed in
396      both media units. This makes it easier since this is the case for fr500.
397      Catch the invalid combinations here.  Insns of major class FR400_MAJOR_M_2
398      cannot coexist with any other media insn in a vliw.  */
399   switch (major)
400     {
401     case FR400_MAJOR_M_2:
402       return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
403         &&   ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
404     default:
405       break;
406     }
407   return 1;
408 }
409
410 static int
411 fr500_check_insn_major_constraints (
412   FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
413 )
414 {
415   /* TODO: A table might be faster for some of the more complex instances
416      here.  */
417   switch (major)
418     {
419     case FR500_MAJOR_I_1:
420     case FR500_MAJOR_I_4:
421     case FR500_MAJOR_I_5:
422     case FR500_MAJOR_I_6:
423     case FR500_MAJOR_B_1:
424     case FR500_MAJOR_B_2:
425     case FR500_MAJOR_B_3:
426     case FR500_MAJOR_B_4:
427     case FR500_MAJOR_B_5:
428     case FR500_MAJOR_B_6:
429     case FR500_MAJOR_F_4:
430     case FR500_MAJOR_F_8:
431     case FR500_MAJOR_M_8:
432       return 1; /* OK */
433     case FR500_MAJOR_I_2:
434       /* Cannot coexist with I-3 insn.  */
435       return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
436     case FR500_MAJOR_I_3:
437       /* Cannot coexist with I-2 insn.  */
438       return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
439     case FR500_MAJOR_F_1:
440     case FR500_MAJOR_F_2:
441       /* Cannot coexist with F-5, F-6, or M-7 insn.  */
442       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
443         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
444         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
445     case FR500_MAJOR_F_3:
446       /* Cannot coexist with F-7, or M-7 insn.  */
447       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
448         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
449     case FR500_MAJOR_F_5:
450       /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn.  */
451       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
452         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
453         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
454         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
455         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
456     case FR500_MAJOR_F_6:
457       /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn.  */
458       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
459         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
460         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
461         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
462         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
463     case FR500_MAJOR_F_7:
464       /* Cannot coexist with F-3, F-5, F-7, or M-7 insn.  */
465       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
466         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
467         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
468         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
469     case FR500_MAJOR_M_1:
470       /* Cannot coexist with M-7 insn.  */
471       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
472     case FR500_MAJOR_M_2:
473     case FR500_MAJOR_M_3:
474       /* Cannot coexist with M-5, M-6 or M-7 insn.  */
475       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
476         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
477         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
478     case FR500_MAJOR_M_4:
479       /* Cannot coexist with M-6 insn.  */
480       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
481     case FR500_MAJOR_M_5:
482       /* Cannot coexist with M-2, M-3, M-5, M-6  or M-7 insn.  */
483       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
484         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
485         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
486         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
487         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
488     case FR500_MAJOR_M_6:
489       /* Cannot coexist with M-2, M-3, M-4, M-5, M-6  or M-7 insn.  */
490       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
491         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
492         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
493         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
494         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
495         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
496     case FR500_MAJOR_M_7:
497       /* Cannot coexist with M-1, M-2, M-3, M-5, M-6  or M-7 insn.  */
498       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
499         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
500         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
501         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
502         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
503         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
504         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
505         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
506         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
507         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
508         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
509         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
510     default:
511       abort ();
512       break;
513     }
514   return 1;
515 }
516
517 static int
518 check_insn_major_constraints (
519   FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
520 )
521 {
522   int rc;
523   switch (vliw->mach)
524     {
525     case bfd_mach_fr400:
526       rc = fr400_check_insn_major_constraints (vliw, major);
527       break;
528     default:
529       rc = fr500_check_insn_major_constraints (vliw, major);
530       break;
531     }
532   return rc;
533 }
534
535 /* Add in insn to the VLIW vliw if possible. Return 0 if successful,
536    non-zero otherwise.  */
537 int
538 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
539 {
540   int index;
541   CGEN_ATTR_VALUE_TYPE major;
542   CGEN_ATTR_VALUE_TYPE unit;
543   VLIW_COMBO *new_vliw;
544
545   if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
546     return 1;
547
548   index = vliw->next_slot;
549   if (index >= FRV_VLIW_SIZE)
550     return 1;
551
552   unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
553   if (unit == UNIT_NIL)
554     abort (); /* no UNIT specified for this insn in frv.cpu  */
555
556   switch (vliw->mach)
557     {
558     case bfd_mach_fr400:
559       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
560       break;
561     default:
562       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
563       break;
564     }
565
566   if (index <= 0)
567     {
568       /* Any insn can be added to slot 0.  */
569       while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
570         ++vliw->current_vliw;
571       vliw->major[0] = major;
572       vliw->next_slot = 1;
573       return 0;
574     }
575
576   /* If there are already insns in the vliw(s) check to see that
577      this one can be added.  Do this by finding an allowable vliw
578      combination that can accept the new insn.  */
579   if (! (vliw->elf_flags & EF_FRV_NOPACK))
580     {
581       new_vliw = add_next_to_vliw (vliw, unit);
582       if (new_vliw && check_insn_major_constraints (vliw, major))
583         {
584           vliw->current_vliw = new_vliw;
585           vliw->major[index] = major;
586           vliw->next_slot++;
587           return 0;
588         }
589
590       /* The frv machine supports all packing conbinations.  If we fail,
591          to add the insn, then it could not be handled as if it was the fr500.
592          Just return as if it was handled ok.  */
593       if (vliw->mach == bfd_mach_frv)
594         return 0;
595     }
596
597   vliw->constraint_violation = 1;
598   return 1;
599 }
600
601 int
602 spr_valid (regno)
603      long regno;
604 {
605   if (regno < 0)     return 0;
606   if (regno <= 4095) return 1;
607   return 0;
608 }
609 /* -- */
610 \f
611 /* -- asm.c */
612 static const char * parse_ulo16
613   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
614 static const char * parse_uslo16
615   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
616 static const char * parse_uhi16
617   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
618 static long parse_register_number
619   PARAMS ((const char **));
620 static const char * parse_spr
621   PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
622 static const char * parse_d12
623   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
624 static const char * parse_s12
625   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
626 static const char * parse_u12
627   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
628 static const char * parse_even_register
629   PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
630 static const char * parse_A0
631   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
632 static const char * parse_A1
633   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
634 static const char * parse_A
635   PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
636
637 static const char *
638 parse_ulo16 (cd, strp, opindex, valuep)
639      CGEN_CPU_DESC cd;
640      const char **strp;
641      int opindex;
642      unsigned long *valuep;
643 {
644   const char *errmsg;
645   enum cgen_parse_operand_result result_type;
646   bfd_vma value;
647  
648   if (**strp == '#' || **strp == '%')
649     {
650       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
651         {
652           *strp += 4;
653           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
654                                        &result_type, &value);
655           if (**strp != ')')
656             return "missing `)'";
657           ++*strp;
658           if (errmsg == NULL
659               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
660             value &= 0xffff;
661           *valuep = value;
662           return errmsg;
663         }
664       if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
665         {
666           *strp += 9;
667           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
668                                        &result_type, &value);
669           if (**strp != ')')
670             return "missing ')'";
671           ++*strp;
672           if (errmsg == NULL
673               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
674             value >>= 16;
675           *valuep = value;
676           return errmsg;
677         }
678     }
679   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
680 }
681
682 static const char *
683 parse_uslo16 (cd, strp, opindex, valuep)
684      CGEN_CPU_DESC cd;
685      const char **strp;
686      int opindex;
687      unsigned long *valuep;
688 {
689   const char *errmsg;
690   enum cgen_parse_operand_result result_type;
691   bfd_vma value;
692  
693   if (**strp == '#' || **strp == '%')
694     {
695       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
696         {
697           *strp += 4;
698           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
699                                        &result_type, &value);
700           if (**strp != ')')
701             return "missing `)'";
702           ++*strp;
703           if (errmsg == NULL
704               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
705             value &= 0xffff;
706           *valuep = value;
707           return errmsg;
708         }
709       else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
710         {
711           *strp += 9;
712           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
713                                        &result_type, &value);
714           if (**strp != ')')
715             return "missing ')'";
716           ++*strp;
717           if (errmsg == NULL
718               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
719             value &= 0xffff;
720           *valuep = value;
721           return errmsg;
722         }
723     }
724   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
725 }
726
727 static const char *
728 parse_uhi16 (cd, strp, opindex, valuep)
729      CGEN_CPU_DESC cd;
730      const char **strp;
731      int opindex;
732      unsigned long *valuep;
733 {
734   const char *errmsg;
735   enum cgen_parse_operand_result result_type;
736   bfd_vma value;
737  
738   if (**strp == '#' || **strp == '%')
739     {
740       if (strncasecmp (*strp + 1, "hi(", 3) == 0)
741         {
742           *strp += 4;
743           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
744                                        &result_type, &value);
745           if (**strp != ')')
746             return "missing `)'";
747           ++*strp;
748           if (errmsg == NULL
749               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
750             value >>= 16;
751           *valuep = value;
752           return errmsg;
753         }
754       else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
755         {
756           *strp += 9;
757           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
758                                        &result_type, &value);
759           if (**strp != ')')
760             return "missing ')'";
761           ++*strp;
762           if (errmsg == NULL
763               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
764             value >>= 16;
765           *valuep = value;
766           return errmsg;
767         }
768     }
769   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
770 }
771
772 static long
773 parse_register_number (strp)
774      const char **strp;
775 {
776   int regno;
777   if (**strp < '0' || **strp > '9')
778     return -1; /* error */
779
780   regno = **strp - '0';
781   for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
782     regno = regno * 10 + (**strp - '0');
783
784   return regno;
785 }
786
787 static const char *
788 parse_spr (cd, strp, table, valuep)
789      CGEN_CPU_DESC cd;
790      const char **strp;
791      CGEN_KEYWORD * table;
792      long *valuep;
793 {
794   const char *save_strp;
795   long regno;
796
797   /* Check for spr index notation.  */
798   if (strncasecmp (*strp, "spr[", 4) == 0)
799     {
800       *strp += 4;
801       regno = parse_register_number (strp);
802       if (**strp != ']')
803         return "missing `]'";
804       ++*strp;
805       if (! spr_valid (regno))
806         return "Special purpose register number is out of range";
807       *valuep = regno;
808       return NULL;
809     }
810
811   save_strp = *strp;
812   regno = parse_register_number (strp);
813   if (regno != -1)
814     {
815       if (! spr_valid (regno))
816         return "Special purpose register number is out of range";
817       *valuep = regno;
818       return NULL;
819     }
820
821   *strp = save_strp;
822   return cgen_parse_keyword (cd, strp, table, valuep);
823 }
824
825 static const char *
826 parse_d12 (cd, strp, opindex, valuep)
827      CGEN_CPU_DESC cd;
828      const char **strp;
829      int opindex;
830      long *valuep;
831 {
832   const char *errmsg;
833   enum cgen_parse_operand_result result_type;
834   bfd_vma value;
835  
836   /* Check for small data reference.  */
837   if (**strp == '#' || **strp == '%')
838     {
839       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
840         {
841           *strp += 9;
842           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
843                                        &result_type, &value);
844           if (**strp != ')')
845             return "missing `)'";
846           ++*strp;
847           *valuep = value;
848           return errmsg;
849         }
850     }
851   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
852 }
853
854 static const char *
855 parse_s12 (cd, strp, opindex, valuep)
856      CGEN_CPU_DESC cd;
857      const char **strp;
858      int opindex;
859      long *valuep;
860 {
861   const char *errmsg;
862   enum cgen_parse_operand_result result_type;
863   bfd_vma value;
864  
865   /* Check for small data reference.  */
866   if ((**strp == '#' || **strp == '%')
867       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
868     {
869       *strp += 9;
870       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
871                                     &result_type, &value);
872       if (**strp != ')')
873         return "missing `)'";
874       ++*strp;
875       *valuep = value;
876       return errmsg;
877     }
878   else
879     {
880       if (**strp == '#')
881         ++*strp;
882       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
883     }
884 }
885
886 static const char *
887 parse_u12 (cd, strp, opindex, valuep)
888      CGEN_CPU_DESC cd;
889      const char **strp;
890      int opindex;
891      long *valuep;
892 {
893   const char *errmsg;
894   enum cgen_parse_operand_result result_type;
895   bfd_vma value;
896  
897   /* Check for small data reference.  */
898   if ((**strp == '#' || **strp == '%')
899       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
900     {
901       *strp += 9;
902       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
903                                     &result_type, &value);
904       if (**strp != ')')
905         return "missing `)'";
906       ++*strp;
907       *valuep = value;
908       return errmsg;
909     }
910   else
911     {
912       if (**strp == '#')
913         ++*strp;
914       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
915     }
916 }
917
918 static const char *
919 parse_A (cd, strp, opindex, valuep, A)
920      CGEN_CPU_DESC cd;
921      const char **strp;
922      int opindex;
923      long *valuep;
924      long A;
925 {
926   const char *errmsg;
927  
928   if (**strp == '#')
929     ++*strp;
930
931   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
932   if (errmsg)
933     return errmsg;
934
935   if (*valuep != A)
936     return "Value of A operand must be 0 or 1";
937
938   return NULL;
939 }
940
941 static const char *
942 parse_A0 (cd, strp, opindex, valuep)
943      CGEN_CPU_DESC cd;
944      const char **strp;
945      int opindex;
946      long *valuep;
947 {
948   return parse_A (cd, strp, opindex, valuep, 0);
949 }
950
951 static const char *
952 parse_A1 (cd, strp, opindex, valuep)
953      CGEN_CPU_DESC cd;
954      const char **strp;
955      int opindex;
956      long *valuep;
957 {
958   return parse_A (cd, strp, opindex, valuep, 1);
959 }
960
961 static const char *
962 parse_even_register (cd, strP, tableP, valueP)
963      CGEN_CPU_DESC  cd;
964      const char **  strP;
965      CGEN_KEYWORD * tableP;
966      long *         valueP;
967 {
968   const char * errmsg;
969   const char * saved_star_strP = * strP;
970
971   errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
972
973   if (errmsg == NULL && ((* valueP) & 1))
974     {
975       errmsg = _("register number must be even");
976       * strP = saved_star_strP;
977     }
978
979   return errmsg;
980 }
981 /* -- */
982 \f
983 /* -- dis.c */
984 static void print_spr
985   PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
986 static void print_hi
987   PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
988 static void print_lo
989   PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
990
991 static void
992 print_spr (cd, dis_info, names, regno, attrs)
993      CGEN_CPU_DESC cd;
994      PTR dis_info;
995      CGEN_KEYWORD *names;
996      long regno;
997      unsigned int attrs;
998 {
999   /* Use the register index format for any unnamed registers.  */
1000   if (cgen_keyword_lookup_value (names, regno) == NULL)
1001     {
1002       disassemble_info *info = (disassemble_info *) dis_info;
1003       (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1004     }
1005   else
1006     print_keyword (cd, dis_info, names, regno, attrs);
1007 }
1008
1009 static void
1010 print_hi (cd, dis_info, value, attrs, pc, length)
1011      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1012      PTR dis_info;
1013      long value;
1014      unsigned int attrs ATTRIBUTE_UNUSED;
1015      bfd_vma pc ATTRIBUTE_UNUSED;
1016      int length ATTRIBUTE_UNUSED;
1017 {
1018   disassemble_info *info = (disassemble_info *) dis_info;
1019   if (value)
1020     (*info->fprintf_func) (info->stream, "0x%lx", value);
1021   else
1022     (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
1023 }
1024
1025 static void
1026 print_lo (cd, dis_info, value, attrs, pc, length)
1027      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1028      PTR dis_info;
1029      long value;
1030      unsigned int attrs ATTRIBUTE_UNUSED;
1031      bfd_vma pc ATTRIBUTE_UNUSED;
1032      int length ATTRIBUTE_UNUSED;
1033 {
1034   disassemble_info *info = (disassemble_info *) dis_info;
1035   if (value)
1036     (*info->fprintf_func) (info->stream, "0x%lx", value);
1037   else
1038     (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
1039 }
1040
1041 /* -- */