Add code to handle even-numbered only register operands
[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 slots 2 and 3.
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 /* FM0      */     UNIT_FM0,
232 /* FM1      */     UNIT_FM1,
233 /* FM01     */     UNIT_FM01,
234 /* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
235 /* B1       */     UNIT_B0,
236 /* B01      */     UNIT_B0,
237 /* C        */     UNIT_C,
238 /* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0 unit.  */
239 /* LOAD     */     UNIT_I0   /* load                only in I0 unit.  */
240 };
241
242 static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
243 {
244 /* unit in insn    actual unit */
245 /* NIL      */     UNIT_NIL,
246 /* I0       */     UNIT_I0,
247 /* I1       */     UNIT_I1,
248 /* I01      */     UNIT_I01, 
249 /* FM0      */     UNIT_FM0,
250 /* FM1      */     UNIT_FM1,
251 /* FM01     */     UNIT_FM01,
252 /* B0       */     UNIT_B0,
253 /* B1       */     UNIT_B1,
254 /* B01      */     UNIT_B01,
255 /* C        */     UNIT_C,
256 /* MULT-DIV */     UNIT_I01, /* multiply and divide in I0 or I1 unit.  */
257 /* LOAD     */     UNIT_I01  /* load                in I0 or I1 unit.  */
258 };
259
260 void
261 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
262 {
263   vliw->next_slot = 0;
264   vliw->constraint_violation = 0;
265   vliw->mach = mach;
266   vliw->elf_flags = elf_flags;
267
268   switch (mach)
269     {
270     case bfd_mach_fr400:
271       vliw->current_vliw = fr400_allowed_vliw;
272       vliw->unit_mapping = fr400_unit_mapping;
273       break;
274     default:
275       vliw->current_vliw = fr500_allowed_vliw;
276       vliw->unit_mapping = fr500_unit_mapping;
277       break;
278     }
279 }
280
281 /* Return 1 if unit1 is a match for unit2.
282    Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
283    *_allowed_vliw tables above.  */
284 static int
285 match_unit (FRV_VLIW *vliw,
286             CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
287 {
288   /* Map any specialized implementation units to actual ones.  */
289   unit1 = vliw->unit_mapping[unit1];
290
291   if (unit1 == unit2)
292     return 1;
293   if (unit1 < unit2)
294     return 0;
295
296   switch (unit1)
297     {
298     case UNIT_I01:
299     case UNIT_FM01:
300     case UNIT_B01:
301       /* The 01 versions of these units are within 2 enums of the 0 or 1
302          versions.  */
303       if (unit1 - unit2 <= 2)
304         return 1;
305       break;
306     default:
307       break;
308     }
309
310   return 0;
311 }
312
313 /* Return 1 if the vliws match, 0 otherwise.  */
314
315 static int
316 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
317 {
318   int i;
319
320   for (i = 0; i < vliw_size; ++i)
321     {
322       if ((*vliw1)[i] != (*vliw2)[i])
323         return 0;
324     }
325
326   return 1;
327 }
328
329 /* Find the next vliw vliw in the table that can accomodate the new insn.
330    If one is found then return it. Otherwise return NULL.  */
331
332 static VLIW_COMBO *
333 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
334 {
335   int           next    = vliw->next_slot;
336   VLIW_COMBO    *current = vliw->current_vliw;
337   VLIW_COMBO    *potential;
338
339   if (next <= 0)
340     abort (); /* Should never happen */
341
342   /* The table is sorted by units allowed within slots, so vliws with
343      identical starting sequences are together.  */
344   potential = current;
345   do
346     {
347       if (match_unit (vliw, unit, (*potential)[next]))
348         return potential;
349       ++potential;
350     }
351   while (match_vliw (potential, current, next));
352
353   return NULL;
354 }
355
356 /* Look for the given major insn type in the given vliw. Return 1 if found,
357    return 0 otherwise.  */
358
359 static int
360 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
361 {
362   int i;
363
364   for (i = 0; i < vliw->next_slot; ++i)
365     if (vliw->major[i] == major)
366       return 1;
367
368   return 0;
369 }
370
371 /* Check for constraints between the insns in the vliw due to major insn
372    types.  */
373
374 static int
375 fr400_check_insn_major_constraints (
376   FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
377 )
378 {
379   /* In the cpu file, all media insns are represented as being allowed in
380      both media units. This makes it easier since this is the case for fr500.
381      Catch the invalid combinations here.  Insns of major class FR400_MAJOR_M_2
382      cannot coexist with any other media insn in a vliw.  */
383   switch (major)
384     {
385     case FR400_MAJOR_M_2:
386       return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
387         &&   ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
388     default:
389       break;
390     }
391   return 1;
392 }
393
394 static int
395 fr500_check_insn_major_constraints (
396   FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
397 )
398 {
399   /* TODO: A table might be faster for some of the more complex instances
400      here.  */
401   switch (major)
402     {
403     case FR500_MAJOR_I_1:
404     case FR500_MAJOR_I_4:
405     case FR500_MAJOR_I_5:
406     case FR500_MAJOR_I_6:
407     case FR500_MAJOR_B_1:
408     case FR500_MAJOR_B_2:
409     case FR500_MAJOR_B_3:
410     case FR500_MAJOR_B_4:
411     case FR500_MAJOR_B_5:
412     case FR500_MAJOR_B_6:
413     case FR500_MAJOR_F_4:
414     case FR500_MAJOR_F_8:
415     case FR500_MAJOR_M_8:
416       return 1; /* OK */
417     case FR500_MAJOR_I_2:
418       /* Cannot coexist with I-3 insn.  */
419       return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
420     case FR500_MAJOR_I_3:
421       /* Cannot coexist with I-2 insn.  */
422       return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
423     case FR500_MAJOR_F_1:
424     case FR500_MAJOR_F_2:
425       /* Cannot coexist with F-5, F-6, or M-7 insn.  */
426       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
427         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
428         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
429     case FR500_MAJOR_F_3:
430       /* Cannot coexist with F-7, or M-7 insn.  */
431       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
432         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
433     case FR500_MAJOR_F_5:
434       /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn.  */
435       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
436         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
437         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
438         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
439         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
440     case FR500_MAJOR_F_6:
441       /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn.  */
442       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
443         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
444         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
445         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
446         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
447     case FR500_MAJOR_F_7:
448       /* Cannot coexist with F-3, F-5, F-7, or M-7 insn.  */
449       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
450         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
451         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
452         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
453     case FR500_MAJOR_M_1:
454       /* Cannot coexist with M-7 insn.  */
455       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
456     case FR500_MAJOR_M_2:
457     case FR500_MAJOR_M_3:
458       /* Cannot coexist with M-5, M-6 or M-7 insn.  */
459       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
460         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
461         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
462     case FR500_MAJOR_M_4:
463       /* Cannot coexist with M-6 insn.  */
464       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
465     case FR500_MAJOR_M_5:
466       /* Cannot coexist with M-2, M-3, M-5, M-6  or M-7 insn.  */
467       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
468         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
469         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
470         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
471         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
472     case FR500_MAJOR_M_6:
473       /* Cannot coexist with M-2, M-3, M-4, M-5, M-6  or M-7 insn.  */
474       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
475         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
476         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
477         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
478         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
479         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
480     case FR500_MAJOR_M_7:
481       /* Cannot coexist with M-1, M-2, M-3, M-5, M-6  or M-7 insn.  */
482       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
483         &&   ! 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         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
489         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
490         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
491         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
492         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
493         &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
494     default:
495       abort ();
496       break;
497     }
498   return 1;
499 }
500
501 static int
502 check_insn_major_constraints (
503   FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
504 )
505 {
506   int rc;
507   switch (vliw->mach)
508     {
509     case bfd_mach_fr400:
510       rc = fr400_check_insn_major_constraints (vliw, major);
511       break;
512     default:
513       rc = fr500_check_insn_major_constraints (vliw, major);
514       break;
515     }
516   return rc;
517 }
518
519 /* Add in insn to the VLIW vliw if possible. Return 0 if successful,
520    non-zero otherwise.  */
521 int
522 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
523 {
524   int index;
525   CGEN_ATTR_VALUE_TYPE major;
526   CGEN_ATTR_VALUE_TYPE unit;
527   VLIW_COMBO *new_vliw;
528
529   if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
530     return 1;
531
532   index = vliw->next_slot;
533   if (index >= FRV_VLIW_SIZE)
534     return 1;
535
536   unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
537   if (unit == UNIT_NIL)
538     abort (); /* no UNIT specified for this insn in frv.cpu  */
539
540   if (vliw->mach == bfd_mach_fr400)
541     major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
542   else
543     major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
544
545   if (index <= 0)
546     {
547       /* Any insn can be added to slot 0.  */
548       while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
549         ++vliw->current_vliw;
550       vliw->major[0] = major;
551       vliw->next_slot = 1;
552       return 0;
553     }
554
555   /* If there are already insns in the vliw(s) check to see that
556      this one can be added.  Do this by finding an allowable vliw
557      combination that can accept the new insn.  */
558   if (! (vliw->elf_flags & EF_FRV_NOPACK))
559     {
560       new_vliw = add_next_to_vliw (vliw, unit);
561       if (new_vliw && check_insn_major_constraints (vliw, major))
562         {
563           vliw->current_vliw = new_vliw;
564           vliw->major[index] = major;
565           vliw->next_slot++;
566           return 0;
567         }
568
569       /* The frv machine supports all packing conbinations.  If we fail,
570          to add the insn, then it could not be handled as if it was the fr500.
571          Just return as if it was handled ok.  */
572       if (vliw->mach == bfd_mach_frv)
573         return 0;
574     }
575
576   vliw->constraint_violation = 1;
577   return 1;
578 }
579
580 int
581 spr_valid (regno)
582      long regno;
583 {
584   if (regno < 0)     return 0;
585   if (regno <= 4095) return 1;
586   return 0;
587 }
588 /* -- */
589 \f
590 /* -- asm.c */
591 static const char * parse_ulo16
592   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
593 static const char * parse_uslo16
594   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
595 static const char * parse_uhi16
596   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
597 static long parse_register_number
598   PARAMS ((const char **));
599 static const char * parse_spr
600   PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
601 static const char * parse_d12
602   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
603 static const char * parse_s12
604   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
605 static const char * parse_u12
606   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
607 static const char * parse_even_register
608   PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
609
610 static const char *
611 parse_ulo16 (cd, strp, opindex, valuep)
612      CGEN_CPU_DESC cd;
613      const char **strp;
614      int opindex;
615      unsigned long *valuep;
616 {
617   const char *errmsg;
618   enum cgen_parse_operand_result result_type;
619   bfd_vma value;
620  
621   if (**strp == '#' || **strp == '%')
622     {
623       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
624         {
625           *strp += 4;
626           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
627                                        &result_type, &value);
628           if (**strp != ')')
629             return "missing `)'";
630           ++*strp;
631           if (errmsg == NULL
632               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
633             value &= 0xffff;
634           *valuep = value;
635           return errmsg;
636         }
637       if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
638         {
639           *strp += 9;
640           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
641                                        &result_type, &value);
642           if (**strp != ')')
643             return "missing ')'";
644           ++*strp;
645           if (errmsg == NULL
646               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
647             value >>= 16;
648           *valuep = value;
649           return errmsg;
650         }
651     }
652   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
653 }
654
655 static const char *
656 parse_uslo16 (cd, strp, opindex, valuep)
657      CGEN_CPU_DESC cd;
658      const char **strp;
659      int opindex;
660      unsigned long *valuep;
661 {
662   const char *errmsg;
663   enum cgen_parse_operand_result result_type;
664   bfd_vma value;
665  
666   if (**strp == '#' || **strp == '%')
667     {
668       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
669         {
670           *strp += 4;
671           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
672                                        &result_type, &value);
673           if (**strp != ')')
674             return "missing `)'";
675           ++*strp;
676           if (errmsg == NULL
677               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
678             value &= 0xffff;
679           *valuep = value;
680           return errmsg;
681         }
682       else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
683         {
684           *strp += 9;
685           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
686                                        &result_type, &value);
687           if (**strp != ')')
688             return "missing ')'";
689           ++*strp;
690           if (errmsg == NULL
691               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
692             value &= 0xffff;
693           *valuep = value;
694           return errmsg;
695         }
696     }
697   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
698 }
699
700 static const char *
701 parse_uhi16 (cd, strp, opindex, valuep)
702      CGEN_CPU_DESC cd;
703      const char **strp;
704      int opindex;
705      unsigned long *valuep;
706 {
707   const char *errmsg;
708   enum cgen_parse_operand_result result_type;
709   bfd_vma value;
710  
711   if (**strp == '#' || **strp == '%')
712     {
713       if (strncasecmp (*strp + 1, "hi(", 3) == 0)
714         {
715           *strp += 4;
716           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
717                                        &result_type, &value);
718           if (**strp != ')')
719             return "missing `)'";
720           ++*strp;
721           if (errmsg == NULL
722               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
723             value >>= 16;
724           *valuep = value;
725           return errmsg;
726         }
727       else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
728         {
729           *strp += 9;
730           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
731                                        &result_type, &value);
732           if (**strp != ')')
733             return "missing ')'";
734           ++*strp;
735           if (errmsg == NULL
736               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
737             value >>= 16;
738           *valuep = value;
739           return errmsg;
740         }
741     }
742   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
743 }
744
745 static long
746 parse_register_number (strp)
747      const char **strp;
748 {
749   int regno;
750   if (**strp < '0' || **strp > '9')
751     return -1; /* error */
752
753   regno = **strp - '0';
754   for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
755     regno = regno * 10 + (**strp - '0');
756
757   return regno;
758 }
759
760 static const char *
761 parse_spr (cd, strp, table, valuep)
762      CGEN_CPU_DESC cd;
763      const char **strp;
764      CGEN_KEYWORD * table;
765      long *valuep;
766 {
767   const char *save_strp;
768   long regno;
769
770   /* Check for spr index notation.  */
771   if (strncasecmp (*strp, "spr[", 4) == 0)
772     {
773       *strp += 4;
774       regno = parse_register_number (strp);
775       if (**strp != ']')
776         return "missing `]'";
777       ++*strp;
778       if (! spr_valid (regno))
779         return "Special purpose register number is out of range";
780       *valuep = regno;
781       return NULL;
782     }
783
784   save_strp = *strp;
785   regno = parse_register_number (strp);
786   if (regno != -1)
787     {
788       if (! spr_valid (regno))
789         return "Special purpose register number is out of range";
790       *valuep = regno;
791       return NULL;
792     }
793
794   *strp = save_strp;
795   return cgen_parse_keyword (cd, strp, table, valuep);
796 }
797
798 static const char *
799 parse_d12 (cd, strp, opindex, valuep)
800      CGEN_CPU_DESC cd;
801      const char **strp;
802      int opindex;
803      long *valuep;
804 {
805   const char *errmsg;
806   enum cgen_parse_operand_result result_type;
807   bfd_vma value;
808  
809   /* Check for small data reference.  */
810   if (**strp == '#' || **strp == '%')
811     {
812       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
813         {
814           *strp += 9;
815           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
816                                        &result_type, &value);
817           if (**strp != ')')
818             return "missing `)'";
819           ++*strp;
820           *valuep = value;
821           return errmsg;
822         }
823     }
824   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
825 }
826
827 static const char *
828 parse_s12 (cd, strp, opindex, valuep)
829      CGEN_CPU_DESC cd;
830      const char **strp;
831      int opindex;
832      long *valuep;
833 {
834   const char *errmsg;
835   enum cgen_parse_operand_result result_type;
836   bfd_vma value;
837  
838   /* Check for small data reference.  */
839   if ((**strp == '#' || **strp == '%')
840       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
841     {
842       *strp += 9;
843       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
844                                     &result_type, &value);
845       if (**strp != ')')
846         return "missing `)'";
847       ++*strp;
848       *valuep = value;
849       return errmsg;
850     }
851   else
852     {
853       if (**strp == '#')
854         ++*strp;
855       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
856     }
857 }
858
859 static const char *
860 parse_u12 (cd, strp, opindex, valuep)
861      CGEN_CPU_DESC cd;
862      const char **strp;
863      int opindex;
864      long *valuep;
865 {
866   const char *errmsg;
867   enum cgen_parse_operand_result result_type;
868   bfd_vma value;
869  
870   /* Check for small data reference.  */
871   if ((**strp == '#' || **strp == '%')
872       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
873     {
874       *strp += 9;
875       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
876                                     &result_type, &value);
877       if (**strp != ')')
878         return "missing `)'";
879       ++*strp;
880       *valuep = value;
881       return errmsg;
882     }
883   else
884     {
885       if (**strp == '#')
886         ++*strp;
887       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
888     }
889 }
890
891 static const char *
892 parse_even_register (cd, strP, tableP, valueP)
893      CGEN_CPU_DESC  cd;
894      const char **  strP;
895      CGEN_KEYWORD * tableP;
896      long *         valueP;
897 {
898   const char * errmsg;
899   const char * saved_star_strP = * strP;
900
901   errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
902
903   if (errmsg == NULL && ((* valueP) & 1))
904     {
905       errmsg = _("register number must be even");
906       * strP = saved_star_strP;
907     }
908
909   return errmsg;
910 }
911 /* -- */
912 \f
913 /* -- dis.c */
914 static void print_spr
915   PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
916 static void print_hi
917   PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
918 static void print_lo
919   PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
920
921 static void
922 print_spr (cd, dis_info, names, regno, attrs)
923      CGEN_CPU_DESC cd;
924      PTR dis_info;
925      CGEN_KEYWORD *names;
926      long regno;
927      unsigned int attrs;
928 {
929   /* Use the register index format for any unnamed registers.  */
930   if (cgen_keyword_lookup_value (names, regno) == NULL)
931     {
932       disassemble_info *info = (disassemble_info *) dis_info;
933       (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
934     }
935   else
936     print_keyword (cd, dis_info, names, regno, attrs);
937 }
938
939 static void
940 print_hi (cd, dis_info, value, attrs, pc, length)
941      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
942      PTR dis_info;
943      long value;
944      unsigned int attrs ATTRIBUTE_UNUSED;
945      bfd_vma pc ATTRIBUTE_UNUSED;
946      int length ATTRIBUTE_UNUSED;
947 {
948   disassemble_info *info = (disassemble_info *) dis_info;
949   if (value)
950     (*info->fprintf_func) (info->stream, "0x%lx", value);
951   else
952     (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
953 }
954
955 static void
956 print_lo (cd, dis_info, value, attrs, pc, length)
957      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
958      PTR dis_info;
959      long value;
960      unsigned int attrs ATTRIBUTE_UNUSED;
961      bfd_vma pc ATTRIBUTE_UNUSED;
962      int length ATTRIBUTE_UNUSED;
963 {
964   disassemble_info *info = (disassemble_info *) dis_info;
965   if (value)
966     (*info->fprintf_func) (info->stream, "0x%lx", value);
967   else
968     (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
969 }
970
971 /* -- */