2003-09-04 Andrew Cagney <cagney@redhat.com>
[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 the extra slots.
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 /* IALL */ UNIT_I01, /* only I0 and I1 units */
232 /* FM0 */ UNIT_FM0,
233 /* FM1 */ UNIT_FM1,
234 /* FM01 */ UNIT_FM01,
235 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
236 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
237 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
238 /* B1 */ UNIT_B0,
239 /* B01 */ UNIT_B0,
240 /* C */ UNIT_C,
241 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
242 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
243 /* STORE */ UNIT_I0, /* store only in I0 unit. */
244 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
245 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
246 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
247 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
248 };
249
250 static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
251 {
252 /* unit in insn actual unit */
253 /* NIL */ UNIT_NIL,
254 /* I0 */ UNIT_I0,
255 /* I1 */ UNIT_I1,
256 /* I01 */ UNIT_I01,
257 /* IALL */ UNIT_I01, /* only I0 and I1 units */
258 /* FM0 */ UNIT_FM0,
259 /* FM1 */ UNIT_FM1,
260 /* FM01 */ UNIT_FM01,
261 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
262 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
263 /* B0 */ UNIT_B0,
264 /* B1 */ UNIT_B1,
265 /* B01 */ UNIT_B01,
266 /* C */ UNIT_C,
267 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
268 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
269 /* STORE */ UNIT_I0, /* store only in I0 unit. */
270 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
271 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
272 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
273 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
274 };
275
276 void
277 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
278 {
279 vliw->next_slot = 0;
280 vliw->constraint_violation = 0;
281 vliw->mach = mach;
282 vliw->elf_flags = elf_flags;
283
284 switch (mach)
285 {
286 case bfd_mach_fr400:
287 vliw->current_vliw = fr400_allowed_vliw;
288 vliw->unit_mapping = fr400_unit_mapping;
289 break;
290 default:
291 vliw->current_vliw = fr500_allowed_vliw;
292 vliw->unit_mapping = fr500_unit_mapping;
293 break;
294 }
295 }
296
297 /* Return 1 if unit1 is a match for unit2.
298 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
299 *_allowed_vliw tables above. */
300 static int
301 match_unit (FRV_VLIW *vliw,
302 CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
303 {
304 /* Map any specialized implementation units to actual ones. */
305 unit1 = vliw->unit_mapping[unit1];
306
307 if (unit1 == unit2)
308 return 1;
309 if (unit1 < unit2)
310 return 0;
311
312 switch (unit1)
313 {
314 case UNIT_I01:
315 case UNIT_FM01:
316 case UNIT_B01:
317 /* The 01 versions of these units are within 2 enums of the 0 or 1
318 versions. */
319 if (unit1 - unit2 <= 2)
320 return 1;
321 break;
322 default:
323 break;
324 }
325
326 return 0;
327 }
328
329 /* Return 1 if the vliws match, 0 otherwise. */
330
331 static int
332 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
333 {
334 int i;
335
336 for (i = 0; i < vliw_size; ++i)
337 {
338 if ((*vliw1)[i] != (*vliw2)[i])
339 return 0;
340 }
341
342 return 1;
343 }
344
345 /* Find the next vliw vliw in the table that can accomodate the new insn.
346 If one is found then return it. Otherwise return NULL. */
347
348 static VLIW_COMBO *
349 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
350 {
351 int next = vliw->next_slot;
352 VLIW_COMBO *current = vliw->current_vliw;
353 VLIW_COMBO *potential;
354
355 if (next <= 0)
356 abort (); /* Should never happen */
357
358 /* The table is sorted by units allowed within slots, so vliws with
359 identical starting sequences are together. */
360 potential = current;
361 do
362 {
363 if (match_unit (vliw, unit, (*potential)[next]))
364 return potential;
365 ++potential;
366 }
367 while (match_vliw (potential, current, next));
368
369 return NULL;
370 }
371
372 /* Look for the given major insn type in the given vliw. Return 1 if found,
373 return 0 otherwise. */
374
375 static int
376 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
377 {
378 int i;
379
380 for (i = 0; i < vliw->next_slot; ++i)
381 if (vliw->major[i] == major)
382 return 1;
383
384 return 0;
385 }
386
387 /* Check for constraints between the insns in the vliw due to major insn
388 types. */
389
390 static int
391 fr400_check_insn_major_constraints (
392 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
393 )
394 {
395 /* In the cpu file, all media insns are represented as being allowed in
396 both media units. This makes it easier since this is the case for fr500.
397 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
398 cannot coexist with any other media insn in a vliw. */
399 switch (major)
400 {
401 case FR400_MAJOR_M_2:
402 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
403 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
404 default:
405 break;
406 }
407 return 1;
408 }
409
410 static int
411 fr500_check_insn_major_constraints (
412 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
413 )
414 {
415 /* TODO: A table might be faster for some of the more complex instances
416 here. */
417 switch (major)
418 {
419 case FR500_MAJOR_I_1:
420 case FR500_MAJOR_I_4:
421 case FR500_MAJOR_I_5:
422 case FR500_MAJOR_I_6:
423 case FR500_MAJOR_B_1:
424 case FR500_MAJOR_B_2:
425 case FR500_MAJOR_B_3:
426 case FR500_MAJOR_B_4:
427 case FR500_MAJOR_B_5:
428 case FR500_MAJOR_B_6:
429 case FR500_MAJOR_F_4:
430 case FR500_MAJOR_F_8:
431 case FR500_MAJOR_M_8:
432 return 1; /* OK */
433 case FR500_MAJOR_I_2:
434 /* Cannot coexist with I-3 insn. */
435 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
436 case FR500_MAJOR_I_3:
437 /* Cannot coexist with I-2 insn. */
438 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
439 case FR500_MAJOR_F_1:
440 case FR500_MAJOR_F_2:
441 /* Cannot coexist with F-5, F-6, or M-7 insn. */
442 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
443 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
444 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
445 case FR500_MAJOR_F_3:
446 /* Cannot coexist with F-7, or M-7 insn. */
447 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
448 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
449 case FR500_MAJOR_F_5:
450 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
451 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
452 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
453 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
454 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
455 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
456 case FR500_MAJOR_F_6:
457 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
458 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
459 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
460 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
461 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
462 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
463 case FR500_MAJOR_F_7:
464 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
465 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
466 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
467 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
468 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
469 case FR500_MAJOR_M_1:
470 /* Cannot coexist with M-7 insn. */
471 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
472 case FR500_MAJOR_M_2:
473 case FR500_MAJOR_M_3:
474 /* Cannot coexist with M-5, M-6 or M-7 insn. */
475 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
476 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
477 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
478 case FR500_MAJOR_M_4:
479 /* Cannot coexist with M-6 insn. */
480 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
481 case FR500_MAJOR_M_5:
482 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
483 return ! 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 case FR500_MAJOR_M_6:
489 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
490 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
491 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
492 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
493 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
494 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
495 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
496 case FR500_MAJOR_M_7:
497 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
498 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
499 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
500 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
501 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
502 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
503 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
504 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
505 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
506 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
507 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
508 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
509 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
510 default:
511 abort ();
512 break;
513 }
514 return 1;
515 }
516
517 static int
518 check_insn_major_constraints (
519 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
520 )
521 {
522 int rc;
523 switch (vliw->mach)
524 {
525 case bfd_mach_fr400:
526 rc = fr400_check_insn_major_constraints (vliw, major);
527 break;
528 default:
529 rc = fr500_check_insn_major_constraints (vliw, major);
530 break;
531 }
532 return rc;
533 }
534
535 /* Add in insn to the VLIW vliw if possible. Return 0 if successful,
536 non-zero otherwise. */
537 int
538 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
539 {
540 int index;
541 CGEN_ATTR_VALUE_TYPE major;
542 CGEN_ATTR_VALUE_TYPE unit;
543 VLIW_COMBO *new_vliw;
544
545 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
546 return 1;
547
548 index = vliw->next_slot;
549 if (index >= FRV_VLIW_SIZE)
550 return 1;
551
552 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
553 if (unit == UNIT_NIL)
554 abort (); /* no UNIT specified for this insn in frv.cpu */
555
556 switch (vliw->mach)
557 {
558 case bfd_mach_fr400:
559 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
560 break;
561 default:
562 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
563 break;
564 }
565
566 if (index <= 0)
567 {
568 /* Any insn can be added to slot 0. */
569 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
570 ++vliw->current_vliw;
571 vliw->major[0] = major;
572 vliw->next_slot = 1;
573 return 0;
574 }
575
576 /* If there are already insns in the vliw(s) check to see that
577 this one can be added. Do this by finding an allowable vliw
578 combination that can accept the new insn. */
579 if (! (vliw->elf_flags & EF_FRV_NOPACK))
580 {
581 new_vliw = add_next_to_vliw (vliw, unit);
582 if (new_vliw && check_insn_major_constraints (vliw, major))
583 {
584 vliw->current_vliw = new_vliw;
585 vliw->major[index] = major;
586 vliw->next_slot++;
587 return 0;
588 }
589
590 /* The frv machine supports all packing conbinations. If we fail,
591 to add the insn, then it could not be handled as if it was the fr500.
592 Just return as if it was handled ok. */
593 if (vliw->mach == bfd_mach_frv)
594 return 0;
595 }
596
597 vliw->constraint_violation = 1;
598 return 1;
599 }
600
601 int
602 spr_valid (regno)
603 long regno;
604 {
605 if (regno < 0) return 0;
606 if (regno <= 4095) return 1;
607 return 0;
608 }
609 /* -- */
610 \f
611 /* -- asm.c */
612 static const char * parse_ulo16
613 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
614 static const char * parse_uslo16
615 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
616 static const char * parse_uhi16
617 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
618 static long parse_register_number
619 PARAMS ((const char **));
620 static const char * parse_spr
621 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
622 static const char * parse_d12
623 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
624 static const char * parse_s12
625 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
626 static const char * parse_u12
627 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
628 static const char * parse_even_register
629 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
630 static const char * parse_A0
631 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
632 static const char * parse_A1
633 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
634 static const char * parse_A
635 PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
636
637 static const char *
638 parse_ulo16 (cd, strp, opindex, valuep)
639 CGEN_CPU_DESC cd;
640 const char **strp;
641 int opindex;
642 unsigned long *valuep;
643 {
644 const char *errmsg;
645 enum cgen_parse_operand_result result_type;
646 bfd_vma value;
647
648 if (**strp == '#' || **strp == '%')
649 {
650 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
651 {
652 *strp += 4;
653 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
654 &result_type, &value);
655 if (**strp != ')')
656 return "missing `)'";
657 ++*strp;
658 if (errmsg == NULL
659 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
660 value &= 0xffff;
661 *valuep = value;
662 return errmsg;
663 }
664 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
665 {
666 *strp += 9;
667 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
668 &result_type, &value);
669 if (**strp != ')')
670 return "missing ')'";
671 ++*strp;
672 if (errmsg == NULL
673 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
674 value >>= 16;
675 *valuep = value;
676 return errmsg;
677 }
678 }
679 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
680 }
681
682 static const char *
683 parse_uslo16 (cd, strp, opindex, valuep)
684 CGEN_CPU_DESC cd;
685 const char **strp;
686 int opindex;
687 unsigned long *valuep;
688 {
689 const char *errmsg;
690 enum cgen_parse_operand_result result_type;
691 bfd_vma value;
692
693 if (**strp == '#' || **strp == '%')
694 {
695 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
696 {
697 *strp += 4;
698 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
699 &result_type, &value);
700 if (**strp != ')')
701 return "missing `)'";
702 ++*strp;
703 if (errmsg == NULL
704 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
705 value &= 0xffff;
706 *valuep = value;
707 return errmsg;
708 }
709 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
710 {
711 *strp += 9;
712 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
713 &result_type, &value);
714 if (**strp != ')')
715 return "missing ')'";
716 ++*strp;
717 if (errmsg == NULL
718 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
719 value &= 0xffff;
720 *valuep = value;
721 return errmsg;
722 }
723 }
724 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
725 }
726
727 static const char *
728 parse_uhi16 (cd, strp, opindex, valuep)
729 CGEN_CPU_DESC cd;
730 const char **strp;
731 int opindex;
732 unsigned long *valuep;
733 {
734 const char *errmsg;
735 enum cgen_parse_operand_result result_type;
736 bfd_vma value;
737
738 if (**strp == '#' || **strp == '%')
739 {
740 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
741 {
742 *strp += 4;
743 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
744 &result_type, &value);
745 if (**strp != ')')
746 return "missing `)'";
747 ++*strp;
748 if (errmsg == NULL
749 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
750 value >>= 16;
751 *valuep = value;
752 return errmsg;
753 }
754 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
755 {
756 *strp += 9;
757 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
758 &result_type, &value);
759 if (**strp != ')')
760 return "missing ')'";
761 ++*strp;
762 if (errmsg == NULL
763 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
764 value >>= 16;
765 *valuep = value;
766 return errmsg;
767 }
768 }
769 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
770 }
771
772 static long
773 parse_register_number (strp)
774 const char **strp;
775 {
776 int regno;
777 if (**strp < '0' || **strp > '9')
778 return -1; /* error */
779
780 regno = **strp - '0';
781 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
782 regno = regno * 10 + (**strp - '0');
783
784 return regno;
785 }
786
787 static const char *
788 parse_spr (cd, strp, table, valuep)
789 CGEN_CPU_DESC cd;
790 const char **strp;
791 CGEN_KEYWORD * table;
792 long *valuep;
793 {
794 const char *save_strp;
795 long regno;
796
797 /* Check for spr index notation. */
798 if (strncasecmp (*strp, "spr[", 4) == 0)
799 {
800 *strp += 4;
801 regno = parse_register_number (strp);
802 if (**strp != ']')
803 return "missing `]'";
804 ++*strp;
805 if (! spr_valid (regno))
806 return "Special purpose register number is out of range";
807 *valuep = regno;
808 return NULL;
809 }
810
811 save_strp = *strp;
812 regno = parse_register_number (strp);
813 if (regno != -1)
814 {
815 if (! spr_valid (regno))
816 return "Special purpose register number is out of range";
817 *valuep = regno;
818 return NULL;
819 }
820
821 *strp = save_strp;
822 return cgen_parse_keyword (cd, strp, table, valuep);
823 }
824
825 static const char *
826 parse_d12 (cd, strp, opindex, valuep)
827 CGEN_CPU_DESC cd;
828 const char **strp;
829 int opindex;
830 long *valuep;
831 {
832 const char *errmsg;
833 enum cgen_parse_operand_result result_type;
834 bfd_vma value;
835
836 /* Check for small data reference. */
837 if (**strp == '#' || **strp == '%')
838 {
839 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
840 {
841 *strp += 9;
842 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
843 &result_type, &value);
844 if (**strp != ')')
845 return "missing `)'";
846 ++*strp;
847 *valuep = value;
848 return errmsg;
849 }
850 }
851 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
852 }
853
854 static const char *
855 parse_s12 (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_GPREL12,
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 static const char *
887 parse_u12 (cd, strp, opindex, valuep)
888 CGEN_CPU_DESC cd;
889 const char **strp;
890 int opindex;
891 long *valuep;
892 {
893 const char *errmsg;
894 enum cgen_parse_operand_result result_type;
895 bfd_vma value;
896
897 /* Check for small data reference. */
898 if ((**strp == '#' || **strp == '%')
899 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
900 {
901 *strp += 9;
902 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
903 &result_type, &value);
904 if (**strp != ')')
905 return "missing `)'";
906 ++*strp;
907 *valuep = value;
908 return errmsg;
909 }
910 else
911 {
912 if (**strp == '#')
913 ++*strp;
914 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
915 }
916 }
917
918 static const char *
919 parse_A (cd, strp, opindex, valuep, A)
920 CGEN_CPU_DESC cd;
921 const char **strp;
922 int opindex;
923 long *valuep;
924 long A;
925 {
926 const char *errmsg;
927
928 if (**strp == '#')
929 ++*strp;
930
931 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
932 if (errmsg)
933 return errmsg;
934
935 if (*valuep != A)
936 return "Value of A operand must be 0 or 1";
937
938 return NULL;
939 }
940
941 static const char *
942 parse_A0 (cd, strp, opindex, valuep)
943 CGEN_CPU_DESC cd;
944 const char **strp;
945 int opindex;
946 long *valuep;
947 {
948 return parse_A (cd, strp, opindex, valuep, 0);
949 }
950
951 static const char *
952 parse_A1 (cd, strp, opindex, valuep)
953 CGEN_CPU_DESC cd;
954 const char **strp;
955 int opindex;
956 long *valuep;
957 {
958 return parse_A (cd, strp, opindex, valuep, 1);
959 }
960
961 static const char *
962 parse_even_register (cd, strP, tableP, valueP)
963 CGEN_CPU_DESC cd;
964 const char ** strP;
965 CGEN_KEYWORD * tableP;
966 long * valueP;
967 {
968 const char * errmsg;
969 const char * saved_star_strP = * strP;
970
971 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
972
973 if (errmsg == NULL && ((* valueP) & 1))
974 {
975 errmsg = _("register number must be even");
976 * strP = saved_star_strP;
977 }
978
979 return errmsg;
980 }
981 /* -- */
982 \f
983 /* -- dis.c */
984 static void print_spr
985 PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
986 static void print_hi
987 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
988 static void print_lo
989 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
990
991 static void
992 print_spr (cd, dis_info, names, regno, attrs)
993 CGEN_CPU_DESC cd;
994 PTR dis_info;
995 CGEN_KEYWORD *names;
996 long regno;
997 unsigned int attrs;
998 {
999 /* Use the register index format for any unnamed registers. */
1000 if (cgen_keyword_lookup_value (names, regno) == NULL)
1001 {
1002 disassemble_info *info = (disassemble_info *) dis_info;
1003 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1004 }
1005 else
1006 print_keyword (cd, dis_info, names, regno, attrs);
1007 }
1008
1009 static void
1010 print_hi (cd, dis_info, value, attrs, pc, length)
1011 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1012 PTR dis_info;
1013 long value;
1014 unsigned int attrs ATTRIBUTE_UNUSED;
1015 bfd_vma pc ATTRIBUTE_UNUSED;
1016 int length ATTRIBUTE_UNUSED;
1017 {
1018 disassemble_info *info = (disassemble_info *) dis_info;
1019 if (value)
1020 (*info->fprintf_func) (info->stream, "0x%lx", value);
1021 else
1022 (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
1023 }
1024
1025 static void
1026 print_lo (cd, dis_info, value, attrs, pc, length)
1027 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1028 PTR dis_info;
1029 long value;
1030 unsigned int attrs ATTRIBUTE_UNUSED;
1031 bfd_vma pc ATTRIBUTE_UNUSED;
1032 int length ATTRIBUTE_UNUSED;
1033 {
1034 disassemble_info *info = (disassemble_info *) dis_info;
1035 if (value)
1036 (*info->fprintf_func) (info->stream, "0x%lx", value);
1037 else
1038 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
1039 }
1040
1041 /* -- */
This page took 0.055914 seconds and 4 git commands to generate.