1 /* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*-
3 Copyright 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
5 Contributed by Red Hat Inc; developed under contract from Fujitsu.
7 This file is part of the GNU Binutils.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
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
54 typedef CGEN_ATTR_VALUE_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
59 int constraint_violation;
61 unsigned long elf_flags;
62 CGEN_ATTR_VALUE_TYPE *unit_mapping;
63 VLIW_COMBO *current_vliw;
64 CGEN_ATTR_VALUE_TYPE major[FRV_VLIW_SIZE];
65 const CGEN_INSN* insn[FRV_VLIW_SIZE];
68 int frv_is_branch_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
69 int frv_is_float_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
70 int frv_is_media_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
71 int frv_is_branch_insn PARAMS ((const CGEN_INSN *));
72 int frv_is_float_insn PARAMS ((const CGEN_INSN *));
73 int frv_is_media_insn PARAMS ((const CGEN_INSN *));
74 void frv_vliw_reset PARAMS ((FRV_VLIW *, unsigned long mach, unsigned long elf_flags));
75 int frv_vliw_add_insn PARAMS ((FRV_VLIW *, const CGEN_INSN *));
76 int spr_valid PARAMS ((long));
84 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, CGEN_ATTR_VALUE_TYPE));
86 PARAMS ((VLIW_COMBO *, VLIW_COMBO *, int));
87 static VLIW_COMBO * add_next_to_vliw
88 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
89 static int find_major_in_vliw
90 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
91 static int fr400_check_insn_major_constraints
92 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
93 static int fr450_check_insn_major_constraints
94 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
95 static int fr500_check_insn_major_constraints
96 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
97 static int fr550_check_insn_major_constraints
98 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, const CGEN_INSN *));
99 static int check_insn_major_constraints
100 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, const CGEN_INSN *));
103 frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
108 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
109 return 1; /* is a branch */
112 if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
113 return 1; /* is a branch */
116 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
117 return 1; /* is a branch */
121 return 0; /* not a branch */
125 frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
131 return 0; /* No float insns */
133 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
134 return 1; /* is a float insn */
138 return 0; /* not a branch */
142 frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
147 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
148 return 1; /* is a media insn */
151 if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
152 return 1; /* is a media insn */
155 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
156 return 1; /* is a media insn */
160 return 0; /* not a branch */
164 frv_is_branch_insn (const CGEN_INSN *insn)
166 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
169 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
172 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
180 frv_is_float_insn (const CGEN_INSN *insn)
182 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
185 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
188 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
196 frv_is_media_insn (const CGEN_INSN *insn)
198 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
201 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
204 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
211 /* This table represents the allowable packing for vliw insns for the fr400.
212 The fr400 has only 2 vliw slots. Represent this by not allowing any insns
214 Subsets of any given row are also allowed. */
215 static VLIW_COMBO fr400_allowed_vliw[] =
217 /* slot0 slot1 slot2 slot3 */
218 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
219 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
220 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
221 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
222 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
223 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
224 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
225 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
228 /* This table represents the allowable packing for vliw insns for the fr500.
229 The fr500 has only 4 vliw slots. Represent this by not allowing any insns
231 Subsets of any given row are also allowed. */
232 static VLIW_COMBO fr500_allowed_vliw[] =
234 /* slot0 slot1 slot2 slot3 */
235 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO },
236 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO },
237 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO },
238 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
239 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
240 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
241 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
242 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
243 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
244 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
245 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
248 /* This table represents the allowable packing for vliw insns for the fr550.
249 Subsets of any given row are also allowed. */
250 static VLIW_COMBO fr550_allowed_vliw[] =
252 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */
253 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL },
254 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL },
255 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
256 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
257 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 },
258 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 },
259 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 },
260 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 },
261 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 },
262 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL },
263 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
264 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
265 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL },
266 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
267 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL },
268 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
269 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
270 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL },
271 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
272 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
273 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
274 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
275 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
276 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
277 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
278 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
279 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
280 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
283 /* Some insns are assigned specialized implementation units which map to
284 different actual implementation units on different machines. These
285 tables perform that mapping. */
286 static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
288 /* unit in insn actual unit */
293 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
295 /* IALL */ UNIT_I01, /* only I0 and I1 units */
298 /* FM01 */ UNIT_FM01,
299 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
300 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
301 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
302 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
303 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
307 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
308 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
309 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
310 /* STORE */ UNIT_I0, /* store only in I0 unit. */
311 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
312 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
313 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
314 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
315 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
318 /* Some insns are assigned specialized implementation units which map to
319 different actual implementation units on different machines. These
320 tables perform that mapping. */
321 static CGEN_ATTR_VALUE_TYPE fr450_unit_mapping[] =
323 /* unit in insn actual unit */
328 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
330 /* IALL */ UNIT_I01, /* only I0 and I1 units */
333 /* FM01 */ UNIT_FM01,
334 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
335 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
336 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
337 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
338 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
342 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
343 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
344 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
345 /* STORE */ UNIT_I0, /* store only in I0 unit. */
346 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
347 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
348 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
349 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1. */
350 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
353 static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
355 /* unit in insn actual unit */
360 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
362 /* IALL */ UNIT_I01, /* only I0 and I1 units */
365 /* FM01 */ UNIT_FM01,
366 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
367 /* FM3 */ UNIT_NIL, /* no F3 or M2 units */
368 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
369 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
374 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
375 /* IACC */ UNIT_NIL, /* iacc multiply not implemented */
376 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
377 /* STORE */ UNIT_I0, /* store only in I0 unit. */
378 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
379 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
380 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
381 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
382 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
385 static CGEN_ATTR_VALUE_TYPE fr550_unit_mapping[] =
387 /* unit in insn actual unit */
394 /* IALL */ UNIT_IALL,
397 /* FM01 */ UNIT_FM01,
400 /* FMALL */ UNIT_FMALL,
401 /* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */
406 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
407 /* IACC */ UNIT_NIL, /* iacc multiply not implemented. */
408 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
409 /* STORE */ UNIT_I01, /* store in I0 or I1 unit. */
410 /* SCAN */ UNIT_IALL, /* scan in any integer unit. */
411 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
412 /* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */
413 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1 unit. */
414 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
418 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
421 vliw->constraint_violation = 0;
423 vliw->elf_flags = elf_flags;
428 vliw->current_vliw = fr400_allowed_vliw;
429 vliw->unit_mapping = fr400_unit_mapping;
432 vliw->current_vliw = fr400_allowed_vliw;
433 vliw->unit_mapping = fr450_unit_mapping;
436 vliw->current_vliw = fr550_allowed_vliw;
437 vliw->unit_mapping = fr550_unit_mapping;
440 vliw->current_vliw = fr500_allowed_vliw;
441 vliw->unit_mapping = fr500_unit_mapping;
446 /* Return 1 if unit1 is a match for unit2.
447 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
448 *_allowed_vliw tables above. */
450 match_unit (FRV_VLIW *vliw,
451 CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
453 /* Map any specialized implementation units to actual ones. */
454 unit1 = vliw->unit_mapping[unit1];
466 /* The 01 versions of these units are within 2 enums of the 0 or 1
468 if (unit1 - unit2 <= 2)
473 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
475 if (unit1 - unit2 <= 5)
485 /* Return 1 if the vliws match, 0 otherwise. */
488 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
492 for (i = 0; i < vliw_size; ++i)
494 if ((*vliw1)[i] != (*vliw2)[i])
501 /* Find the next vliw vliw in the table that can accomodate the new insn.
502 If one is found then return it. Otherwise return NULL. */
505 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
507 int next = vliw->next_slot;
508 VLIW_COMBO *current = vliw->current_vliw;
509 VLIW_COMBO *potential;
513 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
515 abort (); /* Should never happen */
518 /* The table is sorted by units allowed within slots, so vliws with
519 identical starting sequences are together. */
523 if (match_unit (vliw, unit, (*potential)[next]))
527 while (match_vliw (potential, current, next));
532 /* Look for the given major insn type in the given vliw. Return 1 if found,
533 return 0 otherwise. */
536 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
540 for (i = 0; i < vliw->next_slot; ++i)
541 if (vliw->major[i] == major)
547 /* Check for constraints between the insns in the vliw due to major insn
551 fr400_check_insn_major_constraints (
552 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
555 /* In the cpu file, all media insns are represented as being allowed in
556 both media units. This makes it easier since this is the case for fr500.
557 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
558 cannot coexist with any other media insn in a vliw. */
561 case FR400_MAJOR_M_2:
562 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
563 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
564 case FR400_MAJOR_M_1:
565 return !find_major_in_vliw (vliw, FR400_MAJOR_M_2);
573 fr450_check_insn_major_constraints (
574 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
577 CGEN_ATTR_VALUE_TYPE other_major;
579 /* Our caller guarantees there's at least one other instruction. */
580 other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
582 /* (M4, M5) and (M4, M6) are allowed. */
583 if (other_major == FR450_MAJOR_M_4)
584 if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
587 /* Otherwise, instructions in even-numbered media categories cannot be
588 executed in parallel with other media instructions. */
591 case FR450_MAJOR_M_2:
592 case FR450_MAJOR_M_4:
593 case FR450_MAJOR_M_6:
594 return !(other_major >= FR450_MAJOR_M_1
595 && other_major <= FR450_MAJOR_M_6);
597 case FR450_MAJOR_M_1:
598 case FR450_MAJOR_M_3:
599 case FR450_MAJOR_M_5:
600 return !(other_major == FR450_MAJOR_M_2
601 || other_major == FR450_MAJOR_M_4
602 || other_major == FR450_MAJOR_M_6);
611 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit
615 for (i = 0; i < vliw->next_slot; ++i)
616 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
619 return 0; /* not found */
624 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, CGEN_ATTR_VALUE_TYPE slot
629 for (i = 0; i < vliw->next_slot; ++i)
630 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
637 fr550_find_media_in_vliw (FRV_VLIW *vliw)
641 for (i = 0; i < vliw->next_slot; ++i)
643 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
646 /* Found a media insn, however, MNOP and MCLRACC don't count. */
647 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
648 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
649 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
652 return 1; /* found one */
659 fr550_find_float_in_vliw (FRV_VLIW *vliw)
663 for (i = 0; i < vliw->next_slot; ++i)
665 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
668 /* Found a floating point insn, however, FNOP doesn't count. */
669 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
672 return 1; /* found one */
679 fr550_check_insn_major_constraints (
680 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn
683 CGEN_ATTR_VALUE_TYPE unit;
684 CGEN_ATTR_VALUE_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
688 /* If it's a store, then there must be another store in I1 */
689 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
690 if (unit == UNIT_STORE)
691 return find_unit_in_vliw (vliw, UNIT_STORE);
695 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist with
697 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
698 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
699 return ! fr550_find_media_in_vliw (vliw);
700 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
701 floating point insns. */
702 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
703 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
704 return ! fr550_find_float_in_vliw (vliw);
705 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
708 if (major == FR550_MAJOR_F_2)
709 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2, slot - (UNIT_FM2 - UNIT_FM0))
710 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4, slot - (UNIT_FM2 - UNIT_FM0));
711 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
713 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
714 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2, slot - (UNIT_FM2 - UNIT_FM0));
715 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
717 if (major == FR550_MAJOR_M_4)
718 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4, slot - (UNIT_FM2 - UNIT_FM0));
723 return 1; /* all ok */
727 fr500_check_insn_major_constraints (
728 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
731 /* TODO: A table might be faster for some of the more complex instances
735 case FR500_MAJOR_I_1:
736 case FR500_MAJOR_I_4:
737 case FR500_MAJOR_I_5:
738 case FR500_MAJOR_I_6:
739 case FR500_MAJOR_B_1:
740 case FR500_MAJOR_B_2:
741 case FR500_MAJOR_B_3:
742 case FR500_MAJOR_B_4:
743 case FR500_MAJOR_B_5:
744 case FR500_MAJOR_B_6:
745 case FR500_MAJOR_F_4:
746 case FR500_MAJOR_F_8:
747 case FR500_MAJOR_M_8:
749 case FR500_MAJOR_I_2:
750 /* Cannot coexist with I-3 insn. */
751 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
752 case FR500_MAJOR_I_3:
753 /* Cannot coexist with I-2 insn. */
754 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
755 case FR500_MAJOR_F_1:
756 case FR500_MAJOR_F_2:
757 /* Cannot coexist with F-5, F-6, or M-7 insn. */
758 return ! 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_3:
762 /* Cannot coexist with F-7, or M-7 insn. */
763 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
764 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
765 case FR500_MAJOR_F_5:
766 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
767 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
768 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
769 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
770 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
771 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
772 case FR500_MAJOR_F_6:
773 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
774 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
775 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
776 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
777 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
778 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
779 case FR500_MAJOR_F_7:
780 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
781 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
782 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
783 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
784 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
785 case FR500_MAJOR_M_1:
786 /* Cannot coexist with M-7 insn. */
787 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
788 case FR500_MAJOR_M_2:
789 case FR500_MAJOR_M_3:
790 /* Cannot coexist with M-5, M-6 or M-7 insn. */
791 return ! 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_4:
795 /* Cannot coexist with M-6 insn. */
796 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
797 case FR500_MAJOR_M_5:
798 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
799 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
800 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
801 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
802 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
803 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
804 case FR500_MAJOR_M_6:
805 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
806 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
807 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
808 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
809 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
810 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
811 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
812 case FR500_MAJOR_M_7:
813 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
814 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
815 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
816 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
817 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
818 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
819 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
820 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
821 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
822 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
823 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
824 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
825 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
827 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
836 check_insn_major_constraints (
837 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn
844 rc = fr400_check_insn_major_constraints (vliw, major);
847 rc = fr450_check_insn_major_constraints (vliw, major);
850 rc = fr550_check_insn_major_constraints (vliw, major, insn);
853 rc = fr500_check_insn_major_constraints (vliw, major);
859 /* Add in insn to the VLIW vliw if possible. Return 0 if successful,
860 non-zero otherwise. */
862 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
865 CGEN_ATTR_VALUE_TYPE major;
866 CGEN_ATTR_VALUE_TYPE unit;
867 VLIW_COMBO *new_vliw;
869 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
872 index = vliw->next_slot;
873 if (index >= FRV_VLIW_SIZE)
876 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
877 if (unit == UNIT_NIL)
879 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
881 abort (); /* no UNIT specified for this insn in frv.cpu */
887 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
890 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
893 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
896 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
902 /* Any insn can be added to slot 0. */
903 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
904 ++vliw->current_vliw;
905 vliw->major[0] = major;
906 vliw->insn[0] = insn;
911 /* If there are already insns in the vliw(s) check to see that
912 this one can be added. Do this by finding an allowable vliw
913 combination that can accept the new insn. */
914 if (! (vliw->elf_flags & EF_FRV_NOPACK))
916 new_vliw = add_next_to_vliw (vliw, unit);
917 if (new_vliw && check_insn_major_constraints (vliw, major, insn))
919 vliw->current_vliw = new_vliw;
920 vliw->major[index] = major;
921 vliw->insn[index] = insn;
926 /* The frv machine supports all packing conbinations. If we fail,
927 to add the insn, then it could not be handled as if it was the fr500.
928 Just return as if it was handled ok. */
929 if (vliw->mach == bfd_mach_frv)
933 vliw->constraint_violation = 1;
941 if (regno < 0) return 0;
942 if (regno <= 4095) return 1;
948 static const char * parse_ulo16
949 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
950 static const char * parse_uslo16
951 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
952 static const char * parse_uhi16
953 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
954 static long parse_register_number
955 PARAMS ((const char **));
956 static const char * parse_spr
957 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
958 static const char * parse_d12
959 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
960 static const char * parse_s12
961 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
962 static const char * parse_u12
963 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
964 static const char * parse_even_register
965 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
966 static const char * parse_A0
967 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
968 static const char * parse_A1
969 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
970 static const char * parse_A
971 PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
974 parse_ulo16 (cd, strp, opindex, valuep)
978 unsigned long *valuep;
981 enum cgen_parse_operand_result result_type;
984 if (**strp == '#' || **strp == '%')
986 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
989 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
990 &result_type, &value);
992 return "missing `)'";
995 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1000 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1003 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
1004 &result_type, &value);
1006 return "missing ')'";
1009 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1014 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1017 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
1018 &result_type, &value);
1020 return "missing ')'";
1023 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1028 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1031 errmsg = cgen_parse_address (cd, strp, opindex,
1032 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1033 &result_type, &value);
1035 return "missing ')'";
1038 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1043 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1046 errmsg = cgen_parse_address (cd, strp, opindex,
1047 BFD_RELOC_FRV_GOTOFFLO,
1048 &result_type, &value);
1050 return "missing ')'";
1053 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1058 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1061 errmsg = cgen_parse_address (cd, strp, opindex,
1062 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1063 &result_type, &value);
1065 return "missing ')'";
1068 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1074 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1078 parse_uslo16 (cd, strp, opindex, valuep)
1082 unsigned long *valuep;
1085 enum cgen_parse_operand_result result_type;
1088 if (**strp == '#' || **strp == '%')
1090 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1093 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1094 &result_type, &value);
1096 return "missing `)'";
1099 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1104 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1107 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
1108 &result_type, &value);
1110 return "missing ')'";
1113 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1118 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1121 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
1122 &result_type, &value);
1124 return "missing ')'";
1127 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1132 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1135 errmsg = cgen_parse_address (cd, strp, opindex,
1136 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1137 &result_type, &value);
1139 return "missing ')'";
1142 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1147 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1150 errmsg = cgen_parse_address (cd, strp, opindex,
1151 BFD_RELOC_FRV_GOTOFFLO,
1152 &result_type, &value);
1154 return "missing ')'";
1157 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1162 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1165 errmsg = cgen_parse_address (cd, strp, opindex,
1166 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1167 &result_type, &value);
1169 return "missing ')'";
1172 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1178 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1182 parse_uhi16 (cd, strp, opindex, valuep)
1186 unsigned long *valuep;
1189 enum cgen_parse_operand_result result_type;
1192 if (**strp == '#' || **strp == '%')
1194 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1197 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1198 &result_type, &value);
1200 return "missing `)'";
1203 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1208 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1211 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
1212 &result_type, &value);
1214 return "missing ')'";
1217 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1222 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1225 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTHI,
1226 &result_type, &value);
1228 return "missing ')'";
1231 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1236 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1239 errmsg = cgen_parse_address (cd, strp, opindex,
1240 BFD_RELOC_FRV_FUNCDESC_GOTHI,
1241 &result_type, &value);
1243 return "missing ')'";
1246 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1251 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1254 errmsg = cgen_parse_address (cd, strp, opindex,
1255 BFD_RELOC_FRV_GOTOFFHI,
1256 &result_type, &value);
1258 return "missing ')'";
1261 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1266 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1269 errmsg = cgen_parse_address (cd, strp, opindex,
1270 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1271 &result_type, &value);
1273 return "missing ')'";
1276 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1282 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1286 parse_register_number (strp)
1290 if (**strp < '0' || **strp > '9')
1291 return -1; /* error */
1293 regno = **strp - '0';
1294 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1295 regno = regno * 10 + (**strp - '0');
1301 parse_spr (cd, strp, table, valuep)
1304 CGEN_KEYWORD * table;
1307 const char *save_strp;
1310 /* Check for spr index notation. */
1311 if (strncasecmp (*strp, "spr[", 4) == 0)
1314 regno = parse_register_number (strp);
1316 return "missing `]'";
1318 if (! spr_valid (regno))
1319 return "Special purpose register number is out of range";
1325 regno = parse_register_number (strp);
1328 if (! spr_valid (regno))
1329 return "Special purpose register number is out of range";
1335 return cgen_parse_keyword (cd, strp, table, valuep);
1339 parse_d12 (cd, strp, opindex, valuep)
1346 enum cgen_parse_operand_result result_type;
1349 /* Check for small data reference. */
1350 if (**strp == '#' || **strp == '%')
1352 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1355 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
1356 &result_type, &value);
1358 return "missing `)'";
1363 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1366 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
1367 &result_type, &value);
1369 return "missing ')'";
1374 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1377 errmsg = cgen_parse_address (cd, strp, opindex,
1378 BFD_RELOC_FRV_FUNCDESC_GOT12,
1379 &result_type, &value);
1381 return "missing ')'";
1386 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1389 errmsg = cgen_parse_address (cd, strp, opindex,
1390 BFD_RELOC_FRV_GOTOFF12,
1391 &result_type, &value);
1393 return "missing ')'";
1398 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1401 errmsg = cgen_parse_address (cd, strp, opindex,
1402 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1403 &result_type, &value);
1405 return "missing ')'";
1411 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1415 parse_s12 (cd, strp, opindex, valuep)
1422 enum cgen_parse_operand_result result_type;
1425 /* Check for small data reference. */
1426 if ((**strp == '#' || **strp == '%')
1427 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1430 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
1431 &result_type, &value);
1433 return "missing `)'";
1438 else if ((**strp == '#' || **strp == '%')
1439 && strncasecmp (*strp + 1, "got12(", 6) == 0)
1442 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
1443 &result_type, &value);
1445 return "missing ')'";
1450 else if ((**strp == '#' || **strp == '%')
1451 && strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1454 errmsg = cgen_parse_address (cd, strp, opindex,
1455 BFD_RELOC_FRV_FUNCDESC_GOT12,
1456 &result_type, &value);
1458 return "missing ')'";
1463 else if ((**strp == '#' || **strp == '%')
1464 && strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1467 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTOFF12,
1468 &result_type, &value);
1470 return "missing ')'";
1475 else if ((**strp == '#' || **strp == '%')
1476 && strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1479 errmsg = cgen_parse_address (cd, strp, opindex,
1480 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1481 &result_type, &value);
1483 return "missing ')'";
1492 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1497 parse_u12 (cd, strp, opindex, valuep)
1504 enum cgen_parse_operand_result result_type;
1507 /* Check for small data reference. */
1508 if ((**strp == '#' || **strp == '%')
1509 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1512 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
1513 &result_type, &value);
1515 return "missing `)'";
1524 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1529 parse_A (cd, strp, opindex, valuep, A)
1541 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1546 return "Value of A operand must be 0 or 1";
1552 parse_A0 (cd, strp, opindex, valuep)
1558 return parse_A (cd, strp, opindex, valuep, 0);
1562 parse_A1 (cd, strp, opindex, valuep)
1568 return parse_A (cd, strp, opindex, valuep, 1);
1572 parse_even_register (cd, strP, tableP, valueP)
1575 CGEN_KEYWORD * tableP;
1578 const char * errmsg;
1579 const char * saved_star_strP = * strP;
1581 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1583 if (errmsg == NULL && ((* valueP) & 1))
1585 errmsg = _("register number must be even");
1586 * strP = saved_star_strP;
1594 static void print_spr
1595 PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
1596 static void print_hi
1597 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
1598 static void print_lo
1599 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
1602 print_spr (cd, dis_info, names, regno, attrs)
1605 CGEN_KEYWORD *names;
1609 /* Use the register index format for any unnamed registers. */
1610 if (cgen_keyword_lookup_value (names, regno) == NULL)
1612 disassemble_info *info = (disassemble_info *) dis_info;
1613 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1616 print_keyword (cd, dis_info, names, regno, attrs);
1620 print_hi (cd, dis_info, value, attrs, pc, length)
1621 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1624 unsigned int attrs ATTRIBUTE_UNUSED;
1625 bfd_vma pc ATTRIBUTE_UNUSED;
1626 int length ATTRIBUTE_UNUSED;
1628 disassemble_info *info = (disassemble_info *) dis_info;
1630 (*info->fprintf_func) (info->stream, "0x%lx", value);
1632 (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
1636 print_lo (cd, dis_info, value, attrs, pc, length)
1637 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1640 unsigned int attrs ATTRIBUTE_UNUSED;
1641 bfd_vma pc ATTRIBUTE_UNUSED;
1642 int length ATTRIBUTE_UNUSED;
1644 disassemble_info *info = (disassemble_info *) dis_info;
1646 (*info->fprintf_func) (info->stream, "0x%lx", value);
1648 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);