* MAINTAINERS: Remove self as M88k maintainer. Future M88k
[deliverable/binutils-gdb.git] / cpu / frv.opc
1 /* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*-
2
3 Copyright 2003 Free Software Foundation, Inc.
4
5 Contributed by Red Hat Inc; developed under contract from Fujitsu.
6
7 This file is part of the GNU Binutils.
8
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.
13
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.
18
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.
22
23 */
24
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.
31
32 Each section is delimited with start and end markers.
33
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"
39 */
40 \f
41 /* -- opc.h */
42
43 #undef CGEN_DIS_HASH_SIZE
44 #define CGEN_DIS_HASH_SIZE 128
45 #undef CGEN_DIS_HASH
46 #define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
47
48 /* Allows reason codes to be output when assembler errors occur. */
49 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
50
51 /* Vliw support. */
52 #define FRV_VLIW_SIZE 4 /* fr500 has largest vliw size of 4. */
53 typedef CGEN_ATTR_VALUE_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
54
55 typedef struct
56 {
57 int next_slot;
58 int constraint_violation;
59 unsigned long mach;
60 unsigned long elf_flags;
61 CGEN_ATTR_VALUE_TYPE *unit_mapping;
62 VLIW_COMBO *current_vliw;
63 CGEN_ATTR_VALUE_TYPE major[FRV_VLIW_SIZE];
64 } FRV_VLIW;
65
66 int frv_is_branch_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
67 int frv_is_float_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
68 int frv_is_media_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
69 int frv_is_branch_insn PARAMS ((const CGEN_INSN *));
70 int frv_is_float_insn PARAMS ((const CGEN_INSN *));
71 int frv_is_media_insn PARAMS ((const CGEN_INSN *));
72 void frv_vliw_reset PARAMS ((FRV_VLIW *, unsigned long mach, unsigned long elf_flags));
73 int frv_vliw_add_insn PARAMS ((FRV_VLIW *, const CGEN_INSN *));
74 int spr_valid PARAMS ((long));
75 /* -- */
76 \f
77 /* -- opc.c */
78 #include "elf/frv.h"
79
80 static int match_unit
81 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, CGEN_ATTR_VALUE_TYPE));
82 static int match_vliw
83 PARAMS ((VLIW_COMBO *, VLIW_COMBO *, int));
84 static VLIW_COMBO * add_next_to_vliw
85 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
86 static int find_major_in_vliw
87 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
88 static int fr400_check_insn_major_constraints
89 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
90 static int fr500_check_insn_major_constraints
91 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
92 static int check_insn_major_constraints
93 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
94
95 int
96 frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
97 {
98 switch (mach)
99 {
100 case bfd_mach_fr400:
101 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
102 return 1; /* is a branch */
103 break;
104 default:
105 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
106 return 1; /* is a branch */
107 break;
108 }
109
110 return 0; /* not a branch */
111 }
112
113 int
114 frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
115 {
116 switch (mach)
117 {
118 case bfd_mach_fr400:
119 return 0; /* No float insns */
120 default:
121 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
122 return 1; /* is a float insn */
123 break;
124 }
125
126 return 0; /* not a branch */
127 }
128
129 int
130 frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
131 {
132 switch (mach)
133 {
134 case bfd_mach_fr400:
135 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
136 return 1; /* is a media insn */
137 break;
138 default:
139 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
140 return 1; /* is a media insn */
141 break;
142 }
143
144 return 0; /* not a branch */
145 }
146
147 int
148 frv_is_branch_insn (const CGEN_INSN *insn)
149 {
150 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
151 bfd_mach_fr400))
152 return 1;
153 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
154 bfd_mach_fr500))
155 return 1;
156
157 return 0;
158 }
159
160 int
161 frv_is_float_insn (const CGEN_INSN *insn)
162 {
163 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
164 bfd_mach_fr400))
165 return 1;
166 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
167 bfd_mach_fr500))
168 return 1;
169
170 return 0;
171 }
172
173 int
174 frv_is_media_insn (const CGEN_INSN *insn)
175 {
176 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
177 bfd_mach_fr400))
178 return 1;
179 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
180 bfd_mach_fr500))
181 return 1;
182
183 return 0;
184 }
185
186 /* This table represents the allowable packing for vliw insns for the fr400.
187 The fr400 has only 2 vliw slots. Represent this by not allowing any insns
188 in slots 2 and 3.
189 Subsets of any given row are also allowed. */
190 static VLIW_COMBO fr400_allowed_vliw[] =
191 {
192 /* slot0 slot1 slot2 slot3 */
193 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL },
194 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL },
195 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL },
196 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL },
197 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL },
198 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL },
199 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL },
200 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
201 };
202
203 /* This table represents the allowable packing for vliw insns for the fr500.
204 Subsets of any given row are also allowed. */
205 static VLIW_COMBO fr500_allowed_vliw[] =
206 {
207 /* slot0 slot1 slot2 slot3 */
208 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 },
209 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 },
210 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 },
211 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 },
212 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 },
213 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL },
214 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 },
215 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL },
216 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
217 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL },
218 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
219 };
220
221 /* Some insns are assigned specialized implementation units which map to
222 different actual implementation units on different machines. These
223 tables perform that mapping. */
224 static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
225 {
226 /* unit in insn actual unit */
227 /* NIL */ UNIT_NIL,
228 /* I0 */ UNIT_I0,
229 /* I1 */ UNIT_I1,
230 /* I01 */ UNIT_I01,
231 /* FM0 */ UNIT_FM0,
232 /* FM1 */ UNIT_FM1,
233 /* FM01 */ UNIT_FM01,
234 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
235 /* B1 */ UNIT_B0,
236 /* B01 */ UNIT_B0,
237 /* C */ UNIT_C,
238 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
239 /* LOAD */ UNIT_I0 /* load only in I0 unit. */
240 };
241
242 static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
243 {
244 /* unit in insn actual unit */
245 /* NIL */ UNIT_NIL,
246 /* I0 */ UNIT_I0,
247 /* I1 */ UNIT_I1,
248 /* I01 */ UNIT_I01,
249 /* FM0 */ UNIT_FM0,
250 /* FM1 */ UNIT_FM1,
251 /* FM01 */ UNIT_FM01,
252 /* B0 */ UNIT_B0,
253 /* B1 */ UNIT_B1,
254 /* B01 */ UNIT_B01,
255 /* C */ UNIT_C,
256 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
257 /* LOAD */ UNIT_I01 /* load in I0 or I1 unit. */
258 };
259
260 void
261 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
262 {
263 vliw->next_slot = 0;
264 vliw->constraint_violation = 0;
265 vliw->mach = mach;
266 vliw->elf_flags = elf_flags;
267
268 switch (mach)
269 {
270 case bfd_mach_fr400:
271 vliw->current_vliw = fr400_allowed_vliw;
272 vliw->unit_mapping = fr400_unit_mapping;
273 break;
274 default:
275 vliw->current_vliw = fr500_allowed_vliw;
276 vliw->unit_mapping = fr500_unit_mapping;
277 break;
278 }
279 }
280
281 /* Return 1 if unit1 is a match for unit2.
282 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
283 *_allowed_vliw tables above. */
284 static int
285 match_unit (FRV_VLIW *vliw,
286 CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
287 {
288 /* Map any specialized implementation units to actual ones. */
289 unit1 = vliw->unit_mapping[unit1];
290
291 if (unit1 == unit2)
292 return 1;
293 if (unit1 < unit2)
294 return 0;
295
296 switch (unit1)
297 {
298 case UNIT_I01:
299 case UNIT_FM01:
300 case UNIT_B01:
301 /* The 01 versions of these units are within 2 enums of the 0 or 1
302 versions. */
303 if (unit1 - unit2 <= 2)
304 return 1;
305 break;
306 default:
307 break;
308 }
309
310 return 0;
311 }
312
313 /* Return 1 if the vliws match, 0 otherwise. */
314
315 static int
316 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
317 {
318 int i;
319
320 for (i = 0; i < vliw_size; ++i)
321 {
322 if ((*vliw1)[i] != (*vliw2)[i])
323 return 0;
324 }
325
326 return 1;
327 }
328
329 /* Find the next vliw vliw in the table that can accomodate the new insn.
330 If one is found then return it. Otherwise return NULL. */
331
332 static VLIW_COMBO *
333 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
334 {
335 int next = vliw->next_slot;
336 VLIW_COMBO *current = vliw->current_vliw;
337 VLIW_COMBO *potential;
338
339 if (next <= 0)
340 abort (); /* Should never happen */
341
342 /* The table is sorted by units allowed within slots, so vliws with
343 identical starting sequences are together. */
344 potential = current;
345 do
346 {
347 if (match_unit (vliw, unit, (*potential)[next]))
348 return potential;
349 ++potential;
350 }
351 while (match_vliw (potential, current, next));
352
353 return NULL;
354 }
355
356 /* Look for the given major insn type in the given vliw. Return 1 if found,
357 return 0 otherwise. */
358
359 static int
360 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
361 {
362 int i;
363
364 for (i = 0; i < vliw->next_slot; ++i)
365 if (vliw->major[i] == major)
366 return 1;
367
368 return 0;
369 }
370
371 /* Check for constraints between the insns in the vliw due to major insn
372 types. */
373
374 static int
375 fr400_check_insn_major_constraints (
376 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
377 )
378 {
379 /* In the cpu file, all media insns are represented as being allowed in
380 both media units. This makes it easier since this is the case for fr500.
381 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
382 cannot coexist with any other media insn in a vliw. */
383 switch (major)
384 {
385 case FR400_MAJOR_M_2:
386 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
387 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
388 default:
389 break;
390 }
391 return 1;
392 }
393
394 static int
395 fr500_check_insn_major_constraints (
396 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
397 )
398 {
399 /* TODO: A table might be faster for some of the more complex instances
400 here. */
401 switch (major)
402 {
403 case FR500_MAJOR_I_1:
404 case FR500_MAJOR_I_4:
405 case FR500_MAJOR_I_5:
406 case FR500_MAJOR_I_6:
407 case FR500_MAJOR_B_1:
408 case FR500_MAJOR_B_2:
409 case FR500_MAJOR_B_3:
410 case FR500_MAJOR_B_4:
411 case FR500_MAJOR_B_5:
412 case FR500_MAJOR_B_6:
413 case FR500_MAJOR_F_4:
414 case FR500_MAJOR_F_8:
415 case FR500_MAJOR_M_8:
416 return 1; /* OK */
417 case FR500_MAJOR_I_2:
418 /* Cannot coexist with I-3 insn. */
419 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
420 case FR500_MAJOR_I_3:
421 /* Cannot coexist with I-2 insn. */
422 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
423 case FR500_MAJOR_F_1:
424 case FR500_MAJOR_F_2:
425 /* Cannot coexist with F-5, F-6, or M-7 insn. */
426 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
427 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
428 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
429 case FR500_MAJOR_F_3:
430 /* Cannot coexist with F-7, or M-7 insn. */
431 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
432 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
433 case FR500_MAJOR_F_5:
434 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
435 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
436 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
437 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
438 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
439 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
440 case FR500_MAJOR_F_6:
441 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
442 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
443 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
444 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
445 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
446 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
447 case FR500_MAJOR_F_7:
448 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
449 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
450 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
451 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
452 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
453 case FR500_MAJOR_M_1:
454 /* Cannot coexist with M-7 insn. */
455 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
456 case FR500_MAJOR_M_2:
457 case FR500_MAJOR_M_3:
458 /* Cannot coexist with M-5, M-6 or M-7 insn. */
459 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
460 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
461 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
462 case FR500_MAJOR_M_4:
463 /* Cannot coexist with M-6 insn. */
464 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
465 case FR500_MAJOR_M_5:
466 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
467 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
468 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
469 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
470 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
471 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
472 case FR500_MAJOR_M_6:
473 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
474 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
475 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
476 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
477 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
478 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
479 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
480 case FR500_MAJOR_M_7:
481 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
482 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
483 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
484 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
485 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
486 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
487 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
488 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
489 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
490 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
491 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
492 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
493 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
494 default:
495 abort ();
496 break;
497 }
498 return 1;
499 }
500
501 static int
502 check_insn_major_constraints (
503 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
504 )
505 {
506 int rc;
507 switch (vliw->mach)
508 {
509 case bfd_mach_fr400:
510 rc = fr400_check_insn_major_constraints (vliw, major);
511 break;
512 default:
513 rc = fr500_check_insn_major_constraints (vliw, major);
514 break;
515 }
516 return rc;
517 }
518
519 /* Add in insn to the VLIW vliw if possible. Return 0 if successful,
520 non-zero otherwise. */
521 int
522 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
523 {
524 int index;
525 CGEN_ATTR_VALUE_TYPE major;
526 CGEN_ATTR_VALUE_TYPE unit;
527 VLIW_COMBO *new_vliw;
528
529 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
530 return 1;
531
532 index = vliw->next_slot;
533 if (index >= FRV_VLIW_SIZE)
534 return 1;
535
536 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
537 if (unit == UNIT_NIL)
538 abort (); /* no UNIT specified for this insn in frv.cpu */
539
540 if (vliw->mach == bfd_mach_fr400)
541 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
542 else
543 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
544
545 if (index <= 0)
546 {
547 /* Any insn can be added to slot 0. */
548 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
549 ++vliw->current_vliw;
550 vliw->major[0] = major;
551 vliw->next_slot = 1;
552 return 0;
553 }
554
555 /* If there are already insns in the vliw(s) check to see that
556 this one can be added. Do this by finding an allowable vliw
557 combination that can accept the new insn. */
558 if (! (vliw->elf_flags & EF_FRV_NOPACK))
559 {
560 new_vliw = add_next_to_vliw (vliw, unit);
561 if (new_vliw && check_insn_major_constraints (vliw, major))
562 {
563 vliw->current_vliw = new_vliw;
564 vliw->major[index] = major;
565 vliw->next_slot++;
566 return 0;
567 }
568
569 /* The frv machine supports all packing conbinations. If we fail,
570 to add the insn, then it could not be handled as if it was the fr500.
571 Just return as if it was handled ok. */
572 if (vliw->mach == bfd_mach_frv)
573 return 0;
574 }
575
576 vliw->constraint_violation = 1;
577 return 1;
578 }
579
580 int
581 spr_valid (regno)
582 long regno;
583 {
584 if (regno < 0) return 0;
585 if (regno <= 4095) return 1;
586 return 0;
587 }
588 /* -- */
589 \f
590 /* -- asm.c */
591 static const char * parse_ulo16
592 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
593 static const char * parse_uslo16
594 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
595 static const char * parse_uhi16
596 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
597 static long parse_register_number
598 PARAMS ((const char **));
599 static const char * parse_spr
600 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
601 static const char * parse_d12
602 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
603 static const char * parse_s12
604 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
605 static const char * parse_u12
606 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
607 static const char * parse_even_register
608 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
609
610 static const char *
611 parse_ulo16 (cd, strp, opindex, valuep)
612 CGEN_CPU_DESC cd;
613 const char **strp;
614 int opindex;
615 unsigned long *valuep;
616 {
617 const char *errmsg;
618 enum cgen_parse_operand_result result_type;
619 bfd_vma value;
620
621 if (**strp == '#' || **strp == '%')
622 {
623 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
624 {
625 *strp += 4;
626 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
627 &result_type, &value);
628 if (**strp != ')')
629 return "missing `)'";
630 ++*strp;
631 if (errmsg == NULL
632 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
633 value &= 0xffff;
634 *valuep = value;
635 return errmsg;
636 }
637 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
638 {
639 *strp += 9;
640 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
641 &result_type, &value);
642 if (**strp != ')')
643 return "missing ')'";
644 ++*strp;
645 if (errmsg == NULL
646 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
647 value >>= 16;
648 *valuep = value;
649 return errmsg;
650 }
651 }
652 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
653 }
654
655 static const char *
656 parse_uslo16 (cd, strp, opindex, valuep)
657 CGEN_CPU_DESC cd;
658 const char **strp;
659 int opindex;
660 unsigned long *valuep;
661 {
662 const char *errmsg;
663 enum cgen_parse_operand_result result_type;
664 bfd_vma value;
665
666 if (**strp == '#' || **strp == '%')
667 {
668 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
669 {
670 *strp += 4;
671 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
672 &result_type, &value);
673 if (**strp != ')')
674 return "missing `)'";
675 ++*strp;
676 if (errmsg == NULL
677 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
678 value &= 0xffff;
679 *valuep = value;
680 return errmsg;
681 }
682 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
683 {
684 *strp += 9;
685 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
686 &result_type, &value);
687 if (**strp != ')')
688 return "missing ')'";
689 ++*strp;
690 if (errmsg == NULL
691 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
692 value &= 0xffff;
693 *valuep = value;
694 return errmsg;
695 }
696 }
697 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
698 }
699
700 static const char *
701 parse_uhi16 (cd, strp, opindex, valuep)
702 CGEN_CPU_DESC cd;
703 const char **strp;
704 int opindex;
705 unsigned long *valuep;
706 {
707 const char *errmsg;
708 enum cgen_parse_operand_result result_type;
709 bfd_vma value;
710
711 if (**strp == '#' || **strp == '%')
712 {
713 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
714 {
715 *strp += 4;
716 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
717 &result_type, &value);
718 if (**strp != ')')
719 return "missing `)'";
720 ++*strp;
721 if (errmsg == NULL
722 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
723 value >>= 16;
724 *valuep = value;
725 return errmsg;
726 }
727 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
728 {
729 *strp += 9;
730 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
731 &result_type, &value);
732 if (**strp != ')')
733 return "missing ')'";
734 ++*strp;
735 if (errmsg == NULL
736 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
737 value >>= 16;
738 *valuep = value;
739 return errmsg;
740 }
741 }
742 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
743 }
744
745 static long
746 parse_register_number (strp)
747 const char **strp;
748 {
749 int regno;
750 if (**strp < '0' || **strp > '9')
751 return -1; /* error */
752
753 regno = **strp - '0';
754 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
755 regno = regno * 10 + (**strp - '0');
756
757 return regno;
758 }
759
760 static const char *
761 parse_spr (cd, strp, table, valuep)
762 CGEN_CPU_DESC cd;
763 const char **strp;
764 CGEN_KEYWORD * table;
765 long *valuep;
766 {
767 const char *save_strp;
768 long regno;
769
770 /* Check for spr index notation. */
771 if (strncasecmp (*strp, "spr[", 4) == 0)
772 {
773 *strp += 4;
774 regno = parse_register_number (strp);
775 if (**strp != ']')
776 return "missing `]'";
777 ++*strp;
778 if (! spr_valid (regno))
779 return "Special purpose register number is out of range";
780 *valuep = regno;
781 return NULL;
782 }
783
784 save_strp = *strp;
785 regno = parse_register_number (strp);
786 if (regno != -1)
787 {
788 if (! spr_valid (regno))
789 return "Special purpose register number is out of range";
790 *valuep = regno;
791 return NULL;
792 }
793
794 *strp = save_strp;
795 return cgen_parse_keyword (cd, strp, table, valuep);
796 }
797
798 static const char *
799 parse_d12 (cd, strp, opindex, valuep)
800 CGEN_CPU_DESC cd;
801 const char **strp;
802 int opindex;
803 long *valuep;
804 {
805 const char *errmsg;
806 enum cgen_parse_operand_result result_type;
807 bfd_vma value;
808
809 /* Check for small data reference. */
810 if (**strp == '#' || **strp == '%')
811 {
812 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
813 {
814 *strp += 9;
815 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
816 &result_type, &value);
817 if (**strp != ')')
818 return "missing `)'";
819 ++*strp;
820 *valuep = value;
821 return errmsg;
822 }
823 }
824 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
825 }
826
827 static const char *
828 parse_s12 (cd, strp, opindex, valuep)
829 CGEN_CPU_DESC cd;
830 const char **strp;
831 int opindex;
832 long *valuep;
833 {
834 const char *errmsg;
835 enum cgen_parse_operand_result result_type;
836 bfd_vma value;
837
838 /* Check for small data reference. */
839 if ((**strp == '#' || **strp == '%')
840 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
841 {
842 *strp += 9;
843 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
844 &result_type, &value);
845 if (**strp != ')')
846 return "missing `)'";
847 ++*strp;
848 *valuep = value;
849 return errmsg;
850 }
851 else
852 {
853 if (**strp == '#')
854 ++*strp;
855 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
856 }
857 }
858
859 static const char *
860 parse_u12 (cd, strp, opindex, valuep)
861 CGEN_CPU_DESC cd;
862 const char **strp;
863 int opindex;
864 long *valuep;
865 {
866 const char *errmsg;
867 enum cgen_parse_operand_result result_type;
868 bfd_vma value;
869
870 /* Check for small data reference. */
871 if ((**strp == '#' || **strp == '%')
872 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
873 {
874 *strp += 9;
875 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
876 &result_type, &value);
877 if (**strp != ')')
878 return "missing `)'";
879 ++*strp;
880 *valuep = value;
881 return errmsg;
882 }
883 else
884 {
885 if (**strp == '#')
886 ++*strp;
887 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
888 }
889 }
890
891 static const char *
892 parse_even_register (cd, strP, tableP, valueP)
893 CGEN_CPU_DESC cd;
894 const char ** strP;
895 CGEN_KEYWORD * tableP;
896 long * valueP;
897 {
898 const char * errmsg;
899 const char * saved_star_strP = * strP;
900
901 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
902
903 if (errmsg == NULL && ((* valueP) & 1))
904 {
905 errmsg = _("register number must be even");
906 * strP = saved_star_strP;
907 }
908
909 return errmsg;
910 }
911 /* -- */
912 \f
913 /* -- dis.c */
914 static void print_spr
915 PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
916 static void print_hi
917 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
918 static void print_lo
919 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
920
921 static void
922 print_spr (cd, dis_info, names, regno, attrs)
923 CGEN_CPU_DESC cd;
924 PTR dis_info;
925 CGEN_KEYWORD *names;
926 long regno;
927 unsigned int attrs;
928 {
929 /* Use the register index format for any unnamed registers. */
930 if (cgen_keyword_lookup_value (names, regno) == NULL)
931 {
932 disassemble_info *info = (disassemble_info *) dis_info;
933 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
934 }
935 else
936 print_keyword (cd, dis_info, names, regno, attrs);
937 }
938
939 static void
940 print_hi (cd, dis_info, value, attrs, pc, length)
941 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
942 PTR dis_info;
943 long value;
944 unsigned int attrs ATTRIBUTE_UNUSED;
945 bfd_vma pc ATTRIBUTE_UNUSED;
946 int length ATTRIBUTE_UNUSED;
947 {
948 disassemble_info *info = (disassemble_info *) dis_info;
949 if (value)
950 (*info->fprintf_func) (info->stream, "0x%lx", value);
951 else
952 (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
953 }
954
955 static void
956 print_lo (cd, dis_info, value, attrs, pc, length)
957 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
958 PTR dis_info;
959 long value;
960 unsigned int attrs ATTRIBUTE_UNUSED;
961 bfd_vma pc ATTRIBUTE_UNUSED;
962 int length ATTRIBUTE_UNUSED;
963 {
964 disassemble_info *info = (disassemble_info *) dis_info;
965 if (value)
966 (*info->fprintf_func) (info->stream, "0x%lx", value);
967 else
968 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
969 }
970
971 /* -- */
This page took 0.055458 seconds and 4 git commands to generate.