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