1 |
205 |
julius |
/* Copyright (C) 2000, 2003, 2004, 2005, 2007 Free Software Foundation
|
2 |
|
|
Contributed by Alexandre Oliva <aoliva@cygnus.com>
|
3 |
|
|
|
4 |
|
|
This file is free software; you can redistribute it and/or modify it
|
5 |
|
|
under the terms of the GNU General Public License as published by
|
6 |
|
|
the Free Software Foundation; either version 3 of the License, or
|
7 |
|
|
(at your option) any later version.
|
8 |
|
|
|
9 |
|
|
This program is distributed in the hope that it will be useful, but
|
10 |
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
11 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12 |
|
|
General Public License for more details.
|
13 |
|
|
|
14 |
|
|
You should have received a copy of the GNU General Public License
|
15 |
|
|
along with this program; if not, write to the Free Software
|
16 |
|
|
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
17 |
|
|
MA 02110-1301, USA. */
|
18 |
|
|
|
19 |
|
|
/* Generator of tests for Maverick.
|
20 |
|
|
|
21 |
|
|
See the following file for usage and documentation. */
|
22 |
|
|
#include "../all/test-gen.c"
|
23 |
|
|
|
24 |
|
|
/* These are the ARM registers. Some of them have canonical names
|
25 |
|
|
other than r##, so we'll use both in the asm input, but only the
|
26 |
|
|
canonical names in the expected disassembler output. */
|
27 |
|
|
char *arm_regs[] =
|
28 |
|
|
{
|
29 |
|
|
/* Canonical names. */
|
30 |
|
|
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
31 |
|
|
"r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
|
32 |
|
|
/* Alternate names, i.e., those that can be used in the assembler,
|
33 |
|
|
* but that will never be emitted by the disassembler. */
|
34 |
|
|
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
35 |
|
|
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
|
36 |
|
|
};
|
37 |
|
|
|
38 |
|
|
/* The various types of registers: ARM's registers, Maverick's
|
39 |
|
|
f/d/fx/dx registers, Maverick's accumulators and Maverick's
|
40 |
|
|
status register. */
|
41 |
|
|
#define armreg(shift) \
|
42 |
|
|
reg_r (arm_regs, shift, 0xf, mk_get_bits (5u))
|
43 |
|
|
#define mvreg(prefix, shift) \
|
44 |
|
|
reg_p ("mv" prefix, shift, mk_get_bits (4u))
|
45 |
|
|
#define acreg(shift) \
|
46 |
|
|
reg_p ("mvax", shift, mk_get_bits (2u))
|
47 |
|
|
#define dspsc \
|
48 |
|
|
literal ("dspsc"), tick_random
|
49 |
|
|
|
50 |
|
|
/* This outputs the condition flag that may follow each ARM insn.
|
51 |
|
|
Since the condition 15 is invalid, we use it to check that the
|
52 |
|
|
assembler recognizes the absence of a condition as `al'. However,
|
53 |
|
|
the disassembler won't ever output `al', so, if we emit it in the
|
54 |
|
|
assembler, expect the condition to be omitted in the disassembler
|
55 |
|
|
output. */
|
56 |
|
|
|
57 |
|
|
int
|
58 |
|
|
arm_cond (func_arg * arg, insn_data * data)
|
59 |
|
|
#define arm_cond { arm_cond }
|
60 |
|
|
{
|
61 |
|
|
static const char conds[16][3] =
|
62 |
|
|
{
|
63 |
|
|
"eq", "ne", "cs", "cc",
|
64 |
|
|
"mi", "pl", "vs", "vc",
|
65 |
|
|
"hi", "ls", "ge", "lt",
|
66 |
|
|
"gt", "le", "al", ""
|
67 |
|
|
};
|
68 |
|
|
unsigned val = get_bits (4u);
|
69 |
|
|
|
70 |
|
|
data->as_in = data->dis_out = strdup (conds[val]);
|
71 |
|
|
if (val == 14)
|
72 |
|
|
data->dis_out = strdup ("");
|
73 |
|
|
data->bits = (val == 15 ? 14 : val) << 28;
|
74 |
|
|
return 0;
|
75 |
|
|
}
|
76 |
|
|
|
77 |
|
|
/* The sign of an offset is actually used to determined whether the
|
78 |
|
|
absolute value of the offset should be added or subtracted, so we
|
79 |
|
|
must adjust negative values so that they do not overflow: -1024 is
|
80 |
|
|
not valid, but -0 is distinct from +0. */
|
81 |
|
|
int
|
82 |
|
|
off8s (func_arg * arg, insn_data * data)
|
83 |
|
|
#define off8s { off8s }
|
84 |
|
|
{
|
85 |
|
|
int val;
|
86 |
|
|
char value[9];
|
87 |
|
|
|
88 |
|
|
/* Zero values are problematical.
|
89 |
|
|
The assembler performs translations on the addressing modes
|
90 |
|
|
for these values, meaning that we cannot just recreate the
|
91 |
|
|
disassembler string in the LDST macro without knowing what
|
92 |
|
|
value had been generated in off8s. */
|
93 |
|
|
do
|
94 |
|
|
{
|
95 |
|
|
val = get_bits (9s);
|
96 |
|
|
}
|
97 |
|
|
while (val == -1 || val == 0);
|
98 |
|
|
|
99 |
|
|
val <<= 2;
|
100 |
|
|
if (val < 0)
|
101 |
|
|
{
|
102 |
|
|
val = -4 - val;
|
103 |
|
|
sprintf (value, ", #-%i", val);
|
104 |
|
|
data->dis_out = strdup (value);
|
105 |
|
|
sprintf (value, ", #-%i", val);
|
106 |
|
|
data->as_in = strdup (value);
|
107 |
|
|
data->bits = val >> 2;
|
108 |
|
|
}
|
109 |
|
|
else
|
110 |
|
|
{
|
111 |
|
|
sprintf (value, ", #%i", val);
|
112 |
|
|
data->as_in = data->dis_out = strdup (value);
|
113 |
|
|
data->bits = (val >> 2) | (1 << 23);
|
114 |
|
|
}
|
115 |
|
|
|
116 |
|
|
return 0;
|
117 |
|
|
}
|
118 |
|
|
|
119 |
|
|
/* This function generates a 7-bit signed constant, emitted as
|
120 |
|
|
follows: the 4 least-significant bits are stored in the 4
|
121 |
|
|
least-significant bits of the word; the 3 most-significant bits are
|
122 |
|
|
stored in bits 7:5, i.e., bit 4 is skipped. */
|
123 |
|
|
int
|
124 |
|
|
imm7 (func_arg *arg, insn_data *data)
|
125 |
|
|
#define imm7 { imm7 }
|
126 |
|
|
{
|
127 |
|
|
int val = get_bits (7s);
|
128 |
|
|
char value[6];
|
129 |
|
|
|
130 |
|
|
data->bits = (val & 0x0f) | (2 * (val & 0x70));
|
131 |
|
|
sprintf (value, "#%i", val);
|
132 |
|
|
data->as_in = data->dis_out = strdup (value);
|
133 |
|
|
return 0;
|
134 |
|
|
}
|
135 |
|
|
|
136 |
|
|
/* Convenience wrapper to define_insn, that prefixes every insn with
|
137 |
|
|
`cf' (so, if you specify command-line arguments, remember that `cf'
|
138 |
|
|
must *not* be part of the string), and post-fixes a condition code.
|
139 |
|
|
insname and insnvar specify the main insn name and a variant;
|
140 |
|
|
they're just concatenated, and insnvar is often empty. word is the
|
141 |
|
|
bit pattern that defines the insn, properly shifted, and funcs is a
|
142 |
|
|
sequence of funcs that define the operands and the syntax of the
|
143 |
|
|
insn. */
|
144 |
|
|
#define mv_insn(insname, insnvar, word, funcs...) \
|
145 |
|
|
define_insn (insname ## insnvar, \
|
146 |
|
|
literal ("cf"), \
|
147 |
|
|
insn_bits (insname, word), \
|
148 |
|
|
arm_cond, \
|
149 |
|
|
tab, \
|
150 |
|
|
## funcs)
|
151 |
|
|
|
152 |
|
|
/* Define a single LDC/STC variant. op is the main insn opcode; ld
|
153 |
|
|
stands for load (it should be 0 on stores), dword selects 64-bit
|
154 |
|
|
operations, pre should be enabled for pre-increment, and wb, for
|
155 |
|
|
write-back. sep1, sep2 and sep3 are syntactical elements ([]!)
|
156 |
|
|
that the assembler will use to enable pre and wb. It would
|
157 |
|
|
probably have been cleaner to couple the syntactical elements with
|
158 |
|
|
the pre/wb bits directly, but it would have required the definition
|
159 |
|
|
of more functions. */
|
160 |
|
|
#define LDST(insname, insnvar, op, ld, dword, regname, pre, wb, sep1, sep2, sep3) \
|
161 |
|
|
mv_insn (insname, insnvar, \
|
162 |
|
|
(12 << 24) | (op << 8) | (ld << 20) | (pre << 24) | (dword << 22) | (wb << 21), \
|
163 |
|
|
mvreg (regname, 12), comma, \
|
164 |
|
|
lsqbkt, armreg (16), sep1, off8s, sep2, sep3, \
|
165 |
|
|
tick_random)
|
166 |
|
|
|
167 |
|
|
/* Define all variants of an LDR or STR instruction, namely,
|
168 |
|
|
pre-indexed without write-back, pre-indexed with write-back and
|
169 |
|
|
post-indexed. */
|
170 |
|
|
#define LDSTall(insname, op, ld, dword, regname) \
|
171 |
|
|
LDST (insname, _p, op, ld, dword, regname, 1, 0, nothing, rsqbkt, nothing); \
|
172 |
|
|
LDST (insname, _pw, op, ld, dword, regname, 1, 1, nothing, rsqbkt, literal ("!")); \
|
173 |
|
|
LDST (insname, ,op, ld, dword, regname, 0, 1, rsqbkt, nothing, nothing)
|
174 |
|
|
|
175 |
|
|
/* Produce the insn identifiers of all LDST variants of a given insn.
|
176 |
|
|
To be used in the initialization of an insn group array. */
|
177 |
|
|
#define insns_LDSTall(insname) \
|
178 |
|
|
insn (insname ## _p), insn (insname ## _pw), insn (insname)
|
179 |
|
|
|
180 |
|
|
/* Define a CDP variant that uses two registers, at offsets 12 and 16.
|
181 |
|
|
The two opcodes and the co-processor number identify the CDP
|
182 |
|
|
insn. */
|
183 |
|
|
#define CDP2(insname, var, cpnum, opcode1, opcode2, reg1name, reg2name) \
|
184 |
|
|
mv_insn (insname##var, , \
|
185 |
|
|
(14 << 24) | ((opcode1) << 20) | ((cpnum) << 8) | ((opcode2) << 5), \
|
186 |
|
|
mvreg (reg1name, 12), comma, mvreg (reg2name, 16))
|
187 |
|
|
|
188 |
|
|
/* Define a 32-bit integer CDP instruction with two operands. */
|
189 |
|
|
#define CDP2fx(insname, opcode1, opcode2) \
|
190 |
|
|
CDP2 (insname, 32, 5, opcode1, opcode2, "fx", "fx")
|
191 |
|
|
|
192 |
|
|
/* Define a 64-bit integer CDP instruction with two operands. */
|
193 |
|
|
#define CDP2dx(insname, opcode1, opcode2) \
|
194 |
|
|
CDP2 (insname, 64, 5, opcode1, opcode2, "dx", "dx")
|
195 |
|
|
|
196 |
|
|
/* Define a float CDP instruction with two operands. */
|
197 |
|
|
#define CDP2f(insname, opcode1, opcode2) \
|
198 |
|
|
CDP2 (insname, s, 4, opcode1, opcode2, "f", "f")
|
199 |
|
|
|
200 |
|
|
/* Define a double CDP instruction with two operands. */
|
201 |
|
|
#define CDP2d(insname, opcode1, opcode2) \
|
202 |
|
|
CDP2 (insname, d, 4, opcode1, opcode2, "d", "d")
|
203 |
|
|
|
204 |
|
|
/* Define a CDP instruction with two register operands and one 7-bit
|
205 |
|
|
signed immediate generated with imm7. */
|
206 |
|
|
#define CDP2_imm7(insname, cpnum, opcode1, reg1name, reg2name) \
|
207 |
|
|
mv_insn (insname, , (14 << 24) | ((opcode1) << 20) | ((cpnum) << 8), \
|
208 |
|
|
mvreg (reg1name, 12), comma, mvreg (reg2name, 16), comma, imm7, \
|
209 |
|
|
tick_random)
|
210 |
|
|
|
211 |
|
|
/* Produce the insn identifiers of CDP floating-point or integer insn
|
212 |
|
|
pairs (i.e., it appends the suffixes for 32-bit and 64-bit
|
213 |
|
|
insns. */
|
214 |
|
|
#define CDPfp_insns(insname) \
|
215 |
|
|
insn (insname ## s), insn (insname ## d)
|
216 |
|
|
#define CDPx_insns(insname) \
|
217 |
|
|
insn (insname ## 32), insn (insname ## 64)
|
218 |
|
|
|
219 |
|
|
/* Define a CDP instruction with 3 operands, at offsets 12, 16, 0. */
|
220 |
|
|
#define CDP3(insname, var, cpnum, opcode1, opcode2, reg1name, reg2name, reg3name) \
|
221 |
|
|
mv_insn (insname##var, , \
|
222 |
|
|
(14 << 24) | ((opcode1) << 20) | ((cpnum) << 8) | ((opcode2) << 5), \
|
223 |
|
|
mvreg (reg1name, 12), comma, mvreg (reg2name, 16), comma, \
|
224 |
|
|
mvreg (reg3name, 0), tick_random)
|
225 |
|
|
|
226 |
|
|
/* Define a 32-bit integer CDP instruction with three operands. */
|
227 |
|
|
#define CDP3fx(insname, opcode1, opcode2) \
|
228 |
|
|
CDP3 (insname, 32, 5, opcode1, opcode2, "fx", "fx", "fx")
|
229 |
|
|
|
230 |
|
|
/* Define a 64-bit integer CDP instruction with three operands. */
|
231 |
|
|
#define CDP3dx(insname, opcode1, opcode2) \
|
232 |
|
|
CDP3 (insname, 64, 5, opcode1, opcode2, "dx", "dx", "dx")
|
233 |
|
|
|
234 |
|
|
/* Define a float CDP instruction with three operands. */
|
235 |
|
|
#define CDP3f(insname, opcode1, opcode2) \
|
236 |
|
|
CDP3 (insname, s, 4, opcode1, opcode2, "f", "f", "f")
|
237 |
|
|
|
238 |
|
|
/* Define a double CDP instruction with three operands. */
|
239 |
|
|
#define CDP3d(insname, opcode1, opcode2) \
|
240 |
|
|
CDP3 (insname, d, 4, opcode1, opcode2, "d", "d", "d")
|
241 |
|
|
|
242 |
|
|
/* Define a CDP instruction with four operands, at offsets 5, 12, 16
|
243 |
|
|
* and 0. Used only for ACC instructions. */
|
244 |
|
|
#define CDP4(insname, opcode1, reg2spec, reg3name, reg4name) \
|
245 |
|
|
mv_insn (insname, , (14 << 24) | ((opcode1) << 20) | (6 << 8), \
|
246 |
|
|
acreg (5), comma, reg2spec, comma, \
|
247 |
|
|
mvreg (reg3name, 16), comma, mvreg (reg4name, 0))
|
248 |
|
|
|
249 |
|
|
/* Define a CDP4 instruction with one accumulator operands. */
|
250 |
|
|
#define CDP41A(insname, opcode1) \
|
251 |
|
|
CDP4 (insname, opcode1, mvreg ("fx", 12), "fx", "fx")
|
252 |
|
|
|
253 |
|
|
/* Define a CDP4 instruction with two accumulator operands. */
|
254 |
|
|
#define CDP42A(insname, opcode1) \
|
255 |
|
|
CDP4 (insname, opcode1, acreg (12), "fx", "fx")
|
256 |
|
|
|
257 |
|
|
/* Define a MCR or MRC instruction with two register operands. */
|
258 |
|
|
#define MCRC2(insname, cpnum, opcode1, dir, opcode2, reg1spec, reg2spec) \
|
259 |
|
|
mv_insn (insname, , \
|
260 |
|
|
((14 << 24) | ((opcode1) << 21) | ((dir) << 20)| \
|
261 |
|
|
((cpnum) << 8) | ((opcode2) << 5) | (1 << 4)), \
|
262 |
|
|
reg1spec, comma, reg2spec)
|
263 |
|
|
|
264 |
|
|
/* Define a move from a DSP register to an ARM register. */
|
265 |
|
|
#define MVDSPARM(insname, cpnum, opcode2, regDSPname) \
|
266 |
|
|
MCRC2 (mv ## insname, cpnum, 0, 0, opcode2, \
|
267 |
|
|
mvreg (regDSPname, 16), armreg (12))
|
268 |
|
|
|
269 |
|
|
/* Define a move from an ARM register to a DSP register. */
|
270 |
|
|
#define MVARMDSP(insname, cpnum, opcode2, regDSPname) \
|
271 |
|
|
MCRC2 (mv ## insname, cpnum, 0, 1, opcode2, \
|
272 |
|
|
armreg (12), mvreg (regDSPname, 16))
|
273 |
|
|
|
274 |
|
|
/* Move between coprocessor registers. A two operand CDP insn. */
|
275 |
|
|
#define MCC2(insname, opcode1, opcode2, reg1spec, reg2spec) \
|
276 |
|
|
mv_insn (insname, , \
|
277 |
|
|
((14 << 24) | ((opcode1) << 20) | \
|
278 |
|
|
(4 << 8) | ((opcode2) << 5)), \
|
279 |
|
|
reg1spec, comma, reg2spec)
|
280 |
|
|
|
281 |
|
|
/* Define a move from a DSP register to a DSP accumulator. */
|
282 |
|
|
#define MVDSPACC(insname, opcode2, regDSPname) \
|
283 |
|
|
MCC2 (mv ## insname, 2, opcode2, acreg (12), mvreg (regDSPname, 16))
|
284 |
|
|
|
285 |
|
|
/* Define a move from a DSP accumulator to a DSP register. */
|
286 |
|
|
#define MVACCDSP(insname, opcode2, regDSPname) \
|
287 |
|
|
MCC2 (mv ## insname, 1, opcode2, mvreg (regDSPname, 12), acreg (16))
|
288 |
|
|
|
289 |
|
|
/* Define move insns between a float DSP register and an ARM
|
290 |
|
|
register. */
|
291 |
|
|
#define MVf(nameAD, nameDA, opcode2) \
|
292 |
|
|
MVDSPARM (nameAD, 4, opcode2, "f"); \
|
293 |
|
|
MVARMDSP (nameDA, 4, opcode2, "f")
|
294 |
|
|
|
295 |
|
|
/* Define move insns between a double DSP register and an ARM
|
296 |
|
|
register. */
|
297 |
|
|
#define MVd(nameAD, nameDA, opcode2) \
|
298 |
|
|
MVDSPARM (nameAD, 4, opcode2, "d"); \
|
299 |
|
|
MVARMDSP (nameDA, 4, opcode2, "d")
|
300 |
|
|
|
301 |
|
|
/* Define move insns between a 32-bit integer DSP register and an ARM
|
302 |
|
|
register. */
|
303 |
|
|
#define MVfx(nameAD, nameDA, opcode2) \
|
304 |
|
|
MVDSPARM (nameAD, 5, opcode2, "fx"); \
|
305 |
|
|
MVARMDSP (nameDA, 5, opcode2, "fx")
|
306 |
|
|
|
307 |
|
|
/* Define move insns between a 64-bit integer DSP register and an ARM
|
308 |
|
|
register. */
|
309 |
|
|
#define MVdx(nameAD, nameDA, opcode2) \
|
310 |
|
|
MVDSPARM (nameAD, 5, opcode2, "dx"); \
|
311 |
|
|
MVARMDSP (nameDA, 5, opcode2, "dx")
|
312 |
|
|
|
313 |
|
|
/* Define move insns between a 32-bit DSP register and a DSP
|
314 |
|
|
accumulator. */
|
315 |
|
|
#define MVfxa(nameFA, nameAF, opcode2) \
|
316 |
|
|
MVDSPACC (nameFA, opcode2, "fx"); \
|
317 |
|
|
MVACCDSP (nameAF, opcode2, "fx")
|
318 |
|
|
|
319 |
|
|
/* Define move insns between a 64-bit DSP register and a DSP
|
320 |
|
|
accumulator. */
|
321 |
|
|
#define MVdxa(nameDA, nameAD, opcode2) \
|
322 |
|
|
MVDSPACC (nameDA, opcode2, "dx"); \
|
323 |
|
|
MVACCDSP (nameAD, opcode2, "dx")
|
324 |
|
|
|
325 |
|
|
/* Produce the insn identifiers for a pair of mv insns. */
|
326 |
|
|
#define insns_MV(name1, name2) \
|
327 |
|
|
insn (mv ## name1), insn (mv ## name2)
|
328 |
|
|
|
329 |
|
|
/* Define a MCR or MRC instruction with three register operands. */
|
330 |
|
|
#define MCRC3(insname, cpnum, opcode1, dir, opcode2, reg1spec, reg2spec, reg3spec) \
|
331 |
|
|
mv_insn (insname, , \
|
332 |
|
|
((14 << 24) | ((opcode1) << 21) | ((dir) << 20)| \
|
333 |
|
|
((cpnum) << 8) | ((opcode2) << 5) | (1 << 4)), \
|
334 |
|
|
reg1spec, comma, reg2spec, comma, reg3spec, \
|
335 |
|
|
tick_random)
|
336 |
|
|
|
337 |
|
|
/* Define all load_store insns. */
|
338 |
|
|
LDSTall (ldrs, 4, 1, 0, "f");
|
339 |
|
|
LDSTall (ldrd, 4, 1, 1, "d");
|
340 |
|
|
LDSTall (ldr32, 5, 1, 0, "fx");
|
341 |
|
|
LDSTall (ldr64, 5, 1, 1, "dx");
|
342 |
|
|
LDSTall (strs, 4, 0, 0, "f");
|
343 |
|
|
LDSTall (strd, 4, 0, 1, "d");
|
344 |
|
|
LDSTall (str32, 5, 0, 0, "fx");
|
345 |
|
|
LDSTall (str64, 5, 0, 1, "dx");
|
346 |
|
|
|
347 |
|
|
/* Create the load_store insn group. */
|
348 |
|
|
func *load_store_insns[] =
|
349 |
|
|
{
|
350 |
|
|
insns_LDSTall (ldrs), insns_LDSTall (ldrd),
|
351 |
|
|
insns_LDSTall (ldr32), insns_LDSTall (ldr64),
|
352 |
|
|
insns_LDSTall (strs), insns_LDSTall (strd),
|
353 |
|
|
insns_LDSTall (str32), insns_LDSTall (str64),
|
354 |
|
|
|
355 |
|
|
};
|
356 |
|
|
|
357 |
|
|
/* Define all move insns. */
|
358 |
|
|
MVf (sr, rs, 2);
|
359 |
|
|
MVd (dlr, rdl, 0);
|
360 |
|
|
MVd (dhr, rdh, 1);
|
361 |
|
|
MVdx (64lr, r64l, 0);
|
362 |
|
|
MVdx (64hr, r64h, 1);
|
363 |
|
|
MVfxa (al32, 32al, 2);
|
364 |
|
|
MVfxa (am32, 32am, 3);
|
365 |
|
|
MVfxa (ah32, 32ah, 4);
|
366 |
|
|
MVfxa (a32, 32a, 5);
|
367 |
|
|
MVdxa (a64, 64a, 6);
|
368 |
|
|
MCC2 (mvsc32, 2, 7, dspsc, mvreg ("dx", 12));
|
369 |
|
|
MCC2 (mv32sc, 1, 7, mvreg ("dx", 12), dspsc);
|
370 |
|
|
CDP2 (cpys, , 4, 0, 0, "f", "f");
|
371 |
|
|
CDP2 (cpyd, , 4, 0, 1, "d", "d");
|
372 |
|
|
|
373 |
|
|
/* Create the move insns group. */
|
374 |
|
|
func * move_insns[] =
|
375 |
|
|
{
|
376 |
|
|
insns_MV (sr, rs), insns_MV (dlr, rdl), insns_MV (dhr, rdh),
|
377 |
|
|
insns_MV (64lr, r64l), insns_MV (64hr, r64h),
|
378 |
|
|
insns_MV (al32, 32al), insns_MV (am32, 32am), insns_MV (ah32, 32ah),
|
379 |
|
|
insns_MV (a32, 32a), insns_MV (a64, 64a),
|
380 |
|
|
insn (mvsc32), insn (mv32sc), insn (cpys), insn (cpyd),
|
381 |
|
|
|
382 |
|
|
};
|
383 |
|
|
|
384 |
|
|
/* Define all conversion insns. */
|
385 |
|
|
CDP2 (cvtsd, , 4, 0, 3, "d", "f");
|
386 |
|
|
CDP2 (cvtds, , 4, 0, 2, "f", "d");
|
387 |
|
|
CDP2 (cvt32s, , 4, 0, 4, "f", "fx");
|
388 |
|
|
CDP2 (cvt32d, , 4, 0, 5, "d", "fx");
|
389 |
|
|
CDP2 (cvt64s, , 4, 0, 6, "f", "dx");
|
390 |
|
|
CDP2 (cvt64d, , 4, 0, 7, "d", "dx");
|
391 |
|
|
CDP2 (cvts32, , 5, 1, 4, "fx", "f");
|
392 |
|
|
CDP2 (cvtd32, , 5, 1, 5, "fx", "d");
|
393 |
|
|
CDP2 (truncs32, , 5, 1, 6, "fx", "f");
|
394 |
|
|
CDP2 (truncd32, , 5, 1, 7, "fx", "d");
|
395 |
|
|
|
396 |
|
|
/* Create the conv insns group. */
|
397 |
|
|
func * conv_insns[] =
|
398 |
|
|
{
|
399 |
|
|
insn (cvtsd), insn (cvtds), insn (cvt32s), insn (cvt32d),
|
400 |
|
|
insn (cvt64s), insn (cvt64d), insn (cvts32), insn (cvtd32),
|
401 |
|
|
insn (truncs32), insn (truncd32),
|
402 |
|
|
|
403 |
|
|
};
|
404 |
|
|
|
405 |
|
|
/* Define all shift insns. */
|
406 |
|
|
MCRC3 (rshl32, 5, 0, 0, 2, mvreg ("fx", 16), mvreg ("fx", 0), armreg (12));
|
407 |
|
|
MCRC3 (rshl64, 5, 0, 0, 3, mvreg ("dx", 16), mvreg ("dx", 0), armreg (12));
|
408 |
|
|
CDP2_imm7 (sh32, 5, 0, "fx", "fx");
|
409 |
|
|
CDP2_imm7 (sh64, 5, 2, "dx", "dx");
|
410 |
|
|
|
411 |
|
|
/* Create the shift insns group. */
|
412 |
|
|
func *shift_insns[] =
|
413 |
|
|
{
|
414 |
|
|
insn (rshl32), insn (rshl64),
|
415 |
|
|
insn (sh32), insn (sh64),
|
416 |
|
|
|
417 |
|
|
};
|
418 |
|
|
|
419 |
|
|
/* Define all comparison insns. */
|
420 |
|
|
MCRC3 (cmps, 4, 0, 1, 4, armreg (12), mvreg ("f", 16), mvreg ("f", 0));
|
421 |
|
|
MCRC3 (cmpd, 4, 0, 1, 5, armreg (12), mvreg ("d", 16), mvreg ("d", 0));
|
422 |
|
|
MCRC3 (cmp32, 5, 0, 1, 4, armreg (12), mvreg ("fx", 16), mvreg ("fx", 0));
|
423 |
|
|
MCRC3 (cmp64, 5, 0, 1, 5, armreg (12), mvreg ("dx", 16), mvreg ("dx", 0));
|
424 |
|
|
|
425 |
|
|
/* Create the comp insns group. */
|
426 |
|
|
func *comp_insns[] =
|
427 |
|
|
{
|
428 |
|
|
insn (cmps), insn (cmpd),
|
429 |
|
|
insn (cmp32), insn (cmp64),
|
430 |
|
|
|
431 |
|
|
};
|
432 |
|
|
|
433 |
|
|
/* Define all floating-point arithmetic insns. */
|
434 |
|
|
CDP2f (abs, 3, 0);
|
435 |
|
|
CDP2d (abs, 3, 1);
|
436 |
|
|
CDP2f (neg, 3, 2);
|
437 |
|
|
CDP2d (neg, 3, 3);
|
438 |
|
|
CDP3f (add, 3, 4);
|
439 |
|
|
CDP3d (add, 3, 5);
|
440 |
|
|
CDP3f (sub, 3, 6);
|
441 |
|
|
CDP3d (sub, 3, 7);
|
442 |
|
|
CDP3f (mul, 1, 0);
|
443 |
|
|
CDP3d (mul, 1, 1);
|
444 |
|
|
|
445 |
|
|
/* Create the fp-arith insns group. */
|
446 |
|
|
func *fp_arith_insns[] =
|
447 |
|
|
{
|
448 |
|
|
CDPfp_insns (abs), CDPfp_insns (neg),
|
449 |
|
|
CDPfp_insns (add), CDPfp_insns (sub), CDPfp_insns (mul),
|
450 |
|
|
|
451 |
|
|
};
|
452 |
|
|
|
453 |
|
|
/* Define all integer arithmetic insns. */
|
454 |
|
|
CDP2fx (abs, 3, 0);
|
455 |
|
|
CDP2dx (abs, 3, 1);
|
456 |
|
|
CDP2fx (neg, 3, 2);
|
457 |
|
|
CDP2dx (neg, 3, 3);
|
458 |
|
|
CDP3fx (add, 3, 4);
|
459 |
|
|
CDP3dx (add, 3, 5);
|
460 |
|
|
CDP3fx (sub, 3, 6);
|
461 |
|
|
CDP3dx (sub, 3, 7);
|
462 |
|
|
CDP3fx (mul, 1, 0);
|
463 |
|
|
CDP3dx (mul, 1, 1);
|
464 |
|
|
CDP3fx (mac, 1, 2);
|
465 |
|
|
CDP3fx (msc, 1, 3);
|
466 |
|
|
|
467 |
|
|
/* Create the int-arith insns group. */
|
468 |
|
|
func * int_arith_insns[] =
|
469 |
|
|
{
|
470 |
|
|
CDPx_insns (abs), CDPx_insns (neg),
|
471 |
|
|
CDPx_insns (add), CDPx_insns (sub), CDPx_insns (mul),
|
472 |
|
|
insn (mac32), insn (msc32),
|
473 |
|
|
|
474 |
|
|
};
|
475 |
|
|
|
476 |
|
|
/* Define all accumulator arithmetic insns. */
|
477 |
|
|
CDP41A (madd32, 0);
|
478 |
|
|
CDP41A (msub32, 1);
|
479 |
|
|
CDP42A (madda32, 2);
|
480 |
|
|
CDP42A (msuba32, 3);
|
481 |
|
|
|
482 |
|
|
/* Create the acc-arith insns group. */
|
483 |
|
|
func * acc_arith_insns[] =
|
484 |
|
|
{
|
485 |
|
|
insn (madd32), insn (msub32),
|
486 |
|
|
insn (madda32), insn (msuba32),
|
487 |
|
|
|
488 |
|
|
};
|
489 |
|
|
|
490 |
|
|
/* Create the set of all groups. */
|
491 |
|
|
group_t groups[] =
|
492 |
|
|
{
|
493 |
|
|
{ "load_store", load_store_insns },
|
494 |
|
|
{ "move", move_insns },
|
495 |
|
|
{ "conv", conv_insns },
|
496 |
|
|
{ "shift", shift_insns },
|
497 |
|
|
{ "comp", comp_insns },
|
498 |
|
|
{ "fp_arith", fp_arith_insns },
|
499 |
|
|
{ "int_arith", int_arith_insns },
|
500 |
|
|
{ "acc_arith", acc_arith_insns },
|
501 |
|
|
{ 0 }
|
502 |
|
|
};
|
503 |
|
|
|
504 |
|
|
int
|
505 |
|
|
main (int argc, char *argv[])
|
506 |
|
|
{
|
507 |
|
|
FILE *as_in = stdout, *dis_out = stderr;
|
508 |
|
|
|
509 |
|
|
/* Check whether we're filtering insns. */
|
510 |
|
|
if (argc > 1)
|
511 |
|
|
skip_list = argv + 1;
|
512 |
|
|
|
513 |
|
|
/* Output assembler header. */
|
514 |
|
|
fputs ("\t.text\n"
|
515 |
|
|
"\t.align\n",
|
516 |
|
|
as_in);
|
517 |
|
|
/* Output comments for the testsuite-driver and the initial
|
518 |
|
|
disassembler output. */
|
519 |
|
|
fputs ("#objdump: -dr --prefix-address --show-raw-insn\n"
|
520 |
|
|
"#name: Maverick\n"
|
521 |
|
|
"#as: -mcpu=ep9312\n"
|
522 |
|
|
"\n"
|
523 |
|
|
"# Test the instructions of the Cirrus Maverick floating point co-processor\n"
|
524 |
|
|
"\n"
|
525 |
|
|
".*: +file format.*arm.*\n"
|
526 |
|
|
"\n"
|
527 |
|
|
"Disassembly of section .text:\n",
|
528 |
|
|
dis_out);
|
529 |
|
|
|
530 |
|
|
/* Now emit all (selected) insns. */
|
531 |
|
|
output_groups (groups, as_in, dis_out);
|
532 |
|
|
|
533 |
|
|
exit (0);
|
534 |
|
|
}
|