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