e4b96575db631553d8543cda0abe0e541fcecd2a
[deliverable/binutils-gdb.git] / cpu / frv.opc
1 /* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*-
2
3 Copyright 2000, 2001, 2003, 2004 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 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];
55
56 typedef struct
57 {
58 int next_slot;
59 int constraint_violation;
60 unsigned long mach;
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];
66 } FRV_VLIW;
67
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));
77 /* -- */
78 \f
79 /* -- opc.c */
80 #include "elf/frv.h"
81 #include <stdio.h>
82
83 static int match_unit
84 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, CGEN_ATTR_VALUE_TYPE));
85 static int match_vliw
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 fr500_check_insn_major_constraints
94 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
95 static int fr550_check_insn_major_constraints
96 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, const CGEN_INSN *));
97 static int check_insn_major_constraints
98 PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, const CGEN_INSN *));
99
100 int
101 frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
102 {
103 switch (mach)
104 {
105 case bfd_mach_fr400:
106 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
107 return 1; /* is a branch */
108 break;
109 default:
110 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
111 return 1; /* is a branch */
112 break;
113 }
114
115 return 0; /* not a branch */
116 }
117
118 int
119 frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
120 {
121 switch (mach)
122 {
123 case bfd_mach_fr400:
124 return 0; /* No float insns */
125 default:
126 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
127 return 1; /* is a float insn */
128 break;
129 }
130
131 return 0; /* not a branch */
132 }
133
134 int
135 frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
136 {
137 switch (mach)
138 {
139 case bfd_mach_fr400:
140 if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
141 return 1; /* is a media insn */
142 break;
143 default:
144 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
145 return 1; /* is a media insn */
146 break;
147 }
148
149 return 0; /* not a branch */
150 }
151
152 int
153 frv_is_branch_insn (const CGEN_INSN *insn)
154 {
155 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
156 bfd_mach_fr400))
157 return 1;
158 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
159 bfd_mach_fr500))
160 return 1;
161
162 return 0;
163 }
164
165 int
166 frv_is_float_insn (const CGEN_INSN *insn)
167 {
168 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
169 bfd_mach_fr400))
170 return 1;
171 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
172 bfd_mach_fr500))
173 return 1;
174
175 return 0;
176 }
177
178 int
179 frv_is_media_insn (const CGEN_INSN *insn)
180 {
181 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
182 bfd_mach_fr400))
183 return 1;
184 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
185 bfd_mach_fr500))
186 return 1;
187
188 return 0;
189 }
190
191 /* This table represents the allowable packing for vliw insns for the fr400.
192 The fr400 has only 2 vliw slots. Represent this by not allowing any insns
193 in the extra slots.
194 Subsets of any given row are also allowed. */
195 static VLIW_COMBO fr400_allowed_vliw[] =
196 {
197 /* slot0 slot1 slot2 slot3 */
198 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
199 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
200 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
201 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
202 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
203 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
204 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
205 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
206 };
207
208 /* This table represents the allowable packing for vliw insns for the fr500.
209 The fr500 has only 4 vliw slots. Represent this by not allowing any insns
210 in the extra slots.
211 Subsets of any given row are also allowed. */
212 static VLIW_COMBO fr500_allowed_vliw[] =
213 {
214 /* slot0 slot1 slot2 slot3 */
215 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO },
216 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO },
217 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO },
218 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
219 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
220 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
221 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
222 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
223 { UNIT_B0, UNIT_B1, 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 }
226 };
227
228 /* This table represents the allowable packing for vliw insns for the fr550.
229 Subsets of any given row are also allowed. */
230 static VLIW_COMBO fr550_allowed_vliw[] =
231 {
232 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */
233 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL },
234 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL },
235 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
236 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
237 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 },
238 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 },
239 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 },
240 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 },
241 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 },
242 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL },
243 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
244 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
245 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL },
246 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
247 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL },
248 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
249 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
250 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL },
251 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
252 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
253 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
254 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
255 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
256 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
257 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
258 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
259 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
260 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
261 };
262
263 /* Some insns are assigned specialized implementation units which map to
264 different actual implementation units on different machines. These
265 tables perform that mapping. */
266 static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
267 {
268 /* unit in insn actual unit */
269 /* NIL */ UNIT_NIL,
270 /* I0 */ UNIT_I0,
271 /* I1 */ UNIT_I1,
272 /* I01 */ UNIT_I01,
273 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
274 /* I3 */ UNIT_NIL,
275 /* IALL */ UNIT_I01, /* only I0 and I1 units */
276 /* FM0 */ UNIT_FM0,
277 /* FM1 */ UNIT_FM1,
278 /* FM01 */ UNIT_FM01,
279 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
280 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
281 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
282 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
283 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
284 /* B1 */ UNIT_B0,
285 /* B01 */ UNIT_B0,
286 /* C */ UNIT_C,
287 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
288 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
289 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
290 /* STORE */ UNIT_I0, /* store only in I0 unit. */
291 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
292 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
293 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
294 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
295 };
296
297 static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
298 {
299 /* unit in insn actual unit */
300 /* NIL */ UNIT_NIL,
301 /* I0 */ UNIT_I0,
302 /* I1 */ UNIT_I1,
303 /* I01 */ UNIT_I01,
304 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
305 /* I3 */ UNIT_NIL,
306 /* IALL */ UNIT_I01, /* only I0 and I1 units */
307 /* FM0 */ UNIT_FM0,
308 /* FM1 */ UNIT_FM1,
309 /* FM01 */ UNIT_FM01,
310 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
311 /* FM3 */ UNIT_NIL, /* no F3 or M2 units */
312 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
313 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
314 /* B0 */ UNIT_B0,
315 /* B1 */ UNIT_B1,
316 /* B01 */ UNIT_B01,
317 /* C */ UNIT_C,
318 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
319 /* IACC */ UNIT_NIL, /* iacc multiply not implemented */
320 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
321 /* STORE */ UNIT_I0, /* store only in I0 unit. */
322 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
323 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
324 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
325 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
326 };
327
328 static CGEN_ATTR_VALUE_TYPE fr550_unit_mapping[] =
329 {
330 /* unit in insn actual unit */
331 /* NIL */ UNIT_NIL,
332 /* I0 */ UNIT_I0,
333 /* I1 */ UNIT_I1,
334 /* I01 */ UNIT_I01,
335 /* I2 */ UNIT_I2,
336 /* I3 */ UNIT_I3,
337 /* IALL */ UNIT_IALL,
338 /* FM0 */ UNIT_FM0,
339 /* FM1 */ UNIT_FM1,
340 /* FM01 */ UNIT_FM01,
341 /* FM2 */ UNIT_FM2,
342 /* FM3 */ UNIT_FM3,
343 /* FMALL */ UNIT_FMALL,
344 /* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */
345 /* B0 */ UNIT_B0,
346 /* B1 */ UNIT_B1,
347 /* B01 */ UNIT_B01,
348 /* C */ UNIT_C,
349 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
350 /* IACC */ UNIT_NIL, /* iacc multiply not implemented. */
351 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
352 /* STORE */ UNIT_I01, /* store in I0 or I1 unit. */
353 /* SCAN */ UNIT_IALL, /* scan in any integer unit. */
354 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
355 /* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */
356 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
357 };
358
359 void
360 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
361 {
362 vliw->next_slot = 0;
363 vliw->constraint_violation = 0;
364 vliw->mach = mach;
365 vliw->elf_flags = elf_flags;
366
367 switch (mach)
368 {
369 case bfd_mach_fr400:
370 vliw->current_vliw = fr400_allowed_vliw;
371 vliw->unit_mapping = fr400_unit_mapping;
372 break;
373 case bfd_mach_fr550:
374 vliw->current_vliw = fr550_allowed_vliw;
375 vliw->unit_mapping = fr550_unit_mapping;
376 break;
377 default:
378 vliw->current_vliw = fr500_allowed_vliw;
379 vliw->unit_mapping = fr500_unit_mapping;
380 break;
381 }
382 }
383
384 /* Return 1 if unit1 is a match for unit2.
385 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
386 *_allowed_vliw tables above. */
387 static int
388 match_unit (FRV_VLIW *vliw,
389 CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
390 {
391 /* Map any specialized implementation units to actual ones. */
392 unit1 = vliw->unit_mapping[unit1];
393
394 if (unit1 == unit2)
395 return 1;
396 if (unit1 < unit2)
397 return 0;
398
399 switch (unit1)
400 {
401 case UNIT_I01:
402 case UNIT_FM01:
403 case UNIT_B01:
404 /* The 01 versions of these units are within 2 enums of the 0 or 1
405 versions. */
406 if (unit1 - unit2 <= 2)
407 return 1;
408 break;
409 case UNIT_IALL:
410 case UNIT_FMALL:
411 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
412 versions. */
413 if (unit1 - unit2 <= 5)
414 return 1;
415 break;
416 default:
417 break;
418 }
419
420 return 0;
421 }
422
423 /* Return 1 if the vliws match, 0 otherwise. */
424
425 static int
426 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
427 {
428 int i;
429
430 for (i = 0; i < vliw_size; ++i)
431 {
432 if ((*vliw1)[i] != (*vliw2)[i])
433 return 0;
434 }
435
436 return 1;
437 }
438
439 /* Find the next vliw vliw in the table that can accomodate the new insn.
440 If one is found then return it. Otherwise return NULL. */
441
442 static VLIW_COMBO *
443 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
444 {
445 int next = vliw->next_slot;
446 VLIW_COMBO *current = vliw->current_vliw;
447 VLIW_COMBO *potential;
448
449 if (next <= 0)
450 {
451 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
452 __LINE__);
453 abort (); /* Should never happen */
454 }
455
456 /* The table is sorted by units allowed within slots, so vliws with
457 identical starting sequences are together. */
458 potential = current;
459 do
460 {
461 if (match_unit (vliw, unit, (*potential)[next]))
462 return potential;
463 ++potential;
464 }
465 while (match_vliw (potential, current, next));
466
467 return NULL;
468 }
469
470 /* Look for the given major insn type in the given vliw. Return 1 if found,
471 return 0 otherwise. */
472
473 static int
474 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
475 {
476 int i;
477
478 for (i = 0; i < vliw->next_slot; ++i)
479 if (vliw->major[i] == major)
480 return 1;
481
482 return 0;
483 }
484
485 /* Check for constraints between the insns in the vliw due to major insn
486 types. */
487
488 static int
489 fr400_check_insn_major_constraints (
490 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
491 )
492 {
493 /* In the cpu file, all media insns are represented as being allowed in
494 both media units. This makes it easier since this is the case for fr500.
495 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
496 cannot coexist with any other media insn in a vliw. */
497 switch (major)
498 {
499 case FR400_MAJOR_M_2:
500 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
501 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
502 case FR400_MAJOR_M_1:
503 return !find_major_in_vliw (vliw, FR400_MAJOR_M_2);
504 default:
505 break;
506 }
507 return 1;
508 }
509
510 static int
511 find_unit_in_vliw (
512 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit
513 )
514 {
515 int i;
516 for (i = 0; i < vliw->next_slot; ++i)
517 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
518 return 1;
519
520 return 0; /* not found */
521 }
522
523 static int
524 find_major_in_slot (
525 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, CGEN_ATTR_VALUE_TYPE slot
526 )
527 {
528 int i;
529
530 for (i = 0; i < vliw->next_slot; ++i)
531 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
532 return 1;
533
534 return 0;
535 }
536
537 static int
538 fr550_find_media_in_vliw (FRV_VLIW *vliw)
539 {
540 int i;
541
542 for (i = 0; i < vliw->next_slot; ++i)
543 {
544 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
545 continue;
546
547 /* Found a media insn, however, MNOP and MCLRACC don't count. */
548 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
549 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
550 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
551 continue;
552
553 return 1; /* found one */
554 }
555
556 return 0;
557 }
558
559 static int
560 fr550_find_float_in_vliw (FRV_VLIW *vliw)
561 {
562 int i;
563
564 for (i = 0; i < vliw->next_slot; ++i)
565 {
566 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
567 continue;
568
569 /* Found a floating point insn, however, FNOP doesn't count. */
570 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
571 continue;
572
573 return 1; /* found one */
574 }
575
576 return 0;
577 }
578
579 static int
580 fr550_check_insn_major_constraints (
581 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn
582 )
583 {
584 CGEN_ATTR_VALUE_TYPE unit;
585 CGEN_ATTR_VALUE_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
586 switch (slot)
587 {
588 case UNIT_I2:
589 /* If it's a store, then there must be another store in I1 */
590 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
591 if (unit == UNIT_STORE)
592 return find_unit_in_vliw (vliw, UNIT_STORE);
593 break;
594 case UNIT_FM2:
595 case UNIT_FM3:
596 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist with
597 media insns. */
598 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
599 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
600 return ! fr550_find_media_in_vliw (vliw);
601 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
602 floating point insns. */
603 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
604 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
605 return ! fr550_find_float_in_vliw (vliw);
606 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
607 respectively.
608 */
609 if (major == FR550_MAJOR_F_2)
610 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2, slot - (UNIT_FM2 - UNIT_FM0))
611 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4, slot - (UNIT_FM2 - UNIT_FM0));
612 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
613 respectively. */
614 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
615 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2, slot - (UNIT_FM2 - UNIT_FM0));
616 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
617 respectively. */
618 if (major == FR550_MAJOR_M_4)
619 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4, slot - (UNIT_FM2 - UNIT_FM0));
620 break;
621 default:
622 break;
623 }
624 return 1; /* all ok */
625 }
626
627 static int
628 fr500_check_insn_major_constraints (
629 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
630 )
631 {
632 /* TODO: A table might be faster for some of the more complex instances
633 here. */
634 switch (major)
635 {
636 case FR500_MAJOR_I_1:
637 case FR500_MAJOR_I_4:
638 case FR500_MAJOR_I_5:
639 case FR500_MAJOR_I_6:
640 case FR500_MAJOR_B_1:
641 case FR500_MAJOR_B_2:
642 case FR500_MAJOR_B_3:
643 case FR500_MAJOR_B_4:
644 case FR500_MAJOR_B_5:
645 case FR500_MAJOR_B_6:
646 case FR500_MAJOR_F_4:
647 case FR500_MAJOR_F_8:
648 case FR500_MAJOR_M_8:
649 return 1; /* OK */
650 case FR500_MAJOR_I_2:
651 /* Cannot coexist with I-3 insn. */
652 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
653 case FR500_MAJOR_I_3:
654 /* Cannot coexist with I-2 insn. */
655 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
656 case FR500_MAJOR_F_1:
657 case FR500_MAJOR_F_2:
658 /* Cannot coexist with F-5, F-6, or M-7 insn. */
659 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
660 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
661 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
662 case FR500_MAJOR_F_3:
663 /* Cannot coexist with F-7, or M-7 insn. */
664 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
665 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
666 case FR500_MAJOR_F_5:
667 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
668 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
669 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
670 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
671 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
672 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
673 case FR500_MAJOR_F_6:
674 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
675 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
676 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
677 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
678 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
679 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
680 case FR500_MAJOR_F_7:
681 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
682 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
683 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
684 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
685 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
686 case FR500_MAJOR_M_1:
687 /* Cannot coexist with M-7 insn. */
688 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
689 case FR500_MAJOR_M_2:
690 case FR500_MAJOR_M_3:
691 /* Cannot coexist with M-5, M-6 or M-7 insn. */
692 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
693 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
694 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
695 case FR500_MAJOR_M_4:
696 /* Cannot coexist with M-6 insn. */
697 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
698 case FR500_MAJOR_M_5:
699 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
700 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
701 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
702 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
703 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
704 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
705 case FR500_MAJOR_M_6:
706 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
707 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
708 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
709 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
710 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
711 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
712 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
713 case FR500_MAJOR_M_7:
714 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
715 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
716 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
717 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
718 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
719 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
720 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
721 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
722 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
723 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
724 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
725 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
726 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
727 default:
728 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
729 __LINE__);
730 abort ();
731 break;
732 }
733 return 1;
734 }
735
736 static int
737 check_insn_major_constraints (
738 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn
739 )
740 {
741 int rc;
742 switch (vliw->mach)
743 {
744 case bfd_mach_fr400:
745 rc = fr400_check_insn_major_constraints (vliw, major);
746 break;
747 case bfd_mach_fr550:
748 rc = fr550_check_insn_major_constraints (vliw, major, insn);
749 break;
750 default:
751 rc = fr500_check_insn_major_constraints (vliw, major);
752 break;
753 }
754 return rc;
755 }
756
757 /* Add in insn to the VLIW vliw if possible. Return 0 if successful,
758 non-zero otherwise. */
759 int
760 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
761 {
762 int index;
763 CGEN_ATTR_VALUE_TYPE major;
764 CGEN_ATTR_VALUE_TYPE unit;
765 VLIW_COMBO *new_vliw;
766
767 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
768 return 1;
769
770 index = vliw->next_slot;
771 if (index >= FRV_VLIW_SIZE)
772 return 1;
773
774 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
775 if (unit == UNIT_NIL)
776 {
777 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
778 __LINE__);
779 abort (); /* no UNIT specified for this insn in frv.cpu */
780 }
781
782 switch (vliw->mach)
783 {
784 case bfd_mach_fr400:
785 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
786 break;
787 case bfd_mach_fr550:
788 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
789 break;
790 default:
791 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
792 break;
793 }
794
795 if (index <= 0)
796 {
797 /* Any insn can be added to slot 0. */
798 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
799 ++vliw->current_vliw;
800 vliw->major[0] = major;
801 vliw->insn[0] = insn;
802 vliw->next_slot = 1;
803 return 0;
804 }
805
806 /* If there are already insns in the vliw(s) check to see that
807 this one can be added. Do this by finding an allowable vliw
808 combination that can accept the new insn. */
809 if (! (vliw->elf_flags & EF_FRV_NOPACK))
810 {
811 new_vliw = add_next_to_vliw (vliw, unit);
812 if (new_vliw && check_insn_major_constraints (vliw, major, insn))
813 {
814 vliw->current_vliw = new_vliw;
815 vliw->major[index] = major;
816 vliw->insn[index] = insn;
817 vliw->next_slot++;
818 return 0;
819 }
820
821 /* The frv machine supports all packing conbinations. If we fail,
822 to add the insn, then it could not be handled as if it was the fr500.
823 Just return as if it was handled ok. */
824 if (vliw->mach == bfd_mach_frv)
825 return 0;
826 }
827
828 vliw->constraint_violation = 1;
829 return 1;
830 }
831
832 int
833 spr_valid (regno)
834 long regno;
835 {
836 if (regno < 0) return 0;
837 if (regno <= 4095) return 1;
838 return 0;
839 }
840 /* -- */
841 \f
842 /* -- asm.c */
843 static const char * parse_ulo16
844 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
845 static const char * parse_uslo16
846 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
847 static const char * parse_uhi16
848 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
849 static long parse_register_number
850 PARAMS ((const char **));
851 static const char * parse_spr
852 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
853 static const char * parse_d12
854 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
855 static const char * parse_s12
856 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
857 static const char * parse_u12
858 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
859 static const char * parse_even_register
860 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
861 static const char * parse_A0
862 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
863 static const char * parse_A1
864 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
865 static const char * parse_A
866 PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
867
868 static const char *
869 parse_ulo16 (cd, strp, opindex, valuep)
870 CGEN_CPU_DESC cd;
871 const char **strp;
872 int opindex;
873 unsigned long *valuep;
874 {
875 const char *errmsg;
876 enum cgen_parse_operand_result result_type;
877 bfd_vma value;
878
879 if (**strp == '#' || **strp == '%')
880 {
881 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
882 {
883 *strp += 4;
884 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
885 &result_type, &value);
886 if (**strp != ')')
887 return "missing `)'";
888 ++*strp;
889 if (errmsg == NULL
890 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
891 value &= 0xffff;
892 *valuep = value;
893 return errmsg;
894 }
895 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
896 {
897 *strp += 9;
898 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
899 &result_type, &value);
900 if (**strp != ')')
901 return "missing ')'";
902 ++*strp;
903 if (errmsg == NULL
904 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
905 value &= 0xffff;
906 *valuep = value;
907 return errmsg;
908 }
909 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
910 {
911 *strp += 7;
912 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
913 &result_type, &value);
914 if (**strp != ')')
915 return "missing ')'";
916 ++*strp;
917 if (errmsg == NULL
918 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
919 value &= 0xffff;
920 *valuep = value;
921 return errmsg;
922 }
923 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
924 {
925 *strp += 15;
926 errmsg = cgen_parse_address (cd, strp, opindex,
927 BFD_RELOC_FRV_FUNCDESC_GOTLO,
928 &result_type, &value);
929 if (**strp != ')')
930 return "missing ')'";
931 ++*strp;
932 if (errmsg == NULL
933 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
934 value &= 0xffff;
935 *valuep = value;
936 return errmsg;
937 }
938 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
939 {
940 *strp += 10;
941 errmsg = cgen_parse_address (cd, strp, opindex,
942 BFD_RELOC_FRV_GOTOFFLO,
943 &result_type, &value);
944 if (**strp != ')')
945 return "missing ')'";
946 ++*strp;
947 if (errmsg == NULL
948 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
949 value &= 0xffff;
950 *valuep = value;
951 return errmsg;
952 }
953 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
954 {
955 *strp += 18;
956 errmsg = cgen_parse_address (cd, strp, opindex,
957 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
958 &result_type, &value);
959 if (**strp != ')')
960 return "missing ')'";
961 ++*strp;
962 if (errmsg == NULL
963 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
964 value &= 0xffff;
965 *valuep = value;
966 return errmsg;
967 }
968 }
969 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
970 }
971
972 static const char *
973 parse_uslo16 (cd, strp, opindex, valuep)
974 CGEN_CPU_DESC cd;
975 const char **strp;
976 int opindex;
977 unsigned long *valuep;
978 {
979 const char *errmsg;
980 enum cgen_parse_operand_result result_type;
981 bfd_vma value;
982
983 if (**strp == '#' || **strp == '%')
984 {
985 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
986 {
987 *strp += 4;
988 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
989 &result_type, &value);
990 if (**strp != ')')
991 return "missing `)'";
992 ++*strp;
993 if (errmsg == NULL
994 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
995 value &= 0xffff;
996 *valuep = value;
997 return errmsg;
998 }
999 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1000 {
1001 *strp += 9;
1002 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
1003 &result_type, &value);
1004 if (**strp != ')')
1005 return "missing ')'";
1006 ++*strp;
1007 if (errmsg == NULL
1008 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1009 value &= 0xffff;
1010 *valuep = value;
1011 return errmsg;
1012 }
1013 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1014 {
1015 *strp += 7;
1016 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
1017 &result_type, &value);
1018 if (**strp != ')')
1019 return "missing ')'";
1020 ++*strp;
1021 if (errmsg == NULL
1022 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1023 value &= 0xffff;
1024 *valuep = value;
1025 return errmsg;
1026 }
1027 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1028 {
1029 *strp += 15;
1030 errmsg = cgen_parse_address (cd, strp, opindex,
1031 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1032 &result_type, &value);
1033 if (**strp != ')')
1034 return "missing ')'";
1035 ++*strp;
1036 if (errmsg == NULL
1037 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1038 value &= 0xffff;
1039 *valuep = value;
1040 return errmsg;
1041 }
1042 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1043 {
1044 *strp += 10;
1045 errmsg = cgen_parse_address (cd, strp, opindex,
1046 BFD_RELOC_FRV_GOTOFFLO,
1047 &result_type, &value);
1048 if (**strp != ')')
1049 return "missing ')'";
1050 ++*strp;
1051 if (errmsg == NULL
1052 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1053 value &= 0xffff;
1054 *valuep = value;
1055 return errmsg;
1056 }
1057 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1058 {
1059 *strp += 18;
1060 errmsg = cgen_parse_address (cd, strp, opindex,
1061 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1062 &result_type, &value);
1063 if (**strp != ')')
1064 return "missing ')'";
1065 ++*strp;
1066 if (errmsg == NULL
1067 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1068 value &= 0xffff;
1069 *valuep = value;
1070 return errmsg;
1071 }
1072 }
1073 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1074 }
1075
1076 static const char *
1077 parse_uhi16 (cd, strp, opindex, valuep)
1078 CGEN_CPU_DESC cd;
1079 const char **strp;
1080 int opindex;
1081 unsigned long *valuep;
1082 {
1083 const char *errmsg;
1084 enum cgen_parse_operand_result result_type;
1085 bfd_vma value;
1086
1087 if (**strp == '#' || **strp == '%')
1088 {
1089 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1090 {
1091 *strp += 4;
1092 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1093 &result_type, &value);
1094 if (**strp != ')')
1095 return "missing `)'";
1096 ++*strp;
1097 if (errmsg == NULL
1098 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1099 value >>= 16;
1100 *valuep = value;
1101 return errmsg;
1102 }
1103 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1104 {
1105 *strp += 9;
1106 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
1107 &result_type, &value);
1108 if (**strp != ')')
1109 return "missing ')'";
1110 ++*strp;
1111 if (errmsg == NULL
1112 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1113 value >>= 16;
1114 *valuep = value;
1115 return errmsg;
1116 }
1117 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1118 {
1119 *strp += 7;
1120 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTHI,
1121 &result_type, &value);
1122 if (**strp != ')')
1123 return "missing ')'";
1124 ++*strp;
1125 if (errmsg == NULL
1126 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1127 value >>= 16;
1128 *valuep = value;
1129 return errmsg;
1130 }
1131 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1132 {
1133 *strp += 15;
1134 errmsg = cgen_parse_address (cd, strp, opindex,
1135 BFD_RELOC_FRV_FUNCDESC_GOTHI,
1136 &result_type, &value);
1137 if (**strp != ')')
1138 return "missing ')'";
1139 ++*strp;
1140 if (errmsg == NULL
1141 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1142 value >>= 16;
1143 *valuep = value;
1144 return errmsg;
1145 }
1146 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1147 {
1148 *strp += 10;
1149 errmsg = cgen_parse_address (cd, strp, opindex,
1150 BFD_RELOC_FRV_GOTOFFHI,
1151 &result_type, &value);
1152 if (**strp != ')')
1153 return "missing ')'";
1154 ++*strp;
1155 if (errmsg == NULL
1156 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1157 value >>= 16;
1158 *valuep = value;
1159 return errmsg;
1160 }
1161 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1162 {
1163 *strp += 18;
1164 errmsg = cgen_parse_address (cd, strp, opindex,
1165 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1166 &result_type, &value);
1167 if (**strp != ')')
1168 return "missing ')'";
1169 ++*strp;
1170 if (errmsg == NULL
1171 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1172 value >>= 16;
1173 *valuep = value;
1174 return errmsg;
1175 }
1176 }
1177 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1178 }
1179
1180 static long
1181 parse_register_number (strp)
1182 const char **strp;
1183 {
1184 int regno;
1185 if (**strp < '0' || **strp > '9')
1186 return -1; /* error */
1187
1188 regno = **strp - '0';
1189 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1190 regno = regno * 10 + (**strp - '0');
1191
1192 return regno;
1193 }
1194
1195 static const char *
1196 parse_spr (cd, strp, table, valuep)
1197 CGEN_CPU_DESC cd;
1198 const char **strp;
1199 CGEN_KEYWORD * table;
1200 long *valuep;
1201 {
1202 const char *save_strp;
1203 long regno;
1204
1205 /* Check for spr index notation. */
1206 if (strncasecmp (*strp, "spr[", 4) == 0)
1207 {
1208 *strp += 4;
1209 regno = parse_register_number (strp);
1210 if (**strp != ']')
1211 return "missing `]'";
1212 ++*strp;
1213 if (! spr_valid (regno))
1214 return "Special purpose register number is out of range";
1215 *valuep = regno;
1216 return NULL;
1217 }
1218
1219 save_strp = *strp;
1220 regno = parse_register_number (strp);
1221 if (regno != -1)
1222 {
1223 if (! spr_valid (regno))
1224 return "Special purpose register number is out of range";
1225 *valuep = regno;
1226 return NULL;
1227 }
1228
1229 *strp = save_strp;
1230 return cgen_parse_keyword (cd, strp, table, valuep);
1231 }
1232
1233 static const char *
1234 parse_d12 (cd, strp, opindex, valuep)
1235 CGEN_CPU_DESC cd;
1236 const char **strp;
1237 int opindex;
1238 long *valuep;
1239 {
1240 const char *errmsg;
1241 enum cgen_parse_operand_result result_type;
1242 bfd_vma value;
1243
1244 /* Check for small data reference. */
1245 if (**strp == '#' || **strp == '%')
1246 {
1247 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1248 {
1249 *strp += 9;
1250 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
1251 &result_type, &value);
1252 if (**strp != ')')
1253 return "missing `)'";
1254 ++*strp;
1255 *valuep = value;
1256 return errmsg;
1257 }
1258 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1259 {
1260 *strp += 7;
1261 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
1262 &result_type, &value);
1263 if (**strp != ')')
1264 return "missing ')'";
1265 ++*strp;
1266 *valuep = value;
1267 return errmsg;
1268 }
1269 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1270 {
1271 *strp += 15;
1272 errmsg = cgen_parse_address (cd, strp, opindex,
1273 BFD_RELOC_FRV_FUNCDESC_GOT12,
1274 &result_type, &value);
1275 if (**strp != ')')
1276 return "missing ')'";
1277 ++*strp;
1278 *valuep = value;
1279 return errmsg;
1280 }
1281 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1282 {
1283 *strp += 10;
1284 errmsg = cgen_parse_address (cd, strp, opindex,
1285 BFD_RELOC_FRV_GOTOFF12,
1286 &result_type, &value);
1287 if (**strp != ')')
1288 return "missing ')'";
1289 ++*strp;
1290 *valuep = value;
1291 return errmsg;
1292 }
1293 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1294 {
1295 *strp += 18;
1296 errmsg = cgen_parse_address (cd, strp, opindex,
1297 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1298 &result_type, &value);
1299 if (**strp != ')')
1300 return "missing ')'";
1301 ++*strp;
1302 *valuep = value;
1303 return errmsg;
1304 }
1305 }
1306 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1307 }
1308
1309 static const char *
1310 parse_s12 (cd, strp, opindex, valuep)
1311 CGEN_CPU_DESC cd;
1312 const char **strp;
1313 int opindex;
1314 long *valuep;
1315 {
1316 const char *errmsg;
1317 enum cgen_parse_operand_result result_type;
1318 bfd_vma value;
1319
1320 /* Check for small data reference. */
1321 if ((**strp == '#' || **strp == '%')
1322 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1323 {
1324 *strp += 9;
1325 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
1326 &result_type, &value);
1327 if (**strp != ')')
1328 return "missing `)'";
1329 ++*strp;
1330 *valuep = value;
1331 return errmsg;
1332 }
1333 else if ((**strp == '#' || **strp == '%')
1334 && strncasecmp (*strp + 1, "got12(", 6) == 0)
1335 {
1336 *strp += 7;
1337 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
1338 &result_type, &value);
1339 if (**strp != ')')
1340 return "missing ')'";
1341 ++*strp;
1342 *valuep = value;
1343 return errmsg;
1344 }
1345 else if ((**strp == '#' || **strp == '%')
1346 && strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1347 {
1348 *strp += 15;
1349 errmsg = cgen_parse_address (cd, strp, opindex,
1350 BFD_RELOC_FRV_FUNCDESC_GOT12,
1351 &result_type, &value);
1352 if (**strp != ')')
1353 return "missing ')'";
1354 ++*strp;
1355 *valuep = value;
1356 return errmsg;
1357 }
1358 else if ((**strp == '#' || **strp == '%')
1359 && strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1360 {
1361 *strp += 10;
1362 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTOFF12,
1363 &result_type, &value);
1364 if (**strp != ')')
1365 return "missing ')'";
1366 ++*strp;
1367 *valuep = value;
1368 return errmsg;
1369 }
1370 else if ((**strp == '#' || **strp == '%')
1371 && strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1372 {
1373 *strp += 18;
1374 errmsg = cgen_parse_address (cd, strp, opindex,
1375 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1376 &result_type, &value);
1377 if (**strp != ')')
1378 return "missing ')'";
1379 ++*strp;
1380 *valuep = value;
1381 return errmsg;
1382 }
1383 else
1384 {
1385 if (**strp == '#')
1386 ++*strp;
1387 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1388 }
1389 }
1390
1391 static const char *
1392 parse_u12 (cd, strp, opindex, valuep)
1393 CGEN_CPU_DESC cd;
1394 const char **strp;
1395 int opindex;
1396 long *valuep;
1397 {
1398 const char *errmsg;
1399 enum cgen_parse_operand_result result_type;
1400 bfd_vma value;
1401
1402 /* Check for small data reference. */
1403 if ((**strp == '#' || **strp == '%')
1404 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1405 {
1406 *strp += 9;
1407 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
1408 &result_type, &value);
1409 if (**strp != ')')
1410 return "missing `)'";
1411 ++*strp;
1412 *valuep = value;
1413 return errmsg;
1414 }
1415 else
1416 {
1417 if (**strp == '#')
1418 ++*strp;
1419 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1420 }
1421 }
1422
1423 static const char *
1424 parse_A (cd, strp, opindex, valuep, A)
1425 CGEN_CPU_DESC cd;
1426 const char **strp;
1427 int opindex;
1428 long *valuep;
1429 long A;
1430 {
1431 const char *errmsg;
1432
1433 if (**strp == '#')
1434 ++*strp;
1435
1436 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1437 if (errmsg)
1438 return errmsg;
1439
1440 if (*valuep != A)
1441 return "Value of A operand must be 0 or 1";
1442
1443 return NULL;
1444 }
1445
1446 static const char *
1447 parse_A0 (cd, strp, opindex, valuep)
1448 CGEN_CPU_DESC cd;
1449 const char **strp;
1450 int opindex;
1451 long *valuep;
1452 {
1453 return parse_A (cd, strp, opindex, valuep, 0);
1454 }
1455
1456 static const char *
1457 parse_A1 (cd, strp, opindex, valuep)
1458 CGEN_CPU_DESC cd;
1459 const char **strp;
1460 int opindex;
1461 long *valuep;
1462 {
1463 return parse_A (cd, strp, opindex, valuep, 1);
1464 }
1465
1466 static const char *
1467 parse_even_register (cd, strP, tableP, valueP)
1468 CGEN_CPU_DESC cd;
1469 const char ** strP;
1470 CGEN_KEYWORD * tableP;
1471 long * valueP;
1472 {
1473 const char * errmsg;
1474 const char * saved_star_strP = * strP;
1475
1476 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1477
1478 if (errmsg == NULL && ((* valueP) & 1))
1479 {
1480 errmsg = _("register number must be even");
1481 * strP = saved_star_strP;
1482 }
1483
1484 return errmsg;
1485 }
1486 /* -- */
1487 \f
1488 /* -- dis.c */
1489 static void print_spr
1490 PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
1491 static void print_hi
1492 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
1493 static void print_lo
1494 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
1495
1496 static void
1497 print_spr (cd, dis_info, names, regno, attrs)
1498 CGEN_CPU_DESC cd;
1499 PTR dis_info;
1500 CGEN_KEYWORD *names;
1501 long regno;
1502 unsigned int attrs;
1503 {
1504 /* Use the register index format for any unnamed registers. */
1505 if (cgen_keyword_lookup_value (names, regno) == NULL)
1506 {
1507 disassemble_info *info = (disassemble_info *) dis_info;
1508 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1509 }
1510 else
1511 print_keyword (cd, dis_info, names, regno, attrs);
1512 }
1513
1514 static void
1515 print_hi (cd, dis_info, value, attrs, pc, length)
1516 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1517 PTR dis_info;
1518 long value;
1519 unsigned int attrs ATTRIBUTE_UNUSED;
1520 bfd_vma pc ATTRIBUTE_UNUSED;
1521 int length ATTRIBUTE_UNUSED;
1522 {
1523 disassemble_info *info = (disassemble_info *) dis_info;
1524 if (value)
1525 (*info->fprintf_func) (info->stream, "0x%lx", value);
1526 else
1527 (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
1528 }
1529
1530 static void
1531 print_lo (cd, dis_info, value, attrs, pc, length)
1532 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1533 PTR dis_info;
1534 long value;
1535 unsigned int attrs ATTRIBUTE_UNUSED;
1536 bfd_vma pc ATTRIBUTE_UNUSED;
1537 int length ATTRIBUTE_UNUSED;
1538 {
1539 disassemble_info *info = (disassemble_info *) dis_info;
1540 if (value)
1541 (*info->fprintf_func) (info->stream, "0x%lx", value);
1542 else
1543 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
1544 }
1545
1546 /* -- */
This page took 0.067925 seconds and 4 git commands to generate.