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