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