1 /* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*-
3 Copyright 2000, 2001, 2003, 2004, 2005, 2007 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 3 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. */
25 /* This file is an addendum to frv.cpu. Heavy use of C code isn't
26 appropriate in .cpu files, so it resides here. This especially applies
27 to assembly/disassembly where parsing/printing can be quite involved.
28 Such things aren't really part of the specification of the cpu, per se,
29 so .cpu files provide the general framework and .opc files handle the
30 nitty-gritty details as necessary.
32 Each section is delimited with start and end markers.
34 <arch>-opc.h additions use: "-- opc.h"
35 <arch>-opc.c additions use: "-- opc.c"
36 <arch>-asm.c additions use: "-- asm.c"
37 <arch>-dis.c additions use: "-- dis.c"
38 <arch>-ibd.h additions use: "-- ibd.h". */
42 #undef CGEN_DIS_HASH_SIZE
43 #define CGEN_DIS_HASH_SIZE 128
45 #define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
47 /* Allows reason codes to be output when assembler errors occur. */
48 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
51 #define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8. */
52 #define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
54 typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
59 int constraint_violation;
61 unsigned long elf_flags;
62 CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping;
63 VLIW_COMBO * current_vliw;
64 CGEN_ATTR_VALUE_ENUM_TYPE major[FRV_VLIW_SIZE];
65 const CGEN_INSN * insn[FRV_VLIW_SIZE];
68 int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
69 int frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
70 int frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
71 int frv_is_branch_insn (const CGEN_INSN *);
72 int frv_is_float_insn (const CGEN_INSN *);
73 int frv_is_media_insn (const CGEN_INSN *);
74 void frv_vliw_reset (FRV_VLIW *, unsigned long, unsigned long);
75 int frv_vliw_add_insn (FRV_VLIW *, const CGEN_INSN *);
83 /* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
87 frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
92 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
96 if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
100 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
108 /* Returns TRUE if {MAJOR,MACH} supports floating point insns. */
111 frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
119 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
127 /* Returns TRUE if {MAJOR,MACH} supports media insns. */
130 frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
135 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
139 if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
143 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
152 frv_is_branch_insn (const CGEN_INSN *insn)
154 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
157 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
160 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
168 frv_is_float_insn (const CGEN_INSN *insn)
170 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
173 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
176 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
184 frv_is_media_insn (const CGEN_INSN *insn)
186 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
189 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
192 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
199 /* This table represents the allowable packing for vliw insns for the fr400.
200 The fr400 has only 2 vliw slots. Represent this by not allowing any insns
202 Subsets of any given row are also allowed. */
203 static VLIW_COMBO fr400_allowed_vliw[] =
205 /* slot0 slot1 slot2 slot3 */
206 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
207 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
208 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
209 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
210 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
211 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
212 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
213 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
216 /* This table represents the allowable packing for vliw insns for the fr500.
217 The fr500 has only 4 vliw slots. Represent this by not allowing any insns
219 Subsets of any given row are also allowed. */
220 static VLIW_COMBO fr500_allowed_vliw[] =
222 /* slot0 slot1 slot2 slot3 */
223 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO },
224 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO },
225 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO },
226 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
227 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
228 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
229 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
230 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
231 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
232 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
233 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
236 /* This table represents the allowable packing for vliw insns for the fr550.
237 Subsets of any given row are also allowed. */
238 static VLIW_COMBO fr550_allowed_vliw[] =
240 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */
241 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL },
242 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL },
243 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
244 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
245 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 },
246 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 },
247 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 },
248 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 },
249 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 },
250 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL },
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_FM3, UNIT_B0, UNIT_B1 },
253 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL },
254 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
255 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL },
256 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
257 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
258 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL },
259 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
260 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
261 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
262 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
263 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
264 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
265 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
266 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
267 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
268 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
271 /* Some insns are assigned specialized implementation units which map to
272 different actual implementation units on different machines. These
273 tables perform that mapping. */
274 static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
276 /* unit in insn actual unit */
281 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
283 /* IALL */ UNIT_I01, /* only I0 and I1 units */
286 /* FM01 */ UNIT_FM01,
287 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
288 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
289 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
290 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
291 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
295 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
296 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
297 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
298 /* STORE */ UNIT_I0, /* store only in I0 unit. */
299 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
300 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
301 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
302 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
303 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
306 /* Some insns are assigned specialized implementation units which map to
307 different actual implementation units on different machines. These
308 tables perform that mapping. */
309 static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
311 /* unit in insn actual unit */
316 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
318 /* IALL */ UNIT_I01, /* only I0 and I1 units */
321 /* FM01 */ UNIT_FM01,
322 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
323 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
324 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
325 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
326 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
330 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
331 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
332 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
333 /* STORE */ UNIT_I0, /* store only in I0 unit. */
334 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
335 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
336 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
337 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1. */
338 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
341 static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
343 /* unit in insn actual unit */
348 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
350 /* IALL */ UNIT_I01, /* only I0 and I1 units */
353 /* FM01 */ UNIT_FM01,
354 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
355 /* FM3 */ UNIT_NIL, /* no F3 or M2 units */
356 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
357 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
362 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
363 /* IACC */ UNIT_NIL, /* iacc multiply not implemented */
364 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
365 /* STORE */ UNIT_I0, /* store only in I0 unit. */
366 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
367 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
368 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
369 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
370 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
373 static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
375 /* unit in insn actual unit */
382 /* IALL */ UNIT_IALL,
385 /* FM01 */ UNIT_FM01,
388 /* FMALL */ UNIT_FMALL,
389 /* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */
394 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
395 /* IACC */ UNIT_NIL, /* iacc multiply not implemented. */
396 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
397 /* STORE */ UNIT_I01, /* store in I0 or I1 unit. */
398 /* SCAN */ UNIT_IALL, /* scan in any integer unit. */
399 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
400 /* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */
401 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1 unit. */
402 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
406 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
409 vliw->constraint_violation = 0;
411 vliw->elf_flags = elf_flags;
416 vliw->current_vliw = fr400_allowed_vliw;
417 vliw->unit_mapping = fr400_unit_mapping;
420 vliw->current_vliw = fr400_allowed_vliw;
421 vliw->unit_mapping = fr450_unit_mapping;
424 vliw->current_vliw = fr550_allowed_vliw;
425 vliw->unit_mapping = fr550_unit_mapping;
428 vliw->current_vliw = fr500_allowed_vliw;
429 vliw->unit_mapping = fr500_unit_mapping;
434 /* Return TRUE if unit1 is a match for unit2.
435 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
436 *_allowed_vliw tables above. */
438 match_unit (FRV_VLIW *vliw,
439 CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
441 /* Map any specialized implementation units to actual ones. */
442 unit1 = vliw->unit_mapping[unit1];
454 /* The 01 versions of these units are within 2 enums of the 0 or 1
456 if (unit1 - unit2 <= 2)
461 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
463 if (unit1 - unit2 <= 5)
473 /* Return TRUE if the vliws match, FALSE otherwise. */
476 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
480 for (i = 0; i < vliw_size; ++i)
481 if ((*vliw1)[i] != (*vliw2)[i])
487 /* Find the next vliw vliw in the table that can accomodate the new insn.
488 If one is found then return it. Otherwise return NULL. */
491 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
493 int next = vliw->next_slot;
494 VLIW_COMBO *current = vliw->current_vliw;
495 VLIW_COMBO *potential;
499 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
501 abort (); /* Should never happen. */
504 /* The table is sorted by units allowed within slots, so vliws with
505 identical starting sequences are together. */
509 if (match_unit (vliw, unit, (*potential)[next]))
513 while (match_vliw (potential, current, next));
518 /* Look for the given major insn type in the given vliw.
519 Returns TRUE if found, FALSE otherwise. */
522 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
526 for (i = 0; i < vliw->next_slot; ++i)
527 if (vliw->major[i] == major)
533 /* Check for constraints between the insns in the vliw due to major insn
537 fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
539 /* In the cpu file, all media insns are represented as being allowed in
540 both media units. This makes it easier since this is the case for fr500.
541 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
542 cannot coexist with any other media insn in a vliw. */
545 case FR400_MAJOR_M_2:
546 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
547 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
548 case FR400_MAJOR_M_1:
549 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
557 fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
559 CGEN_ATTR_VALUE_ENUM_TYPE other_major;
561 /* Our caller guarantees there's at least one other instruction. */
562 other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
564 /* (M4, M5) and (M4, M6) are allowed. */
565 if (other_major == FR450_MAJOR_M_4)
566 if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
569 /* Otherwise, instructions in even-numbered media categories cannot be
570 executed in parallel with other media instructions. */
573 case FR450_MAJOR_M_2:
574 case FR450_MAJOR_M_4:
575 case FR450_MAJOR_M_6:
576 return !(other_major >= FR450_MAJOR_M_1
577 && other_major <= FR450_MAJOR_M_6);
579 case FR450_MAJOR_M_1:
580 case FR450_MAJOR_M_3:
581 case FR450_MAJOR_M_5:
582 return !(other_major == FR450_MAJOR_M_2
583 || other_major == FR450_MAJOR_M_4
584 || other_major == FR450_MAJOR_M_6);
592 find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
596 for (i = 0; i < vliw->next_slot; ++i)
597 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
600 return FALSE; /* Not found. */
604 find_major_in_slot (FRV_VLIW *vliw,
605 CGEN_ATTR_VALUE_ENUM_TYPE major,
606 CGEN_ATTR_VALUE_ENUM_TYPE slot)
610 for (i = 0; i < vliw->next_slot; ++i)
611 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
618 fr550_find_media_in_vliw (FRV_VLIW *vliw)
622 for (i = 0; i < vliw->next_slot; ++i)
624 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
627 /* Found a media insn, however, MNOP and MCLRACC don't count. */
628 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
629 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
630 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
633 return TRUE; /* Found one. */
640 fr550_find_float_in_vliw (FRV_VLIW *vliw)
644 for (i = 0; i < vliw->next_slot; ++i)
646 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
649 /* Found a floating point insn, however, FNOP doesn't count. */
650 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
653 return TRUE; /* Found one. */
660 fr550_check_insn_major_constraints (FRV_VLIW *vliw,
661 CGEN_ATTR_VALUE_ENUM_TYPE major,
662 const CGEN_INSN *insn)
664 CGEN_ATTR_VALUE_ENUM_TYPE unit;
665 CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
669 /* If it's a store, then there must be another store in I1 */
670 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
671 if (unit == UNIT_STORE)
672 return find_unit_in_vliw (vliw, UNIT_STORE);
676 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
678 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
679 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
680 return ! fr550_find_media_in_vliw (vliw);
681 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
682 floating point insns. */
683 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
684 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
685 return ! fr550_find_float_in_vliw (vliw);
686 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
688 if (major == FR550_MAJOR_F_2)
689 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
690 slot - (UNIT_FM2 - UNIT_FM0))
691 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
692 slot - (UNIT_FM2 - UNIT_FM0));
693 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
695 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
696 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
697 slot - (UNIT_FM2 - UNIT_FM0));
698 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
700 if (major == FR550_MAJOR_M_4)
701 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
702 slot - (UNIT_FM2 - UNIT_FM0));
707 return TRUE; /* All OK. */
711 fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
713 /* TODO: A table might be faster for some of the more complex instances
717 case FR500_MAJOR_I_1:
718 case FR500_MAJOR_I_4:
719 case FR500_MAJOR_I_5:
720 case FR500_MAJOR_I_6:
721 case FR500_MAJOR_B_1:
722 case FR500_MAJOR_B_2:
723 case FR500_MAJOR_B_3:
724 case FR500_MAJOR_B_4:
725 case FR500_MAJOR_B_5:
726 case FR500_MAJOR_B_6:
727 case FR500_MAJOR_F_4:
728 case FR500_MAJOR_F_8:
729 case FR500_MAJOR_M_8:
730 return TRUE; /* OK */
731 case FR500_MAJOR_I_2:
732 /* Cannot coexist with I-3 insn. */
733 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
734 case FR500_MAJOR_I_3:
735 /* Cannot coexist with I-2 insn. */
736 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
737 case FR500_MAJOR_F_1:
738 case FR500_MAJOR_F_2:
739 /* Cannot coexist with F-5, F-6, or M-7 insn. */
740 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
741 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
742 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
743 case FR500_MAJOR_F_3:
744 /* Cannot coexist with F-7, or M-7 insn. */
745 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
746 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
747 case FR500_MAJOR_F_5:
748 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
749 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
750 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
751 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
752 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
753 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
754 case FR500_MAJOR_F_6:
755 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
756 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
757 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
758 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
759 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
760 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
761 case FR500_MAJOR_F_7:
762 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
763 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
764 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
765 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
766 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
767 case FR500_MAJOR_M_1:
768 /* Cannot coexist with M-7 insn. */
769 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
770 case FR500_MAJOR_M_2:
771 case FR500_MAJOR_M_3:
772 /* Cannot coexist with M-5, M-6 or M-7 insn. */
773 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
774 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
775 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
776 case FR500_MAJOR_M_4:
777 /* Cannot coexist with M-6 insn. */
778 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
779 case FR500_MAJOR_M_5:
780 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
781 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
782 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
783 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
784 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
785 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
786 case FR500_MAJOR_M_6:
787 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
788 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
789 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
790 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
791 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
792 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
793 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
794 case FR500_MAJOR_M_7:
795 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
796 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
797 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
798 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
799 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
800 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
801 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
802 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
803 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
804 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
805 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
806 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
807 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
809 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
818 check_insn_major_constraints (FRV_VLIW *vliw,
819 CGEN_ATTR_VALUE_ENUM_TYPE major,
820 const CGEN_INSN *insn)
825 return fr400_check_insn_major_constraints (vliw, major);
828 return fr450_check_insn_major_constraints (vliw, major);
831 return fr550_check_insn_major_constraints (vliw, major, insn);
834 return fr500_check_insn_major_constraints (vliw, major);
838 /* Add in insn to the VLIW vliw if possible.
839 Return 0 if successful, non-zero otherwise. */
842 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
845 CGEN_ATTR_VALUE_ENUM_TYPE major;
846 CGEN_ATTR_VALUE_ENUM_TYPE unit;
847 VLIW_COMBO *new_vliw;
849 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
852 index = vliw->next_slot;
853 if (index >= FRV_VLIW_SIZE)
856 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
857 if (unit == UNIT_NIL)
859 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
861 abort (); /* No UNIT specified for this insn in frv.cpu. */
867 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
870 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
873 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
876 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
882 /* Any insn can be added to slot 0. */
883 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
884 ++vliw->current_vliw;
885 vliw->major[0] = major;
886 vliw->insn[0] = insn;
891 /* If there are already insns in the vliw(s) check to see that
892 this one can be added. Do this by finding an allowable vliw
893 combination that can accept the new insn. */
894 if (! (vliw->elf_flags & EF_FRV_NOPACK))
896 new_vliw = add_next_to_vliw (vliw, unit);
897 if (new_vliw && check_insn_major_constraints (vliw, major, insn))
899 vliw->current_vliw = new_vliw;
900 vliw->major[index] = major;
901 vliw->insn[index] = insn;
906 /* The frv machine supports all packing conbinations. If we fail,
907 to add the insn, then it could not be handled as if it was the fr500.
908 Just return as if it was handled ok. */
909 if (vliw->mach == bfd_mach_frv)
913 vliw->constraint_violation = 1;
918 spr_valid (long regno)
920 if (regno < 0) return FALSE;
921 if (regno <= 4095) return TRUE;
927 inline static const char *
928 parse_symbolic_address (CGEN_CPU_DESC cd,
932 enum cgen_parse_operand_result *resultp,
935 enum cgen_parse_operand_result result_type;
936 const char *errmsg = (* cd->parse_operand_fn)
937 (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
938 &result_type, valuep);
941 && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
942 return "symbolic expression required";
945 *resultp = result_type;
951 parse_ldd_annotation (CGEN_CPU_DESC cd,
954 unsigned long *valuep)
957 enum cgen_parse_operand_result result_type;
960 if (**strp == '#' || **strp == '%')
962 if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
965 errmsg = parse_symbolic_address (cd, strp, opindex,
966 BFD_RELOC_FRV_TLSDESC_RELAX,
967 &result_type, &value);
969 return "missing ')'";
978 while (**strp == ' ' || **strp == '\t')
982 return "missing `@'";
990 parse_call_annotation (CGEN_CPU_DESC cd,
993 unsigned long *valuep)
996 enum cgen_parse_operand_result result_type;
999 if (**strp == '#' || **strp == '%')
1001 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1004 errmsg = parse_symbolic_address (cd, strp, opindex,
1005 BFD_RELOC_FRV_GETTLSOFF_RELAX,
1006 &result_type, &value);
1008 return "missing ')'";
1017 while (**strp == ' ' || **strp == '\t')
1021 return "missing `@'";
1029 parse_ld_annotation (CGEN_CPU_DESC cd,
1032 unsigned long *valuep)
1035 enum cgen_parse_operand_result result_type;
1038 if (**strp == '#' || **strp == '%')
1040 if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
1043 errmsg = parse_symbolic_address (cd, strp, opindex,
1044 BFD_RELOC_FRV_TLSOFF_RELAX,
1045 &result_type, &value);
1047 return "missing ')'";
1056 while (**strp == ' ' || **strp == '\t')
1060 return "missing `@'";
1068 parse_ulo16 (CGEN_CPU_DESC cd,
1071 unsigned long *valuep)
1074 enum cgen_parse_operand_result result_type;
1077 if (**strp == '#' || **strp == '%')
1079 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1082 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1083 & result_type, & value);
1085 return "missing `)'";
1088 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1093 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1096 errmsg = parse_symbolic_address (cd, strp, opindex,
1097 BFD_RELOC_FRV_GPRELLO,
1098 & result_type, & value);
1100 return "missing ')'";
1105 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1108 errmsg = parse_symbolic_address (cd, strp, opindex,
1109 BFD_RELOC_FRV_GOTLO,
1110 & result_type, & value);
1112 return "missing ')'";
1117 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1120 errmsg = parse_symbolic_address (cd, strp, opindex,
1121 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1122 & result_type, & value);
1124 return "missing ')'";
1129 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1132 errmsg = parse_symbolic_address (cd, strp, opindex,
1133 BFD_RELOC_FRV_GOTOFFLO,
1134 & result_type, & value);
1136 return "missing ')'";
1141 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1144 errmsg = parse_symbolic_address (cd, strp, opindex,
1145 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1146 & result_type, & value);
1148 return "missing ')'";
1153 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1156 errmsg = parse_symbolic_address (cd, strp, opindex,
1157 BFD_RELOC_FRV_GOTTLSDESCLO,
1158 & result_type, & value);
1160 return "missing ')'";
1165 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1168 errmsg = parse_symbolic_address (cd, strp, opindex,
1169 BFD_RELOC_FRV_TLSMOFFLO,
1170 & result_type, & value);
1172 return "missing ')'";
1177 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1180 errmsg = parse_symbolic_address (cd, strp, opindex,
1181 BFD_RELOC_FRV_GOTTLSOFFLO,
1182 & result_type, & value);
1184 return "missing ')'";
1190 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1194 parse_uslo16 (CGEN_CPU_DESC cd,
1197 signed long *valuep)
1200 enum cgen_parse_operand_result result_type;
1203 if (**strp == '#' || **strp == '%')
1205 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1208 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1209 & result_type, & value);
1211 return "missing `)'";
1214 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1219 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1222 errmsg = parse_symbolic_address (cd, strp, opindex,
1223 BFD_RELOC_FRV_GPRELLO,
1224 & result_type, & value);
1226 return "missing ')'";
1231 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1234 errmsg = parse_symbolic_address (cd, strp, opindex,
1235 BFD_RELOC_FRV_GOTLO,
1236 & result_type, & value);
1238 return "missing ')'";
1243 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1246 errmsg = parse_symbolic_address (cd, strp, opindex,
1247 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1248 & result_type, & value);
1250 return "missing ')'";
1255 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1258 errmsg = parse_symbolic_address (cd, strp, opindex,
1259 BFD_RELOC_FRV_GOTOFFLO,
1260 & result_type, & value);
1262 return "missing ')'";
1267 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1270 errmsg = parse_symbolic_address (cd, strp, opindex,
1271 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1272 & result_type, & value);
1274 return "missing ')'";
1279 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1282 errmsg = parse_symbolic_address (cd, strp, opindex,
1283 BFD_RELOC_FRV_GOTTLSDESCLO,
1284 & result_type, & value);
1286 return "missing ')'";
1291 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1294 errmsg = parse_symbolic_address (cd, strp, opindex,
1295 BFD_RELOC_FRV_TLSMOFFLO,
1296 & result_type, & value);
1298 return "missing ')'";
1303 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1306 errmsg = parse_symbolic_address (cd, strp, opindex,
1307 BFD_RELOC_FRV_GOTTLSOFFLO,
1308 & result_type, & value);
1310 return "missing ')'";
1316 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1320 parse_uhi16 (CGEN_CPU_DESC cd,
1323 unsigned long *valuep)
1326 enum cgen_parse_operand_result result_type;
1329 if (**strp == '#' || **strp == '%')
1331 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1334 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1335 & result_type, & value);
1337 return "missing `)'";
1340 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1342 /* If bfd_vma is wider than 32 bits, but we have a sign-
1343 or zero-extension, truncate it. */
1344 if (value >= - ((bfd_vma)1 << 31)
1345 || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
1346 value &= (((bfd_vma)1 << 16) << 16) - 1;
1352 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1355 errmsg = parse_symbolic_address (cd, strp, opindex,
1356 BFD_RELOC_FRV_GPRELHI,
1357 & result_type, & value);
1359 return "missing ')'";
1364 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1367 errmsg = parse_symbolic_address (cd, strp, opindex,
1368 BFD_RELOC_FRV_GOTHI,
1369 & result_type, & value);
1371 return "missing ')'";
1376 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1379 errmsg = parse_symbolic_address (cd, strp, opindex,
1380 BFD_RELOC_FRV_FUNCDESC_GOTHI,
1381 & result_type, & value);
1383 return "missing ')'";
1388 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1391 errmsg = parse_symbolic_address (cd, strp, opindex,
1392 BFD_RELOC_FRV_GOTOFFHI,
1393 & result_type, & value);
1395 return "missing ')'";
1400 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1403 errmsg = parse_symbolic_address (cd, strp, opindex,
1404 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1405 & result_type, & value);
1407 return "missing ')'";
1412 else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
1415 errmsg = parse_symbolic_address (cd, strp, opindex,
1416 BFD_RELOC_FRV_GOTTLSDESCHI,
1417 &result_type, &value);
1419 return "missing ')'";
1424 else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
1427 errmsg = parse_symbolic_address (cd, strp, opindex,
1428 BFD_RELOC_FRV_TLSMOFFHI,
1429 & result_type, & value);
1431 return "missing ')'";
1436 else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
1439 errmsg = parse_symbolic_address (cd, strp, opindex,
1440 BFD_RELOC_FRV_GOTTLSOFFHI,
1441 & result_type, & value);
1443 return "missing ')'";
1449 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1453 parse_register_number (const char **strp)
1457 if (**strp < '0' || **strp > '9')
1458 return -1; /* error */
1460 regno = **strp - '0';
1461 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1462 regno = regno * 10 + (**strp - '0');
1468 parse_spr (CGEN_CPU_DESC cd,
1470 CGEN_KEYWORD * table,
1473 const char *save_strp;
1476 /* Check for spr index notation. */
1477 if (strncasecmp (*strp, "spr[", 4) == 0)
1480 regno = parse_register_number (strp);
1482 return _("missing `]'");
1484 if (! spr_valid (regno))
1485 return _("Special purpose register number is out of range");
1491 regno = parse_register_number (strp);
1494 if (! spr_valid (regno))
1495 return _("Special purpose register number is out of range");
1501 return cgen_parse_keyword (cd, strp, table, valuep);
1505 parse_d12 (CGEN_CPU_DESC cd,
1511 enum cgen_parse_operand_result result_type;
1514 /* Check for small data reference. */
1515 if (**strp == '#' || **strp == '%')
1517 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1520 errmsg = parse_symbolic_address (cd, strp, opindex,
1521 BFD_RELOC_FRV_GPREL12,
1522 & result_type, & value);
1524 return "missing `)'";
1529 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1532 errmsg = parse_symbolic_address (cd, strp, opindex,
1533 BFD_RELOC_FRV_GOT12,
1534 & result_type, & value);
1536 return "missing ')'";
1541 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1544 errmsg = parse_symbolic_address (cd, strp, opindex,
1545 BFD_RELOC_FRV_FUNCDESC_GOT12,
1546 & result_type, & value);
1548 return "missing ')'";
1553 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1556 errmsg = parse_symbolic_address (cd, strp, opindex,
1557 BFD_RELOC_FRV_GOTOFF12,
1558 & result_type, & value);
1560 return "missing ')'";
1565 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1568 errmsg = parse_symbolic_address (cd, strp, opindex,
1569 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1570 & result_type, & value);
1572 return "missing ')'";
1577 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1580 errmsg = parse_symbolic_address (cd, strp, opindex,
1581 BFD_RELOC_FRV_GOTTLSDESC12,
1582 & result_type, & value);
1584 return "missing ')'";
1589 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1592 errmsg = parse_symbolic_address (cd, strp, opindex,
1593 BFD_RELOC_FRV_TLSMOFF12,
1594 & result_type, & value);
1596 return "missing ')'";
1601 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1604 errmsg = parse_symbolic_address (cd, strp, opindex,
1605 BFD_RELOC_FRV_GOTTLSOFF12,
1606 & result_type, & value);
1608 return "missing ')'";
1614 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1618 parse_s12 (CGEN_CPU_DESC cd,
1624 enum cgen_parse_operand_result result_type;
1627 /* Check for small data reference. */
1628 if (**strp == '#' || **strp == '%')
1630 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1633 errmsg = parse_symbolic_address (cd, strp, opindex,
1634 BFD_RELOC_FRV_GPREL12,
1635 & result_type, & value);
1637 return "missing `)'";
1642 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1645 errmsg = parse_symbolic_address (cd, strp, opindex,
1646 BFD_RELOC_FRV_GOT12,
1647 & result_type, & value);
1649 return "missing ')'";
1654 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1657 errmsg = parse_symbolic_address (cd, strp, opindex,
1658 BFD_RELOC_FRV_FUNCDESC_GOT12,
1659 & result_type, & value);
1661 return "missing ')'";
1666 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1669 errmsg = parse_symbolic_address (cd, strp, opindex,
1670 BFD_RELOC_FRV_GOTOFF12,
1671 & result_type, & value);
1673 return "missing ')'";
1678 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1681 errmsg = parse_symbolic_address (cd, strp, opindex,
1682 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1683 & result_type, & value);
1685 return "missing ')'";
1690 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1693 errmsg = parse_symbolic_address (cd, strp, opindex,
1694 BFD_RELOC_FRV_GOTTLSDESC12,
1695 & result_type, & value);
1697 return "missing ')'";
1702 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1705 errmsg = parse_symbolic_address (cd, strp, opindex,
1706 BFD_RELOC_FRV_TLSMOFF12,
1707 & result_type, & value);
1709 return "missing ')'";
1714 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1717 errmsg = parse_symbolic_address (cd, strp, opindex,
1718 BFD_RELOC_FRV_GOTTLSOFF12,
1719 & result_type, & value);
1721 return "missing ')'";
1730 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1734 parse_u12 (CGEN_CPU_DESC cd,
1740 enum cgen_parse_operand_result result_type;
1743 /* Check for small data reference. */
1744 if ((**strp == '#' || **strp == '%')
1745 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1748 errmsg = parse_symbolic_address (cd, strp, opindex,
1749 BFD_RELOC_FRV_GPRELU12,
1750 & result_type, & value);
1752 return "missing `)'";
1761 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1766 parse_A (CGEN_CPU_DESC cd,
1769 unsigned long *valuep,
1777 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1782 return _("Value of A operand must be 0 or 1");
1788 parse_A0 (CGEN_CPU_DESC cd,
1791 unsigned long *valuep)
1793 return parse_A (cd, strp, opindex, valuep, 0);
1797 parse_A1 (CGEN_CPU_DESC cd,
1800 unsigned long *valuep)
1802 return parse_A (cd, strp, opindex, valuep, 1);
1806 parse_even_register (CGEN_CPU_DESC cd,
1808 CGEN_KEYWORD * tableP,
1811 const char * errmsg;
1812 const char * saved_star_strP = * strP;
1814 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1816 if (errmsg == NULL && ((* valueP) & 1))
1818 errmsg = _("register number must be even");
1819 * strP = saved_star_strP;
1826 parse_call_label (CGEN_CPU_DESC cd,
1830 enum cgen_parse_operand_result *resultp,
1836 /* Check for small data reference. */
1837 if (opinfo == 0 && (**strp == '#' || **strp == '%'))
1839 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1842 errmsg = parse_symbolic_address (cd, strp, opindex,
1843 BFD_RELOC_FRV_GETTLSOFF,
1846 return _("missing `)'");
1853 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
1860 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1862 long reloc_ann ATTRIBUTE_UNUSED,
1863 long value ATTRIBUTE_UNUSED,
1864 bfd_vma pc ATTRIBUTE_UNUSED,
1865 int length ATTRIBUTE_UNUSED)
1867 disassemble_info *info = (disassemble_info *) dis_info;
1869 (*info->fprintf_func) (info->stream, "@");
1873 print_spr (CGEN_CPU_DESC cd,
1875 CGEN_KEYWORD *names,
1879 /* Use the register index format for any unnamed registers. */
1880 if (cgen_keyword_lookup_value (names, regno) == NULL)
1882 disassemble_info *info = (disassemble_info *) dis_info;
1883 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1886 print_keyword (cd, dis_info, names, regno, attrs);
1890 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1893 unsigned int attrs ATTRIBUTE_UNUSED,
1894 bfd_vma pc ATTRIBUTE_UNUSED,
1895 int length ATTRIBUTE_UNUSED)
1897 disassemble_info *info = (disassemble_info *) dis_info;
1899 (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
1903 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1906 unsigned int attrs ATTRIBUTE_UNUSED,
1907 bfd_vma pc ATTRIBUTE_UNUSED,
1908 int length ATTRIBUTE_UNUSED)
1910 disassemble_info *info = (disassemble_info *) dis_info;
1912 (*info->fprintf_func) (info->stream, "0x%lx", value);
1914 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);