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