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 bool frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
70 bool frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
71 bool frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
72 bool frv_is_branch_insn (const CGEN_INSN *);
73 bool frv_is_float_insn (const CGEN_INSN *);
74 bool 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 *);
77 bool spr_valid (long);
85 /* DEBUG appears below as argument of OP macro. */
88 /* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
92 frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
97 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
101 if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
105 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
113 /* Returns TRUE if {MAJOR,MACH} supports floating point insns. */
116 frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
124 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
132 /* Returns TRUE if {MAJOR,MACH} supports media insns. */
135 frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
140 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
144 if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
148 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
157 frv_is_branch_insn (const CGEN_INSN *insn)
159 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
162 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
165 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
173 frv_is_float_insn (const CGEN_INSN *insn)
175 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
178 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
181 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
189 frv_is_media_insn (const CGEN_INSN *insn)
191 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
194 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
197 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
204 /* This table represents the allowable packing for vliw insns for the fr400.
205 The fr400 has only 2 vliw slots. Represent this by not allowing any insns
207 Subsets of any given row are also allowed. */
208 static VLIW_COMBO fr400_allowed_vliw[] =
210 /* slot0 slot1 slot2 slot3 */
211 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
212 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
213 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
214 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
215 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
216 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
217 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
218 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
221 /* This table represents the allowable packing for vliw insns for the fr500.
222 The fr500 has only 4 vliw slots. Represent this by not allowing any insns
224 Subsets of any given row are also allowed. */
225 static VLIW_COMBO fr500_allowed_vliw[] =
227 /* slot0 slot1 slot2 slot3 */
228 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO },
229 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO },
230 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO },
231 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
232 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
233 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
234 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
235 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
236 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
237 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
238 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
241 /* This table represents the allowable packing for vliw insns for the fr550.
242 Subsets of any given row are also allowed. */
243 static VLIW_COMBO fr550_allowed_vliw[] =
245 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */
246 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL },
247 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL },
248 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
249 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
250 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 },
251 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 },
252 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 },
253 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 },
254 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 },
255 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL },
256 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
257 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
258 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL },
259 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
260 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL },
261 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
262 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
263 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL },
264 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
265 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
266 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
267 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
268 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
269 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
270 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
271 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
272 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
273 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
276 /* Some insns are assigned specialized implementation units which map to
277 different actual implementation units on different machines. These
278 tables perform that mapping. */
279 static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
281 /* unit in insn actual unit */
286 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
288 /* IALL */ UNIT_I01, /* only I0 and I1 units */
291 /* FM01 */ UNIT_FM01,
292 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
293 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
294 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
295 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
296 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
300 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
301 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
302 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
303 /* STORE */ UNIT_I0, /* store only in I0 unit. */
304 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
305 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
306 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
307 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
308 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
311 /* Some insns are assigned specialized implementation units which map to
312 different actual implementation units on different machines. These
313 tables perform that mapping. */
314 static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
316 /* unit in insn actual unit */
321 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
323 /* IALL */ UNIT_I01, /* only I0 and I1 units */
326 /* FM01 */ UNIT_FM01,
327 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
328 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
329 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
330 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
331 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
335 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
336 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
337 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
338 /* STORE */ UNIT_I0, /* store only in I0 unit. */
339 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
340 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
341 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
342 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1. */
343 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
346 static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
348 /* unit in insn actual unit */
353 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
355 /* IALL */ UNIT_I01, /* only I0 and I1 units */
358 /* FM01 */ UNIT_FM01,
359 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
360 /* FM3 */ UNIT_NIL, /* no F3 or M2 units */
361 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
362 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
367 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
368 /* IACC */ UNIT_NIL, /* iacc multiply not implemented */
369 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
370 /* STORE */ UNIT_I0, /* store only in I0 unit. */
371 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
372 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
373 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
374 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
375 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
378 static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
380 /* unit in insn actual unit */
387 /* IALL */ UNIT_IALL,
390 /* FM01 */ UNIT_FM01,
393 /* FMALL */ UNIT_FMALL,
394 /* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */
399 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
400 /* IACC */ UNIT_NIL, /* iacc multiply not implemented. */
401 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
402 /* STORE */ UNIT_I01, /* store in I0 or I1 unit. */
403 /* SCAN */ UNIT_IALL, /* scan in any integer unit. */
404 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
405 /* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */
406 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1 unit. */
407 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
411 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
414 vliw->constraint_violation = 0;
416 vliw->elf_flags = elf_flags;
421 vliw->current_vliw = fr400_allowed_vliw;
422 vliw->unit_mapping = fr400_unit_mapping;
425 vliw->current_vliw = fr400_allowed_vliw;
426 vliw->unit_mapping = fr450_unit_mapping;
429 vliw->current_vliw = fr550_allowed_vliw;
430 vliw->unit_mapping = fr550_unit_mapping;
433 vliw->current_vliw = fr500_allowed_vliw;
434 vliw->unit_mapping = fr500_unit_mapping;
439 /* Return TRUE if unit1 is a match for unit2.
440 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
441 *_allowed_vliw tables above. */
443 match_unit (FRV_VLIW *vliw,
444 CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
446 /* Map any specialized implementation units to actual ones. */
447 unit1 = vliw->unit_mapping[unit1];
459 /* The 01 versions of these units are within 2 enums of the 0 or 1
461 if (unit1 - unit2 <= 2)
466 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
468 if (unit1 - unit2 <= 5)
478 /* Return TRUE if the vliws match, FALSE otherwise. */
481 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
485 for (i = 0; i < vliw_size; ++i)
486 if ((*vliw1)[i] != (*vliw2)[i])
492 /* Find the next vliw vliw in the table that can accomodate the new insn.
493 If one is found then return it. Otherwise return NULL. */
496 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
498 int next = vliw->next_slot;
499 VLIW_COMBO *current = vliw->current_vliw;
500 VLIW_COMBO *potential;
504 /* xgettext:c-format */
505 opcodes_error_handler (_("internal error: bad vliw->next_slot value"));
509 /* The table is sorted by units allowed within slots, so vliws with
510 identical starting sequences are together. */
514 if (match_unit (vliw, unit, (*potential)[next]))
518 while (match_vliw (potential, current, next));
523 /* Look for the given major insn type in the given vliw.
524 Returns TRUE if found, FALSE otherwise. */
527 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
531 for (i = 0; i < vliw->next_slot; ++i)
532 if (vliw->major[i] == major)
538 /* Check for constraints between the insns in the vliw due to major insn
542 fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
544 /* In the cpu file, all media insns are represented as being allowed in
545 both media units. This makes it easier since this is the case for fr500.
546 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
547 cannot coexist with any other media insn in a vliw. */
550 case FR400_MAJOR_M_2:
551 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
552 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
553 case FR400_MAJOR_M_1:
554 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
562 fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
564 CGEN_ATTR_VALUE_ENUM_TYPE other_major;
566 /* Our caller guarantees there's at least one other instruction. */
567 other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
569 /* (M4, M5) and (M4, M6) are allowed. */
570 if (other_major == FR450_MAJOR_M_4)
571 if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
574 /* Otherwise, instructions in even-numbered media categories cannot be
575 executed in parallel with other media instructions. */
578 case FR450_MAJOR_M_2:
579 case FR450_MAJOR_M_4:
580 case FR450_MAJOR_M_6:
581 return !(other_major >= FR450_MAJOR_M_1
582 && other_major <= FR450_MAJOR_M_6);
584 case FR450_MAJOR_M_1:
585 case FR450_MAJOR_M_3:
586 case FR450_MAJOR_M_5:
587 return !(other_major == FR450_MAJOR_M_2
588 || other_major == FR450_MAJOR_M_4
589 || other_major == FR450_MAJOR_M_6);
597 find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
601 for (i = 0; i < vliw->next_slot; ++i)
602 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
605 return false; /* Not found. */
609 find_major_in_slot (FRV_VLIW *vliw,
610 CGEN_ATTR_VALUE_ENUM_TYPE major,
611 CGEN_ATTR_VALUE_ENUM_TYPE slot)
615 for (i = 0; i < vliw->next_slot; ++i)
616 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
623 fr550_find_media_in_vliw (FRV_VLIW *vliw)
627 for (i = 0; i < vliw->next_slot; ++i)
629 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
632 /* Found a media insn, however, MNOP and MCLRACC don't count. */
633 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
634 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
635 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
638 return true; /* Found one. */
645 fr550_find_float_in_vliw (FRV_VLIW *vliw)
649 for (i = 0; i < vliw->next_slot; ++i)
651 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
654 /* Found a floating point insn, however, FNOP doesn't count. */
655 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
658 return true; /* Found one. */
665 fr550_check_insn_major_constraints (FRV_VLIW *vliw,
666 CGEN_ATTR_VALUE_ENUM_TYPE major,
667 const CGEN_INSN *insn)
669 CGEN_ATTR_VALUE_ENUM_TYPE unit;
670 CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
674 /* If it's a store, then there must be another store in I1 */
675 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
676 if (unit == UNIT_STORE)
677 return find_unit_in_vliw (vliw, UNIT_STORE);
681 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
683 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
684 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
685 return ! fr550_find_media_in_vliw (vliw);
686 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
687 floating point insns. */
688 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
689 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
690 return ! fr550_find_float_in_vliw (vliw);
691 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
693 if (major == FR550_MAJOR_F_2)
694 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
695 slot - (UNIT_FM2 - UNIT_FM0))
696 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
697 slot - (UNIT_FM2 - UNIT_FM0));
698 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
700 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
701 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
702 slot - (UNIT_FM2 - UNIT_FM0));
703 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
705 if (major == FR550_MAJOR_M_4)
706 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
707 slot - (UNIT_FM2 - UNIT_FM0));
712 return true; /* All OK. */
716 fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
718 /* TODO: A table might be faster for some of the more complex instances
722 case FR500_MAJOR_I_1:
723 case FR500_MAJOR_I_4:
724 case FR500_MAJOR_I_5:
725 case FR500_MAJOR_I_6:
726 case FR500_MAJOR_B_1:
727 case FR500_MAJOR_B_2:
728 case FR500_MAJOR_B_3:
729 case FR500_MAJOR_B_4:
730 case FR500_MAJOR_B_5:
731 case FR500_MAJOR_B_6:
732 case FR500_MAJOR_F_4:
733 case FR500_MAJOR_F_8:
734 case FR500_MAJOR_M_8:
735 return true; /* OK */
736 case FR500_MAJOR_I_2:
737 /* Cannot coexist with I-3 insn. */
738 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
739 case FR500_MAJOR_I_3:
740 /* Cannot coexist with I-2 insn. */
741 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
742 case FR500_MAJOR_F_1:
743 case FR500_MAJOR_F_2:
744 /* Cannot coexist with F-5, F-6, or M-7 insn. */
745 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
746 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
747 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
748 case FR500_MAJOR_F_3:
749 /* Cannot coexist with F-7, or M-7 insn. */
750 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
751 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
752 case FR500_MAJOR_F_5:
753 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
754 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
755 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
756 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
757 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
758 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
759 case FR500_MAJOR_F_6:
760 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
761 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
762 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
763 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
764 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
765 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
766 case FR500_MAJOR_F_7:
767 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
768 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
769 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
770 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
771 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
772 case FR500_MAJOR_M_1:
773 /* Cannot coexist with M-7 insn. */
774 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
775 case FR500_MAJOR_M_2:
776 case FR500_MAJOR_M_3:
777 /* Cannot coexist with M-5, M-6 or M-7 insn. */
778 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
779 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
780 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
781 case FR500_MAJOR_M_4:
782 /* Cannot coexist with M-6 insn. */
783 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
784 case FR500_MAJOR_M_5:
785 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
786 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
787 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
788 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
789 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
790 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
791 case FR500_MAJOR_M_6:
792 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
793 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
794 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
795 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
796 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
797 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
798 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
799 case FR500_MAJOR_M_7:
800 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
801 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
802 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
803 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
804 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
805 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
806 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
807 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
808 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
809 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
810 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
811 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
812 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
814 /* xgettext:c-format */
815 opcodes_error_handler (_("internal error: bad major code"));
823 check_insn_major_constraints (FRV_VLIW *vliw,
824 CGEN_ATTR_VALUE_ENUM_TYPE major,
825 const CGEN_INSN *insn)
830 return fr400_check_insn_major_constraints (vliw, major);
833 return fr450_check_insn_major_constraints (vliw, major);
836 return fr550_check_insn_major_constraints (vliw, major, insn);
839 return fr500_check_insn_major_constraints (vliw, major);
843 /* Add in insn to the VLIW vliw if possible.
844 Return 0 if successful, non-zero otherwise. */
847 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
850 CGEN_ATTR_VALUE_ENUM_TYPE major;
851 CGEN_ATTR_VALUE_ENUM_TYPE unit;
852 VLIW_COMBO *new_vliw;
854 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
857 slot_index = vliw->next_slot;
858 if (slot_index >= FRV_VLIW_SIZE)
861 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
862 if (unit == UNIT_NIL)
864 /* xgettext:c-format */
865 opcodes_error_handler (_("internal error: bad insn unit"));
872 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
875 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
878 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
881 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
887 /* Any insn can be added to slot 0. */
888 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
889 ++vliw->current_vliw;
890 vliw->major[0] = major;
891 vliw->insn[0] = insn;
896 /* If there are already insns in the vliw(s) check to see that
897 this one can be added. Do this by finding an allowable vliw
898 combination that can accept the new insn. */
899 if (! (vliw->elf_flags & EF_FRV_NOPACK))
901 new_vliw = add_next_to_vliw (vliw, unit);
902 if (new_vliw && check_insn_major_constraints (vliw, major, insn))
904 vliw->current_vliw = new_vliw;
905 vliw->major[slot_index] = major;
906 vliw->insn[slot_index] = insn;
911 /* The frv machine supports all packing conbinations. If we fail,
912 to add the insn, then it could not be handled as if it was the fr500.
913 Just return as if it was handled ok. */
914 if (vliw->mach == bfd_mach_frv)
918 vliw->constraint_violation = 1;
923 spr_valid (long regno)
925 if (regno < 0) return false;
926 if (regno <= 4095) return true;
932 inline static const char *
933 parse_symbolic_address (CGEN_CPU_DESC cd,
937 enum cgen_parse_operand_result *resultp,
940 enum cgen_parse_operand_result result_type;
941 const char *errmsg = (* cd->parse_operand_fn)
942 (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
943 &result_type, valuep);
946 && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
947 return "symbolic expression required";
950 *resultp = result_type;
956 parse_ldd_annotation (CGEN_CPU_DESC cd,
959 unsigned long *valuep)
962 enum cgen_parse_operand_result result_type;
965 if (**strp == '#' || **strp == '%')
967 if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
970 errmsg = parse_symbolic_address (cd, strp, opindex,
971 BFD_RELOC_FRV_TLSDESC_RELAX,
972 &result_type, &value);
974 return "missing ')'";
983 while (**strp == ' ' || **strp == '\t')
987 return "missing `@'";
995 parse_call_annotation (CGEN_CPU_DESC cd,
998 unsigned long *valuep)
1001 enum cgen_parse_operand_result result_type;
1004 if (**strp == '#' || **strp == '%')
1006 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1009 errmsg = parse_symbolic_address (cd, strp, opindex,
1010 BFD_RELOC_FRV_GETTLSOFF_RELAX,
1011 &result_type, &value);
1013 return "missing ')'";
1022 while (**strp == ' ' || **strp == '\t')
1026 return "missing `@'";
1034 parse_ld_annotation (CGEN_CPU_DESC cd,
1037 unsigned long *valuep)
1040 enum cgen_parse_operand_result result_type;
1043 if (**strp == '#' || **strp == '%')
1045 if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
1048 errmsg = parse_symbolic_address (cd, strp, opindex,
1049 BFD_RELOC_FRV_TLSOFF_RELAX,
1050 &result_type, &value);
1052 return "missing ')'";
1061 while (**strp == ' ' || **strp == '\t')
1065 return "missing `@'";
1073 parse_ulo16 (CGEN_CPU_DESC cd,
1076 unsigned long *valuep)
1079 enum cgen_parse_operand_result result_type;
1082 if (**strp == '#' || **strp == '%')
1084 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1087 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1088 & result_type, & value);
1090 return "missing `)'";
1093 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1098 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1101 errmsg = parse_symbolic_address (cd, strp, opindex,
1102 BFD_RELOC_FRV_GPRELLO,
1103 & result_type, & value);
1105 return "missing ')'";
1110 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1113 errmsg = parse_symbolic_address (cd, strp, opindex,
1114 BFD_RELOC_FRV_GOTLO,
1115 & result_type, & value);
1117 return "missing ')'";
1122 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1125 errmsg = parse_symbolic_address (cd, strp, opindex,
1126 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1127 & result_type, & value);
1129 return "missing ')'";
1134 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1137 errmsg = parse_symbolic_address (cd, strp, opindex,
1138 BFD_RELOC_FRV_GOTOFFLO,
1139 & result_type, & value);
1141 return "missing ')'";
1146 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1149 errmsg = parse_symbolic_address (cd, strp, opindex,
1150 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1151 & result_type, & value);
1153 return "missing ')'";
1158 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1161 errmsg = parse_symbolic_address (cd, strp, opindex,
1162 BFD_RELOC_FRV_GOTTLSDESCLO,
1163 & result_type, & value);
1165 return "missing ')'";
1170 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1173 errmsg = parse_symbolic_address (cd, strp, opindex,
1174 BFD_RELOC_FRV_TLSMOFFLO,
1175 & result_type, & value);
1177 return "missing ')'";
1182 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1185 errmsg = parse_symbolic_address (cd, strp, opindex,
1186 BFD_RELOC_FRV_GOTTLSOFFLO,
1187 & result_type, & value);
1189 return "missing ')'";
1195 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1199 parse_uslo16 (CGEN_CPU_DESC cd,
1202 signed long *valuep)
1205 enum cgen_parse_operand_result result_type;
1208 if (**strp == '#' || **strp == '%')
1210 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1213 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1214 & result_type, & value);
1216 return "missing `)'";
1219 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1224 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1227 errmsg = parse_symbolic_address (cd, strp, opindex,
1228 BFD_RELOC_FRV_GPRELLO,
1229 & result_type, & value);
1231 return "missing ')'";
1236 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1239 errmsg = parse_symbolic_address (cd, strp, opindex,
1240 BFD_RELOC_FRV_GOTLO,
1241 & result_type, & value);
1243 return "missing ')'";
1248 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1251 errmsg = parse_symbolic_address (cd, strp, opindex,
1252 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1253 & result_type, & value);
1255 return "missing ')'";
1260 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1263 errmsg = parse_symbolic_address (cd, strp, opindex,
1264 BFD_RELOC_FRV_GOTOFFLO,
1265 & result_type, & value);
1267 return "missing ')'";
1272 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1275 errmsg = parse_symbolic_address (cd, strp, opindex,
1276 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1277 & result_type, & value);
1279 return "missing ')'";
1284 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1287 errmsg = parse_symbolic_address (cd, strp, opindex,
1288 BFD_RELOC_FRV_GOTTLSDESCLO,
1289 & result_type, & value);
1291 return "missing ')'";
1296 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1299 errmsg = parse_symbolic_address (cd, strp, opindex,
1300 BFD_RELOC_FRV_TLSMOFFLO,
1301 & result_type, & value);
1303 return "missing ')'";
1308 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1311 errmsg = parse_symbolic_address (cd, strp, opindex,
1312 BFD_RELOC_FRV_GOTTLSOFFLO,
1313 & result_type, & value);
1315 return "missing ')'";
1321 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1325 parse_uhi16 (CGEN_CPU_DESC cd,
1328 unsigned long *valuep)
1331 enum cgen_parse_operand_result result_type;
1334 if (**strp == '#' || **strp == '%')
1336 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1339 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1340 & result_type, & value);
1342 return "missing `)'";
1345 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1347 /* If value is wider than 32 bits then be
1348 careful about how we extract bits 16-31. */
1349 if (sizeof (value) > 4)
1350 value &= (((bfd_vma)1 << 16) << 16) - 1;
1357 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1360 errmsg = parse_symbolic_address (cd, strp, opindex,
1361 BFD_RELOC_FRV_GPRELHI,
1362 & result_type, & value);
1364 return "missing ')'";
1369 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1372 errmsg = parse_symbolic_address (cd, strp, opindex,
1373 BFD_RELOC_FRV_GOTHI,
1374 & result_type, & value);
1376 return "missing ')'";
1381 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1384 errmsg = parse_symbolic_address (cd, strp, opindex,
1385 BFD_RELOC_FRV_FUNCDESC_GOTHI,
1386 & result_type, & value);
1388 return "missing ')'";
1393 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1396 errmsg = parse_symbolic_address (cd, strp, opindex,
1397 BFD_RELOC_FRV_GOTOFFHI,
1398 & result_type, & value);
1400 return "missing ')'";
1405 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1408 errmsg = parse_symbolic_address (cd, strp, opindex,
1409 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1410 & result_type, & value);
1412 return "missing ')'";
1417 else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
1420 errmsg = parse_symbolic_address (cd, strp, opindex,
1421 BFD_RELOC_FRV_GOTTLSDESCHI,
1422 &result_type, &value);
1424 return "missing ')'";
1429 else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
1432 errmsg = parse_symbolic_address (cd, strp, opindex,
1433 BFD_RELOC_FRV_TLSMOFFHI,
1434 & result_type, & value);
1436 return "missing ')'";
1441 else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
1444 errmsg = parse_symbolic_address (cd, strp, opindex,
1445 BFD_RELOC_FRV_GOTTLSOFFHI,
1446 & result_type, & value);
1448 return "missing ')'";
1454 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1458 parse_register_number (const char **strp)
1462 if (**strp < '0' || **strp > '9')
1463 return -1; /* error */
1465 regno = **strp - '0';
1466 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1467 regno = regno * 10 + (**strp - '0');
1473 parse_spr (CGEN_CPU_DESC cd,
1475 CGEN_KEYWORD * table,
1478 const char *save_strp;
1481 /* Check for spr index notation. */
1482 if (strncasecmp (*strp, "spr[", 4) == 0)
1485 regno = parse_register_number (strp);
1487 return _("missing `]'");
1489 if (! spr_valid (regno))
1490 return _("Special purpose register number is out of range");
1496 regno = parse_register_number (strp);
1499 if (! spr_valid (regno))
1500 return _("Special purpose register number is out of range");
1506 return cgen_parse_keyword (cd, strp, table, valuep);
1510 parse_d12 (CGEN_CPU_DESC cd,
1516 enum cgen_parse_operand_result result_type;
1519 /* Check for small data reference. */
1520 if (**strp == '#' || **strp == '%')
1522 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1525 errmsg = parse_symbolic_address (cd, strp, opindex,
1526 BFD_RELOC_FRV_GPREL12,
1527 & result_type, & value);
1529 return "missing `)'";
1534 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1537 errmsg = parse_symbolic_address (cd, strp, opindex,
1538 BFD_RELOC_FRV_GOT12,
1539 & result_type, & value);
1541 return "missing ')'";
1546 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1549 errmsg = parse_symbolic_address (cd, strp, opindex,
1550 BFD_RELOC_FRV_FUNCDESC_GOT12,
1551 & result_type, & value);
1553 return "missing ')'";
1558 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1561 errmsg = parse_symbolic_address (cd, strp, opindex,
1562 BFD_RELOC_FRV_GOTOFF12,
1563 & result_type, & value);
1565 return "missing ')'";
1570 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1573 errmsg = parse_symbolic_address (cd, strp, opindex,
1574 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1575 & result_type, & value);
1577 return "missing ')'";
1582 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1585 errmsg = parse_symbolic_address (cd, strp, opindex,
1586 BFD_RELOC_FRV_GOTTLSDESC12,
1587 & result_type, & value);
1589 return "missing ')'";
1594 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1597 errmsg = parse_symbolic_address (cd, strp, opindex,
1598 BFD_RELOC_FRV_TLSMOFF12,
1599 & result_type, & value);
1601 return "missing ')'";
1606 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1609 errmsg = parse_symbolic_address (cd, strp, opindex,
1610 BFD_RELOC_FRV_GOTTLSOFF12,
1611 & result_type, & value);
1613 return "missing ')'";
1619 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1623 parse_s12 (CGEN_CPU_DESC cd,
1629 enum cgen_parse_operand_result result_type;
1632 /* Check for small data reference. */
1633 if (**strp == '#' || **strp == '%')
1635 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1638 errmsg = parse_symbolic_address (cd, strp, opindex,
1639 BFD_RELOC_FRV_GPREL12,
1640 & result_type, & value);
1642 return "missing `)'";
1647 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1650 errmsg = parse_symbolic_address (cd, strp, opindex,
1651 BFD_RELOC_FRV_GOT12,
1652 & result_type, & value);
1654 return "missing ')'";
1659 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1662 errmsg = parse_symbolic_address (cd, strp, opindex,
1663 BFD_RELOC_FRV_FUNCDESC_GOT12,
1664 & result_type, & value);
1666 return "missing ')'";
1671 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1674 errmsg = parse_symbolic_address (cd, strp, opindex,
1675 BFD_RELOC_FRV_GOTOFF12,
1676 & result_type, & value);
1678 return "missing ')'";
1683 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1686 errmsg = parse_symbolic_address (cd, strp, opindex,
1687 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1688 & result_type, & value);
1690 return "missing ')'";
1695 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1698 errmsg = parse_symbolic_address (cd, strp, opindex,
1699 BFD_RELOC_FRV_GOTTLSDESC12,
1700 & result_type, & value);
1702 return "missing ')'";
1707 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1710 errmsg = parse_symbolic_address (cd, strp, opindex,
1711 BFD_RELOC_FRV_TLSMOFF12,
1712 & result_type, & value);
1714 return "missing ')'";
1719 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1722 errmsg = parse_symbolic_address (cd, strp, opindex,
1723 BFD_RELOC_FRV_GOTTLSOFF12,
1724 & result_type, & value);
1726 return "missing ')'";
1735 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1739 parse_u12 (CGEN_CPU_DESC cd,
1745 enum cgen_parse_operand_result result_type;
1748 /* Check for small data reference. */
1749 if ((**strp == '#' || **strp == '%')
1750 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1753 errmsg = parse_symbolic_address (cd, strp, opindex,
1754 BFD_RELOC_FRV_GPRELU12,
1755 & result_type, & value);
1757 return "missing `)'";
1766 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1771 parse_A (CGEN_CPU_DESC cd,
1774 unsigned long *valuep,
1782 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1787 return _("Value of A operand must be 0 or 1");
1793 parse_A0 (CGEN_CPU_DESC cd,
1796 unsigned long *valuep)
1798 return parse_A (cd, strp, opindex, valuep, 0);
1802 parse_A1 (CGEN_CPU_DESC cd,
1805 unsigned long *valuep)
1807 return parse_A (cd, strp, opindex, valuep, 1);
1811 parse_even_register (CGEN_CPU_DESC cd,
1813 CGEN_KEYWORD * tableP,
1816 const char * errmsg;
1817 const char * saved_star_strP = * strP;
1819 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1821 if (errmsg == NULL && ((* valueP) & 1))
1823 errmsg = _("register number must be even");
1824 * strP = saved_star_strP;
1831 parse_call_label (CGEN_CPU_DESC cd,
1835 enum cgen_parse_operand_result *resultp,
1841 /* Check for small data reference. */
1842 if (opinfo == 0 && (**strp == '#' || **strp == '%'))
1844 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1847 errmsg = parse_symbolic_address (cd, strp, opindex,
1848 BFD_RELOC_FRV_GETTLSOFF,
1851 return _("missing `)'");
1858 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
1865 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1867 long reloc_ann ATTRIBUTE_UNUSED,
1868 long value ATTRIBUTE_UNUSED,
1869 bfd_vma pc ATTRIBUTE_UNUSED,
1870 int length ATTRIBUTE_UNUSED)
1872 disassemble_info *info = (disassemble_info *) dis_info;
1874 (*info->fprintf_func) (info->stream, "@");
1878 print_spr (CGEN_CPU_DESC cd,
1880 CGEN_KEYWORD *names,
1884 /* Use the register index format for any unnamed registers. */
1885 if (cgen_keyword_lookup_value (names, regno) == NULL)
1887 disassemble_info *info = (disassemble_info *) dis_info;
1888 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1891 print_keyword (cd, dis_info, names, regno, attrs);
1895 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1898 unsigned int attrs ATTRIBUTE_UNUSED,
1899 bfd_vma pc ATTRIBUTE_UNUSED,
1900 int length ATTRIBUTE_UNUSED)
1902 disassemble_info *info = (disassemble_info *) dis_info;
1904 (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
1908 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1911 unsigned int attrs ATTRIBUTE_UNUSED,
1912 bfd_vma pc ATTRIBUTE_UNUSED,
1913 int length ATTRIBUTE_UNUSED)
1915 disassemble_info *info = (disassemble_info *) dis_info;
1917 (*info->fprintf_func) (info->stream, "0x%lx", value);
1919 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);