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