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