1 /* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*-
3 Copyright 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
5 Contributed by Red Hat Inc; developed under contract from Fujitsu.
7 This file is part of the GNU Binutils.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
24 /* This file is an addendum to frv.cpu. Heavy use of C code isn't
25 appropriate in .cpu files, so it resides here. This especially applies
26 to assembly/disassembly where parsing/printing can be quite involved.
27 Such things aren't really part of the specification of the cpu, per se,
28 so .cpu files provide the general framework and .opc files handle the
29 nitty-gritty details as necessary.
31 Each section is delimited with start and end markers.
33 <arch>-opc.h additions use: "-- opc.h"
34 <arch>-opc.c additions use: "-- opc.c"
35 <arch>-asm.c additions use: "-- asm.c"
36 <arch>-dis.c additions use: "-- dis.c"
37 <arch>-ibd.h additions use: "-- ibd.h". */
41 #undef CGEN_DIS_HASH_SIZE
42 #define CGEN_DIS_HASH_SIZE 128
44 #define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
46 /* Allows reason codes to be output when assembler errors occur. */
47 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
50 #define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8. */
51 #define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
53 typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
58 int constraint_violation;
60 unsigned long elf_flags;
61 CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping;
62 VLIW_COMBO * current_vliw;
63 CGEN_ATTR_VALUE_ENUM_TYPE major[FRV_VLIW_SIZE];
64 const CGEN_INSN * insn[FRV_VLIW_SIZE];
67 int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
68 int frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
69 int frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
70 int frv_is_branch_insn (const CGEN_INSN *);
71 int frv_is_float_insn (const CGEN_INSN *);
72 int frv_is_media_insn (const CGEN_INSN *);
73 void frv_vliw_reset (FRV_VLIW *, unsigned long, unsigned long);
74 int frv_vliw_add_insn (FRV_VLIW *, const CGEN_INSN *);
82 /* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
86 frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
91 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
95 if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
99 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
107 /* Returns TRUE if {MAJOR,MACH} supports floating point insns. */
110 frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
118 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
126 /* Returns TRUE if {MAJOR,MACH} supports media insns. */
129 frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
134 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
138 if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
142 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
151 frv_is_branch_insn (const CGEN_INSN *insn)
153 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
156 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
159 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
167 frv_is_float_insn (const CGEN_INSN *insn)
169 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
172 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
175 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
183 frv_is_media_insn (const CGEN_INSN *insn)
185 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
188 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
191 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
198 /* This table represents the allowable packing for vliw insns for the fr400.
199 The fr400 has only 2 vliw slots. Represent this by not allowing any insns
201 Subsets of any given row are also allowed. */
202 static VLIW_COMBO fr400_allowed_vliw[] =
204 /* slot0 slot1 slot2 slot3 */
205 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
206 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
207 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
208 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
209 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
210 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
211 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
212 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
215 /* This table represents the allowable packing for vliw insns for the fr500.
216 The fr500 has only 4 vliw slots. Represent this by not allowing any insns
218 Subsets of any given row are also allowed. */
219 static VLIW_COMBO fr500_allowed_vliw[] =
221 /* slot0 slot1 slot2 slot3 */
222 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO },
223 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO },
224 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO },
225 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
226 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
227 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
228 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
229 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
230 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
231 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
232 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
235 /* This table represents the allowable packing for vliw insns for the fr550.
236 Subsets of any given row are also allowed. */
237 static VLIW_COMBO fr550_allowed_vliw[] =
239 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */
240 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL },
241 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL },
242 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
243 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
244 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 },
245 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 },
246 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 },
247 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 },
248 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 },
249 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL },
250 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
251 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
252 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL },
253 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
254 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL },
255 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
256 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
257 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL },
258 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
259 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
260 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
261 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
262 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
263 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
264 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
265 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
266 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
267 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
270 /* Some insns are assigned specialized implementation units which map to
271 different actual implementation units on different machines. These
272 tables perform that mapping. */
273 static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
275 /* unit in insn actual unit */
280 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
282 /* IALL */ UNIT_I01, /* only I0 and I1 units */
285 /* FM01 */ UNIT_FM01,
286 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
287 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
288 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
289 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
290 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
294 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
295 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
296 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
297 /* STORE */ UNIT_I0, /* store only in I0 unit. */
298 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
299 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
300 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
301 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
302 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
305 /* Some insns are assigned specialized implementation units which map to
306 different actual implementation units on different machines. These
307 tables perform that mapping. */
308 static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
310 /* unit in insn actual unit */
315 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
317 /* IALL */ UNIT_I01, /* only I0 and I1 units */
320 /* FM01 */ UNIT_FM01,
321 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
322 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
323 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
324 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
325 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
329 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
330 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
331 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
332 /* STORE */ UNIT_I0, /* store only in I0 unit. */
333 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
334 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
335 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
336 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1. */
337 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
340 static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
342 /* unit in insn actual unit */
347 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
349 /* IALL */ UNIT_I01, /* only I0 and I1 units */
352 /* FM01 */ UNIT_FM01,
353 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
354 /* FM3 */ UNIT_NIL, /* no F3 or M2 units */
355 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
356 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
361 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
362 /* IACC */ UNIT_NIL, /* iacc multiply not implemented */
363 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
364 /* STORE */ UNIT_I0, /* store only in I0 unit. */
365 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
366 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
367 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
368 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
369 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
372 static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
374 /* unit in insn actual unit */
381 /* IALL */ UNIT_IALL,
384 /* FM01 */ UNIT_FM01,
387 /* FMALL */ UNIT_FMALL,
388 /* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */
393 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
394 /* IACC */ UNIT_NIL, /* iacc multiply not implemented. */
395 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
396 /* STORE */ UNIT_I01, /* store in I0 or I1 unit. */
397 /* SCAN */ UNIT_IALL, /* scan in any integer unit. */
398 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
399 /* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */
400 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1 unit. */
401 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
405 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
408 vliw->constraint_violation = 0;
410 vliw->elf_flags = elf_flags;
415 vliw->current_vliw = fr400_allowed_vliw;
416 vliw->unit_mapping = fr400_unit_mapping;
419 vliw->current_vliw = fr400_allowed_vliw;
420 vliw->unit_mapping = fr450_unit_mapping;
423 vliw->current_vliw = fr550_allowed_vliw;
424 vliw->unit_mapping = fr550_unit_mapping;
427 vliw->current_vliw = fr500_allowed_vliw;
428 vliw->unit_mapping = fr500_unit_mapping;
433 /* Return TRUE if unit1 is a match for unit2.
434 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
435 *_allowed_vliw tables above. */
437 match_unit (FRV_VLIW *vliw,
438 CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
440 /* Map any specialized implementation units to actual ones. */
441 unit1 = vliw->unit_mapping[unit1];
453 /* The 01 versions of these units are within 2 enums of the 0 or 1
455 if (unit1 - unit2 <= 2)
460 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
462 if (unit1 - unit2 <= 5)
472 /* Return TRUE if the vliws match, FALSE otherwise. */
475 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
479 for (i = 0; i < vliw_size; ++i)
480 if ((*vliw1)[i] != (*vliw2)[i])
486 /* Find the next vliw vliw in the table that can accomodate the new insn.
487 If one is found then return it. Otherwise return NULL. */
490 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
492 int next = vliw->next_slot;
493 VLIW_COMBO *current = vliw->current_vliw;
494 VLIW_COMBO *potential;
498 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
500 abort (); /* Should never happen. */
503 /* The table is sorted by units allowed within slots, so vliws with
504 identical starting sequences are together. */
508 if (match_unit (vliw, unit, (*potential)[next]))
512 while (match_vliw (potential, current, next));
517 /* Look for the given major insn type in the given vliw.
518 Returns TRUE if found, FALSE otherwise. */
521 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
525 for (i = 0; i < vliw->next_slot; ++i)
526 if (vliw->major[i] == major)
532 /* Check for constraints between the insns in the vliw due to major insn
536 fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
538 /* In the cpu file, all media insns are represented as being allowed in
539 both media units. This makes it easier since this is the case for fr500.
540 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
541 cannot coexist with any other media insn in a vliw. */
544 case FR400_MAJOR_M_2:
545 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
546 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
547 case FR400_MAJOR_M_1:
548 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
556 fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
558 CGEN_ATTR_VALUE_ENUM_TYPE other_major;
560 /* Our caller guarantees there's at least one other instruction. */
561 other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
563 /* (M4, M5) and (M4, M6) are allowed. */
564 if (other_major == FR450_MAJOR_M_4)
565 if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
568 /* Otherwise, instructions in even-numbered media categories cannot be
569 executed in parallel with other media instructions. */
572 case FR450_MAJOR_M_2:
573 case FR450_MAJOR_M_4:
574 case FR450_MAJOR_M_6:
575 return !(other_major >= FR450_MAJOR_M_1
576 && other_major <= FR450_MAJOR_M_6);
578 case FR450_MAJOR_M_1:
579 case FR450_MAJOR_M_3:
580 case FR450_MAJOR_M_5:
581 return !(other_major == FR450_MAJOR_M_2
582 || other_major == FR450_MAJOR_M_4
583 || other_major == FR450_MAJOR_M_6);
591 find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
595 for (i = 0; i < vliw->next_slot; ++i)
596 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
599 return FALSE; /* Not found. */
603 find_major_in_slot (FRV_VLIW *vliw,
604 CGEN_ATTR_VALUE_ENUM_TYPE major,
605 CGEN_ATTR_VALUE_ENUM_TYPE slot)
609 for (i = 0; i < vliw->next_slot; ++i)
610 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
617 fr550_find_media_in_vliw (FRV_VLIW *vliw)
621 for (i = 0; i < vliw->next_slot; ++i)
623 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
626 /* Found a media insn, however, MNOP and MCLRACC don't count. */
627 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
628 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
629 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
632 return TRUE; /* Found one. */
639 fr550_find_float_in_vliw (FRV_VLIW *vliw)
643 for (i = 0; i < vliw->next_slot; ++i)
645 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
648 /* Found a floating point insn, however, FNOP doesn't count. */
649 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
652 return TRUE; /* Found one. */
659 fr550_check_insn_major_constraints (FRV_VLIW *vliw,
660 CGEN_ATTR_VALUE_ENUM_TYPE major,
661 const CGEN_INSN *insn)
663 CGEN_ATTR_VALUE_ENUM_TYPE unit;
664 CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
668 /* If it's a store, then there must be another store in I1 */
669 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
670 if (unit == UNIT_STORE)
671 return find_unit_in_vliw (vliw, UNIT_STORE);
675 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
677 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
678 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
679 return ! fr550_find_media_in_vliw (vliw);
680 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
681 floating point insns. */
682 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
683 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
684 return ! fr550_find_float_in_vliw (vliw);
685 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
687 if (major == FR550_MAJOR_F_2)
688 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
689 slot - (UNIT_FM2 - UNIT_FM0))
690 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
691 slot - (UNIT_FM2 - UNIT_FM0));
692 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
694 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
695 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
696 slot - (UNIT_FM2 - UNIT_FM0));
697 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
699 if (major == FR550_MAJOR_M_4)
700 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
701 slot - (UNIT_FM2 - UNIT_FM0));
706 return TRUE; /* All OK. */
710 fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
712 /* TODO: A table might be faster for some of the more complex instances
716 case FR500_MAJOR_I_1:
717 case FR500_MAJOR_I_4:
718 case FR500_MAJOR_I_5:
719 case FR500_MAJOR_I_6:
720 case FR500_MAJOR_B_1:
721 case FR500_MAJOR_B_2:
722 case FR500_MAJOR_B_3:
723 case FR500_MAJOR_B_4:
724 case FR500_MAJOR_B_5:
725 case FR500_MAJOR_B_6:
726 case FR500_MAJOR_F_4:
727 case FR500_MAJOR_F_8:
728 case FR500_MAJOR_M_8:
729 return TRUE; /* OK */
730 case FR500_MAJOR_I_2:
731 /* Cannot coexist with I-3 insn. */
732 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
733 case FR500_MAJOR_I_3:
734 /* Cannot coexist with I-2 insn. */
735 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
736 case FR500_MAJOR_F_1:
737 case FR500_MAJOR_F_2:
738 /* Cannot coexist with F-5, F-6, or M-7 insn. */
739 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
740 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
741 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
742 case FR500_MAJOR_F_3:
743 /* Cannot coexist with F-7, or M-7 insn. */
744 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
745 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
746 case FR500_MAJOR_F_5:
747 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
748 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
749 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
750 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
751 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
752 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
753 case FR500_MAJOR_F_6:
754 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
755 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
756 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
757 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
758 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
759 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
760 case FR500_MAJOR_F_7:
761 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
762 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
763 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
764 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
765 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
766 case FR500_MAJOR_M_1:
767 /* Cannot coexist with M-7 insn. */
768 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
769 case FR500_MAJOR_M_2:
770 case FR500_MAJOR_M_3:
771 /* Cannot coexist with M-5, M-6 or M-7 insn. */
772 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
773 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
774 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
775 case FR500_MAJOR_M_4:
776 /* Cannot coexist with M-6 insn. */
777 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
778 case FR500_MAJOR_M_5:
779 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
780 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
781 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
782 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
783 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
784 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
785 case FR500_MAJOR_M_6:
786 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
787 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
788 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
789 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
790 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
791 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
792 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
793 case FR500_MAJOR_M_7:
794 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
795 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
796 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
797 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
798 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
799 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
800 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
801 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
802 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
803 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
804 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
805 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
806 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
808 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
817 check_insn_major_constraints (FRV_VLIW *vliw,
818 CGEN_ATTR_VALUE_ENUM_TYPE major,
819 const CGEN_INSN *insn)
824 return fr400_check_insn_major_constraints (vliw, major);
827 return fr450_check_insn_major_constraints (vliw, major);
830 return fr550_check_insn_major_constraints (vliw, major, insn);
833 return fr500_check_insn_major_constraints (vliw, major);
837 /* Add in insn to the VLIW vliw if possible.
838 Return 0 if successful, non-zero otherwise. */
841 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
844 CGEN_ATTR_VALUE_ENUM_TYPE major;
845 CGEN_ATTR_VALUE_ENUM_TYPE unit;
846 VLIW_COMBO *new_vliw;
848 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
851 index = vliw->next_slot;
852 if (index >= FRV_VLIW_SIZE)
855 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
856 if (unit == UNIT_NIL)
858 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
860 abort (); /* No UNIT specified for this insn in frv.cpu. */
866 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
869 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
872 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
875 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
881 /* Any insn can be added to slot 0. */
882 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
883 ++vliw->current_vliw;
884 vliw->major[0] = major;
885 vliw->insn[0] = insn;
890 /* If there are already insns in the vliw(s) check to see that
891 this one can be added. Do this by finding an allowable vliw
892 combination that can accept the new insn. */
893 if (! (vliw->elf_flags & EF_FRV_NOPACK))
895 new_vliw = add_next_to_vliw (vliw, unit);
896 if (new_vliw && check_insn_major_constraints (vliw, major, insn))
898 vliw->current_vliw = new_vliw;
899 vliw->major[index] = major;
900 vliw->insn[index] = insn;
905 /* The frv machine supports all packing conbinations. If we fail,
906 to add the insn, then it could not be handled as if it was the fr500.
907 Just return as if it was handled ok. */
908 if (vliw->mach == bfd_mach_frv)
912 vliw->constraint_violation = 1;
917 spr_valid (long regno)
919 if (regno < 0) return FALSE;
920 if (regno <= 4095) return TRUE;
926 inline static const char *
927 parse_symbolic_address (CGEN_CPU_DESC cd,
931 enum cgen_parse_operand_result *resultp,
934 enum cgen_parse_operand_result result_type;
935 const char *errmsg = (* cd->parse_operand_fn)
936 (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
937 &result_type, valuep);
940 && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
941 return "symbolic expression required";
944 *resultp = result_type;
950 parse_ldd_annotation (CGEN_CPU_DESC cd,
953 unsigned long *valuep)
956 enum cgen_parse_operand_result result_type;
959 if (**strp == '#' || **strp == '%')
961 if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
964 errmsg = parse_symbolic_address (cd, strp, opindex,
965 BFD_RELOC_FRV_TLSDESC_RELAX,
966 &result_type, &value);
968 return "missing ')'";
977 while (**strp == ' ' || **strp == '\t')
981 return "missing `@'";
989 parse_call_annotation (CGEN_CPU_DESC cd,
992 unsigned long *valuep)
995 enum cgen_parse_operand_result result_type;
998 if (**strp == '#' || **strp == '%')
1000 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1003 errmsg = parse_symbolic_address (cd, strp, opindex,
1004 BFD_RELOC_FRV_GETTLSOFF_RELAX,
1005 &result_type, &value);
1007 return "missing ')'";
1016 while (**strp == ' ' || **strp == '\t')
1020 return "missing `@'";
1028 parse_ld_annotation (CGEN_CPU_DESC cd,
1031 unsigned long *valuep)
1034 enum cgen_parse_operand_result result_type;
1037 if (**strp == '#' || **strp == '%')
1039 if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
1042 errmsg = parse_symbolic_address (cd, strp, opindex,
1043 BFD_RELOC_FRV_TLSOFF_RELAX,
1044 &result_type, &value);
1046 return "missing ')'";
1055 while (**strp == ' ' || **strp == '\t')
1059 return "missing `@'";
1067 parse_ulo16 (CGEN_CPU_DESC cd,
1070 unsigned long *valuep)
1073 enum cgen_parse_operand_result result_type;
1076 if (**strp == '#' || **strp == '%')
1078 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1081 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1082 & result_type, & value);
1084 return "missing `)'";
1087 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1092 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1095 errmsg = parse_symbolic_address (cd, strp, opindex,
1096 BFD_RELOC_FRV_GPRELLO,
1097 & result_type, & value);
1099 return "missing ')'";
1104 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1107 errmsg = parse_symbolic_address (cd, strp, opindex,
1108 BFD_RELOC_FRV_GOTLO,
1109 & result_type, & value);
1111 return "missing ')'";
1116 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1119 errmsg = parse_symbolic_address (cd, strp, opindex,
1120 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1121 & result_type, & value);
1123 return "missing ')'";
1128 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1131 errmsg = parse_symbolic_address (cd, strp, opindex,
1132 BFD_RELOC_FRV_GOTOFFLO,
1133 & result_type, & value);
1135 return "missing ')'";
1140 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1143 errmsg = parse_symbolic_address (cd, strp, opindex,
1144 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1145 & result_type, & value);
1147 return "missing ')'";
1152 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1155 errmsg = parse_symbolic_address (cd, strp, opindex,
1156 BFD_RELOC_FRV_GOTTLSDESCLO,
1157 & result_type, & value);
1159 return "missing ')'";
1164 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1167 errmsg = parse_symbolic_address (cd, strp, opindex,
1168 BFD_RELOC_FRV_TLSMOFFLO,
1169 & result_type, & value);
1171 return "missing ')'";
1176 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1179 errmsg = parse_symbolic_address (cd, strp, opindex,
1180 BFD_RELOC_FRV_GOTTLSOFFLO,
1181 & result_type, & value);
1183 return "missing ')'";
1189 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1193 parse_uslo16 (CGEN_CPU_DESC cd,
1196 signed long *valuep)
1199 enum cgen_parse_operand_result result_type;
1202 if (**strp == '#' || **strp == '%')
1204 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1207 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1208 & result_type, & value);
1210 return "missing `)'";
1213 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1218 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1221 errmsg = parse_symbolic_address (cd, strp, opindex,
1222 BFD_RELOC_FRV_GPRELLO,
1223 & result_type, & value);
1225 return "missing ')'";
1230 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1233 errmsg = parse_symbolic_address (cd, strp, opindex,
1234 BFD_RELOC_FRV_GOTLO,
1235 & result_type, & value);
1237 return "missing ')'";
1242 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1245 errmsg = parse_symbolic_address (cd, strp, opindex,
1246 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1247 & result_type, & value);
1249 return "missing ')'";
1254 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1257 errmsg = parse_symbolic_address (cd, strp, opindex,
1258 BFD_RELOC_FRV_GOTOFFLO,
1259 & result_type, & value);
1261 return "missing ')'";
1266 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1269 errmsg = parse_symbolic_address (cd, strp, opindex,
1270 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1271 & result_type, & value);
1273 return "missing ')'";
1278 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1281 errmsg = parse_symbolic_address (cd, strp, opindex,
1282 BFD_RELOC_FRV_GOTTLSDESCLO,
1283 & result_type, & value);
1285 return "missing ')'";
1290 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1293 errmsg = parse_symbolic_address (cd, strp, opindex,
1294 BFD_RELOC_FRV_TLSMOFFLO,
1295 & result_type, & value);
1297 return "missing ')'";
1302 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1305 errmsg = parse_symbolic_address (cd, strp, opindex,
1306 BFD_RELOC_FRV_GOTTLSOFFLO,
1307 & result_type, & value);
1309 return "missing ')'";
1315 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1319 parse_uhi16 (CGEN_CPU_DESC cd,
1322 unsigned long *valuep)
1325 enum cgen_parse_operand_result result_type;
1328 if (**strp == '#' || **strp == '%')
1330 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1333 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1334 & result_type, & value);
1336 return "missing `)'";
1339 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1341 /* If bfd_vma is wider than 32 bits, but we have a sign-
1342 or zero-extension, truncate it. */
1343 if (value >= - ((bfd_vma)1 << 31)
1344 || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
1345 value &= (((bfd_vma)1 << 16) << 16) - 1;
1351 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1354 errmsg = parse_symbolic_address (cd, strp, opindex,
1355 BFD_RELOC_FRV_GPRELHI,
1356 & result_type, & value);
1358 return "missing ')'";
1363 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1366 errmsg = parse_symbolic_address (cd, strp, opindex,
1367 BFD_RELOC_FRV_GOTHI,
1368 & result_type, & value);
1370 return "missing ')'";
1375 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1378 errmsg = parse_symbolic_address (cd, strp, opindex,
1379 BFD_RELOC_FRV_FUNCDESC_GOTHI,
1380 & result_type, & value);
1382 return "missing ')'";
1387 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1390 errmsg = parse_symbolic_address (cd, strp, opindex,
1391 BFD_RELOC_FRV_GOTOFFHI,
1392 & result_type, & value);
1394 return "missing ')'";
1399 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1402 errmsg = parse_symbolic_address (cd, strp, opindex,
1403 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1404 & result_type, & value);
1406 return "missing ')'";
1411 else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
1414 errmsg = parse_symbolic_address (cd, strp, opindex,
1415 BFD_RELOC_FRV_GOTTLSDESCHI,
1416 &result_type, &value);
1418 return "missing ')'";
1423 else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
1426 errmsg = parse_symbolic_address (cd, strp, opindex,
1427 BFD_RELOC_FRV_TLSMOFFHI,
1428 & result_type, & value);
1430 return "missing ')'";
1435 else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
1438 errmsg = parse_symbolic_address (cd, strp, opindex,
1439 BFD_RELOC_FRV_GOTTLSOFFHI,
1440 & result_type, & value);
1442 return "missing ')'";
1448 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1452 parse_register_number (const char **strp)
1456 if (**strp < '0' || **strp > '9')
1457 return -1; /* error */
1459 regno = **strp - '0';
1460 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1461 regno = regno * 10 + (**strp - '0');
1467 parse_spr (CGEN_CPU_DESC cd,
1469 CGEN_KEYWORD * table,
1472 const char *save_strp;
1475 /* Check for spr index notation. */
1476 if (strncasecmp (*strp, "spr[", 4) == 0)
1479 regno = parse_register_number (strp);
1481 return _("missing `]'");
1483 if (! spr_valid (regno))
1484 return _("Special purpose register number is out of range");
1490 regno = parse_register_number (strp);
1493 if (! spr_valid (regno))
1494 return _("Special purpose register number is out of range");
1500 return cgen_parse_keyword (cd, strp, table, valuep);
1504 parse_d12 (CGEN_CPU_DESC cd,
1510 enum cgen_parse_operand_result result_type;
1513 /* Check for small data reference. */
1514 if (**strp == '#' || **strp == '%')
1516 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1519 errmsg = parse_symbolic_address (cd, strp, opindex,
1520 BFD_RELOC_FRV_GPREL12,
1521 & result_type, & value);
1523 return "missing `)'";
1528 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1531 errmsg = parse_symbolic_address (cd, strp, opindex,
1532 BFD_RELOC_FRV_GOT12,
1533 & result_type, & value);
1535 return "missing ')'";
1540 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1543 errmsg = parse_symbolic_address (cd, strp, opindex,
1544 BFD_RELOC_FRV_FUNCDESC_GOT12,
1545 & result_type, & value);
1547 return "missing ')'";
1552 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1555 errmsg = parse_symbolic_address (cd, strp, opindex,
1556 BFD_RELOC_FRV_GOTOFF12,
1557 & result_type, & value);
1559 return "missing ')'";
1564 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1567 errmsg = parse_symbolic_address (cd, strp, opindex,
1568 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1569 & result_type, & value);
1571 return "missing ')'";
1576 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1579 errmsg = parse_symbolic_address (cd, strp, opindex,
1580 BFD_RELOC_FRV_GOTTLSDESC12,
1581 & result_type, & value);
1583 return "missing ')'";
1588 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1591 errmsg = parse_symbolic_address (cd, strp, opindex,
1592 BFD_RELOC_FRV_TLSMOFF12,
1593 & result_type, & value);
1595 return "missing ')'";
1600 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1603 errmsg = parse_symbolic_address (cd, strp, opindex,
1604 BFD_RELOC_FRV_GOTTLSOFF12,
1605 & result_type, & value);
1607 return "missing ')'";
1613 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1617 parse_s12 (CGEN_CPU_DESC cd,
1623 enum cgen_parse_operand_result result_type;
1626 /* Check for small data reference. */
1627 if (**strp == '#' || **strp == '%')
1629 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1632 errmsg = parse_symbolic_address (cd, strp, opindex,
1633 BFD_RELOC_FRV_GPREL12,
1634 & result_type, & value);
1636 return "missing `)'";
1641 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1644 errmsg = parse_symbolic_address (cd, strp, opindex,
1645 BFD_RELOC_FRV_GOT12,
1646 & result_type, & value);
1648 return "missing ')'";
1653 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1656 errmsg = parse_symbolic_address (cd, strp, opindex,
1657 BFD_RELOC_FRV_FUNCDESC_GOT12,
1658 & result_type, & value);
1660 return "missing ')'";
1665 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1668 errmsg = parse_symbolic_address (cd, strp, opindex,
1669 BFD_RELOC_FRV_GOTOFF12,
1670 & result_type, & value);
1672 return "missing ')'";
1677 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1680 errmsg = parse_symbolic_address (cd, strp, opindex,
1681 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1682 & result_type, & value);
1684 return "missing ')'";
1689 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1692 errmsg = parse_symbolic_address (cd, strp, opindex,
1693 BFD_RELOC_FRV_GOTTLSDESC12,
1694 & result_type, & value);
1696 return "missing ')'";
1701 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1704 errmsg = parse_symbolic_address (cd, strp, opindex,
1705 BFD_RELOC_FRV_TLSMOFF12,
1706 & result_type, & value);
1708 return "missing ')'";
1713 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1716 errmsg = parse_symbolic_address (cd, strp, opindex,
1717 BFD_RELOC_FRV_GOTTLSOFF12,
1718 & result_type, & value);
1720 return "missing ')'";
1729 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1733 parse_u12 (CGEN_CPU_DESC cd,
1739 enum cgen_parse_operand_result result_type;
1742 /* Check for small data reference. */
1743 if ((**strp == '#' || **strp == '%')
1744 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1747 errmsg = parse_symbolic_address (cd, strp, opindex,
1748 BFD_RELOC_FRV_GPRELU12,
1749 & result_type, & value);
1751 return "missing `)'";
1760 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1765 parse_A (CGEN_CPU_DESC cd,
1768 unsigned long *valuep,
1776 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1781 return _("Value of A operand must be 0 or 1");
1787 parse_A0 (CGEN_CPU_DESC cd,
1790 unsigned long *valuep)
1792 return parse_A (cd, strp, opindex, valuep, 0);
1796 parse_A1 (CGEN_CPU_DESC cd,
1799 unsigned long *valuep)
1801 return parse_A (cd, strp, opindex, valuep, 1);
1805 parse_even_register (CGEN_CPU_DESC cd,
1807 CGEN_KEYWORD * tableP,
1810 const char * errmsg;
1811 const char * saved_star_strP = * strP;
1813 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1815 if (errmsg == NULL && ((* valueP) & 1))
1817 errmsg = _("register number must be even");
1818 * strP = saved_star_strP;
1825 parse_call_label (CGEN_CPU_DESC cd,
1829 enum cgen_parse_operand_result *resultp,
1835 /* Check for small data reference. */
1836 if (opinfo == 0 && (**strp == '#' || **strp == '%'))
1838 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1841 errmsg = parse_symbolic_address (cd, strp, opindex,
1842 BFD_RELOC_FRV_GETTLSOFF,
1845 return _("missing `)'");
1852 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
1859 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1861 long reloc_ann ATTRIBUTE_UNUSED,
1862 long value ATTRIBUTE_UNUSED,
1863 bfd_vma pc ATTRIBUTE_UNUSED,
1864 int length ATTRIBUTE_UNUSED)
1866 disassemble_info *info = (disassemble_info *) dis_info;
1868 (*info->fprintf_func) (info->stream, "@");
1872 print_spr (CGEN_CPU_DESC cd,
1874 CGEN_KEYWORD *names,
1878 /* Use the register index format for any unnamed registers. */
1879 if (cgen_keyword_lookup_value (names, regno) == NULL)
1881 disassemble_info *info = (disassemble_info *) dis_info;
1882 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1885 print_keyword (cd, dis_info, names, regno, attrs);
1889 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1892 unsigned int attrs ATTRIBUTE_UNUSED,
1893 bfd_vma pc ATTRIBUTE_UNUSED,
1894 int length ATTRIBUTE_UNUSED)
1896 disassemble_info *info = (disassemble_info *) dis_info;
1898 (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
1902 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1905 unsigned int attrs ATTRIBUTE_UNUSED,
1906 bfd_vma pc ATTRIBUTE_UNUSED,
1907 int length ATTRIBUTE_UNUSED)
1909 disassemble_info *info = (disassemble_info *) dis_info;
1911 (*info->fprintf_func) (info->stream, "0x%lx", value);
1913 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);