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