e149508edf4817819e8878caa3e9701ebdfee9fe
[deliverable/binutils-gdb.git] / cpu / frv.opc
1 /* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*-
2
3 Copyright 2000, 2001, 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 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 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
289 /* STORE */ UNIT_I0, /* store only in I0 unit. */
290 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
291 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
292 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
293 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
294 };
295
296 static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
297 {
298 /* unit in insn actual unit */
299 /* NIL */ UNIT_NIL,
300 /* I0 */ UNIT_I0,
301 /* I1 */ UNIT_I1,
302 /* I01 */ UNIT_I01,
303 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
304 /* I3 */ UNIT_NIL,
305 /* IALL */ UNIT_I01, /* only I0 and I1 units */
306 /* FM0 */ UNIT_FM0,
307 /* FM1 */ UNIT_FM1,
308 /* FM01 */ UNIT_FM01,
309 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
310 /* FM3 */ UNIT_NIL, /* no F3 or M2 units */
311 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
312 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
313 /* B0 */ UNIT_B0,
314 /* B1 */ UNIT_B1,
315 /* B01 */ UNIT_B01,
316 /* C */ UNIT_C,
317 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
318 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
319 /* STORE */ UNIT_I0, /* store only in I0 unit. */
320 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
321 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
322 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
323 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
324 };
325
326 static CGEN_ATTR_VALUE_TYPE fr550_unit_mapping[] =
327 {
328 /* unit in insn actual unit */
329 /* NIL */ UNIT_NIL,
330 /* I0 */ UNIT_I0,
331 /* I1 */ UNIT_I1,
332 /* I01 */ UNIT_I01,
333 /* I2 */ UNIT_I2,
334 /* I3 */ UNIT_I3,
335 /* IALL */ UNIT_IALL,
336 /* FM0 */ UNIT_FM0,
337 /* FM1 */ UNIT_FM1,
338 /* FM01 */ UNIT_FM01,
339 /* FM2 */ UNIT_FM2,
340 /* FM3 */ UNIT_FM3,
341 /* FMALL */ UNIT_FMALL,
342 /* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */
343 /* B0 */ UNIT_B0,
344 /* B1 */ UNIT_B1,
345 /* B01 */ UNIT_B01,
346 /* C */ UNIT_C,
347 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
348 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
349 /* STORE */ UNIT_I01, /* store in I0 or I1 unit. */
350 /* SCAN */ UNIT_IALL, /* scan in any integer unit. */
351 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
352 /* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */
353 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
354 };
355
356 void
357 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
358 {
359 vliw->next_slot = 0;
360 vliw->constraint_violation = 0;
361 vliw->mach = mach;
362 vliw->elf_flags = elf_flags;
363
364 switch (mach)
365 {
366 case bfd_mach_fr400:
367 vliw->current_vliw = fr400_allowed_vliw;
368 vliw->unit_mapping = fr400_unit_mapping;
369 break;
370 case bfd_mach_fr550:
371 vliw->current_vliw = fr550_allowed_vliw;
372 vliw->unit_mapping = fr550_unit_mapping;
373 break;
374 default:
375 vliw->current_vliw = fr500_allowed_vliw;
376 vliw->unit_mapping = fr500_unit_mapping;
377 break;
378 }
379 }
380
381 /* Return 1 if unit1 is a match for unit2.
382 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
383 *_allowed_vliw tables above. */
384 static int
385 match_unit (FRV_VLIW *vliw,
386 CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
387 {
388 /* Map any specialized implementation units to actual ones. */
389 unit1 = vliw->unit_mapping[unit1];
390
391 if (unit1 == unit2)
392 return 1;
393 if (unit1 < unit2)
394 return 0;
395
396 switch (unit1)
397 {
398 case UNIT_I01:
399 case UNIT_FM01:
400 case UNIT_B01:
401 /* The 01 versions of these units are within 2 enums of the 0 or 1
402 versions. */
403 if (unit1 - unit2 <= 2)
404 return 1;
405 break;
406 case UNIT_IALL:
407 case UNIT_FMALL:
408 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
409 versions. */
410 if (unit1 - unit2 <= 5)
411 return 1;
412 break;
413 default:
414 break;
415 }
416
417 return 0;
418 }
419
420 /* Return 1 if the vliws match, 0 otherwise. */
421
422 static int
423 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
424 {
425 int i;
426
427 for (i = 0; i < vliw_size; ++i)
428 {
429 if ((*vliw1)[i] != (*vliw2)[i])
430 return 0;
431 }
432
433 return 1;
434 }
435
436 /* Find the next vliw vliw in the table that can accomodate the new insn.
437 If one is found then return it. Otherwise return NULL. */
438
439 static VLIW_COMBO *
440 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
441 {
442 int next = vliw->next_slot;
443 VLIW_COMBO *current = vliw->current_vliw;
444 VLIW_COMBO *potential;
445
446 if (next <= 0)
447 {
448 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
449 __LINE__);
450 abort (); /* Should never happen */
451 }
452
453 /* The table is sorted by units allowed within slots, so vliws with
454 identical starting sequences are together. */
455 potential = current;
456 do
457 {
458 if (match_unit (vliw, unit, (*potential)[next]))
459 return potential;
460 ++potential;
461 }
462 while (match_vliw (potential, current, next));
463
464 return NULL;
465 }
466
467 /* Look for the given major insn type in the given vliw. Return 1 if found,
468 return 0 otherwise. */
469
470 static int
471 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
472 {
473 int i;
474
475 for (i = 0; i < vliw->next_slot; ++i)
476 if (vliw->major[i] == major)
477 return 1;
478
479 return 0;
480 }
481
482 /* Check for constraints between the insns in the vliw due to major insn
483 types. */
484
485 static int
486 fr400_check_insn_major_constraints (
487 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
488 )
489 {
490 /* In the cpu file, all media insns are represented as being allowed in
491 both media units. This makes it easier since this is the case for fr500.
492 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
493 cannot coexist with any other media insn in a vliw. */
494 switch (major)
495 {
496 case FR400_MAJOR_M_2:
497 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
498 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
499 default:
500 break;
501 }
502 return 1;
503 }
504
505 static int
506 find_unit_in_vliw (
507 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit
508 )
509 {
510 int i;
511 for (i = 0; i < vliw->next_slot; ++i)
512 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
513 return 1;
514
515 return 0; /* not found */
516 }
517
518 static int
519 find_major_in_slot (
520 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, CGEN_ATTR_VALUE_TYPE slot
521 )
522 {
523 int i;
524
525 for (i = 0; i < vliw->next_slot; ++i)
526 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
527 return 1;
528
529 return 0;
530 }
531
532 static int
533 fr550_find_media_in_vliw (FRV_VLIW *vliw)
534 {
535 int i;
536
537 for (i = 0; i < vliw->next_slot; ++i)
538 {
539 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
540 continue;
541
542 /* Found a media insn, however, MNOP and MCLRACC don't count. */
543 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
544 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
545 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
546 continue;
547
548 return 1; /* found one */
549 }
550
551 return 0;
552 }
553
554 static int
555 fr550_find_float_in_vliw (FRV_VLIW *vliw)
556 {
557 int i;
558
559 for (i = 0; i < vliw->next_slot; ++i)
560 {
561 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
562 continue;
563
564 /* Found a floating point insn, however, FNOP doesn't count. */
565 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
566 continue;
567
568 return 1; /* found one */
569 }
570
571 return 0;
572 }
573
574 static int
575 fr550_check_insn_major_constraints (
576 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn
577 )
578 {
579 CGEN_ATTR_VALUE_TYPE unit;
580 CGEN_ATTR_VALUE_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
581 switch (slot)
582 {
583 case UNIT_I2:
584 /* If it's a store, then there must be another store in I1 */
585 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
586 if (unit == UNIT_STORE)
587 return find_unit_in_vliw (vliw, UNIT_STORE);
588 break;
589 case UNIT_FM2:
590 case UNIT_FM3:
591 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist with
592 media insns. */
593 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
594 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
595 return ! fr550_find_media_in_vliw (vliw);
596 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
597 floating point insns. */
598 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
599 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
600 return ! fr550_find_float_in_vliw (vliw);
601 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
602 respectively.
603 */
604 if (major == FR550_MAJOR_F_2)
605 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2, slot - (UNIT_FM2 - UNIT_FM0))
606 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4, slot - (UNIT_FM2 - UNIT_FM0));
607 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
608 respectively. */
609 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
610 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2, slot - (UNIT_FM2 - UNIT_FM0));
611 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
612 respectively. */
613 if (major == FR550_MAJOR_M_4)
614 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4, slot - (UNIT_FM2 - UNIT_FM0));
615 break;
616 default:
617 break;
618 }
619 return 1; /* all ok */
620 }
621
622 static int
623 fr500_check_insn_major_constraints (
624 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
625 )
626 {
627 /* TODO: A table might be faster for some of the more complex instances
628 here. */
629 switch (major)
630 {
631 case FR500_MAJOR_I_1:
632 case FR500_MAJOR_I_4:
633 case FR500_MAJOR_I_5:
634 case FR500_MAJOR_I_6:
635 case FR500_MAJOR_B_1:
636 case FR500_MAJOR_B_2:
637 case FR500_MAJOR_B_3:
638 case FR500_MAJOR_B_4:
639 case FR500_MAJOR_B_5:
640 case FR500_MAJOR_B_6:
641 case FR500_MAJOR_F_4:
642 case FR500_MAJOR_F_8:
643 case FR500_MAJOR_M_8:
644 return 1; /* OK */
645 case FR500_MAJOR_I_2:
646 /* Cannot coexist with I-3 insn. */
647 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
648 case FR500_MAJOR_I_3:
649 /* Cannot coexist with I-2 insn. */
650 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
651 case FR500_MAJOR_F_1:
652 case FR500_MAJOR_F_2:
653 /* Cannot coexist with F-5, F-6, or M-7 insn. */
654 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
655 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
656 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
657 case FR500_MAJOR_F_3:
658 /* Cannot coexist with F-7, or M-7 insn. */
659 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
660 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
661 case FR500_MAJOR_F_5:
662 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
663 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
664 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
665 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
666 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
667 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
668 case FR500_MAJOR_F_6:
669 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
670 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
671 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
672 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
673 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
674 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
675 case FR500_MAJOR_F_7:
676 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
677 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
678 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
679 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
680 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
681 case FR500_MAJOR_M_1:
682 /* Cannot coexist with M-7 insn. */
683 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
684 case FR500_MAJOR_M_2:
685 case FR500_MAJOR_M_3:
686 /* Cannot coexist with M-5, M-6 or M-7 insn. */
687 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
688 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
689 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
690 case FR500_MAJOR_M_4:
691 /* Cannot coexist with M-6 insn. */
692 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
693 case FR500_MAJOR_M_5:
694 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
695 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
696 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
697 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
698 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
699 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
700 case FR500_MAJOR_M_6:
701 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
702 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
703 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
704 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
705 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
706 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
707 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
708 case FR500_MAJOR_M_7:
709 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
710 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
711 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
712 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
713 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
714 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
715 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
716 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
717 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
718 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
719 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
720 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
721 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
722 default:
723 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
724 __LINE__);
725 abort ();
726 break;
727 }
728 return 1;
729 }
730
731 static int
732 check_insn_major_constraints (
733 FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn
734 )
735 {
736 int rc;
737 switch (vliw->mach)
738 {
739 case bfd_mach_fr400:
740 rc = fr400_check_insn_major_constraints (vliw, major);
741 break;
742 case bfd_mach_fr550:
743 rc = fr550_check_insn_major_constraints (vliw, major, insn);
744 break;
745 default:
746 rc = fr500_check_insn_major_constraints (vliw, major);
747 break;
748 }
749 return rc;
750 }
751
752 /* Add in insn to the VLIW vliw if possible. Return 0 if successful,
753 non-zero otherwise. */
754 int
755 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
756 {
757 int index;
758 CGEN_ATTR_VALUE_TYPE major;
759 CGEN_ATTR_VALUE_TYPE unit;
760 VLIW_COMBO *new_vliw;
761
762 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
763 return 1;
764
765 index = vliw->next_slot;
766 if (index >= FRV_VLIW_SIZE)
767 return 1;
768
769 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
770 if (unit == UNIT_NIL)
771 {
772 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
773 __LINE__);
774 abort (); /* no UNIT specified for this insn in frv.cpu */
775 }
776
777 switch (vliw->mach)
778 {
779 case bfd_mach_fr400:
780 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
781 break;
782 case bfd_mach_fr550:
783 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
784 break;
785 default:
786 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
787 break;
788 }
789
790 if (index <= 0)
791 {
792 /* Any insn can be added to slot 0. */
793 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
794 ++vliw->current_vliw;
795 vliw->major[0] = major;
796 vliw->insn[0] = insn;
797 vliw->next_slot = 1;
798 return 0;
799 }
800
801 /* If there are already insns in the vliw(s) check to see that
802 this one can be added. Do this by finding an allowable vliw
803 combination that can accept the new insn. */
804 if (! (vliw->elf_flags & EF_FRV_NOPACK))
805 {
806 new_vliw = add_next_to_vliw (vliw, unit);
807 if (new_vliw && check_insn_major_constraints (vliw, major, insn))
808 {
809 vliw->current_vliw = new_vliw;
810 vliw->major[index] = major;
811 vliw->insn[index] = insn;
812 vliw->next_slot++;
813 return 0;
814 }
815
816 /* The frv machine supports all packing conbinations. If we fail,
817 to add the insn, then it could not be handled as if it was the fr500.
818 Just return as if it was handled ok. */
819 if (vliw->mach == bfd_mach_frv)
820 return 0;
821 }
822
823 vliw->constraint_violation = 1;
824 return 1;
825 }
826
827 int
828 spr_valid (regno)
829 long regno;
830 {
831 if (regno < 0) return 0;
832 if (regno <= 4095) return 1;
833 return 0;
834 }
835 /* -- */
836 \f
837 /* -- asm.c */
838 static const char * parse_ulo16
839 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
840 static const char * parse_uslo16
841 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
842 static const char * parse_uhi16
843 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
844 static long parse_register_number
845 PARAMS ((const char **));
846 static const char * parse_spr
847 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
848 static const char * parse_d12
849 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
850 static const char * parse_s12
851 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
852 static const char * parse_u12
853 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
854 static const char * parse_even_register
855 PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
856 static const char * parse_A0
857 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
858 static const char * parse_A1
859 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
860 static const char * parse_A
861 PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
862
863 static const char *
864 parse_ulo16 (cd, strp, opindex, valuep)
865 CGEN_CPU_DESC cd;
866 const char **strp;
867 int opindex;
868 unsigned long *valuep;
869 {
870 const char *errmsg;
871 enum cgen_parse_operand_result result_type;
872 bfd_vma value;
873
874 if (**strp == '#' || **strp == '%')
875 {
876 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
877 {
878 *strp += 4;
879 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
880 &result_type, &value);
881 if (**strp != ')')
882 return "missing `)'";
883 ++*strp;
884 if (errmsg == NULL
885 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
886 value &= 0xffff;
887 *valuep = value;
888 return errmsg;
889 }
890 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
891 {
892 *strp += 9;
893 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
894 &result_type, &value);
895 if (**strp != ')')
896 return "missing ')'";
897 ++*strp;
898 if (errmsg == NULL
899 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
900 value >>= 16;
901 *valuep = value;
902 return errmsg;
903 }
904 }
905 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
906 }
907
908 static const char *
909 parse_uslo16 (cd, strp, opindex, valuep)
910 CGEN_CPU_DESC cd;
911 const char **strp;
912 int opindex;
913 unsigned long *valuep;
914 {
915 const char *errmsg;
916 enum cgen_parse_operand_result result_type;
917 bfd_vma value;
918
919 if (**strp == '#' || **strp == '%')
920 {
921 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
922 {
923 *strp += 4;
924 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
925 &result_type, &value);
926 if (**strp != ')')
927 return "missing `)'";
928 ++*strp;
929 if (errmsg == NULL
930 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
931 value &= 0xffff;
932 *valuep = value;
933 return errmsg;
934 }
935 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
936 {
937 *strp += 9;
938 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
939 &result_type, &value);
940 if (**strp != ')')
941 return "missing ')'";
942 ++*strp;
943 if (errmsg == NULL
944 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
945 value &= 0xffff;
946 *valuep = value;
947 return errmsg;
948 }
949 }
950 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
951 }
952
953 static const char *
954 parse_uhi16 (cd, strp, opindex, valuep)
955 CGEN_CPU_DESC cd;
956 const char **strp;
957 int opindex;
958 unsigned long *valuep;
959 {
960 const char *errmsg;
961 enum cgen_parse_operand_result result_type;
962 bfd_vma value;
963
964 if (**strp == '#' || **strp == '%')
965 {
966 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
967 {
968 *strp += 4;
969 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
970 &result_type, &value);
971 if (**strp != ')')
972 return "missing `)'";
973 ++*strp;
974 if (errmsg == NULL
975 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
976 value >>= 16;
977 *valuep = value;
978 return errmsg;
979 }
980 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
981 {
982 *strp += 9;
983 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
984 &result_type, &value);
985 if (**strp != ')')
986 return "missing ')'";
987 ++*strp;
988 if (errmsg == NULL
989 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
990 value >>= 16;
991 *valuep = value;
992 return errmsg;
993 }
994 }
995 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
996 }
997
998 static long
999 parse_register_number (strp)
1000 const char **strp;
1001 {
1002 int regno;
1003 if (**strp < '0' || **strp > '9')
1004 return -1; /* error */
1005
1006 regno = **strp - '0';
1007 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1008 regno = regno * 10 + (**strp - '0');
1009
1010 return regno;
1011 }
1012
1013 static const char *
1014 parse_spr (cd, strp, table, valuep)
1015 CGEN_CPU_DESC cd;
1016 const char **strp;
1017 CGEN_KEYWORD * table;
1018 long *valuep;
1019 {
1020 const char *save_strp;
1021 long regno;
1022
1023 /* Check for spr index notation. */
1024 if (strncasecmp (*strp, "spr[", 4) == 0)
1025 {
1026 *strp += 4;
1027 regno = parse_register_number (strp);
1028 if (**strp != ']')
1029 return "missing `]'";
1030 ++*strp;
1031 if (! spr_valid (regno))
1032 return "Special purpose register number is out of range";
1033 *valuep = regno;
1034 return NULL;
1035 }
1036
1037 save_strp = *strp;
1038 regno = parse_register_number (strp);
1039 if (regno != -1)
1040 {
1041 if (! spr_valid (regno))
1042 return "Special purpose register number is out of range";
1043 *valuep = regno;
1044 return NULL;
1045 }
1046
1047 *strp = save_strp;
1048 return cgen_parse_keyword (cd, strp, table, valuep);
1049 }
1050
1051 static const char *
1052 parse_d12 (cd, strp, opindex, valuep)
1053 CGEN_CPU_DESC cd;
1054 const char **strp;
1055 int opindex;
1056 long *valuep;
1057 {
1058 const char *errmsg;
1059 enum cgen_parse_operand_result result_type;
1060 bfd_vma value;
1061
1062 /* Check for small data reference. */
1063 if (**strp == '#' || **strp == '%')
1064 {
1065 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1066 {
1067 *strp += 9;
1068 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
1069 &result_type, &value);
1070 if (**strp != ')')
1071 return "missing `)'";
1072 ++*strp;
1073 *valuep = value;
1074 return errmsg;
1075 }
1076 }
1077 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1078 }
1079
1080 static const char *
1081 parse_s12 (cd, strp, opindex, valuep)
1082 CGEN_CPU_DESC cd;
1083 const char **strp;
1084 int opindex;
1085 long *valuep;
1086 {
1087 const char *errmsg;
1088 enum cgen_parse_operand_result result_type;
1089 bfd_vma value;
1090
1091 /* Check for small data reference. */
1092 if ((**strp == '#' || **strp == '%')
1093 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1094 {
1095 *strp += 9;
1096 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
1097 &result_type, &value);
1098 if (**strp != ')')
1099 return "missing `)'";
1100 ++*strp;
1101 *valuep = value;
1102 return errmsg;
1103 }
1104 else
1105 {
1106 if (**strp == '#')
1107 ++*strp;
1108 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1109 }
1110 }
1111
1112 static const char *
1113 parse_u12 (cd, strp, opindex, valuep)
1114 CGEN_CPU_DESC cd;
1115 const char **strp;
1116 int opindex;
1117 long *valuep;
1118 {
1119 const char *errmsg;
1120 enum cgen_parse_operand_result result_type;
1121 bfd_vma value;
1122
1123 /* Check for small data reference. */
1124 if ((**strp == '#' || **strp == '%')
1125 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1126 {
1127 *strp += 9;
1128 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
1129 &result_type, &value);
1130 if (**strp != ')')
1131 return "missing `)'";
1132 ++*strp;
1133 *valuep = value;
1134 return errmsg;
1135 }
1136 else
1137 {
1138 if (**strp == '#')
1139 ++*strp;
1140 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1141 }
1142 }
1143
1144 static const char *
1145 parse_A (cd, strp, opindex, valuep, A)
1146 CGEN_CPU_DESC cd;
1147 const char **strp;
1148 int opindex;
1149 long *valuep;
1150 long A;
1151 {
1152 const char *errmsg;
1153
1154 if (**strp == '#')
1155 ++*strp;
1156
1157 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1158 if (errmsg)
1159 return errmsg;
1160
1161 if (*valuep != A)
1162 return "Value of A operand must be 0 or 1";
1163
1164 return NULL;
1165 }
1166
1167 static const char *
1168 parse_A0 (cd, strp, opindex, valuep)
1169 CGEN_CPU_DESC cd;
1170 const char **strp;
1171 int opindex;
1172 long *valuep;
1173 {
1174 return parse_A (cd, strp, opindex, valuep, 0);
1175 }
1176
1177 static const char *
1178 parse_A1 (cd, strp, opindex, valuep)
1179 CGEN_CPU_DESC cd;
1180 const char **strp;
1181 int opindex;
1182 long *valuep;
1183 {
1184 return parse_A (cd, strp, opindex, valuep, 1);
1185 }
1186
1187 static const char *
1188 parse_even_register (cd, strP, tableP, valueP)
1189 CGEN_CPU_DESC cd;
1190 const char ** strP;
1191 CGEN_KEYWORD * tableP;
1192 long * valueP;
1193 {
1194 const char * errmsg;
1195 const char * saved_star_strP = * strP;
1196
1197 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1198
1199 if (errmsg == NULL && ((* valueP) & 1))
1200 {
1201 errmsg = _("register number must be even");
1202 * strP = saved_star_strP;
1203 }
1204
1205 return errmsg;
1206 }
1207 /* -- */
1208 \f
1209 /* -- dis.c */
1210 static void print_spr
1211 PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
1212 static void print_hi
1213 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
1214 static void print_lo
1215 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
1216
1217 static void
1218 print_spr (cd, dis_info, names, regno, attrs)
1219 CGEN_CPU_DESC cd;
1220 PTR dis_info;
1221 CGEN_KEYWORD *names;
1222 long regno;
1223 unsigned int attrs;
1224 {
1225 /* Use the register index format for any unnamed registers. */
1226 if (cgen_keyword_lookup_value (names, regno) == NULL)
1227 {
1228 disassemble_info *info = (disassemble_info *) dis_info;
1229 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1230 }
1231 else
1232 print_keyword (cd, dis_info, names, regno, attrs);
1233 }
1234
1235 static void
1236 print_hi (cd, dis_info, value, attrs, pc, length)
1237 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1238 PTR dis_info;
1239 long value;
1240 unsigned int attrs ATTRIBUTE_UNUSED;
1241 bfd_vma pc ATTRIBUTE_UNUSED;
1242 int length ATTRIBUTE_UNUSED;
1243 {
1244 disassemble_info *info = (disassemble_info *) dis_info;
1245 if (value)
1246 (*info->fprintf_func) (info->stream, "0x%lx", value);
1247 else
1248 (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
1249 }
1250
1251 static void
1252 print_lo (cd, dis_info, value, attrs, pc, length)
1253 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1254 PTR dis_info;
1255 long value;
1256 unsigned int attrs ATTRIBUTE_UNUSED;
1257 bfd_vma pc ATTRIBUTE_UNUSED;
1258 int length ATTRIBUTE_UNUSED;
1259 {
1260 disassemble_info *info = (disassemble_info *) dis_info;
1261 if (value)
1262 (*info->fprintf_func) (info->stream, "0x%lx", value);
1263 else
1264 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
1265 }
1266
1267 /* -- */
This page took 0.071728 seconds and 3 git commands to generate.