1 /* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*-
3 Copyright 2000, 2001, 2003, 2004, 2005, 2007, 2009
4 Free Software Foundation, Inc.
6 Contributed by Red Hat Inc; developed under contract from Fujitsu.
8 This file is part of the GNU Binutils.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
26 /* This file is an addendum to frv.cpu. Heavy use of C code isn't
27 appropriate in .cpu files, so it resides here. This especially applies
28 to assembly/disassembly where parsing/printing can be quite involved.
29 Such things aren't really part of the specification of the cpu, per se,
30 so .cpu files provide the general framework and .opc files handle the
31 nitty-gritty details as necessary.
33 Each section is delimited with start and end markers.
35 <arch>-opc.h additions use: "-- opc.h"
36 <arch>-opc.c additions use: "-- opc.c"
37 <arch>-asm.c additions use: "-- asm.c"
38 <arch>-dis.c additions use: "-- dis.c"
39 <arch>-ibd.h additions use: "-- ibd.h". */
43 #undef CGEN_DIS_HASH_SIZE
44 #define CGEN_DIS_HASH_SIZE 128
46 #define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
48 /* Allows reason codes to be output when assembler errors occur. */
49 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
52 #define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8. */
53 #define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
55 typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
60 int constraint_violation;
62 unsigned long elf_flags;
63 CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping;
64 VLIW_COMBO * current_vliw;
65 CGEN_ATTR_VALUE_ENUM_TYPE major[FRV_VLIW_SIZE];
66 const CGEN_INSN * insn[FRV_VLIW_SIZE];
69 int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
70 int frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
71 int frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
72 int frv_is_branch_insn (const CGEN_INSN *);
73 int frv_is_float_insn (const CGEN_INSN *);
74 int frv_is_media_insn (const CGEN_INSN *);
75 void frv_vliw_reset (FRV_VLIW *, unsigned long, unsigned long);
76 int frv_vliw_add_insn (FRV_VLIW *, const CGEN_INSN *);
84 /* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
88 frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
93 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
97 if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
101 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
109 /* Returns TRUE if {MAJOR,MACH} supports floating point insns. */
112 frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
120 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
128 /* Returns TRUE if {MAJOR,MACH} supports media insns. */
131 frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
136 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
140 if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
144 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
153 frv_is_branch_insn (const CGEN_INSN *insn)
155 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
158 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
161 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
169 frv_is_float_insn (const CGEN_INSN *insn)
171 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
174 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
177 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
185 frv_is_media_insn (const CGEN_INSN *insn)
187 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
190 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
193 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
200 /* This table represents the allowable packing for vliw insns for the fr400.
201 The fr400 has only 2 vliw slots. Represent this by not allowing any insns
203 Subsets of any given row are also allowed. */
204 static VLIW_COMBO fr400_allowed_vliw[] =
206 /* slot0 slot1 slot2 slot3 */
207 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
208 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
209 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
210 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
211 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
212 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
213 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
214 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
217 /* This table represents the allowable packing for vliw insns for the fr500.
218 The fr500 has only 4 vliw slots. Represent this by not allowing any insns
220 Subsets of any given row are also allowed. */
221 static VLIW_COMBO fr500_allowed_vliw[] =
223 /* slot0 slot1 slot2 slot3 */
224 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO },
225 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO },
226 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO },
227 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
228 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
229 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
230 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
231 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
232 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
233 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
234 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
237 /* This table represents the allowable packing for vliw insns for the fr550.
238 Subsets of any given row are also allowed. */
239 static VLIW_COMBO fr550_allowed_vliw[] =
241 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */
242 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL },
243 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL },
244 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
245 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
246 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 },
247 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 },
248 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 },
249 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 },
250 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 },
251 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL },
252 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
253 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
254 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL },
255 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
256 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL },
257 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
258 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
259 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL },
260 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
261 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
262 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
263 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
264 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
265 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
266 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
267 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
268 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
269 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
272 /* Some insns are assigned specialized implementation units which map to
273 different actual implementation units on different machines. These
274 tables perform that mapping. */
275 static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
277 /* unit in insn actual unit */
282 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
284 /* IALL */ UNIT_I01, /* only I0 and I1 units */
287 /* FM01 */ UNIT_FM01,
288 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
289 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
290 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
291 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
292 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
296 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
297 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
298 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
299 /* STORE */ UNIT_I0, /* store only in I0 unit. */
300 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
301 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
302 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
303 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
304 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
307 /* Some insns are assigned specialized implementation units which map to
308 different actual implementation units on different machines. These
309 tables perform that mapping. */
310 static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
312 /* unit in insn actual unit */
317 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
319 /* IALL */ UNIT_I01, /* only I0 and I1 units */
322 /* FM01 */ UNIT_FM01,
323 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
324 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
325 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
326 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
327 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
331 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
332 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
333 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
334 /* STORE */ UNIT_I0, /* store only in I0 unit. */
335 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
336 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
337 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
338 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1. */
339 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
342 static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
344 /* unit in insn actual unit */
349 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
351 /* IALL */ UNIT_I01, /* only I0 and I1 units */
354 /* FM01 */ UNIT_FM01,
355 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
356 /* FM3 */ UNIT_NIL, /* no F3 or M2 units */
357 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
358 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
363 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
364 /* IACC */ UNIT_NIL, /* iacc multiply not implemented */
365 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
366 /* STORE */ UNIT_I0, /* store only in I0 unit. */
367 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
368 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
369 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
370 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
371 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
374 static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
376 /* unit in insn actual unit */
383 /* IALL */ UNIT_IALL,
386 /* FM01 */ UNIT_FM01,
389 /* FMALL */ UNIT_FMALL,
390 /* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */
395 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
396 /* IACC */ UNIT_NIL, /* iacc multiply not implemented. */
397 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
398 /* STORE */ UNIT_I01, /* store in I0 or I1 unit. */
399 /* SCAN */ UNIT_IALL, /* scan in any integer unit. */
400 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
401 /* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */
402 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1 unit. */
403 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
407 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
410 vliw->constraint_violation = 0;
412 vliw->elf_flags = elf_flags;
417 vliw->current_vliw = fr400_allowed_vliw;
418 vliw->unit_mapping = fr400_unit_mapping;
421 vliw->current_vliw = fr400_allowed_vliw;
422 vliw->unit_mapping = fr450_unit_mapping;
425 vliw->current_vliw = fr550_allowed_vliw;
426 vliw->unit_mapping = fr550_unit_mapping;
429 vliw->current_vliw = fr500_allowed_vliw;
430 vliw->unit_mapping = fr500_unit_mapping;
435 /* Return TRUE if unit1 is a match for unit2.
436 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
437 *_allowed_vliw tables above. */
439 match_unit (FRV_VLIW *vliw,
440 CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
442 /* Map any specialized implementation units to actual ones. */
443 unit1 = vliw->unit_mapping[unit1];
455 /* The 01 versions of these units are within 2 enums of the 0 or 1
457 if (unit1 - unit2 <= 2)
462 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
464 if (unit1 - unit2 <= 5)
474 /* Return TRUE if the vliws match, FALSE otherwise. */
477 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
481 for (i = 0; i < vliw_size; ++i)
482 if ((*vliw1)[i] != (*vliw2)[i])
488 /* Find the next vliw vliw in the table that can accomodate the new insn.
489 If one is found then return it. Otherwise return NULL. */
492 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
494 int next = vliw->next_slot;
495 VLIW_COMBO *current = vliw->current_vliw;
496 VLIW_COMBO *potential;
500 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
502 abort (); /* Should never happen. */
505 /* The table is sorted by units allowed within slots, so vliws with
506 identical starting sequences are together. */
510 if (match_unit (vliw, unit, (*potential)[next]))
514 while (match_vliw (potential, current, next));
519 /* Look for the given major insn type in the given vliw.
520 Returns TRUE if found, FALSE otherwise. */
523 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
527 for (i = 0; i < vliw->next_slot; ++i)
528 if (vliw->major[i] == major)
534 /* Check for constraints between the insns in the vliw due to major insn
538 fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
540 /* In the cpu file, all media insns are represented as being allowed in
541 both media units. This makes it easier since this is the case for fr500.
542 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
543 cannot coexist with any other media insn in a vliw. */
546 case FR400_MAJOR_M_2:
547 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
548 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
549 case FR400_MAJOR_M_1:
550 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
558 fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
560 CGEN_ATTR_VALUE_ENUM_TYPE other_major;
562 /* Our caller guarantees there's at least one other instruction. */
563 other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
565 /* (M4, M5) and (M4, M6) are allowed. */
566 if (other_major == FR450_MAJOR_M_4)
567 if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
570 /* Otherwise, instructions in even-numbered media categories cannot be
571 executed in parallel with other media instructions. */
574 case FR450_MAJOR_M_2:
575 case FR450_MAJOR_M_4:
576 case FR450_MAJOR_M_6:
577 return !(other_major >= FR450_MAJOR_M_1
578 && other_major <= FR450_MAJOR_M_6);
580 case FR450_MAJOR_M_1:
581 case FR450_MAJOR_M_3:
582 case FR450_MAJOR_M_5:
583 return !(other_major == FR450_MAJOR_M_2
584 || other_major == FR450_MAJOR_M_4
585 || other_major == FR450_MAJOR_M_6);
593 find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
597 for (i = 0; i < vliw->next_slot; ++i)
598 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
601 return FALSE; /* Not found. */
605 find_major_in_slot (FRV_VLIW *vliw,
606 CGEN_ATTR_VALUE_ENUM_TYPE major,
607 CGEN_ATTR_VALUE_ENUM_TYPE slot)
611 for (i = 0; i < vliw->next_slot; ++i)
612 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
619 fr550_find_media_in_vliw (FRV_VLIW *vliw)
623 for (i = 0; i < vliw->next_slot; ++i)
625 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
628 /* Found a media insn, however, MNOP and MCLRACC don't count. */
629 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
630 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
631 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
634 return TRUE; /* Found one. */
641 fr550_find_float_in_vliw (FRV_VLIW *vliw)
645 for (i = 0; i < vliw->next_slot; ++i)
647 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
650 /* Found a floating point insn, however, FNOP doesn't count. */
651 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
654 return TRUE; /* Found one. */
661 fr550_check_insn_major_constraints (FRV_VLIW *vliw,
662 CGEN_ATTR_VALUE_ENUM_TYPE major,
663 const CGEN_INSN *insn)
665 CGEN_ATTR_VALUE_ENUM_TYPE unit;
666 CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
670 /* If it's a store, then there must be another store in I1 */
671 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
672 if (unit == UNIT_STORE)
673 return find_unit_in_vliw (vliw, UNIT_STORE);
677 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
679 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
680 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
681 return ! fr550_find_media_in_vliw (vliw);
682 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
683 floating point insns. */
684 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
685 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
686 return ! fr550_find_float_in_vliw (vliw);
687 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
689 if (major == FR550_MAJOR_F_2)
690 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
691 slot - (UNIT_FM2 - UNIT_FM0))
692 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
693 slot - (UNIT_FM2 - UNIT_FM0));
694 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
696 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
697 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
698 slot - (UNIT_FM2 - UNIT_FM0));
699 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
701 if (major == FR550_MAJOR_M_4)
702 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
703 slot - (UNIT_FM2 - UNIT_FM0));
708 return TRUE; /* All OK. */
712 fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
714 /* TODO: A table might be faster for some of the more complex instances
718 case FR500_MAJOR_I_1:
719 case FR500_MAJOR_I_4:
720 case FR500_MAJOR_I_5:
721 case FR500_MAJOR_I_6:
722 case FR500_MAJOR_B_1:
723 case FR500_MAJOR_B_2:
724 case FR500_MAJOR_B_3:
725 case FR500_MAJOR_B_4:
726 case FR500_MAJOR_B_5:
727 case FR500_MAJOR_B_6:
728 case FR500_MAJOR_F_4:
729 case FR500_MAJOR_F_8:
730 case FR500_MAJOR_M_8:
731 return TRUE; /* OK */
732 case FR500_MAJOR_I_2:
733 /* Cannot coexist with I-3 insn. */
734 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
735 case FR500_MAJOR_I_3:
736 /* Cannot coexist with I-2 insn. */
737 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
738 case FR500_MAJOR_F_1:
739 case FR500_MAJOR_F_2:
740 /* Cannot coexist with F-5, F-6, or M-7 insn. */
741 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
742 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
743 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
744 case FR500_MAJOR_F_3:
745 /* Cannot coexist with F-7, or M-7 insn. */
746 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
747 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
748 case FR500_MAJOR_F_5:
749 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
750 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
751 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
752 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
753 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
754 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
755 case FR500_MAJOR_F_6:
756 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
757 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
758 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
759 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
760 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
761 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
762 case FR500_MAJOR_F_7:
763 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
764 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
765 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
766 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
767 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
768 case FR500_MAJOR_M_1:
769 /* Cannot coexist with M-7 insn. */
770 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
771 case FR500_MAJOR_M_2:
772 case FR500_MAJOR_M_3:
773 /* Cannot coexist with M-5, M-6 or M-7 insn. */
774 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
775 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
776 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
777 case FR500_MAJOR_M_4:
778 /* Cannot coexist with M-6 insn. */
779 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
780 case FR500_MAJOR_M_5:
781 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
782 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
783 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
784 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
785 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
786 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
787 case FR500_MAJOR_M_6:
788 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
789 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
790 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
791 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
792 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
793 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
794 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
795 case FR500_MAJOR_M_7:
796 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
797 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
798 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
799 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
800 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
801 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
802 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
803 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
804 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
805 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
806 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
807 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
808 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
810 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
819 check_insn_major_constraints (FRV_VLIW *vliw,
820 CGEN_ATTR_VALUE_ENUM_TYPE major,
821 const CGEN_INSN *insn)
826 return fr400_check_insn_major_constraints (vliw, major);
829 return fr450_check_insn_major_constraints (vliw, major);
832 return fr550_check_insn_major_constraints (vliw, major, insn);
835 return fr500_check_insn_major_constraints (vliw, major);
839 /* Add in insn to the VLIW vliw if possible.
840 Return 0 if successful, non-zero otherwise. */
843 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
846 CGEN_ATTR_VALUE_ENUM_TYPE major;
847 CGEN_ATTR_VALUE_ENUM_TYPE unit;
848 VLIW_COMBO *new_vliw;
850 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
853 slot_index = vliw->next_slot;
854 if (slot_index >= FRV_VLIW_SIZE)
857 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
858 if (unit == UNIT_NIL)
860 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
862 abort (); /* No UNIT specified for this insn in frv.cpu. */
868 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
871 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
874 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
877 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
883 /* Any insn can be added to slot 0. */
884 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
885 ++vliw->current_vliw;
886 vliw->major[0] = major;
887 vliw->insn[0] = insn;
892 /* If there are already insns in the vliw(s) check to see that
893 this one can be added. Do this by finding an allowable vliw
894 combination that can accept the new insn. */
895 if (! (vliw->elf_flags & EF_FRV_NOPACK))
897 new_vliw = add_next_to_vliw (vliw, unit);
898 if (new_vliw && check_insn_major_constraints (vliw, major, insn))
900 vliw->current_vliw = new_vliw;
901 vliw->major[slot_index] = major;
902 vliw->insn[slot_index] = insn;
907 /* The frv machine supports all packing conbinations. If we fail,
908 to add the insn, then it could not be handled as if it was the fr500.
909 Just return as if it was handled ok. */
910 if (vliw->mach == bfd_mach_frv)
914 vliw->constraint_violation = 1;
919 spr_valid (long regno)
921 if (regno < 0) return FALSE;
922 if (regno <= 4095) return TRUE;
928 inline static const char *
929 parse_symbolic_address (CGEN_CPU_DESC cd,
933 enum cgen_parse_operand_result *resultp,
936 enum cgen_parse_operand_result result_type;
937 const char *errmsg = (* cd->parse_operand_fn)
938 (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
939 &result_type, valuep);
942 && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
943 return "symbolic expression required";
946 *resultp = result_type;
952 parse_ldd_annotation (CGEN_CPU_DESC cd,
955 unsigned long *valuep)
958 enum cgen_parse_operand_result result_type;
961 if (**strp == '#' || **strp == '%')
963 if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
966 errmsg = parse_symbolic_address (cd, strp, opindex,
967 BFD_RELOC_FRV_TLSDESC_RELAX,
968 &result_type, &value);
970 return "missing ')'";
979 while (**strp == ' ' || **strp == '\t')
983 return "missing `@'";
991 parse_call_annotation (CGEN_CPU_DESC cd,
994 unsigned long *valuep)
997 enum cgen_parse_operand_result result_type;
1000 if (**strp == '#' || **strp == '%')
1002 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1005 errmsg = parse_symbolic_address (cd, strp, opindex,
1006 BFD_RELOC_FRV_GETTLSOFF_RELAX,
1007 &result_type, &value);
1009 return "missing ')'";
1018 while (**strp == ' ' || **strp == '\t')
1022 return "missing `@'";
1030 parse_ld_annotation (CGEN_CPU_DESC cd,
1033 unsigned long *valuep)
1036 enum cgen_parse_operand_result result_type;
1039 if (**strp == '#' || **strp == '%')
1041 if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
1044 errmsg = parse_symbolic_address (cd, strp, opindex,
1045 BFD_RELOC_FRV_TLSOFF_RELAX,
1046 &result_type, &value);
1048 return "missing ')'";
1057 while (**strp == ' ' || **strp == '\t')
1061 return "missing `@'";
1069 parse_ulo16 (CGEN_CPU_DESC cd,
1072 unsigned long *valuep)
1075 enum cgen_parse_operand_result result_type;
1078 if (**strp == '#' || **strp == '%')
1080 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1083 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1084 & result_type, & value);
1086 return "missing `)'";
1089 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1094 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1097 errmsg = parse_symbolic_address (cd, strp, opindex,
1098 BFD_RELOC_FRV_GPRELLO,
1099 & result_type, & value);
1101 return "missing ')'";
1106 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1109 errmsg = parse_symbolic_address (cd, strp, opindex,
1110 BFD_RELOC_FRV_GOTLO,
1111 & result_type, & value);
1113 return "missing ')'";
1118 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1121 errmsg = parse_symbolic_address (cd, strp, opindex,
1122 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1123 & result_type, & value);
1125 return "missing ')'";
1130 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1133 errmsg = parse_symbolic_address (cd, strp, opindex,
1134 BFD_RELOC_FRV_GOTOFFLO,
1135 & result_type, & value);
1137 return "missing ')'";
1142 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1145 errmsg = parse_symbolic_address (cd, strp, opindex,
1146 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1147 & result_type, & value);
1149 return "missing ')'";
1154 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1157 errmsg = parse_symbolic_address (cd, strp, opindex,
1158 BFD_RELOC_FRV_GOTTLSDESCLO,
1159 & result_type, & value);
1161 return "missing ')'";
1166 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1169 errmsg = parse_symbolic_address (cd, strp, opindex,
1170 BFD_RELOC_FRV_TLSMOFFLO,
1171 & result_type, & value);
1173 return "missing ')'";
1178 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1181 errmsg = parse_symbolic_address (cd, strp, opindex,
1182 BFD_RELOC_FRV_GOTTLSOFFLO,
1183 & result_type, & value);
1185 return "missing ')'";
1191 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1195 parse_uslo16 (CGEN_CPU_DESC cd,
1198 signed long *valuep)
1201 enum cgen_parse_operand_result result_type;
1204 if (**strp == '#' || **strp == '%')
1206 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1209 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1210 & result_type, & value);
1212 return "missing `)'";
1215 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1220 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1223 errmsg = parse_symbolic_address (cd, strp, opindex,
1224 BFD_RELOC_FRV_GPRELLO,
1225 & result_type, & value);
1227 return "missing ')'";
1232 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1235 errmsg = parse_symbolic_address (cd, strp, opindex,
1236 BFD_RELOC_FRV_GOTLO,
1237 & result_type, & value);
1239 return "missing ')'";
1244 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1247 errmsg = parse_symbolic_address (cd, strp, opindex,
1248 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1249 & result_type, & value);
1251 return "missing ')'";
1256 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1259 errmsg = parse_symbolic_address (cd, strp, opindex,
1260 BFD_RELOC_FRV_GOTOFFLO,
1261 & result_type, & value);
1263 return "missing ')'";
1268 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1271 errmsg = parse_symbolic_address (cd, strp, opindex,
1272 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1273 & result_type, & value);
1275 return "missing ')'";
1280 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1283 errmsg = parse_symbolic_address (cd, strp, opindex,
1284 BFD_RELOC_FRV_GOTTLSDESCLO,
1285 & result_type, & value);
1287 return "missing ')'";
1292 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1295 errmsg = parse_symbolic_address (cd, strp, opindex,
1296 BFD_RELOC_FRV_TLSMOFFLO,
1297 & result_type, & value);
1299 return "missing ')'";
1304 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1307 errmsg = parse_symbolic_address (cd, strp, opindex,
1308 BFD_RELOC_FRV_GOTTLSOFFLO,
1309 & result_type, & value);
1311 return "missing ')'";
1317 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1321 parse_uhi16 (CGEN_CPU_DESC cd,
1324 unsigned long *valuep)
1327 enum cgen_parse_operand_result result_type;
1330 if (**strp == '#' || **strp == '%')
1332 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1335 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1336 & result_type, & value);
1338 return "missing `)'";
1341 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1343 /* If bfd_vma is wider than 32 bits, but we have a sign-
1344 or zero-extension, truncate it. */
1345 if (value >= - ((bfd_vma)1 << 31)
1346 || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
1347 value &= (((bfd_vma)1 << 16) << 16) - 1;
1353 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1356 errmsg = parse_symbolic_address (cd, strp, opindex,
1357 BFD_RELOC_FRV_GPRELHI,
1358 & result_type, & value);
1360 return "missing ')'";
1365 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1368 errmsg = parse_symbolic_address (cd, strp, opindex,
1369 BFD_RELOC_FRV_GOTHI,
1370 & result_type, & value);
1372 return "missing ')'";
1377 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1380 errmsg = parse_symbolic_address (cd, strp, opindex,
1381 BFD_RELOC_FRV_FUNCDESC_GOTHI,
1382 & result_type, & value);
1384 return "missing ')'";
1389 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1392 errmsg = parse_symbolic_address (cd, strp, opindex,
1393 BFD_RELOC_FRV_GOTOFFHI,
1394 & result_type, & value);
1396 return "missing ')'";
1401 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1404 errmsg = parse_symbolic_address (cd, strp, opindex,
1405 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1406 & result_type, & value);
1408 return "missing ')'";
1413 else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
1416 errmsg = parse_symbolic_address (cd, strp, opindex,
1417 BFD_RELOC_FRV_GOTTLSDESCHI,
1418 &result_type, &value);
1420 return "missing ')'";
1425 else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
1428 errmsg = parse_symbolic_address (cd, strp, opindex,
1429 BFD_RELOC_FRV_TLSMOFFHI,
1430 & result_type, & value);
1432 return "missing ')'";
1437 else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
1440 errmsg = parse_symbolic_address (cd, strp, opindex,
1441 BFD_RELOC_FRV_GOTTLSOFFHI,
1442 & result_type, & value);
1444 return "missing ')'";
1450 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1454 parse_register_number (const char **strp)
1458 if (**strp < '0' || **strp > '9')
1459 return -1; /* error */
1461 regno = **strp - '0';
1462 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1463 regno = regno * 10 + (**strp - '0');
1469 parse_spr (CGEN_CPU_DESC cd,
1471 CGEN_KEYWORD * table,
1474 const char *save_strp;
1477 /* Check for spr index notation. */
1478 if (strncasecmp (*strp, "spr[", 4) == 0)
1481 regno = parse_register_number (strp);
1483 return _("missing `]'");
1485 if (! spr_valid (regno))
1486 return _("Special purpose register number is out of range");
1492 regno = parse_register_number (strp);
1495 if (! spr_valid (regno))
1496 return _("Special purpose register number is out of range");
1502 return cgen_parse_keyword (cd, strp, table, valuep);
1506 parse_d12 (CGEN_CPU_DESC cd,
1512 enum cgen_parse_operand_result result_type;
1515 /* Check for small data reference. */
1516 if (**strp == '#' || **strp == '%')
1518 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1521 errmsg = parse_symbolic_address (cd, strp, opindex,
1522 BFD_RELOC_FRV_GPREL12,
1523 & result_type, & value);
1525 return "missing `)'";
1530 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1533 errmsg = parse_symbolic_address (cd, strp, opindex,
1534 BFD_RELOC_FRV_GOT12,
1535 & result_type, & value);
1537 return "missing ')'";
1542 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1545 errmsg = parse_symbolic_address (cd, strp, opindex,
1546 BFD_RELOC_FRV_FUNCDESC_GOT12,
1547 & result_type, & value);
1549 return "missing ')'";
1554 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1557 errmsg = parse_symbolic_address (cd, strp, opindex,
1558 BFD_RELOC_FRV_GOTOFF12,
1559 & result_type, & value);
1561 return "missing ')'";
1566 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1569 errmsg = parse_symbolic_address (cd, strp, opindex,
1570 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1571 & result_type, & value);
1573 return "missing ')'";
1578 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1581 errmsg = parse_symbolic_address (cd, strp, opindex,
1582 BFD_RELOC_FRV_GOTTLSDESC12,
1583 & result_type, & value);
1585 return "missing ')'";
1590 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1593 errmsg = parse_symbolic_address (cd, strp, opindex,
1594 BFD_RELOC_FRV_TLSMOFF12,
1595 & result_type, & value);
1597 return "missing ')'";
1602 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1605 errmsg = parse_symbolic_address (cd, strp, opindex,
1606 BFD_RELOC_FRV_GOTTLSOFF12,
1607 & result_type, & value);
1609 return "missing ')'";
1615 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1619 parse_s12 (CGEN_CPU_DESC cd,
1625 enum cgen_parse_operand_result result_type;
1628 /* Check for small data reference. */
1629 if (**strp == '#' || **strp == '%')
1631 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1634 errmsg = parse_symbolic_address (cd, strp, opindex,
1635 BFD_RELOC_FRV_GPREL12,
1636 & result_type, & value);
1638 return "missing `)'";
1643 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1646 errmsg = parse_symbolic_address (cd, strp, opindex,
1647 BFD_RELOC_FRV_GOT12,
1648 & result_type, & value);
1650 return "missing ')'";
1655 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1658 errmsg = parse_symbolic_address (cd, strp, opindex,
1659 BFD_RELOC_FRV_FUNCDESC_GOT12,
1660 & result_type, & value);
1662 return "missing ')'";
1667 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1670 errmsg = parse_symbolic_address (cd, strp, opindex,
1671 BFD_RELOC_FRV_GOTOFF12,
1672 & result_type, & value);
1674 return "missing ')'";
1679 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1682 errmsg = parse_symbolic_address (cd, strp, opindex,
1683 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1684 & result_type, & value);
1686 return "missing ')'";
1691 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1694 errmsg = parse_symbolic_address (cd, strp, opindex,
1695 BFD_RELOC_FRV_GOTTLSDESC12,
1696 & result_type, & value);
1698 return "missing ')'";
1703 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1706 errmsg = parse_symbolic_address (cd, strp, opindex,
1707 BFD_RELOC_FRV_TLSMOFF12,
1708 & result_type, & value);
1710 return "missing ')'";
1715 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1718 errmsg = parse_symbolic_address (cd, strp, opindex,
1719 BFD_RELOC_FRV_GOTTLSOFF12,
1720 & result_type, & value);
1722 return "missing ')'";
1731 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1735 parse_u12 (CGEN_CPU_DESC cd,
1741 enum cgen_parse_operand_result result_type;
1744 /* Check for small data reference. */
1745 if ((**strp == '#' || **strp == '%')
1746 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1749 errmsg = parse_symbolic_address (cd, strp, opindex,
1750 BFD_RELOC_FRV_GPRELU12,
1751 & result_type, & value);
1753 return "missing `)'";
1762 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1767 parse_A (CGEN_CPU_DESC cd,
1770 unsigned long *valuep,
1778 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1783 return _("Value of A operand must be 0 or 1");
1789 parse_A0 (CGEN_CPU_DESC cd,
1792 unsigned long *valuep)
1794 return parse_A (cd, strp, opindex, valuep, 0);
1798 parse_A1 (CGEN_CPU_DESC cd,
1801 unsigned long *valuep)
1803 return parse_A (cd, strp, opindex, valuep, 1);
1807 parse_even_register (CGEN_CPU_DESC cd,
1809 CGEN_KEYWORD * tableP,
1812 const char * errmsg;
1813 const char * saved_star_strP = * strP;
1815 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1817 if (errmsg == NULL && ((* valueP) & 1))
1819 errmsg = _("register number must be even");
1820 * strP = saved_star_strP;
1827 parse_call_label (CGEN_CPU_DESC cd,
1831 enum cgen_parse_operand_result *resultp,
1837 /* Check for small data reference. */
1838 if (opinfo == 0 && (**strp == '#' || **strp == '%'))
1840 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1843 errmsg = parse_symbolic_address (cd, strp, opindex,
1844 BFD_RELOC_FRV_GETTLSOFF,
1847 return _("missing `)'");
1854 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
1861 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1863 long reloc_ann ATTRIBUTE_UNUSED,
1864 long value ATTRIBUTE_UNUSED,
1865 bfd_vma pc ATTRIBUTE_UNUSED,
1866 int length ATTRIBUTE_UNUSED)
1868 disassemble_info *info = (disassemble_info *) dis_info;
1870 (*info->fprintf_func) (info->stream, "@");
1874 print_spr (CGEN_CPU_DESC cd,
1876 CGEN_KEYWORD *names,
1880 /* Use the register index format for any unnamed registers. */
1881 if (cgen_keyword_lookup_value (names, regno) == NULL)
1883 disassemble_info *info = (disassemble_info *) dis_info;
1884 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1887 print_keyword (cd, dis_info, names, regno, attrs);
1891 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1894 unsigned int attrs ATTRIBUTE_UNUSED,
1895 bfd_vma pc ATTRIBUTE_UNUSED,
1896 int length ATTRIBUTE_UNUSED)
1898 disassemble_info *info = (disassemble_info *) dis_info;
1900 (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
1904 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1907 unsigned int attrs ATTRIBUTE_UNUSED,
1908 bfd_vma pc ATTRIBUTE_UNUSED,
1909 int length ATTRIBUTE_UNUSED)
1911 disassemble_info *info = (disassemble_info *) dis_info;
1913 (*info->fprintf_func) (info->stream, "0x%lx", value);
1915 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);