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