1 /* Copyright (C) 2000, 2003 Free Software Foundation
2 Contributed by Alexandre Oliva <aoliva@cygnus.com>
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 2 of the License, or
7 (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Generator of tests for Maverick.
20 See the following file for usage and documentation. */
21 #include "../all/test-gen.c"
23 /* These are the ARM registers. Some of them have canonical names
24 other than r##, so we'll use both in the asm input, but only the
25 canonical names in the expected disassembler output. */
28 /* Canonical names. */
29 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
30 "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
31 /* Alternate names, i.e., those that can be used in the assembler,
32 * but that will never be emitted by the disassembler. */
33 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
34 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
37 /* The various types of registers: ARM's registers, Maverick's
38 f/d/fx/dx registers, Maverick's accumulators and Maverick's
40 #define armreg(shift) \
41 reg_r (arm_regs, shift, 0xf, mk_get_bits (5u))
42 #define mvreg(prefix, shift) \
43 reg_p ("mv" prefix, shift, mk_get_bits (4u))
44 #define acreg(shift) \
45 reg_p ("mvax", shift, mk_get_bits (2u))
47 literal ("dspsc"), tick_random
49 /* This outputs the condition flag that may follow each ARM insn.
50 Since the condition 15 is invalid, we use it to check that the
51 assembler recognizes the absence of a condition as `al'. However,
52 the disassembler won't ever output `al', so, if we emit it in the
53 assembler, expect the condition to be omitted in the disassembler
57 arm_cond (func_arg
* arg
, insn_data
* data
)
58 #define arm_cond { arm_cond }
60 static const char conds
[16][3] =
62 "eq", "ne", "cs", "cc",
63 "mi", "pl", "vs", "vc",
64 "hi", "ls", "ge", "lt",
67 unsigned val
= get_bits (4u);
69 data
->as_in
= data
->dis_out
= strdup (conds
[val
]);
71 data
->dis_out
= strdup ("");
72 data
->bits
= (val
== 15 ? 14 : val
) << 28;
76 /* The sign of an offset is actually used to determined whether the
77 absolute value of the offset should be added or subtracted, so we
78 must adjust negative values so that they do not overflow: -256 is
79 not valid, but -0 is distinct from +0. */
81 off8s (func_arg
* arg
, insn_data
* data
)
82 #define off8s { off8s }
87 /* Values less that -255 or between -3 and 0 are problematical.
88 The assembler performs translations on the addressing modes
89 for these values, meaning that we cannot just recreate the
90 disassembler string in the LDST macro without knowing what
91 value had been generated in off8s. */
96 while (val
< -255 || (val
> -4 && val
< 1));
102 sprintf (value
, ", #-%i", val
);
103 data
->dis_out
= strdup (value
);
104 sprintf (value
, ", #-%i", val
);
105 data
->as_in
= strdup (value
);
112 sprintf (value
, ", #%i", val
);
113 data
->as_in
= data
->dis_out
= strdup (value
);
115 data
->bits
= val
| (1 << 23);
121 /* This function generates a 7-bit signed constant, emitted as
122 follows: the 4 least-significant bits are stored in the 4
123 least-significant bits of the word; the 3 most-significant bits are
124 stored in bits 7:5, i.e., bit 4 is skipped. */
126 imm7 (func_arg
*arg
, insn_data
*data
)
127 #define imm7 { imm7 }
129 int val
= get_bits (7s
);
132 data
->bits
= (val
& 0x0f) | (2 * (val
& 0x70));
133 sprintf (value
, "#%i", val
);
134 data
->as_in
= data
->dis_out
= strdup (value
);
138 /* Convenience wrapper to define_insn, that prefixes every insn with
139 `cf' (so, if you specify command-line arguments, remember that `cf'
140 must *not* be part of the string), and post-fixes a condition code.
141 insname and insnvar specify the main insn name and a variant;
142 they're just concatenated, and insnvar is often empty. word is the
143 bit pattern that defines the insn, properly shifted, and funcs is a
144 sequence of funcs that define the operands and the syntax of the
146 #define mv_insn(insname, insnvar, word, funcs...) \
147 define_insn (insname ## insnvar, \
149 insn_bits (insname, word), \
154 /* Define a single LDC/STC variant. op is the main insn opcode; ld
155 stands for load (it should be 0 on stores), dword selects 64-bit
156 operations, pre should be enabled for pre-increment, and wb, for
157 write-back. sep1, sep2 and sep3 are syntactical elements ([]!)
158 that the assembler will use to enable pre and wb. It would
159 probably have been cleaner to couple the syntactical elements with
160 the pre/wb bits directly, but it would have required the definition
161 of more functions. */
162 #define LDST(insname, insnvar, op, ld, dword, regname, pre, wb, sep1, sep2, sep3) \
163 mv_insn (insname, insnvar, \
164 (12 << 24) | (op << 8) | (ld << 20) | (pre << 24) | (dword << 22) | (wb << 21), \
165 mvreg (regname, 12), comma, \
166 lsqbkt, armreg (16), sep1, off8s, sep2, sep3, \
169 /* Define all variants of an LDR or STR instruction, namely,
170 pre-indexed without write-back, pre-indexed with write-back and
172 #define LDSTall(insname, op, ld, dword, regname) \
173 LDST (insname, _p, op, ld, dword, regname, 1, 0, nothing, rsqbkt, nothing); \
174 LDST (insname, _pw, op, ld, dword, regname, 1, 1, nothing, rsqbkt, literal ("!")); \
175 LDST (insname, ,op, ld, dword, regname, 0, 1, rsqbkt, nothing, nothing)
177 /* Produce the insn identifiers of all LDST variants of a given insn.
178 To be used in the initialization of an insn group array. */
179 #define insns_LDSTall(insname) \
180 insn (insname ## _p), insn (insname ## _pw), insn (insname)
182 /* Define a CDP variant that uses two registers, at offsets 12 and 16.
183 The two opcodes and the co-processor number identify the CDP
185 #define CDP2(insname, var, cpnum, opcode1, opcode2, reg1name, reg2name) \
186 mv_insn (insname##var, , \
187 (14 << 24) | ((opcode1) << 20) | ((cpnum) << 8) | ((opcode2) << 5), \
188 mvreg (reg1name, 12), comma, mvreg (reg2name, 16))
190 /* Define a 32-bit integer CDP instruction with two operands. */
191 #define CDP2fx(insname, opcode1, opcode2) \
192 CDP2 (insname, 32, 5, opcode1, opcode2, "fx", "fx")
194 /* Define a 64-bit integer CDP instruction with two operands. */
195 #define CDP2dx(insname, opcode1, opcode2) \
196 CDP2 (insname, 64, 5, opcode1, opcode2, "dx", "dx")
198 /* Define a float CDP instruction with two operands. */
199 #define CDP2f(insname, opcode1, opcode2) \
200 CDP2 (insname, s, 4, opcode1, opcode2, "f", "f")
202 /* Define a double CDP instruction with two operands. */
203 #define CDP2d(insname, opcode1, opcode2) \
204 CDP2 (insname, d, 4, opcode1, opcode2, "d", "d")
206 /* Define a CDP instruction with two register operands and one 7-bit
207 signed immediate generated with imm7. */
208 #define CDP2_imm7(insname, cpnum, opcode1, reg1name, reg2name) \
209 mv_insn (insname, , (14 << 24) | ((opcode1) << 20) | ((cpnum) << 8), \
210 mvreg (reg1name, 12), comma, mvreg (reg2name, 16), comma, imm7, \
213 /* Produce the insn identifiers of CDP floating-point or integer insn
214 pairs (i.e., it appends the suffixes for 32-bit and 64-bit
216 #define CDPfp_insns(insname) \
217 insn (insname ## s), insn (insname ## d)
218 #define CDPx_insns(insname) \
219 insn (insname ## 32), insn (insname ## 64)
221 /* Define a CDP instruction with 3 operands, at offsets 12, 16, 0. */
222 #define CDP3(insname, var, cpnum, opcode1, opcode2, reg1name, reg2name, reg3name) \
223 mv_insn (insname##var, , \
224 (14 << 24) | ((opcode1) << 20) | ((cpnum) << 8) | ((opcode2) << 5), \
225 mvreg (reg1name, 12), comma, mvreg (reg2name, 16), comma, \
226 mvreg (reg3name, 0), tick_random)
228 /* Define a 32-bit integer CDP instruction with three operands. */
229 #define CDP3fx(insname, opcode1, opcode2) \
230 CDP3 (insname, 32, 5, opcode1, opcode2, "fx", "fx", "fx")
232 /* Define a 64-bit integer CDP instruction with three operands. */
233 #define CDP3dx(insname, opcode1, opcode2) \
234 CDP3 (insname, 64, 5, opcode1, opcode2, "dx", "dx", "dx")
236 /* Define a float CDP instruction with three operands. */
237 #define CDP3f(insname, opcode1, opcode2) \
238 CDP3 (insname, s, 4, opcode1, opcode2, "f", "f", "f")
240 /* Define a double CDP instruction with three operands. */
241 #define CDP3d(insname, opcode1, opcode2) \
242 CDP3 (insname, d, 4, opcode1, opcode2, "d", "d", "d")
244 /* Define a CDP instruction with four operands, at offsets 5, 12, 16
245 * and 0. Used only for ACC instructions. */
246 #define CDP4(insname, opcode1, reg2spec, reg3name, reg4name) \
247 mv_insn (insname, , (14 << 24) | ((opcode1) << 20) | (6 << 8), \
248 acreg (5), comma, reg2spec, comma, \
249 mvreg (reg3name, 16), comma, mvreg (reg4name, 0))
251 /* Define a CDP4 instruction with one accumulator operands. */
252 #define CDP41A(insname, opcode1) \
253 CDP4 (insname, opcode1, mvreg ("fx", 12), "fx", "fx")
255 /* Define a CDP4 instruction with two accumulator operands. */
256 #define CDP42A(insname, opcode1) \
257 CDP4 (insname, opcode1, acreg (12), "fx", "fx")
259 /* Define a MCR or MRC instruction with two register operands. */
260 #define MCRC2(insname, cpnum, opcode1, dir, opcode2, reg1spec, reg2spec) \
261 mv_insn (insname, , \
262 ((14 << 24) | ((opcode1) << 21) | ((dir) << 20)| \
263 ((cpnum) << 8) | ((opcode2) << 5) | (1 << 4)), \
264 reg1spec, comma, reg2spec)
266 /* Define a move from a DSP register to an ARM register. */
267 #define MVDSPARM(insname, cpnum, opcode2, regDSPname) \
268 MCRC2 (mv ## insname, cpnum, 0, 0, opcode2, \
269 mvreg (regDSPname, 16), armreg (12))
271 /* Define a move from an ARM register to a DSP register. */
272 #define MVARMDSP(insname, cpnum, opcode2, regDSPname) \
273 MCRC2 (mv ## insname, cpnum, 0, 1, opcode2, \
274 armreg (12), mvreg (regDSPname, 16))
276 /* Define a move from a DSP register to a DSP accumulator. */
277 #define MVDSPACC(insname, opcode2, regDSPname) \
278 MCRC2 (mv ## insname, 6, 0, 1, opcode2, acreg (0), mvreg (regDSPname, 16))
280 /* Define a move from a DSP accumulator to a DSP register. */
281 #define MVACCDSP(insname, opcode2, regDSPname) \
282 MCRC2 (mv ## insname, 6, 0, 0, opcode2, mvreg (regDSPname, 0), acreg (16))
284 /* Define move insns between a float DSP register and an ARM
286 #define MVf(nameAD, nameDA, opcode2) \
287 MVDSPARM (nameAD, 4, opcode2, "f"); \
288 MVARMDSP (nameDA, 4, opcode2, "f")
290 /* Define move insns between a double DSP register and an ARM
292 #define MVd(nameAD, nameDA, opcode2) \
293 MVDSPARM (nameAD, 4, opcode2, "d"); \
294 MVARMDSP (nameDA, 4, opcode2, "d")
296 /* Define move insns between a 32-bit integer DSP register and an ARM
298 #define MVfx(nameAD, nameDA, opcode2) \
299 MVDSPARM (nameAD, 5, opcode2, "fx"); \
300 MVARMDSP (nameDA, 5, opcode2, "fx")
302 /* Define move insns between a 64-bit integer DSP register and an ARM
304 #define MVdx(nameAD, nameDA, opcode2) \
305 MVDSPARM (nameAD, 5, opcode2, "dx"); \
306 MVARMDSP (nameDA, 5, opcode2, "dx")
308 /* Define move insns between a 32-bit DSP register and a DSP
310 #define MVfxa(nameFA, nameAF, opcode2) \
311 MVDSPACC (nameFA, opcode2, "fx"); \
312 MVACCDSP (nameAF, opcode2, "fx")
314 /* Define move insns between a 64-bit DSP register and a DSP
316 #define MVdxa(nameDA, nameAD, opcode2) \
317 MVDSPACC (nameDA, opcode2, "dx"); \
318 MVACCDSP (nameAD, opcode2, "dx")
320 /* Produce the insn identifiers for a pair of mv insns. */
321 #define insns_MV(name1, name2) \
322 insn (mv ## name1), insn (mv ## name2)
324 /* Define a MCR or MRC instruction with three register operands. */
325 #define MCRC3(insname, cpnum, opcode1, dir, opcode2, reg1spec, reg2spec, reg3spec) \
326 mv_insn (insname, , \
327 ((14 << 24) | ((opcode1) << 21) | ((dir) << 20)| \
328 ((cpnum) << 8) | ((opcode2) << 5) | (1 << 4)), \
329 reg1spec, comma, reg2spec, comma, reg3spec, \
332 /* Define all load_store insns. */
333 LDSTall (ldrs
, 4, 1, 0, "f");
334 LDSTall (ldrd
, 4, 1, 1, "d");
335 LDSTall (ldr32
, 5, 1, 0, "fx");
336 LDSTall (ldr64
, 5, 1, 1, "dx");
337 LDSTall (strs
, 4, 0, 0, "f");
338 LDSTall (strd
, 4, 0, 1, "d");
339 LDSTall (str32
, 5, 0, 0, "fx");
340 LDSTall (str64
, 5, 0, 1, "dx");
342 /* Create the load_store insn group. */
343 func
*load_store_insns
[] =
345 insns_LDSTall (ldrs
), insns_LDSTall (ldrd
),
346 insns_LDSTall (ldr32
), insns_LDSTall (ldr64
),
347 insns_LDSTall (strs
), insns_LDSTall (strd
),
348 insns_LDSTall (str32
), insns_LDSTall (str64
),
352 /* Define all move insns. */
356 MVdx (64lr
, r64l
, 0);
357 MVdx (64hr
, r64h
, 1);
358 MVfxa (al32
, 32al
, 0);
359 MVfxa (am32
, 32am
, 1);
360 MVfxa (ah32
, 32ah
, 2);
363 MCRC2 (mvsc32
, 6, 0, 1, 5, dspsc
, mvreg ("fx", 16));
364 MCRC2 (mv32sc
, 6, 0, 0, 5, mvreg ("fx", 0), dspsc
);
365 CDP2 (cpys
, , 4, 0, 0, "f", "f");
366 CDP2 (cpyd
, , 4, 0, 1, "d", "d");
368 /* Create the move insns group. */
369 func
* move_insns
[] =
371 insns_MV (sr
, rs
), insns_MV (dlr
, rdl
), insns_MV (dhr
, rdh
),
372 insns_MV (64lr
, r64l
), insns_MV (64hr
, r64h
),
373 insns_MV (al32
, 32al
), insns_MV (am32
, 32am
), insns_MV (ah32
, 32ah
),
374 insns_MV (a32
, 32a
), insns_MV (a64
, 64a
),
375 insn (mvsc32
), insn (mv32sc
), insn (cpys
), insn (cpyd
),
379 /* Define all conversion insns. */
380 CDP2 (cvtsd
, , 4, 0, 3, "d", "f");
381 CDP2 (cvtds
, , 4, 0, 2, "f", "d");
382 CDP2 (cvt32s
, , 4, 0, 4, "f", "fx");
383 CDP2 (cvt32d
, , 4, 0, 5, "d", "fx");
384 CDP2 (cvt64s
, , 4, 0, 6, "f", "dx");
385 CDP2 (cvt64d
, , 4, 0, 7, "d", "dx");
386 CDP2 (cvts32
, , 5, 1, 4, "fx", "f");
387 CDP2 (cvtd32
, , 5, 1, 5, "fx", "d");
388 CDP2 (truncs32
, , 5, 1, 6, "fx", "f");
389 CDP2 (truncd32
, , 5, 1, 7, "fx", "d");
391 /* Create the conv insns group. */
392 func
* conv_insns
[] =
394 insn (cvtsd
), insn (cvtds
), insn (cvt32s
), insn (cvt32d
),
395 insn (cvt64s
), insn (cvt64d
), insn (cvts32
), insn (cvtd32
),
396 insn (truncs32
), insn (truncd32
),
400 /* Define all shift insns. */
401 MCRC3 (rshl32
, 5, 0, 0, 2, mvreg ("fx", 16), mvreg ("fx", 0), armreg (12));
402 MCRC3 (rshl64
, 5, 0, 0, 3, mvreg ("dx", 16), mvreg ("dx", 0), armreg (12));
403 CDP2_imm7 (sh32
, 5, 0, "fx", "fx");
404 CDP2_imm7 (sh64
, 5, 2, "dx", "dx");
406 /* Create the shift insns group. */
407 func
*shift_insns
[] =
409 insn (rshl32
), insn (rshl64
),
410 insn (sh32
), insn (sh64
),
414 /* Define all comparison insns. */
415 MCRC3 (cmps
, 4, 0, 1, 4, armreg (12), mvreg ("f", 16), mvreg ("f", 0));
416 MCRC3 (cmpd
, 4, 0, 1, 5, armreg (12), mvreg ("d", 16), mvreg ("d", 0));
417 MCRC3 (cmp32
, 5, 0, 1, 4, armreg (12), mvreg ("fx", 16), mvreg ("fx", 0));
418 MCRC3 (cmp64
, 5, 0, 1, 5, armreg (12), mvreg ("dx", 16), mvreg ("dx", 0));
420 /* Create the comp insns group. */
423 insn (cmps
), insn (cmpd
),
424 insn (cmp32
), insn (cmp64
),
428 /* Define all floating-point arithmetic insns. */
440 /* Create the fp-arith insns group. */
441 func
*fp_arith_insns
[] =
443 CDPfp_insns (abs
), CDPfp_insns (neg
),
444 CDPfp_insns (add
), CDPfp_insns (sub
), CDPfp_insns (mul
),
448 /* Define all integer arithmetic insns. */
462 /* Create the int-arith insns group. */
463 func
* int_arith_insns
[] =
465 CDPx_insns (abs
), CDPx_insns (neg
),
466 CDPx_insns (add
), CDPx_insns (sub
), CDPx_insns (mul
),
467 insn (mac32
), insn (msc32
),
471 /* Define all accumulator arithmetic insns. */
477 /* Create the acc-arith insns group. */
478 func
* acc_arith_insns
[] =
480 insn (madd32
), insn (msub32
),
481 insn (madda32
), insn (msuba32
),
485 /* Create the set of all groups. */
488 { "load_store", load_store_insns
},
489 { "move", move_insns
},
490 { "conv", conv_insns
},
491 { "shift", shift_insns
},
492 { "comp", comp_insns
},
493 { "fp_arith", fp_arith_insns
},
494 { "int_arith", int_arith_insns
},
495 { "acc_arith", acc_arith_insns
},
500 main (int argc
, char *argv
[])
502 FILE *as_in
= stdout
, *dis_out
= stderr
;
504 /* Check whether we're filtering insns. */
506 skip_list
= argv
+ 1;
508 /* Output assembler header. */
512 /* Output comments for the testsuite-driver and the initial
513 disassembler output. */
514 fputs ("#objdump: -dr --prefix-address --show-raw-insn\n"
516 "#as: -mcpu=ep9312\n"
518 "# Test the instructions of the Cirrus Maverick floating point co-processor\n"
520 ".*: +file format.*arm.*\n"
522 "Disassembly of section .text:\n",
525 /* Now emit all (selected) insns. */
526 output_groups (groups
, as_in
, dis_out
);
This page took 0.042414 seconds and 5 git commands to generate.