1 /* Copyright (C) 2000 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.
19 /* Generator of tests for Maverick.
21 * See the following file for usage and documentation. */
22 #include "../all/test-gen.c"
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. */
28 /* Canonical names. */
29 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
30 "r8", "r9", "r10", "r11", "r12", "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 status
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
56 arm_cond (func_arg
*arg
, insn_data
*data
)
57 #define arm_cond { arm_cond }
59 static const char conds
[16][3] = {
60 "eq", "ne", "cs", "cc",
61 "mi", "pl", "vs", "vc",
62 "hi", "ls", "ge", "lt",
65 unsigned val
= get_bits (4u);
67 data
->as_in
= data
->dis_out
= strdup (conds
[val
]);
69 data
->dis_out
= strdup ("");
70 data
->bits
= (val
== 15 ? 14 : val
) << 28;
74 /* The sign of an offset is actually used to determined whether the
75 * absolute value of the offset should be added or subtracted, so we
76 * must adjust negative values so that they do not overflow: -256 is
77 * not valid, but -0 is distinct from +0. */
79 off8s (func_arg
*arg
, insn_data
*data
)
80 #define off8s { off8s }
82 int val
= get_bits (9s
);
83 char value
[6], *strt
= value
;
93 data
->bits
= val
| (1 << 23);
94 sprintf (strt
, "%i", val
);
95 data
->as_in
= data
->dis_out
= strdup (value
);
99 /* This function generates a 7-bit signed constant, emitted as
100 * follows: the 4 least-significant bits are stored in the 4
101 * least-significant bits of the word; the 3 most-significant bits are
102 * stored in bits 7:5, i.e., bit 4 is skipped. */
104 imm7 (func_arg
*arg
, insn_data
*data
)
105 #define imm7 { imm7 }
107 int val
= get_bits (7s
);
110 data
->bits
= (val
& 0x0f) | (2 * (val
& 0x70));
111 sprintf (value
, "#%i", val
);
112 data
->as_in
= data
->dis_out
= strdup (value
);
116 /* Convenience wrapper to define_insn, that prefixes every insn with
117 * `cf' (so, if you specify command-line arguments, remember that `cf'
118 * must *not* be part of the string), and post-fixes a condition code.
119 * insname and insnvar specify the main insn name and a variant;
120 * they're just concatenated, and insnvar is often empty. word is the
121 * bit pattern that defines the insn, properly shifted, and funcs is a
122 * sequence of funcs that define the operands and the syntax of the
124 #define mv_insn(insname, insnvar, word, funcs...) \
125 define_insn(insname ## insnvar, \
127 insn_bits (insname, word), \
132 /* Define a single LDC/STC variant. op is the main insn opcode; ld
133 * stands for load (it should be 0 on stores), dword selects 64-bit
134 * operations, pre should be enabled for pre-increment, and wb, for
135 * write-back. sep1, sep2 and sep3 are syntactical elements ([]!)
136 * that the assembler will use to enable pre and wb. It would
137 * probably have been cleaner to couple the syntactical elements with
138 * the pre/wb bits directly, but it would have required the definition
139 * of more functions. */
140 #define LDST(insname, insnvar, op, ld, dword, regname, pre, wb, sep1, sep2, sep3) \
141 mv_insn (insname, insnvar, \
142 (12<<24)|(op<<8)|(ld<<20)|(pre<<24)|(dword<<22)|(wb<<21), \
143 mvreg (regname, 12), comma, \
144 lsqbkt, armreg (16), sep1, comma, off8s, sep2, sep3, \
147 /* Define all variants of an LDR or STR instruction, namely,
148 * pre-indexed without write-back, pre-indexed with write-back and
150 #define LDSTall(insname, op, ld, dword, regname) \
151 LDST (insname, _p, op, ld, dword, regname, 1, 0, nothing, rsqbkt, nothing); \
152 LDST (insname, _pw, op, ld, dword, regname, 1, 1, nothing, rsqbkt, literal("!")); \
153 LDST (insname, ,op, ld, dword, regname, 0, 0, rsqbkt, nothing, nothing)
155 /* Produce the insn identifiers of all LDST variants of a given insn.
156 * To be used in the initialization of an insn group array. */
157 #define insns_LDSTall(insname) \
158 insn (insname ## _p), insn (insname ## _pw), insn (insname)
160 /* Define a CDP variant that uses two registers, at offsets 12 and 16.
161 * The two opcodes and the co-processor number identify the CDP
163 #define CDP2(insname, var, cpnum, opcode1, opcode2, reg1name, reg2name) \
164 mv_insn (insname##var, , \
165 (14<<24)|((opcode1)<<20)|((cpnum)<<8)|((opcode2)<<5), \
166 mvreg (reg1name, 12), comma, mvreg (reg2name, 16))
168 /* Define a 32-bit integer CDP instruction with two operands. */
169 #define CDP2fx(insname, opcode1, opcode2) \
170 CDP2 (insname, 32, 5, opcode1, opcode2, "fx", "fx")
172 /* Define a 64-bit integer CDP instruction with two operands. */
173 #define CDP2dx(insname, opcode1, opcode2) \
174 CDP2 (insname, 64, 5, opcode1, opcode2, "dx", "dx")
176 /* Define a float CDP instruction with two operands. */
177 #define CDP2f(insname, opcode1, opcode2) \
178 CDP2 (insname, s, 4, opcode1, opcode2, "f", "f")
180 /* Define a double CDP instruction with two operands. */
181 #define CDP2d(insname, opcode1, opcode2) \
182 CDP2 (insname, d, 4, opcode1, opcode2, "d", "d")
184 /* Define a CDP instruction with two register operands and one 7-bit
185 * signed immediate generated with imm7. */
186 #define CDP2_imm7(insname, cpnum, opcode1, reg1name, reg2name) \
187 mv_insn (insname, , (14<<24)|((opcode1)<<20)|((cpnum)<<8), \
188 mvreg (reg1name, 12), comma, mvreg (reg2name, 16), comma, imm7, \
191 /* Produce the insn identifiers of CDP floating-point or integer insn
192 * pairs (i.e., it appends the suffixes for 32-bit and 64-bit
194 #define CDPfp_insns(insname) \
195 insn (insname ## s), insn (insname ## d)
196 #define CDPx_insns(insname) \
197 insn (insname ## 32), insn (insname ## 64)
199 /* Define a CDP instruction with 3 operands, at offsets 12, 16, 0. */
200 #define CDP3(insname, var, cpnum, opcode1, opcode2, reg1name, reg2name, reg3name) \
201 mv_insn (insname##var, , \
202 (14<<24)|((opcode1)<<20)|((cpnum)<<8)|((opcode2)<<5), \
203 mvreg (reg1name, 12), comma, mvreg (reg2name, 16), comma, \
204 mvreg (reg3name, 0), tick_random)
206 /* Define a 32-bit integer CDP instruction with three operands. */
207 #define CDP3fx(insname, opcode1, opcode2) \
208 CDP3 (insname, 32, 5, opcode1, opcode2, "fx", "fx", "fx")
210 /* Define a 64-bit integer CDP instruction with three operands. */
211 #define CDP3dx(insname, opcode1, opcode2) \
212 CDP3 (insname, 64, 5, opcode1, opcode2, "dx", "dx", "dx")
214 /* Define a float CDP instruction with three operands. */
215 #define CDP3f(insname, opcode1, opcode2) \
216 CDP3 (insname, s, 4, opcode1, opcode2, "f", "f", "f")
218 /* Define a double CDP instruction with three operands. */
219 #define CDP3d(insname, opcode1, opcode2) \
220 CDP3 (insname, d, 4, opcode1, opcode2, "d", "d", "d")
222 /* Define a CDP instruction with four operands, at offsets 5, 12, 16
223 * and 0. Used only for ACC instructions. */
224 #define CDP4(insname, opcode1, reg2spec, reg3name, reg4name) \
225 mv_insn (insname, , (14<<24)|((opcode1)<<20)|(6<<8), \
226 acreg (5), comma, reg2spec, comma, \
227 mvreg (reg3name, 16), comma, mvreg (reg4name, 0))
229 /* Define a CDP4 instruction with one accumulator operands. */
230 #define CDP41A(insname, opcode1) \
231 CDP4 (insname, opcode1, mvreg ("fx", 12), "fx", "fx")
233 /* Define a CDP4 instruction with two accumulator operands. */
234 #define CDP42A(insname, opcode1) \
235 CDP4 (insname, opcode1, acreg (12), "fx", "fx")
237 /* Define a MCR or MRC instruction with two register operands. */
238 #define MCRC2(insname, cpnum, opcode1, dir, opcode2, reg1spec, reg2spec) \
239 mv_insn (insname, , \
240 ((14<<24)|((opcode1)<<21)|((dir)<<20)| \
241 ((cpnum)<<8)|((opcode2)<<5)|(1<<4)), \
242 reg1spec, comma, reg2spec)
244 /* Define a move from a DSP register to an ARM register. */
245 #define MVDSPARM(insname, cpnum, opcode2, regDSPname) \
246 MCRC2 (mv ## insname, cpnum, 0, 0, opcode2, \
247 mvreg (regDSPname, 16), armreg(12))
249 /* Define a move from an ARM register to a DSP register. */
250 #define MVARMDSP(insname, cpnum, opcode2, regDSPname) \
251 MCRC2 (mv ## insname, cpnum, 0, 1, opcode2, \
252 armreg (12), mvreg (regDSPname, 16))
254 /* Define a move from a DSP register to a DSP accumulator. */
255 #define MVDSPACC(insname, opcode2, regDSPname) \
256 MCRC2 (mv ## insname, 6, 0, 1, opcode2, acreg (0), mvreg (regDSPname, 16))
258 /* Define a move from a DSP accumulator to a DSP register. */
259 #define MVACCDSP(insname, opcode2, regDSPname) \
260 MCRC2 (mv ## insname, 6, 0, 0, opcode2, mvreg (regDSPname, 0), acreg (16))
262 /* Define move insns between a float DSP register and an ARM
264 #define MVf(nameAD, nameDA, opcode2) \
265 MVDSPARM (nameAD, 4, opcode2, "f"); \
266 MVARMDSP (nameDA, 4, opcode2, "f")
268 /* Define move insns between a double DSP register and an ARM
270 #define MVd(nameAD, nameDA, opcode2) \
271 MVDSPARM (nameAD, 4, opcode2, "d"); \
272 MVARMDSP (nameDA, 4, opcode2, "d")
274 /* Define move insns between a 32-bit integer DSP register and an ARM
276 #define MVfx(nameAD, nameDA, opcode2) \
277 MVDSPARM (nameAD, 5, opcode2, "fx"); \
278 MVARMDSP (nameDA, 5, opcode2, "fx")
280 /* Define move insns between a 64-bit integer DSP register and an ARM
282 #define MVdx(nameAD, nameDA, opcode2) \
283 MVDSPARM (nameAD, 5, opcode2, "dx"); \
284 MVARMDSP (nameDA, 5, opcode2, "dx")
286 /* Define move insns between a 32-bit DSP register and a DSP
288 #define MVfxa(nameFA, nameAF, opcode2) \
289 MVDSPACC (nameFA, opcode2, "fx"); \
290 MVACCDSP (nameAF, opcode2, "fx")
292 /* Define move insns between a 64-bit DSP register and a DSP
294 #define MVdxa(nameDA, nameAD, opcode2) \
295 MVDSPACC (nameDA, opcode2, "dx"); \
296 MVACCDSP (nameAD, opcode2, "dx")
298 /* Produce the insn identifiers for a pair of mv insns. */
299 #define insns_MV(name1, name2) \
300 insn (mv ## name1), insn (mv ## name2)
302 /* Define a MCR or MRC instruction with three register operands. */
303 #define MCRC3(insname, cpnum, opcode1, dir, opcode2, reg1spec, reg2spec, reg3spec) \
304 mv_insn (insname, , \
305 ((14<<24)|((opcode1)<<21)|((dir)<<20)| \
306 ((cpnum)<<8)|((opcode2)<<5)|(1<<4)), \
307 reg1spec, comma, reg2spec, comma, reg3spec, \
310 /* Define all load_store insns. */
311 LDSTall (ldrs
, 4, 1, 0, "f");
312 LDSTall (ldrd
, 4, 1, 1, "d");
313 LDSTall (ldr32
, 5, 1, 0, "fx");
314 LDSTall (ldr64
, 5, 1, 1, "dx");
315 LDSTall (strs
, 4, 0, 0, "f");
316 LDSTall (strd
, 4, 0, 1, "d");
317 LDSTall (str32
, 5, 0, 0, "fx");
318 LDSTall (str64
, 5, 0, 1, "dx");
320 /* Create the load_store insn group. */
321 func
*load_store_insns
[] = {
322 insns_LDSTall (ldrs
), insns_LDSTall (ldrd
),
323 insns_LDSTall (ldr32
), insns_LDSTall (ldr64
),
324 insns_LDSTall (strs
), insns_LDSTall (strd
),
325 insns_LDSTall (str32
), insns_LDSTall (str64
),
329 /* Define all move insns. */
333 MVdx (64lr
, r64l
, 0);
334 MVdx (64hr
, r64h
, 1);
335 MVfxa (al32
, 32al
, 0);
336 MVfxa (am32
, 32am
, 1);
337 MVfxa (ah32
, 32ah
, 2);
340 MCRC2 (mvsc32
, 6, 0, 1, 5, dspsc
, mvreg ("fx", 16));
341 MCRC2 (mv32sc
, 6, 0, 0, 5, mvreg ("fx", 0), dspsc
);
342 CDP2 (cpys
, , 4, 0, 0, "f", "f");
343 CDP2 (cpyd
, , 4, 0, 1, "d", "d");
345 /* Create the move insns group. */
346 func
*move_insns
[] = {
347 insns_MV (sr
, rs
), insns_MV (dlr
, rdl
), insns_MV (dhr
, rdh
),
348 insns_MV (64lr
, r64l
), insns_MV (64hr
, r64h
),
349 insns_MV (al32
, 32al
), insns_MV (am32
, 32am
), insns_MV (ah32
, 32ah
),
350 insns_MV (a32
, 32a
), insns_MV (a64
, 64a
),
351 insn (mvsc32
), insn (mv32sc
), insn (cpys
), insn (cpyd
),
355 /* Define all conversion insns. */
356 CDP2 (cvtsd
, , 4, 0, 3, "d", "f");
357 CDP2 (cvtds
, , 4, 0, 2, "f", "d");
358 CDP2 (cvt32s
, , 4, 0, 4, "f", "fx");
359 CDP2 (cvt32d
, , 4, 0, 5, "d", "fx");
360 CDP2 (cvt64s
, , 4, 0, 6, "f", "dx");
361 CDP2 (cvt64d
, , 4, 0, 7, "d", "dx");
362 CDP2 (cvts32
, , 5, 1, 4, "fx", "f");
363 CDP2 (cvtd32
, , 5, 1, 5, "fx", "d");
364 CDP2 (truncs32
, , 5, 1, 6, "fx", "f");
365 CDP2 (truncd32
, , 5, 1, 7, "fx", "d");
367 /* Create the conv insns group. */
368 func
*conv_insns
[] = {
369 insn (cvtsd
), insn (cvtds
), insn (cvt32s
), insn (cvt32d
),
370 insn (cvt64s
), insn (cvt64d
), insn (cvts32
), insn (cvtd32
),
371 insn (truncs32
), insn (truncd32
),
375 /* Define all shift insns. */
376 MCRC3 (rshl32
, 5, 0, 0, 2, mvreg ("fx", 16), mvreg ("fx", 0), armreg(12));
377 MCRC3 (rshl64
, 5, 0, 0, 3, mvreg ("dx", 16), mvreg ("dx", 0), armreg(12));
378 CDP2_imm7 (sh32
, 5, 0, "fx", "fx");
379 CDP2_imm7 (sh64
, 5, 2, "dx", "dx");
381 /* Create the shift insns group. */
382 func
*shift_insns
[] = {
383 insn (rshl32
), insn (rshl64
),
384 insn (sh32
), insn (sh64
),
388 /* Define all comparison insns. */
389 MCRC3 (cmps
, 4, 0, 1, 4, armreg (12), mvreg ("f", 16), mvreg ("f", 0));
390 MCRC3 (cmpd
, 4, 0, 1, 5, armreg (12), mvreg ("d", 16), mvreg ("d", 0));
391 MCRC3 (cmp32
, 5, 0, 1, 4, armreg (12), mvreg ("fx", 16), mvreg ("fx", 0));
392 MCRC3 (cmp64
, 5, 0, 1, 5, armreg (12), mvreg ("dx", 16), mvreg ("dx", 0));
394 /* Create the comp insns group. */
395 func
*comp_insns
[] = {
396 insn (cmps
), insn (cmpd
),
397 insn (cmp32
), insn (cmp64
),
401 /* Define all floating-point arithmetic insns. */
413 /* Create the fp-arith insns group. */
414 func
*fp_arith_insns
[] = {
415 CDPfp_insns (abs
), CDPfp_insns (neg
),
416 CDPfp_insns (add
), CDPfp_insns (sub
), CDPfp_insns (mul
),
420 /* Define all integer arithmetic insns. */
434 /* Create the int-arith insns group. */
435 func
*int_arith_insns
[] = {
436 CDPx_insns (abs
), CDPx_insns (neg
),
437 CDPx_insns (add
), CDPx_insns (sub
), CDPx_insns (mul
),
438 insn (mac32
), insn (msc32
),
442 /* Define all accumulator arithmetic insns. */
448 /* Create the acc-arith insns group. */
449 func
*acc_arith_insns
[] = {
450 insn (madd32
), insn (msub32
),
451 insn (madda32
), insn (msuba32
),
455 /* Create the set of all groups. */
458 { "load_store", load_store_insns
},
459 { "move", move_insns
},
460 { "conv", conv_insns
},
461 { "shift", shift_insns
},
462 { "comp", comp_insns
},
463 { "fp_arith", fp_arith_insns
},
464 { "int_arith", int_arith_insns
},
465 { "acc_arith", acc_arith_insns
},
470 main(int argc
, char *argv
[])
472 FILE *as_in
= stdout
, *dis_out
= stderr
;
474 /* Check whether we're filtering insns. */
476 skip_list
= argv
+ 1;
478 /* Output assembler header. */
482 /* Output comments for the testsuite-driver and the initial
483 * disassembler output. */
484 fputs ("#objdump: -dr --prefix-address --show-raw-insn\n"
488 "# Test the instructions of Maverick\n"
490 ".*: +file format.*arm.*\n"
492 "Disassembly of section .text:\n",
495 /* Now emit all (selected) insns. */
496 output_groups (groups
, as_in
, dis_out
);
This page took 0.042795 seconds and 4 git commands to generate.