Change source files over to GPLv3.
[deliverable/binutils-gdb.git] / cpu / frv.opc
1 /* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*-
2
3 Copyright 2000, 2001, 2003, 2004, 2005, 2007 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
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 \f
40 /* -- opc.h */
41
42 #undef CGEN_DIS_HASH_SIZE
43 #define CGEN_DIS_HASH_SIZE 128
44 #undef CGEN_DIS_HASH
45 #define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
46
47 /* Allows reason codes to be output when assembler errors occur. */
48 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
49
50 /* Vliw support. */
51 #define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8. */
52 #define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
53
54 typedef CGEN_ATTR_VALUE_ENUM_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_ENUM_TYPE * unit_mapping;
63 VLIW_COMBO * current_vliw;
64 CGEN_ATTR_VALUE_ENUM_TYPE major[FRV_VLIW_SIZE];
65 const CGEN_INSN * insn[FRV_VLIW_SIZE];
66 } FRV_VLIW;
67
68 int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
69 int frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
70 int frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
71 int frv_is_branch_insn (const CGEN_INSN *);
72 int frv_is_float_insn (const CGEN_INSN *);
73 int frv_is_media_insn (const CGEN_INSN *);
74 void frv_vliw_reset (FRV_VLIW *, unsigned long, unsigned long);
75 int frv_vliw_add_insn (FRV_VLIW *, const CGEN_INSN *);
76 int spr_valid (long);
77 /* -- */
78 \f
79 /* -- opc.c */
80 #include "elf/frv.h"
81 #include <stdio.h>
82
83 /* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
84 development tree. */
85
86 bfd_boolean
87 frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
88 {
89 switch (mach)
90 {
91 case bfd_mach_fr400:
92 if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
93 return TRUE;
94 break;
95 case bfd_mach_fr450:
96 if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
97 return TRUE;
98 break;
99 default:
100 if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
101 return TRUE;
102 break;
103 }
104
105 return FALSE;
106 }
107
108 /* Returns TRUE if {MAJOR,MACH} supports floating point insns. */
109
110 bfd_boolean
111 frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
112 {
113 switch (mach)
114 {
115 case bfd_mach_fr400:
116 case bfd_mach_fr450:
117 return FALSE;
118 default:
119 if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
120 return TRUE;
121 break;
122 }
123
124 return FALSE;
125 }
126
127 /* Returns TRUE if {MAJOR,MACH} supports media insns. */
128
129 bfd_boolean
130 frv_is_media_major (CGEN_ATTR_VALUE_ENUM_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 TRUE;
137 break;
138 case bfd_mach_fr450:
139 if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
140 return TRUE;
141 break;
142 default:
143 if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
144 return TRUE;
145 break;
146 }
147
148 return FALSE;
149 }
150
151 bfd_boolean
152 frv_is_branch_insn (const CGEN_INSN *insn)
153 {
154 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
155 bfd_mach_fr400))
156 return TRUE;
157 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
158 bfd_mach_fr450))
159 return TRUE;
160 if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
161 bfd_mach_fr500))
162 return TRUE;
163
164 return FALSE;
165 }
166
167 bfd_boolean
168 frv_is_float_insn (const CGEN_INSN *insn)
169 {
170 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
171 bfd_mach_fr400))
172 return TRUE;
173 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
174 bfd_mach_fr450))
175 return TRUE;
176 if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
177 bfd_mach_fr500))
178 return TRUE;
179
180 return FALSE;
181 }
182
183 bfd_boolean
184 frv_is_media_insn (const CGEN_INSN *insn)
185 {
186 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
187 bfd_mach_fr400))
188 return TRUE;
189 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
190 bfd_mach_fr450))
191 return TRUE;
192 if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
193 bfd_mach_fr500))
194 return TRUE;
195
196 return FALSE;
197 }
198
199 /* This table represents the allowable packing for vliw insns for the fr400.
200 The fr400 has only 2 vliw slots. Represent this by not allowing any insns
201 in the extra slots.
202 Subsets of any given row are also allowed. */
203 static VLIW_COMBO fr400_allowed_vliw[] =
204 {
205 /* slot0 slot1 slot2 slot3 */
206 { UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
207 { UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
208 { UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
209 { UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
210 { UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
211 { UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
212 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
213 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
214 };
215
216 /* This table represents the allowable packing for vliw insns for the fr500.
217 The fr500 has only 4 vliw slots. Represent this by not allowing any insns
218 in the extra slots.
219 Subsets of any given row are also allowed. */
220 static VLIW_COMBO fr500_allowed_vliw[] =
221 {
222 /* slot0 slot1 slot2 slot3 */
223 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO },
224 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO },
225 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO },
226 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
227 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
228 { UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
229 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
230 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
231 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
232 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
233 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
234 };
235
236 /* This table represents the allowable packing for vliw insns for the fr550.
237 Subsets of any given row are also allowed. */
238 static VLIW_COMBO fr550_allowed_vliw[] =
239 {
240 /* slot0 slot1 slot2 slot3 slot4 slot5 slot6 slot7 */
241 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL },
242 { UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL },
243 { UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
244 { UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
245 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 },
246 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 },
247 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 },
248 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 },
249 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 },
250 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL },
251 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
252 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
253 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL },
254 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
255 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL },
256 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
257 { UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
258 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL },
259 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
260 { UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
261 { UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
262 { UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
263 { UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
264 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
265 { UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
266 { UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
267 { UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
268 { UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
269 };
270
271 /* Some insns are assigned specialized implementation units which map to
272 different actual implementation units on different machines. These
273 tables perform that mapping. */
274 static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
275 {
276 /* unit in insn actual unit */
277 /* NIL */ UNIT_NIL,
278 /* I0 */ UNIT_I0,
279 /* I1 */ UNIT_I1,
280 /* I01 */ UNIT_I01,
281 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
282 /* I3 */ UNIT_NIL,
283 /* IALL */ UNIT_I01, /* only I0 and I1 units */
284 /* FM0 */ UNIT_FM0,
285 /* FM1 */ UNIT_FM1,
286 /* FM01 */ UNIT_FM01,
287 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
288 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
289 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
290 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
291 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
292 /* B1 */ UNIT_B0,
293 /* B01 */ UNIT_B0,
294 /* C */ UNIT_C,
295 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
296 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
297 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
298 /* STORE */ UNIT_I0, /* store only in I0 unit. */
299 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
300 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
301 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
302 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
303 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
304 };
305
306 /* Some insns are assigned specialized implementation units which map to
307 different actual implementation units on different machines. These
308 tables perform that mapping. */
309 static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
310 {
311 /* unit in insn actual unit */
312 /* NIL */ UNIT_NIL,
313 /* I0 */ UNIT_I0,
314 /* I1 */ UNIT_I1,
315 /* I01 */ UNIT_I01,
316 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
317 /* I3 */ UNIT_NIL,
318 /* IALL */ UNIT_I01, /* only I0 and I1 units */
319 /* FM0 */ UNIT_FM0,
320 /* FM1 */ UNIT_FM1,
321 /* FM01 */ UNIT_FM01,
322 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
323 /* FM3 */ UNIT_NIL, /* no F3 or M3 units */
324 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
325 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
326 /* B0 */ UNIT_B0, /* branches only in B0 unit. */
327 /* B1 */ UNIT_B0,
328 /* B01 */ UNIT_B0,
329 /* C */ UNIT_C,
330 /* MULT-DIV */ UNIT_I0, /* multiply and divide only in I0 unit. */
331 /* IACC */ UNIT_I01, /* iacc multiply in I0 or I1 unit. */
332 /* LOAD */ UNIT_I0, /* load only in I0 unit. */
333 /* STORE */ UNIT_I0, /* store only in I0 unit. */
334 /* SCAN */ UNIT_I0, /* scan only in I0 unit. */
335 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
336 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
337 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1. */
338 /* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
339 };
340
341 static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
342 {
343 /* unit in insn actual unit */
344 /* NIL */ UNIT_NIL,
345 /* I0 */ UNIT_I0,
346 /* I1 */ UNIT_I1,
347 /* I01 */ UNIT_I01,
348 /* I2 */ UNIT_NIL, /* no I2 or I3 unit */
349 /* I3 */ UNIT_NIL,
350 /* IALL */ UNIT_I01, /* only I0 and I1 units */
351 /* FM0 */ UNIT_FM0,
352 /* FM1 */ UNIT_FM1,
353 /* FM01 */ UNIT_FM01,
354 /* FM2 */ UNIT_NIL, /* no F2 or M2 units */
355 /* FM3 */ UNIT_NIL, /* no F3 or M2 units */
356 /* FMALL */ UNIT_FM01,/* Only F0,F1,M0,M1 units */
357 /* FMLOW */ UNIT_FM0, /* Only F0,M0 units */
358 /* B0 */ UNIT_B0,
359 /* B1 */ UNIT_B1,
360 /* B01 */ UNIT_B01,
361 /* C */ UNIT_C,
362 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
363 /* IACC */ UNIT_NIL, /* iacc multiply not implemented */
364 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
365 /* STORE */ UNIT_I0, /* store only in I0 unit. */
366 /* SCAN */ UNIT_I01, /* scan in I0 or I1 unit. */
367 /* DCPL */ UNIT_C, /* dcpl only in C unit. */
368 /* MDUALACC */ UNIT_FM0, /* media dual acc insn only in FM0 unit. */
369 /* MDCUTSSI */ UNIT_FM0, /* mdcutssi only in FM0 unit. */
370 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
371 };
372
373 static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
374 {
375 /* unit in insn actual unit */
376 /* NIL */ UNIT_NIL,
377 /* I0 */ UNIT_I0,
378 /* I1 */ UNIT_I1,
379 /* I01 */ UNIT_I01,
380 /* I2 */ UNIT_I2,
381 /* I3 */ UNIT_I3,
382 /* IALL */ UNIT_IALL,
383 /* FM0 */ UNIT_FM0,
384 /* FM1 */ UNIT_FM1,
385 /* FM01 */ UNIT_FM01,
386 /* FM2 */ UNIT_FM2,
387 /* FM3 */ UNIT_FM3,
388 /* FMALL */ UNIT_FMALL,
389 /* FMLOW */ UNIT_FM01, /* Only F0,F1,M0,M1 units */
390 /* B0 */ UNIT_B0,
391 /* B1 */ UNIT_B1,
392 /* B01 */ UNIT_B01,
393 /* C */ UNIT_C,
394 /* MULT-DIV */ UNIT_I01, /* multiply and divide in I0 or I1 unit. */
395 /* IACC */ UNIT_NIL, /* iacc multiply not implemented. */
396 /* LOAD */ UNIT_I01, /* load in I0 or I1 unit. */
397 /* STORE */ UNIT_I01, /* store in I0 or I1 unit. */
398 /* SCAN */ UNIT_IALL, /* scan in any integer unit. */
399 /* DCPL */ UNIT_I0, /* dcpl only in I0 unit. */
400 /* MDUALACC */ UNIT_FMALL,/* media dual acc insn in all media units */
401 /* MDCUTSSI */ UNIT_FM01, /* mdcutssi in FM0 or FM1 unit. */
402 /* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
403 };
404
405 void
406 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
407 {
408 vliw->next_slot = 0;
409 vliw->constraint_violation = 0;
410 vliw->mach = mach;
411 vliw->elf_flags = elf_flags;
412
413 switch (mach)
414 {
415 case bfd_mach_fr400:
416 vliw->current_vliw = fr400_allowed_vliw;
417 vliw->unit_mapping = fr400_unit_mapping;
418 break;
419 case bfd_mach_fr450:
420 vliw->current_vliw = fr400_allowed_vliw;
421 vliw->unit_mapping = fr450_unit_mapping;
422 break;
423 case bfd_mach_fr550:
424 vliw->current_vliw = fr550_allowed_vliw;
425 vliw->unit_mapping = fr550_unit_mapping;
426 break;
427 default:
428 vliw->current_vliw = fr500_allowed_vliw;
429 vliw->unit_mapping = fr500_unit_mapping;
430 break;
431 }
432 }
433
434 /* Return TRUE if unit1 is a match for unit2.
435 Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
436 *_allowed_vliw tables above. */
437 static bfd_boolean
438 match_unit (FRV_VLIW *vliw,
439 CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
440 {
441 /* Map any specialized implementation units to actual ones. */
442 unit1 = vliw->unit_mapping[unit1];
443
444 if (unit1 == unit2)
445 return TRUE;
446 if (unit1 < unit2)
447 return FALSE;
448
449 switch (unit1)
450 {
451 case UNIT_I01:
452 case UNIT_FM01:
453 case UNIT_B01:
454 /* The 01 versions of these units are within 2 enums of the 0 or 1
455 versions. */
456 if (unit1 - unit2 <= 2)
457 return TRUE;
458 break;
459 case UNIT_IALL:
460 case UNIT_FMALL:
461 /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
462 versions. */
463 if (unit1 - unit2 <= 5)
464 return TRUE;
465 break;
466 default:
467 break;
468 }
469
470 return FALSE;
471 }
472
473 /* Return TRUE if the vliws match, FALSE otherwise. */
474
475 static bfd_boolean
476 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
477 {
478 int i;
479
480 for (i = 0; i < vliw_size; ++i)
481 if ((*vliw1)[i] != (*vliw2)[i])
482 return FALSE;
483
484 return TRUE;
485 }
486
487 /* Find the next vliw vliw in the table that can accomodate the new insn.
488 If one is found then return it. Otherwise return NULL. */
489
490 static VLIW_COMBO *
491 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
492 {
493 int next = vliw->next_slot;
494 VLIW_COMBO *current = vliw->current_vliw;
495 VLIW_COMBO *potential;
496
497 if (next <= 0)
498 {
499 fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
500 __LINE__);
501 abort (); /* Should never happen. */
502 }
503
504 /* The table is sorted by units allowed within slots, so vliws with
505 identical starting sequences are together. */
506 potential = current;
507 do
508 {
509 if (match_unit (vliw, unit, (*potential)[next]))
510 return potential;
511 ++potential;
512 }
513 while (match_vliw (potential, current, next));
514
515 return NULL;
516 }
517
518 /* Look for the given major insn type in the given vliw.
519 Returns TRUE if found, FALSE otherwise. */
520
521 static bfd_boolean
522 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
523 {
524 int i;
525
526 for (i = 0; i < vliw->next_slot; ++i)
527 if (vliw->major[i] == major)
528 return TRUE;
529
530 return FALSE;
531 }
532
533 /* Check for constraints between the insns in the vliw due to major insn
534 types. */
535
536 static bfd_boolean
537 fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
538 {
539 /* In the cpu file, all media insns are represented as being allowed in
540 both media units. This makes it easier since this is the case for fr500.
541 Catch the invalid combinations here. Insns of major class FR400_MAJOR_M_2
542 cannot coexist with any other media insn in a vliw. */
543 switch (major)
544 {
545 case FR400_MAJOR_M_2:
546 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
547 && ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
548 case FR400_MAJOR_M_1:
549 return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
550 default:
551 break;
552 }
553 return TRUE;
554 }
555
556 static bfd_boolean
557 fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
558 {
559 CGEN_ATTR_VALUE_ENUM_TYPE other_major;
560
561 /* Our caller guarantees there's at least one other instruction. */
562 other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
563
564 /* (M4, M5) and (M4, M6) are allowed. */
565 if (other_major == FR450_MAJOR_M_4)
566 if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
567 return TRUE;
568
569 /* Otherwise, instructions in even-numbered media categories cannot be
570 executed in parallel with other media instructions. */
571 switch (major)
572 {
573 case FR450_MAJOR_M_2:
574 case FR450_MAJOR_M_4:
575 case FR450_MAJOR_M_6:
576 return !(other_major >= FR450_MAJOR_M_1
577 && other_major <= FR450_MAJOR_M_6);
578
579 case FR450_MAJOR_M_1:
580 case FR450_MAJOR_M_3:
581 case FR450_MAJOR_M_5:
582 return !(other_major == FR450_MAJOR_M_2
583 || other_major == FR450_MAJOR_M_4
584 || other_major == FR450_MAJOR_M_6);
585
586 default:
587 return TRUE;
588 }
589 }
590
591 static bfd_boolean
592 find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
593 {
594 int i;
595
596 for (i = 0; i < vliw->next_slot; ++i)
597 if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
598 return TRUE;
599
600 return FALSE; /* Not found. */
601 }
602
603 static bfd_boolean
604 find_major_in_slot (FRV_VLIW *vliw,
605 CGEN_ATTR_VALUE_ENUM_TYPE major,
606 CGEN_ATTR_VALUE_ENUM_TYPE slot)
607 {
608 int i;
609
610 for (i = 0; i < vliw->next_slot; ++i)
611 if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
612 return TRUE;
613
614 return FALSE;
615 }
616
617 static bfd_boolean
618 fr550_find_media_in_vliw (FRV_VLIW *vliw)
619 {
620 int i;
621
622 for (i = 0; i < vliw->next_slot; ++i)
623 {
624 if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
625 continue;
626
627 /* Found a media insn, however, MNOP and MCLRACC don't count. */
628 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
629 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
630 || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
631 continue;
632
633 return TRUE; /* Found one. */
634 }
635
636 return FALSE;
637 }
638
639 static bfd_boolean
640 fr550_find_float_in_vliw (FRV_VLIW *vliw)
641 {
642 int i;
643
644 for (i = 0; i < vliw->next_slot; ++i)
645 {
646 if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
647 continue;
648
649 /* Found a floating point insn, however, FNOP doesn't count. */
650 if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
651 continue;
652
653 return TRUE; /* Found one. */
654 }
655
656 return FALSE;
657 }
658
659 static bfd_boolean
660 fr550_check_insn_major_constraints (FRV_VLIW *vliw,
661 CGEN_ATTR_VALUE_ENUM_TYPE major,
662 const CGEN_INSN *insn)
663 {
664 CGEN_ATTR_VALUE_ENUM_TYPE unit;
665 CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
666 switch (slot)
667 {
668 case UNIT_I2:
669 /* If it's a store, then there must be another store in I1 */
670 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
671 if (unit == UNIT_STORE)
672 return find_unit_in_vliw (vliw, UNIT_STORE);
673 break;
674 case UNIT_FM2:
675 case UNIT_FM3:
676 /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
677 with media insns. */
678 if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
679 && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
680 return ! fr550_find_media_in_vliw (vliw);
681 /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
682 floating point insns. */
683 if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
684 && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
685 return ! fr550_find_float_in_vliw (vliw);
686 /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
687 respectively. */
688 if (major == FR550_MAJOR_F_2)
689 return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
690 slot - (UNIT_FM2 - UNIT_FM0))
691 && ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
692 slot - (UNIT_FM2 - UNIT_FM0));
693 /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
694 respectively. */
695 if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
696 return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
697 slot - (UNIT_FM2 - UNIT_FM0));
698 /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
699 respectively. */
700 if (major == FR550_MAJOR_M_4)
701 return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
702 slot - (UNIT_FM2 - UNIT_FM0));
703 break;
704 default:
705 break;
706 }
707 return TRUE; /* All OK. */
708 }
709
710 static bfd_boolean
711 fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
712 {
713 /* TODO: A table might be faster for some of the more complex instances
714 here. */
715 switch (major)
716 {
717 case FR500_MAJOR_I_1:
718 case FR500_MAJOR_I_4:
719 case FR500_MAJOR_I_5:
720 case FR500_MAJOR_I_6:
721 case FR500_MAJOR_B_1:
722 case FR500_MAJOR_B_2:
723 case FR500_MAJOR_B_3:
724 case FR500_MAJOR_B_4:
725 case FR500_MAJOR_B_5:
726 case FR500_MAJOR_B_6:
727 case FR500_MAJOR_F_4:
728 case FR500_MAJOR_F_8:
729 case FR500_MAJOR_M_8:
730 return TRUE; /* OK */
731 case FR500_MAJOR_I_2:
732 /* Cannot coexist with I-3 insn. */
733 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
734 case FR500_MAJOR_I_3:
735 /* Cannot coexist with I-2 insn. */
736 return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
737 case FR500_MAJOR_F_1:
738 case FR500_MAJOR_F_2:
739 /* Cannot coexist with F-5, F-6, or M-7 insn. */
740 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
741 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
742 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
743 case FR500_MAJOR_F_3:
744 /* Cannot coexist with F-7, or M-7 insn. */
745 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
746 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
747 case FR500_MAJOR_F_5:
748 /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn. */
749 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
750 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
751 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
752 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
753 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
754 case FR500_MAJOR_F_6:
755 /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn. */
756 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
757 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
758 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
759 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
760 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
761 case FR500_MAJOR_F_7:
762 /* Cannot coexist with F-3, F-5, F-7, or M-7 insn. */
763 return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
764 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
765 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
766 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
767 case FR500_MAJOR_M_1:
768 /* Cannot coexist with M-7 insn. */
769 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
770 case FR500_MAJOR_M_2:
771 case FR500_MAJOR_M_3:
772 /* Cannot coexist with M-5, M-6 or M-7 insn. */
773 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
774 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
775 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
776 case FR500_MAJOR_M_4:
777 /* Cannot coexist with M-6 insn. */
778 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
779 case FR500_MAJOR_M_5:
780 /* Cannot coexist with M-2, M-3, M-5, M-6 or M-7 insn. */
781 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
782 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
783 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
784 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
785 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
786 case FR500_MAJOR_M_6:
787 /* Cannot coexist with M-2, M-3, M-4, M-5, M-6 or M-7 insn. */
788 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
789 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
790 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
791 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
792 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
793 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
794 case FR500_MAJOR_M_7:
795 /* Cannot coexist with M-1, M-2, M-3, M-5, M-6 or M-7 insn. */
796 return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
797 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
798 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
799 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
800 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
801 && ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
802 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
803 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
804 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
805 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
806 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
807 && ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
808 default:
809 fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
810 __LINE__);
811 abort ();
812 break;
813 }
814 return TRUE;
815 }
816
817 static bfd_boolean
818 check_insn_major_constraints (FRV_VLIW *vliw,
819 CGEN_ATTR_VALUE_ENUM_TYPE major,
820 const CGEN_INSN *insn)
821 {
822 switch (vliw->mach)
823 {
824 case bfd_mach_fr400:
825 return fr400_check_insn_major_constraints (vliw, major);
826
827 case bfd_mach_fr450:
828 return fr450_check_insn_major_constraints (vliw, major);
829
830 case bfd_mach_fr550:
831 return fr550_check_insn_major_constraints (vliw, major, insn);
832
833 default:
834 return fr500_check_insn_major_constraints (vliw, major);
835 }
836 }
837
838 /* Add in insn to the VLIW vliw if possible.
839 Return 0 if successful, non-zero otherwise. */
840
841 int
842 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
843 {
844 int index;
845 CGEN_ATTR_VALUE_ENUM_TYPE major;
846 CGEN_ATTR_VALUE_ENUM_TYPE unit;
847 VLIW_COMBO *new_vliw;
848
849 if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
850 return 1;
851
852 index = vliw->next_slot;
853 if (index >= FRV_VLIW_SIZE)
854 return 1;
855
856 unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
857 if (unit == UNIT_NIL)
858 {
859 fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
860 __LINE__);
861 abort (); /* No UNIT specified for this insn in frv.cpu. */
862 }
863
864 switch (vliw->mach)
865 {
866 case bfd_mach_fr400:
867 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
868 break;
869 case bfd_mach_fr450:
870 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
871 break;
872 case bfd_mach_fr550:
873 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
874 break;
875 default:
876 major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
877 break;
878 }
879
880 if (index <= 0)
881 {
882 /* Any insn can be added to slot 0. */
883 while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
884 ++vliw->current_vliw;
885 vliw->major[0] = major;
886 vliw->insn[0] = insn;
887 vliw->next_slot = 1;
888 return 0;
889 }
890
891 /* If there are already insns in the vliw(s) check to see that
892 this one can be added. Do this by finding an allowable vliw
893 combination that can accept the new insn. */
894 if (! (vliw->elf_flags & EF_FRV_NOPACK))
895 {
896 new_vliw = add_next_to_vliw (vliw, unit);
897 if (new_vliw && check_insn_major_constraints (vliw, major, insn))
898 {
899 vliw->current_vliw = new_vliw;
900 vliw->major[index] = major;
901 vliw->insn[index] = insn;
902 vliw->next_slot++;
903 return 0;
904 }
905
906 /* The frv machine supports all packing conbinations. If we fail,
907 to add the insn, then it could not be handled as if it was the fr500.
908 Just return as if it was handled ok. */
909 if (vliw->mach == bfd_mach_frv)
910 return 0;
911 }
912
913 vliw->constraint_violation = 1;
914 return 1;
915 }
916
917 bfd_boolean
918 spr_valid (long regno)
919 {
920 if (regno < 0) return FALSE;
921 if (regno <= 4095) return TRUE;
922 return FALSE;
923 }
924 /* -- */
925 \f
926 /* -- asm.c */
927 inline static const char *
928 parse_symbolic_address (CGEN_CPU_DESC cd,
929 const char **strp,
930 int opindex,
931 int opinfo,
932 enum cgen_parse_operand_result *resultp,
933 bfd_vma *valuep)
934 {
935 enum cgen_parse_operand_result result_type;
936 const char *errmsg = (* cd->parse_operand_fn)
937 (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
938 &result_type, valuep);
939
940 if (errmsg == NULL
941 && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
942 return "symbolic expression required";
943
944 if (resultp)
945 *resultp = result_type;
946
947 return errmsg;
948 }
949
950 static const char *
951 parse_ldd_annotation (CGEN_CPU_DESC cd,
952 const char **strp,
953 int opindex,
954 unsigned long *valuep)
955 {
956 const char *errmsg;
957 enum cgen_parse_operand_result result_type;
958 bfd_vma value;
959
960 if (**strp == '#' || **strp == '%')
961 {
962 if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
963 {
964 *strp += 9;
965 errmsg = parse_symbolic_address (cd, strp, opindex,
966 BFD_RELOC_FRV_TLSDESC_RELAX,
967 &result_type, &value);
968 if (**strp != ')')
969 return "missing ')'";
970 if (valuep)
971 *valuep = value;
972 ++*strp;
973 if (errmsg)
974 return errmsg;
975 }
976 }
977
978 while (**strp == ' ' || **strp == '\t')
979 ++*strp;
980
981 if (**strp != '@')
982 return "missing `@'";
983
984 ++*strp;
985
986 return NULL;
987 }
988
989 static const char *
990 parse_call_annotation (CGEN_CPU_DESC cd,
991 const char **strp,
992 int opindex,
993 unsigned long *valuep)
994 {
995 const char *errmsg;
996 enum cgen_parse_operand_result result_type;
997 bfd_vma value;
998
999 if (**strp == '#' || **strp == '%')
1000 {
1001 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1002 {
1003 *strp += 11;
1004 errmsg = parse_symbolic_address (cd, strp, opindex,
1005 BFD_RELOC_FRV_GETTLSOFF_RELAX,
1006 &result_type, &value);
1007 if (**strp != ')')
1008 return "missing ')'";
1009 if (valuep)
1010 *valuep = value;
1011 ++*strp;
1012 if (errmsg)
1013 return errmsg;
1014 }
1015 }
1016
1017 while (**strp == ' ' || **strp == '\t')
1018 ++*strp;
1019
1020 if (**strp != '@')
1021 return "missing `@'";
1022
1023 ++*strp;
1024
1025 return NULL;
1026 }
1027
1028 static const char *
1029 parse_ld_annotation (CGEN_CPU_DESC cd,
1030 const char **strp,
1031 int opindex,
1032 unsigned long *valuep)
1033 {
1034 const char *errmsg;
1035 enum cgen_parse_operand_result result_type;
1036 bfd_vma value;
1037
1038 if (**strp == '#' || **strp == '%')
1039 {
1040 if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
1041 {
1042 *strp += 8;
1043 errmsg = parse_symbolic_address (cd, strp, opindex,
1044 BFD_RELOC_FRV_TLSOFF_RELAX,
1045 &result_type, &value);
1046 if (**strp != ')')
1047 return "missing ')'";
1048 if (valuep)
1049 *valuep = value;
1050 ++*strp;
1051 if (errmsg)
1052 return errmsg;
1053 }
1054 }
1055
1056 while (**strp == ' ' || **strp == '\t')
1057 ++*strp;
1058
1059 if (**strp != '@')
1060 return "missing `@'";
1061
1062 ++*strp;
1063
1064 return NULL;
1065 }
1066
1067 static const char *
1068 parse_ulo16 (CGEN_CPU_DESC cd,
1069 const char **strp,
1070 int opindex,
1071 unsigned long *valuep)
1072 {
1073 const char *errmsg;
1074 enum cgen_parse_operand_result result_type;
1075 bfd_vma value;
1076
1077 if (**strp == '#' || **strp == '%')
1078 {
1079 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1080 {
1081 *strp += 4;
1082 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1083 & result_type, & value);
1084 if (**strp != ')')
1085 return "missing `)'";
1086 ++*strp;
1087 if (errmsg == NULL
1088 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1089 value &= 0xffff;
1090 *valuep = value;
1091 return errmsg;
1092 }
1093 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1094 {
1095 *strp += 9;
1096 errmsg = parse_symbolic_address (cd, strp, opindex,
1097 BFD_RELOC_FRV_GPRELLO,
1098 & result_type, & value);
1099 if (**strp != ')')
1100 return "missing ')'";
1101 ++*strp;
1102 *valuep = value;
1103 return errmsg;
1104 }
1105 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1106 {
1107 *strp += 7;
1108 errmsg = parse_symbolic_address (cd, strp, opindex,
1109 BFD_RELOC_FRV_GOTLO,
1110 & result_type, & value);
1111 if (**strp != ')')
1112 return "missing ')'";
1113 ++*strp;
1114 *valuep = value;
1115 return errmsg;
1116 }
1117 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1118 {
1119 *strp += 15;
1120 errmsg = parse_symbolic_address (cd, strp, opindex,
1121 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1122 & result_type, & value);
1123 if (**strp != ')')
1124 return "missing ')'";
1125 ++*strp;
1126 *valuep = value;
1127 return errmsg;
1128 }
1129 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1130 {
1131 *strp += 10;
1132 errmsg = parse_symbolic_address (cd, strp, opindex,
1133 BFD_RELOC_FRV_GOTOFFLO,
1134 & result_type, & value);
1135 if (**strp != ')')
1136 return "missing ')'";
1137 ++*strp;
1138 *valuep = value;
1139 return errmsg;
1140 }
1141 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1142 {
1143 *strp += 18;
1144 errmsg = parse_symbolic_address (cd, strp, opindex,
1145 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1146 & result_type, & value);
1147 if (**strp != ')')
1148 return "missing ')'";
1149 ++*strp;
1150 *valuep = value;
1151 return errmsg;
1152 }
1153 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1154 {
1155 *strp += 14;
1156 errmsg = parse_symbolic_address (cd, strp, opindex,
1157 BFD_RELOC_FRV_GOTTLSDESCLO,
1158 & result_type, & value);
1159 if (**strp != ')')
1160 return "missing ')'";
1161 ++*strp;
1162 *valuep = value;
1163 return errmsg;
1164 }
1165 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1166 {
1167 *strp += 11;
1168 errmsg = parse_symbolic_address (cd, strp, opindex,
1169 BFD_RELOC_FRV_TLSMOFFLO,
1170 & result_type, & value);
1171 if (**strp != ')')
1172 return "missing ')'";
1173 ++*strp;
1174 *valuep = value;
1175 return errmsg;
1176 }
1177 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1178 {
1179 *strp += 13;
1180 errmsg = parse_symbolic_address (cd, strp, opindex,
1181 BFD_RELOC_FRV_GOTTLSOFFLO,
1182 & result_type, & value);
1183 if (**strp != ')')
1184 return "missing ')'";
1185 ++*strp;
1186 *valuep = value;
1187 return errmsg;
1188 }
1189 }
1190 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1191 }
1192
1193 static const char *
1194 parse_uslo16 (CGEN_CPU_DESC cd,
1195 const char **strp,
1196 int opindex,
1197 signed long *valuep)
1198 {
1199 const char *errmsg;
1200 enum cgen_parse_operand_result result_type;
1201 bfd_vma value;
1202
1203 if (**strp == '#' || **strp == '%')
1204 {
1205 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1206 {
1207 *strp += 4;
1208 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1209 & result_type, & value);
1210 if (**strp != ')')
1211 return "missing `)'";
1212 ++*strp;
1213 if (errmsg == NULL
1214 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1215 value &= 0xffff;
1216 *valuep = value;
1217 return errmsg;
1218 }
1219 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1220 {
1221 *strp += 9;
1222 errmsg = parse_symbolic_address (cd, strp, opindex,
1223 BFD_RELOC_FRV_GPRELLO,
1224 & result_type, & value);
1225 if (**strp != ')')
1226 return "missing ')'";
1227 ++*strp;
1228 *valuep = value;
1229 return errmsg;
1230 }
1231 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1232 {
1233 *strp += 7;
1234 errmsg = parse_symbolic_address (cd, strp, opindex,
1235 BFD_RELOC_FRV_GOTLO,
1236 & result_type, & value);
1237 if (**strp != ')')
1238 return "missing ')'";
1239 ++*strp;
1240 *valuep = value;
1241 return errmsg;
1242 }
1243 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1244 {
1245 *strp += 15;
1246 errmsg = parse_symbolic_address (cd, strp, opindex,
1247 BFD_RELOC_FRV_FUNCDESC_GOTLO,
1248 & result_type, & value);
1249 if (**strp != ')')
1250 return "missing ')'";
1251 ++*strp;
1252 *valuep = value;
1253 return errmsg;
1254 }
1255 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1256 {
1257 *strp += 10;
1258 errmsg = parse_symbolic_address (cd, strp, opindex,
1259 BFD_RELOC_FRV_GOTOFFLO,
1260 & result_type, & value);
1261 if (**strp != ')')
1262 return "missing ')'";
1263 ++*strp;
1264 *valuep = value;
1265 return errmsg;
1266 }
1267 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1268 {
1269 *strp += 18;
1270 errmsg = parse_symbolic_address (cd, strp, opindex,
1271 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1272 & result_type, & value);
1273 if (**strp != ')')
1274 return "missing ')'";
1275 ++*strp;
1276 *valuep = value;
1277 return errmsg;
1278 }
1279 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1280 {
1281 *strp += 14;
1282 errmsg = parse_symbolic_address (cd, strp, opindex,
1283 BFD_RELOC_FRV_GOTTLSDESCLO,
1284 & result_type, & value);
1285 if (**strp != ')')
1286 return "missing ')'";
1287 ++*strp;
1288 *valuep = value;
1289 return errmsg;
1290 }
1291 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1292 {
1293 *strp += 11;
1294 errmsg = parse_symbolic_address (cd, strp, opindex,
1295 BFD_RELOC_FRV_TLSMOFFLO,
1296 & result_type, & value);
1297 if (**strp != ')')
1298 return "missing ')'";
1299 ++*strp;
1300 *valuep = value;
1301 return errmsg;
1302 }
1303 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1304 {
1305 *strp += 13;
1306 errmsg = parse_symbolic_address (cd, strp, opindex,
1307 BFD_RELOC_FRV_GOTTLSOFFLO,
1308 & result_type, & value);
1309 if (**strp != ')')
1310 return "missing ')'";
1311 ++*strp;
1312 *valuep = value;
1313 return errmsg;
1314 }
1315 }
1316 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1317 }
1318
1319 static const char *
1320 parse_uhi16 (CGEN_CPU_DESC cd,
1321 const char **strp,
1322 int opindex,
1323 unsigned long *valuep)
1324 {
1325 const char *errmsg;
1326 enum cgen_parse_operand_result result_type;
1327 bfd_vma value;
1328
1329 if (**strp == '#' || **strp == '%')
1330 {
1331 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1332 {
1333 *strp += 4;
1334 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1335 & result_type, & value);
1336 if (**strp != ')')
1337 return "missing `)'";
1338 ++*strp;
1339 if (errmsg == NULL
1340 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1341 {
1342 /* If bfd_vma is wider than 32 bits, but we have a sign-
1343 or zero-extension, truncate it. */
1344 if (value >= - ((bfd_vma)1 << 31)
1345 || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
1346 value &= (((bfd_vma)1 << 16) << 16) - 1;
1347 value >>= 16;
1348 }
1349 *valuep = value;
1350 return errmsg;
1351 }
1352 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1353 {
1354 *strp += 9;
1355 errmsg = parse_symbolic_address (cd, strp, opindex,
1356 BFD_RELOC_FRV_GPRELHI,
1357 & result_type, & value);
1358 if (**strp != ')')
1359 return "missing ')'";
1360 ++*strp;
1361 *valuep = value;
1362 return errmsg;
1363 }
1364 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1365 {
1366 *strp += 7;
1367 errmsg = parse_symbolic_address (cd, strp, opindex,
1368 BFD_RELOC_FRV_GOTHI,
1369 & result_type, & value);
1370 if (**strp != ')')
1371 return "missing ')'";
1372 ++*strp;
1373 *valuep = value;
1374 return errmsg;
1375 }
1376 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1377 {
1378 *strp += 15;
1379 errmsg = parse_symbolic_address (cd, strp, opindex,
1380 BFD_RELOC_FRV_FUNCDESC_GOTHI,
1381 & result_type, & value);
1382 if (**strp != ')')
1383 return "missing ')'";
1384 ++*strp;
1385 *valuep = value;
1386 return errmsg;
1387 }
1388 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1389 {
1390 *strp += 10;
1391 errmsg = parse_symbolic_address (cd, strp, opindex,
1392 BFD_RELOC_FRV_GOTOFFHI,
1393 & result_type, & value);
1394 if (**strp != ')')
1395 return "missing ')'";
1396 ++*strp;
1397 *valuep = value;
1398 return errmsg;
1399 }
1400 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1401 {
1402 *strp += 18;
1403 errmsg = parse_symbolic_address (cd, strp, opindex,
1404 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1405 & result_type, & value);
1406 if (**strp != ')')
1407 return "missing ')'";
1408 ++*strp;
1409 *valuep = value;
1410 return errmsg;
1411 }
1412 else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
1413 {
1414 *strp += 14;
1415 errmsg = parse_symbolic_address (cd, strp, opindex,
1416 BFD_RELOC_FRV_GOTTLSDESCHI,
1417 &result_type, &value);
1418 if (**strp != ')')
1419 return "missing ')'";
1420 ++*strp;
1421 *valuep = value;
1422 return errmsg;
1423 }
1424 else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
1425 {
1426 *strp += 11;
1427 errmsg = parse_symbolic_address (cd, strp, opindex,
1428 BFD_RELOC_FRV_TLSMOFFHI,
1429 & result_type, & value);
1430 if (**strp != ')')
1431 return "missing ')'";
1432 ++*strp;
1433 *valuep = value;
1434 return errmsg;
1435 }
1436 else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
1437 {
1438 *strp += 13;
1439 errmsg = parse_symbolic_address (cd, strp, opindex,
1440 BFD_RELOC_FRV_GOTTLSOFFHI,
1441 & result_type, & value);
1442 if (**strp != ')')
1443 return "missing ')'";
1444 ++*strp;
1445 *valuep = value;
1446 return errmsg;
1447 }
1448 }
1449 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1450 }
1451
1452 static long
1453 parse_register_number (const char **strp)
1454 {
1455 int regno;
1456
1457 if (**strp < '0' || **strp > '9')
1458 return -1; /* error */
1459
1460 regno = **strp - '0';
1461 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1462 regno = regno * 10 + (**strp - '0');
1463
1464 return regno;
1465 }
1466
1467 static const char *
1468 parse_spr (CGEN_CPU_DESC cd,
1469 const char **strp,
1470 CGEN_KEYWORD * table,
1471 long *valuep)
1472 {
1473 const char *save_strp;
1474 long regno;
1475
1476 /* Check for spr index notation. */
1477 if (strncasecmp (*strp, "spr[", 4) == 0)
1478 {
1479 *strp += 4;
1480 regno = parse_register_number (strp);
1481 if (**strp != ']')
1482 return _("missing `]'");
1483 ++*strp;
1484 if (! spr_valid (regno))
1485 return _("Special purpose register number is out of range");
1486 *valuep = regno;
1487 return NULL;
1488 }
1489
1490 save_strp = *strp;
1491 regno = parse_register_number (strp);
1492 if (regno != -1)
1493 {
1494 if (! spr_valid (regno))
1495 return _("Special purpose register number is out of range");
1496 *valuep = regno;
1497 return NULL;
1498 }
1499
1500 *strp = save_strp;
1501 return cgen_parse_keyword (cd, strp, table, valuep);
1502 }
1503
1504 static const char *
1505 parse_d12 (CGEN_CPU_DESC cd,
1506 const char **strp,
1507 int opindex,
1508 long *valuep)
1509 {
1510 const char *errmsg;
1511 enum cgen_parse_operand_result result_type;
1512 bfd_vma value;
1513
1514 /* Check for small data reference. */
1515 if (**strp == '#' || **strp == '%')
1516 {
1517 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1518 {
1519 *strp += 9;
1520 errmsg = parse_symbolic_address (cd, strp, opindex,
1521 BFD_RELOC_FRV_GPREL12,
1522 & result_type, & value);
1523 if (**strp != ')')
1524 return "missing `)'";
1525 ++*strp;
1526 *valuep = value;
1527 return errmsg;
1528 }
1529 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1530 {
1531 *strp += 7;
1532 errmsg = parse_symbolic_address (cd, strp, opindex,
1533 BFD_RELOC_FRV_GOT12,
1534 & result_type, & value);
1535 if (**strp != ')')
1536 return "missing ')'";
1537 ++*strp;
1538 *valuep = value;
1539 return errmsg;
1540 }
1541 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1542 {
1543 *strp += 15;
1544 errmsg = parse_symbolic_address (cd, strp, opindex,
1545 BFD_RELOC_FRV_FUNCDESC_GOT12,
1546 & result_type, & value);
1547 if (**strp != ')')
1548 return "missing ')'";
1549 ++*strp;
1550 *valuep = value;
1551 return errmsg;
1552 }
1553 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1554 {
1555 *strp += 10;
1556 errmsg = parse_symbolic_address (cd, strp, opindex,
1557 BFD_RELOC_FRV_GOTOFF12,
1558 & result_type, & value);
1559 if (**strp != ')')
1560 return "missing ')'";
1561 ++*strp;
1562 *valuep = value;
1563 return errmsg;
1564 }
1565 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1566 {
1567 *strp += 18;
1568 errmsg = parse_symbolic_address (cd, strp, opindex,
1569 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1570 & result_type, & value);
1571 if (**strp != ')')
1572 return "missing ')'";
1573 ++*strp;
1574 *valuep = value;
1575 return errmsg;
1576 }
1577 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1578 {
1579 *strp += 14;
1580 errmsg = parse_symbolic_address (cd, strp, opindex,
1581 BFD_RELOC_FRV_GOTTLSDESC12,
1582 & result_type, & value);
1583 if (**strp != ')')
1584 return "missing ')'";
1585 ++*strp;
1586 *valuep = value;
1587 return errmsg;
1588 }
1589 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1590 {
1591 *strp += 11;
1592 errmsg = parse_symbolic_address (cd, strp, opindex,
1593 BFD_RELOC_FRV_TLSMOFF12,
1594 & result_type, & value);
1595 if (**strp != ')')
1596 return "missing ')'";
1597 ++*strp;
1598 *valuep = value;
1599 return errmsg;
1600 }
1601 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1602 {
1603 *strp += 13;
1604 errmsg = parse_symbolic_address (cd, strp, opindex,
1605 BFD_RELOC_FRV_GOTTLSOFF12,
1606 & result_type, & value);
1607 if (**strp != ')')
1608 return "missing ')'";
1609 ++*strp;
1610 *valuep = value;
1611 return errmsg;
1612 }
1613 }
1614 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1615 }
1616
1617 static const char *
1618 parse_s12 (CGEN_CPU_DESC cd,
1619 const char **strp,
1620 int opindex,
1621 long *valuep)
1622 {
1623 const char *errmsg;
1624 enum cgen_parse_operand_result result_type;
1625 bfd_vma value;
1626
1627 /* Check for small data reference. */
1628 if (**strp == '#' || **strp == '%')
1629 {
1630 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1631 {
1632 *strp += 9;
1633 errmsg = parse_symbolic_address (cd, strp, opindex,
1634 BFD_RELOC_FRV_GPREL12,
1635 & result_type, & value);
1636 if (**strp != ')')
1637 return "missing `)'";
1638 ++*strp;
1639 *valuep = value;
1640 return errmsg;
1641 }
1642 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1643 {
1644 *strp += 7;
1645 errmsg = parse_symbolic_address (cd, strp, opindex,
1646 BFD_RELOC_FRV_GOT12,
1647 & result_type, & value);
1648 if (**strp != ')')
1649 return "missing ')'";
1650 ++*strp;
1651 *valuep = value;
1652 return errmsg;
1653 }
1654 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1655 {
1656 *strp += 15;
1657 errmsg = parse_symbolic_address (cd, strp, opindex,
1658 BFD_RELOC_FRV_FUNCDESC_GOT12,
1659 & result_type, & value);
1660 if (**strp != ')')
1661 return "missing ')'";
1662 ++*strp;
1663 *valuep = value;
1664 return errmsg;
1665 }
1666 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1667 {
1668 *strp += 10;
1669 errmsg = parse_symbolic_address (cd, strp, opindex,
1670 BFD_RELOC_FRV_GOTOFF12,
1671 & result_type, & value);
1672 if (**strp != ')')
1673 return "missing ')'";
1674 ++*strp;
1675 *valuep = value;
1676 return errmsg;
1677 }
1678 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1679 {
1680 *strp += 18;
1681 errmsg = parse_symbolic_address (cd, strp, opindex,
1682 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1683 & result_type, & value);
1684 if (**strp != ')')
1685 return "missing ')'";
1686 ++*strp;
1687 *valuep = value;
1688 return errmsg;
1689 }
1690 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1691 {
1692 *strp += 14;
1693 errmsg = parse_symbolic_address (cd, strp, opindex,
1694 BFD_RELOC_FRV_GOTTLSDESC12,
1695 & result_type, & value);
1696 if (**strp != ')')
1697 return "missing ')'";
1698 ++*strp;
1699 *valuep = value;
1700 return errmsg;
1701 }
1702 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1703 {
1704 *strp += 11;
1705 errmsg = parse_symbolic_address (cd, strp, opindex,
1706 BFD_RELOC_FRV_TLSMOFF12,
1707 & result_type, & value);
1708 if (**strp != ')')
1709 return "missing ')'";
1710 ++*strp;
1711 *valuep = value;
1712 return errmsg;
1713 }
1714 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1715 {
1716 *strp += 13;
1717 errmsg = parse_symbolic_address (cd, strp, opindex,
1718 BFD_RELOC_FRV_GOTTLSOFF12,
1719 & result_type, & value);
1720 if (**strp != ')')
1721 return "missing ')'";
1722 ++*strp;
1723 *valuep = value;
1724 return errmsg;
1725 }
1726 }
1727
1728 if (**strp == '#')
1729 ++*strp;
1730 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1731 }
1732
1733 static const char *
1734 parse_u12 (CGEN_CPU_DESC cd,
1735 const char **strp,
1736 int opindex,
1737 long *valuep)
1738 {
1739 const char *errmsg;
1740 enum cgen_parse_operand_result result_type;
1741 bfd_vma value;
1742
1743 /* Check for small data reference. */
1744 if ((**strp == '#' || **strp == '%')
1745 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1746 {
1747 *strp += 9;
1748 errmsg = parse_symbolic_address (cd, strp, opindex,
1749 BFD_RELOC_FRV_GPRELU12,
1750 & result_type, & value);
1751 if (**strp != ')')
1752 return "missing `)'";
1753 ++*strp;
1754 *valuep = value;
1755 return errmsg;
1756 }
1757 else
1758 {
1759 if (**strp == '#')
1760 ++*strp;
1761 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1762 }
1763 }
1764
1765 static const char *
1766 parse_A (CGEN_CPU_DESC cd,
1767 const char **strp,
1768 int opindex,
1769 unsigned long *valuep,
1770 unsigned long A)
1771 {
1772 const char *errmsg;
1773
1774 if (**strp == '#')
1775 ++*strp;
1776
1777 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1778 if (errmsg)
1779 return errmsg;
1780
1781 if (*valuep != A)
1782 return _("Value of A operand must be 0 or 1");
1783
1784 return NULL;
1785 }
1786
1787 static const char *
1788 parse_A0 (CGEN_CPU_DESC cd,
1789 const char **strp,
1790 int opindex,
1791 unsigned long *valuep)
1792 {
1793 return parse_A (cd, strp, opindex, valuep, 0);
1794 }
1795
1796 static const char *
1797 parse_A1 (CGEN_CPU_DESC cd,
1798 const char **strp,
1799 int opindex,
1800 unsigned long *valuep)
1801 {
1802 return parse_A (cd, strp, opindex, valuep, 1);
1803 }
1804
1805 static const char *
1806 parse_even_register (CGEN_CPU_DESC cd,
1807 const char ** strP,
1808 CGEN_KEYWORD * tableP,
1809 long * valueP)
1810 {
1811 const char * errmsg;
1812 const char * saved_star_strP = * strP;
1813
1814 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1815
1816 if (errmsg == NULL && ((* valueP) & 1))
1817 {
1818 errmsg = _("register number must be even");
1819 * strP = saved_star_strP;
1820 }
1821
1822 return errmsg;
1823 }
1824
1825 static const char *
1826 parse_call_label (CGEN_CPU_DESC cd,
1827 const char **strp,
1828 int opindex,
1829 int opinfo,
1830 enum cgen_parse_operand_result *resultp,
1831 bfd_vma *valuep)
1832 {
1833 const char *errmsg;
1834 bfd_vma value;
1835
1836 /* Check for small data reference. */
1837 if (opinfo == 0 && (**strp == '#' || **strp == '%'))
1838 {
1839 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1840 {
1841 *strp += 11;
1842 errmsg = parse_symbolic_address (cd, strp, opindex,
1843 BFD_RELOC_FRV_GETTLSOFF,
1844 resultp, &value);
1845 if (**strp != ')')
1846 return _("missing `)'");
1847 ++*strp;
1848 *valuep = value;
1849 return errmsg;
1850 }
1851 }
1852
1853 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
1854 }
1855
1856 /* -- */
1857 \f
1858 /* -- dis.c */
1859 static void
1860 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1861 void * dis_info,
1862 long reloc_ann ATTRIBUTE_UNUSED,
1863 long value ATTRIBUTE_UNUSED,
1864 bfd_vma pc ATTRIBUTE_UNUSED,
1865 int length ATTRIBUTE_UNUSED)
1866 {
1867 disassemble_info *info = (disassemble_info *) dis_info;
1868
1869 (*info->fprintf_func) (info->stream, "@");
1870 }
1871
1872 static void
1873 print_spr (CGEN_CPU_DESC cd,
1874 void * dis_info,
1875 CGEN_KEYWORD *names,
1876 long regno,
1877 unsigned int attrs)
1878 {
1879 /* Use the register index format for any unnamed registers. */
1880 if (cgen_keyword_lookup_value (names, regno) == NULL)
1881 {
1882 disassemble_info *info = (disassemble_info *) dis_info;
1883 (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1884 }
1885 else
1886 print_keyword (cd, dis_info, names, regno, attrs);
1887 }
1888
1889 static void
1890 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1891 void * dis_info,
1892 long value,
1893 unsigned int attrs ATTRIBUTE_UNUSED,
1894 bfd_vma pc ATTRIBUTE_UNUSED,
1895 int length ATTRIBUTE_UNUSED)
1896 {
1897 disassemble_info *info = (disassemble_info *) dis_info;
1898
1899 (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
1900 }
1901
1902 static void
1903 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1904 void * dis_info,
1905 long value,
1906 unsigned int attrs ATTRIBUTE_UNUSED,
1907 bfd_vma pc ATTRIBUTE_UNUSED,
1908 int length ATTRIBUTE_UNUSED)
1909 {
1910 disassemble_info *info = (disassemble_info *) dis_info;
1911 if (value)
1912 (*info->fprintf_func) (info->stream, "0x%lx", value);
1913 else
1914 (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
1915 }
1916
1917 /* -- */
This page took 0.068222 seconds and 4 git commands to generate.