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