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 /* DEBUG appears below as argument of OP macro. */
87 /* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
91 frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
96 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
100 if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
104 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
112 /* Returns TRUE if {MAJOR,MACH} supports floating point insns. */
115 frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
123 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
131 /* Returns TRUE if {MAJOR,MACH} supports media insns. */
134 frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
139 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
143 if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
147 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
156 frv_is_branch_insn (const CGEN_INSN *insn)
158 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
161 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
164 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
172 frv_is_float_insn (const CGEN_INSN *insn)
174 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
177 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
180 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
188 frv_is_media_insn (const CGEN_INSN *insn)
190 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
193 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
196 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
203 /* This table represents the allowable packing for vliw insns for the fr400.
204 The fr400 has only 2 vliw slots. Represent this by not allowing any insns
206 Subsets of any given row are also allowed. */
207 static VLIW_COMBO fr400_allowed_vliw[] =
209 /* slot0 slot1 slot2 slot3 */
210 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
211 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
212 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
213 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
214 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
215 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
216 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
217 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
220 /* This table represents the allowable packing for vliw insns for the fr500.
221 The fr500 has only 4 vliw slots. Represent this by not allowing any insns
223 Subsets of any given row are also allowed. */
224 static VLIW_COMBO fr500_allowed_vliw[] =
226 /* slot0 slot1 slot2 slot3 */
227 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO },
228 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO },
229 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO },
230 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
231 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
232 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
233 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
234 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
235 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
236 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
237 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
240 /* This table represents the allowable packing for vliw insns for the fr550.
241 Subsets of any given row are also allowed. */
242 static VLIW_COMBO fr550_allowed_vliw[] =
244 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */
245 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL },
246 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL },
247 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
248 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
249 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 },
250 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 },
251 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 },
252 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 },
253 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 },
254 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL },
255 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
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_B0, UNIT_B1, UNIT_NIL },
258 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
259 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL },
260 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
261 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
262 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL },
263 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
264 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
265 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
266 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
267 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
268 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
269 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
270 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
271 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
272 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
275 /* Some insns are assigned specialized implementation units which map to
276 different actual implementation units on different machines. These
277 tables perform that mapping. */
278 static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
280 /* unit in insn actual unit */
285 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
287 /* IALL */ UNIT_I01, /* only I0 and I1 units */
290 /* FM01 */ UNIT_FM01,
291 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
292 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
293 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
294 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
295 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
299 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
300 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
301 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
302 /* STORE */ UNIT_I0, /* store only in I0 unit. */
303 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
304 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
305 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
306 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
307 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
310 /* Some insns are assigned specialized implementation units which map to
311 different actual implementation units on different machines. These
312 tables perform that mapping. */
313 static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
315 /* unit in insn actual unit */
320 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
322 /* IALL */ UNIT_I01, /* only I0 and I1 units */
325 /* FM01 */ UNIT_FM01,
326 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
327 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
328 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
329 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
330 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
334 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
335 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
336 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
337 /* STORE */ UNIT_I0, /* store only in I0 unit. */
338 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
339 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
340 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
341 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1. */
342 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
345 static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
347 /* unit in insn actual unit */
352 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
354 /* IALL */ UNIT_I01, /* only I0 and I1 units */
357 /* FM01 */ UNIT_FM01,
358 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
359 /* FM3 */ UNIT_NIL, /* no F3 or M2 units */
360 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
361 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
366 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
367 /* IACC */ UNIT_NIL, /* iacc multiply not implemented */
368 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
369 /* STORE */ UNIT_I0, /* store only in I0 unit. */
370 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
371 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
372 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
373 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
374 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
377 static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
379 /* unit in insn actual unit */
386 /* IALL */ UNIT_IALL,
389 /* FM01 */ UNIT_FM01,
392 /* FMALL */ UNIT_FMALL,
393 /* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */
398 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
399 /* IACC */ UNIT_NIL, /* iacc multiply not implemented. */
400 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
401 /* STORE */ UNIT_I01, /* store in I0 or I1 unit. */
402 /* SCAN */ UNIT_IALL, /* scan in any integer unit. */
403 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
404 /* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */
405 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1 unit. */
406 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
410 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
413 vliw->constraint_violation = 0;
415 vliw->elf_flags = elf_flags;
420 vliw->current_vliw = fr400_allowed_vliw;
421 vliw->unit_mapping = fr400_unit_mapping;
424 vliw->current_vliw = fr400_allowed_vliw;
425 vliw->unit_mapping = fr450_unit_mapping;
428 vliw->current_vliw = fr550_allowed_vliw;
429 vliw->unit_mapping = fr550_unit_mapping;
432 vliw->current_vliw = fr500_allowed_vliw;
433 vliw->unit_mapping = fr500_unit_mapping;
438 /* Return TRUE if unit1 is a match for unit2.
439 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
440 *_allowed_vliw tables above. */
442 match_unit (FRV_VLIW *vliw,
443 CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
445 /* Map any specialized implementation units to actual ones. */
446 unit1 = vliw->unit_mapping[unit1];
458 /* The 01 versions of these units are within 2 enums of the 0 or 1
460 if (unit1 - unit2 <= 2)
465 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
467 if (unit1 - unit2 <= 5)
477 /* Return TRUE if the vliws match, FALSE otherwise. */
480 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
484 for (i = 0; i < vliw_size; ++i)
485 if ((*vliw1)[i] != (*vliw2)[i])
491 /* Find the next vliw vliw in the table that can accomodate the new insn.
492 If one is found then return it. Otherwise return NULL. */
495 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
497 int next = vliw->next_slot;
498 VLIW_COMBO *current = vliw->current_vliw;
499 VLIW_COMBO *potential;
503 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
505 abort (); /* Should never happen. */
508 /* The table is sorted by units allowed within slots, so vliws with
509 identical starting sequences are together. */
513 if (match_unit (vliw, unit, (*potential)[next]))
517 while (match_vliw (potential, current, next));
522 /* Look for the given major insn type in the given vliw.
523 Returns TRUE if found, FALSE otherwise. */
526 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
530 for (i = 0; i < vliw->next_slot; ++i)
531 if (vliw->major[i] == major)
537 /* Check for constraints between the insns in the vliw due to major insn
541 fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
543 /* In the cpu file, all media insns are represented as being allowed in
544 both media units. This makes it easier since this is the case for fr500.
545 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
546 cannot coexist with any other media insn in a vliw. */
549 case FR400_MAJOR_M_2:
550 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
551 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
552 case FR400_MAJOR_M_1:
553 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
561 fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
563 CGEN_ATTR_VALUE_ENUM_TYPE other_major;
565 /* Our caller guarantees there's at least one other instruction. */
566 other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
568 /* (M4, M5) and (M4, M6) are allowed. */
569 if (other_major == FR450_MAJOR_M_4)
570 if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
573 /* Otherwise, instructions in even-numbered media categories cannot be
574 executed in parallel with other media instructions. */
577 case FR450_MAJOR_M_2:
578 case FR450_MAJOR_M_4:
579 case FR450_MAJOR_M_6:
580 return !(other_major >= FR450_MAJOR_M_1
581 && other_major <= FR450_MAJOR_M_6);
583 case FR450_MAJOR_M_1:
584 case FR450_MAJOR_M_3:
585 case FR450_MAJOR_M_5:
586 return !(other_major == FR450_MAJOR_M_2
587 || other_major == FR450_MAJOR_M_4
588 || other_major == FR450_MAJOR_M_6);
596 find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
600 for (i = 0; i < vliw->next_slot; ++i)
601 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
604 return FALSE; /* Not found. */
608 find_major_in_slot (FRV_VLIW *vliw,
609 CGEN_ATTR_VALUE_ENUM_TYPE major,
610 CGEN_ATTR_VALUE_ENUM_TYPE slot)
614 for (i = 0; i < vliw->next_slot; ++i)
615 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
622 fr550_find_media_in_vliw (FRV_VLIW *vliw)
626 for (i = 0; i < vliw->next_slot; ++i)
628 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
631 /* Found a media insn, however, MNOP and MCLRACC don't count. */
632 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
633 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
634 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
637 return TRUE; /* Found one. */
644 fr550_find_float_in_vliw (FRV_VLIW *vliw)
648 for (i = 0; i < vliw->next_slot; ++i)
650 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
653 /* Found a floating point insn, however, FNOP doesn't count. */
654 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
657 return TRUE; /* Found one. */
664 fr550_check_insn_major_constraints (FRV_VLIW *vliw,
665 CGEN_ATTR_VALUE_ENUM_TYPE major,
666 const CGEN_INSN *insn)
668 CGEN_ATTR_VALUE_ENUM_TYPE unit;
669 CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
673 /* If it's a store, then there must be another store in I1 */
674 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
675 if (unit == UNIT_STORE)
676 return find_unit_in_vliw (vliw, UNIT_STORE);
680 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
682 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
683 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
684 return ! fr550_find_media_in_vliw (vliw);
685 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
686 floating point insns. */
687 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
688 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
689 return ! fr550_find_float_in_vliw (vliw);
690 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
692 if (major == FR550_MAJOR_F_2)
693 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
694 slot - (UNIT_FM2 - UNIT_FM0))
695 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
696 slot - (UNIT_FM2 - UNIT_FM0));
697 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
699 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
700 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
701 slot - (UNIT_FM2 - UNIT_FM0));
702 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
704 if (major == FR550_MAJOR_M_4)
705 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
706 slot - (UNIT_FM2 - UNIT_FM0));
711 return TRUE; /* All OK. */
715 fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
717 /* TODO: A table might be faster for some of the more complex instances
721 case FR500_MAJOR_I_1:
722 case FR500_MAJOR_I_4:
723 case FR500_MAJOR_I_5:
724 case FR500_MAJOR_I_6:
725 case FR500_MAJOR_B_1:
726 case FR500_MAJOR_B_2:
727 case FR500_MAJOR_B_3:
728 case FR500_MAJOR_B_4:
729 case FR500_MAJOR_B_5:
730 case FR500_MAJOR_B_6:
731 case FR500_MAJOR_F_4:
732 case FR500_MAJOR_F_8:
733 case FR500_MAJOR_M_8:
734 return TRUE; /* OK */
735 case FR500_MAJOR_I_2:
736 /* Cannot coexist with I-3 insn. */
737 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
738 case FR500_MAJOR_I_3:
739 /* Cannot coexist with I-2 insn. */
740 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
741 case FR500_MAJOR_F_1:
742 case FR500_MAJOR_F_2:
743 /* Cannot coexist with F-5, F-6, or M-7 insn. */
744 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
745 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
746 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
747 case FR500_MAJOR_F_3:
748 /* Cannot coexist with F-7, or M-7 insn. */
749 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
750 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
751 case FR500_MAJOR_F_5:
752 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
753 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
754 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
755 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
756 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
757 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
758 case FR500_MAJOR_F_6:
759 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
760 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
761 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
762 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
763 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
764 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
765 case FR500_MAJOR_F_7:
766 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
767 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
768 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
769 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
770 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
771 case FR500_MAJOR_M_1:
772 /* Cannot coexist with M-7 insn. */
773 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
774 case FR500_MAJOR_M_2:
775 case FR500_MAJOR_M_3:
776 /* Cannot coexist with M-5, M-6 or M-7 insn. */
777 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
778 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
779 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
780 case FR500_MAJOR_M_4:
781 /* Cannot coexist with M-6 insn. */
782 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
783 case FR500_MAJOR_M_5:
784 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
785 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
786 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
787 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
788 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
789 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
790 case FR500_MAJOR_M_6:
791 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
792 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
793 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
794 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
795 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
796 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
797 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
798 case FR500_MAJOR_M_7:
799 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
800 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
801 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
802 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
803 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
804 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
805 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
806 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
807 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
808 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
809 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
810 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
811 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
813 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
822 check_insn_major_constraints (FRV_VLIW *vliw,
823 CGEN_ATTR_VALUE_ENUM_TYPE major,
824 const CGEN_INSN *insn)
829 return fr400_check_insn_major_constraints (vliw, major);
832 return fr450_check_insn_major_constraints (vliw, major);
835 return fr550_check_insn_major_constraints (vliw, major, insn);
838 return fr500_check_insn_major_constraints (vliw, major);
842 /* Add in insn to the VLIW vliw if possible.
843 Return 0 if successful, non-zero otherwise. */
846 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
849 CGEN_ATTR_VALUE_ENUM_TYPE major;
850 CGEN_ATTR_VALUE_ENUM_TYPE unit;
851 VLIW_COMBO *new_vliw;
853 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
856 slot_index = vliw->next_slot;
857 if (slot_index >= FRV_VLIW_SIZE)
860 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
861 if (unit == UNIT_NIL)
863 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
865 abort (); /* No UNIT specified for this insn in frv.cpu. */
871 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
874 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
877 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
880 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
886 /* Any insn can be added to slot 0. */
887 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
888 ++vliw->current_vliw;
889 vliw->major[0] = major;
890 vliw->insn[0] = insn;
895 /* If there are already insns in the vliw(s) check to see that
896 this one can be added. Do this by finding an allowable vliw
897 combination that can accept the new insn. */
898 if (! (vliw->elf_flags & EF_FRV_NOPACK))
900 new_vliw = add_next_to_vliw (vliw, unit);
901 if (new_vliw && check_insn_major_constraints (vliw, major, insn))
903 vliw->current_vliw = new_vliw;
904 vliw->major[slot_index] = major;
905 vliw->insn[slot_index] = insn;
910 /* The frv machine supports all packing conbinations. If we fail,
911 to add the insn, then it could not be handled as if it was the fr500.
912 Just return as if it was handled ok. */
913 if (vliw->mach == bfd_mach_frv)
917 vliw->constraint_violation = 1;
922 spr_valid (long regno)
924 if (regno < 0) return FALSE;
925 if (regno <= 4095) return TRUE;
931 inline static const char *
932 parse_symbolic_address (CGEN_CPU_DESC cd,
936 enum cgen_parse_operand_result *resultp,
939 enum cgen_parse_operand_result result_type;
940 const char *errmsg = (* cd->parse_operand_fn)
941 (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
942 &result_type, valuep);
945 && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
946 return "symbolic expression required";
949 *resultp = result_type;
955 parse_ldd_annotation (CGEN_CPU_DESC cd,
958 unsigned long *valuep)
961 enum cgen_parse_operand_result result_type;
964 if (**strp == '#' || **strp == '%')
966 if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
969 errmsg = parse_symbolic_address (cd, strp, opindex,
970 BFD_RELOC_FRV_TLSDESC_RELAX,
971 &result_type, &value);
973 return "missing ')'";
982 while (**strp == ' ' || **strp == '\t')
986 return "missing `@'";
994 parse_call_annotation (CGEN_CPU_DESC cd,
997 unsigned long *valuep)
1000 enum cgen_parse_operand_result result_type;
1003 if (**strp == '#' || **strp == '%')
1005 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1008 errmsg = parse_symbolic_address (cd, strp, opindex,
1009 BFD_RELOC_FRV_GETTLSOFF_RELAX,
1010 &result_type, &value);
1012 return "missing ')'";
1021 while (**strp == ' ' || **strp == '\t')
1025 return "missing `@'";
1033 parse_ld_annotation (CGEN_CPU_DESC cd,
1036 unsigned long *valuep)
1039 enum cgen_parse_operand_result result_type;
1042 if (**strp == '#' || **strp == '%')
1044 if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
1047 errmsg = parse_symbolic_address (cd, strp, opindex,
1048 BFD_RELOC_FRV_TLSOFF_RELAX,
1049 &result_type, &value);
1051 return "missing ')'";
1060 while (**strp == ' ' || **strp == '\t')
1064 return "missing `@'";
1072 parse_ulo16 (CGEN_CPU_DESC cd,
1075 unsigned long *valuep)
1078 enum cgen_parse_operand_result result_type;
1081 if (**strp == '#' || **strp == '%')
1083 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1086 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1087 & result_type, & value);
1089 return "missing `)'";
1092 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1097 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1100 errmsg = parse_symbolic_address (cd, strp, opindex,
1101 BFD_RELOC_FRV_GPRELLO,
1102 & result_type, & value);
1104 return "missing ')'";
1109 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1112 errmsg = parse_symbolic_address (cd, strp, opindex,
1113 BFD_RELOC_FRV_GOTLO,
1114 & result_type, & value);
1116 return "missing ')'";
1121 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1124 errmsg = parse_symbolic_address (cd, strp, opindex,
1125 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1126 & result_type, & value);
1128 return "missing ')'";
1133 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1136 errmsg = parse_symbolic_address (cd, strp, opindex,
1137 BFD_RELOC_FRV_GOTOFFLO,
1138 & result_type, & value);
1140 return "missing ')'";
1145 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1148 errmsg = parse_symbolic_address (cd, strp, opindex,
1149 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1150 & result_type, & value);
1152 return "missing ')'";
1157 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1160 errmsg = parse_symbolic_address (cd, strp, opindex,
1161 BFD_RELOC_FRV_GOTTLSDESCLO,
1162 & result_type, & value);
1164 return "missing ')'";
1169 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1172 errmsg = parse_symbolic_address (cd, strp, opindex,
1173 BFD_RELOC_FRV_TLSMOFFLO,
1174 & result_type, & value);
1176 return "missing ')'";
1181 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1184 errmsg = parse_symbolic_address (cd, strp, opindex,
1185 BFD_RELOC_FRV_GOTTLSOFFLO,
1186 & result_type, & value);
1188 return "missing ')'";
1194 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1198 parse_uslo16 (CGEN_CPU_DESC cd,
1201 signed long *valuep)
1204 enum cgen_parse_operand_result result_type;
1207 if (**strp == '#' || **strp == '%')
1209 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1212 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1213 & result_type, & value);
1215 return "missing `)'";
1218 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1223 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1226 errmsg = parse_symbolic_address (cd, strp, opindex,
1227 BFD_RELOC_FRV_GPRELLO,
1228 & result_type, & value);
1230 return "missing ')'";
1235 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1238 errmsg = parse_symbolic_address (cd, strp, opindex,
1239 BFD_RELOC_FRV_GOTLO,
1240 & result_type, & value);
1242 return "missing ')'";
1247 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1250 errmsg = parse_symbolic_address (cd, strp, opindex,
1251 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1252 & result_type, & value);
1254 return "missing ')'";
1259 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1262 errmsg = parse_symbolic_address (cd, strp, opindex,
1263 BFD_RELOC_FRV_GOTOFFLO,
1264 & result_type, & value);
1266 return "missing ')'";
1271 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1274 errmsg = parse_symbolic_address (cd, strp, opindex,
1275 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1276 & result_type, & value);
1278 return "missing ')'";
1283 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1286 errmsg = parse_symbolic_address (cd, strp, opindex,
1287 BFD_RELOC_FRV_GOTTLSDESCLO,
1288 & result_type, & value);
1290 return "missing ')'";
1295 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1298 errmsg = parse_symbolic_address (cd, strp, opindex,
1299 BFD_RELOC_FRV_TLSMOFFLO,
1300 & result_type, & value);
1302 return "missing ')'";
1307 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1310 errmsg = parse_symbolic_address (cd, strp, opindex,
1311 BFD_RELOC_FRV_GOTTLSOFFLO,
1312 & result_type, & value);
1314 return "missing ')'";
1320 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1324 parse_uhi16 (CGEN_CPU_DESC cd,
1327 unsigned long *valuep)
1330 enum cgen_parse_operand_result result_type;
1333 if (**strp == '#' || **strp == '%')
1335 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1338 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1339 & result_type, & value);
1341 return "missing `)'";
1344 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1346 /* If value is wider than 32 bits then be
1347 careful about how we extract bits 16-31. */
1348 if (sizeof (value) > 4)
1349 value &= (((bfd_vma)1 << 16) << 16) - 1;
1356 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1359 errmsg = parse_symbolic_address (cd, strp, opindex,
1360 BFD_RELOC_FRV_GPRELHI,
1361 & result_type, & value);
1363 return "missing ')'";
1368 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1371 errmsg = parse_symbolic_address (cd, strp, opindex,
1372 BFD_RELOC_FRV_GOTHI,
1373 & result_type, & value);
1375 return "missing ')'";
1380 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1383 errmsg = parse_symbolic_address (cd, strp, opindex,
1384 BFD_RELOC_FRV_FUNCDESC_GOTHI,
1385 & result_type, & value);
1387 return "missing ')'";
1392 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1395 errmsg = parse_symbolic_address (cd, strp, opindex,
1396 BFD_RELOC_FRV_GOTOFFHI,
1397 & result_type, & value);
1399 return "missing ')'";
1404 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1407 errmsg = parse_symbolic_address (cd, strp, opindex,
1408 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1409 & result_type, & value);
1411 return "missing ')'";
1416 else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
1419 errmsg = parse_symbolic_address (cd, strp, opindex,
1420 BFD_RELOC_FRV_GOTTLSDESCHI,
1421 &result_type, &value);
1423 return "missing ')'";
1428 else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
1431 errmsg = parse_symbolic_address (cd, strp, opindex,
1432 BFD_RELOC_FRV_TLSMOFFHI,
1433 & result_type, & value);
1435 return "missing ')'";
1440 else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
1443 errmsg = parse_symbolic_address (cd, strp, opindex,
1444 BFD_RELOC_FRV_GOTTLSOFFHI,
1445 & result_type, & value);
1447 return "missing ')'";
1453 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1457 parse_register_number (const char **strp)
1461 if (**strp < '0' || **strp > '9')
1462 return -1; /* error */
1464 regno = **strp - '0';
1465 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1466 regno = regno * 10 + (**strp - '0');
1472 parse_spr (CGEN_CPU_DESC cd,
1474 CGEN_KEYWORD * table,
1477 const char *save_strp;
1480 /* Check for spr index notation. */
1481 if (strncasecmp (*strp, "spr[", 4) == 0)
1484 regno = parse_register_number (strp);
1486 return _("missing `]'");
1488 if (! spr_valid (regno))
1489 return _("Special purpose register number is out of range");
1495 regno = parse_register_number (strp);
1498 if (! spr_valid (regno))
1499 return _("Special purpose register number is out of range");
1505 return cgen_parse_keyword (cd, strp, table, valuep);
1509 parse_d12 (CGEN_CPU_DESC cd,
1515 enum cgen_parse_operand_result result_type;
1518 /* Check for small data reference. */
1519 if (**strp == '#' || **strp == '%')
1521 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1524 errmsg = parse_symbolic_address (cd, strp, opindex,
1525 BFD_RELOC_FRV_GPREL12,
1526 & result_type, & value);
1528 return "missing `)'";
1533 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1536 errmsg = parse_symbolic_address (cd, strp, opindex,
1537 BFD_RELOC_FRV_GOT12,
1538 & result_type, & value);
1540 return "missing ')'";
1545 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1548 errmsg = parse_symbolic_address (cd, strp, opindex,
1549 BFD_RELOC_FRV_FUNCDESC_GOT12,
1550 & result_type, & value);
1552 return "missing ')'";
1557 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1560 errmsg = parse_symbolic_address (cd, strp, opindex,
1561 BFD_RELOC_FRV_GOTOFF12,
1562 & result_type, & value);
1564 return "missing ')'";
1569 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1572 errmsg = parse_symbolic_address (cd, strp, opindex,
1573 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1574 & result_type, & value);
1576 return "missing ')'";
1581 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1584 errmsg = parse_symbolic_address (cd, strp, opindex,
1585 BFD_RELOC_FRV_GOTTLSDESC12,
1586 & result_type, & value);
1588 return "missing ')'";
1593 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1596 errmsg = parse_symbolic_address (cd, strp, opindex,
1597 BFD_RELOC_FRV_TLSMOFF12,
1598 & result_type, & value);
1600 return "missing ')'";
1605 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1608 errmsg = parse_symbolic_address (cd, strp, opindex,
1609 BFD_RELOC_FRV_GOTTLSOFF12,
1610 & result_type, & value);
1612 return "missing ')'";
1618 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1622 parse_s12 (CGEN_CPU_DESC cd,
1628 enum cgen_parse_operand_result result_type;
1631 /* Check for small data reference. */
1632 if (**strp == '#' || **strp == '%')
1634 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1637 errmsg = parse_symbolic_address (cd, strp, opindex,
1638 BFD_RELOC_FRV_GPREL12,
1639 & result_type, & value);
1641 return "missing `)'";
1646 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1649 errmsg = parse_symbolic_address (cd, strp, opindex,
1650 BFD_RELOC_FRV_GOT12,
1651 & result_type, & value);
1653 return "missing ')'";
1658 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1661 errmsg = parse_symbolic_address (cd, strp, opindex,
1662 BFD_RELOC_FRV_FUNCDESC_GOT12,
1663 & result_type, & value);
1665 return "missing ')'";
1670 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1673 errmsg = parse_symbolic_address (cd, strp, opindex,
1674 BFD_RELOC_FRV_GOTOFF12,
1675 & result_type, & value);
1677 return "missing ')'";
1682 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1685 errmsg = parse_symbolic_address (cd, strp, opindex,
1686 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1687 & result_type, & value);
1689 return "missing ')'";
1694 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1697 errmsg = parse_symbolic_address (cd, strp, opindex,
1698 BFD_RELOC_FRV_GOTTLSDESC12,
1699 & result_type, & value);
1701 return "missing ')'";
1706 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1709 errmsg = parse_symbolic_address (cd, strp, opindex,
1710 BFD_RELOC_FRV_TLSMOFF12,
1711 & result_type, & value);
1713 return "missing ')'";
1718 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1721 errmsg = parse_symbolic_address (cd, strp, opindex,
1722 BFD_RELOC_FRV_GOTTLSOFF12,
1723 & result_type, & value);
1725 return "missing ')'";
1734 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1738 parse_u12 (CGEN_CPU_DESC cd,
1744 enum cgen_parse_operand_result result_type;
1747 /* Check for small data reference. */
1748 if ((**strp == '#' || **strp == '%')
1749 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1752 errmsg = parse_symbolic_address (cd, strp, opindex,
1753 BFD_RELOC_FRV_GPRELU12,
1754 & result_type, & value);
1756 return "missing `)'";
1765 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1770 parse_A (CGEN_CPU_DESC cd,
1773 unsigned long *valuep,
1781 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1786 return _("Value of A operand must be 0 or 1");
1792 parse_A0 (CGEN_CPU_DESC cd,
1795 unsigned long *valuep)
1797 return parse_A (cd, strp, opindex, valuep, 0);
1801 parse_A1 (CGEN_CPU_DESC cd,
1804 unsigned long *valuep)
1806 return parse_A (cd, strp, opindex, valuep, 1);
1810 parse_even_register (CGEN_CPU_DESC cd,
1812 CGEN_KEYWORD * tableP,
1815 const char * errmsg;
1816 const char * saved_star_strP = * strP;
1818 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1820 if (errmsg == NULL && ((* valueP) & 1))
1822 errmsg = _("register number must be even");
1823 * strP = saved_star_strP;
1830 parse_call_label (CGEN_CPU_DESC cd,
1834 enum cgen_parse_operand_result *resultp,
1840 /* Check for small data reference. */
1841 if (opinfo == 0 && (**strp == '#' || **strp == '%'))
1843 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1846 errmsg = parse_symbolic_address (cd, strp, opindex,
1847 BFD_RELOC_FRV_GETTLSOFF,
1850 return _("missing `)'");
1857 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
1864 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1866 long reloc_ann ATTRIBUTE_UNUSED,
1867 long value ATTRIBUTE_UNUSED,
1868 bfd_vma pc ATTRIBUTE_UNUSED,
1869 int length ATTRIBUTE_UNUSED)
1871 disassemble_info *info = (disassemble_info *) dis_info;
1873 (*info->fprintf_func) (info->stream, "@");
1877 print_spr (CGEN_CPU_DESC cd,
1879 CGEN_KEYWORD *names,
1883 /* Use the register index format for any unnamed registers. */
1884 if (cgen_keyword_lookup_value (names, regno) == NULL)
1886 disassemble_info *info = (disassemble_info *) dis_info;
1887 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1890 print_keyword (cd, dis_info, names, regno, attrs);
1894 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1897 unsigned int attrs ATTRIBUTE_UNUSED,
1898 bfd_vma pc ATTRIBUTE_UNUSED,
1899 int length ATTRIBUTE_UNUSED)
1901 disassemble_info *info = (disassemble_info *) dis_info;
1903 (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
1907 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1910 unsigned int attrs ATTRIBUTE_UNUSED,
1911 bfd_vma pc ATTRIBUTE_UNUSED,
1912 int length ATTRIBUTE_UNUSED)
1914 disassemble_info *info = (disassemble_info *) dis_info;
1916 (*info->fprintf_func) (info->stream, "0x%lx", value);
1918 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);