diff options
Diffstat (limited to 'binutils-2.24/gas/testsuite/gas/all/test-gen.c')
-rw-r--r-- | binutils-2.24/gas/testsuite/gas/all/test-gen.c | 744 |
1 files changed, 0 insertions, 744 deletions
diff --git a/binutils-2.24/gas/testsuite/gas/all/test-gen.c b/binutils-2.24/gas/testsuite/gas/all/test-gen.c deleted file mode 100644 index 96aaeb81..00000000 --- a/binutils-2.24/gas/testsuite/gas/all/test-gen.c +++ /dev/null @@ -1,744 +0,0 @@ -#ifndef TEST_GEN_C -#define TEST_GEN_C 1 - -/* Copyright (C) 2000, 2003, 2005, 2007 Free Software Foundation - Contributed by Alexandre Oliva <aoliva@cygnus.com> - - This file is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* This is a source file with infra-structure to test generators for - assemblers and disassemblers. - - The strategy to generate testcases is as follows. We'll output to - two streams: one will get the assembly source, and the other will - get regexps that match the expected binary patterns. - - To generate each instruction, the functions of a func[] are called, - each with the corresponding func_arg. Each function should set - members of insn_data, to decide what it's going to output to the - assembly source, the corresponding output for the disassembler - tester, and the bits to be set in the instruction word. The - strings to be output must have been allocated with strdup() or - malloc(), so that they can be freed. A function may also modify - insn_size. More details in test-gen.c - - Because this would have generated too many tests, we have chosen to - define ``random'' sequences of numbers/registers, and simply - generate each instruction a couple of times, which should get us - enough coverage. - - In general, test generators should be compiled/run as follows: - - % gcc test.c -o test - % ./test > test.s 2 > test.d - - Please note that this file contains a couple of GCC-isms, such as - macro varargs (also available in C99, but with a difference syntax) - and labeled elements in initializers (so that insn definitions are - simpler and safer). - - It is assumed that the test generator #includes this file after - defining any of the preprocessor macros documented below. The test - generator is supposed to define instructions, at least one group of - instructions, optionally, a sequence of groups. - - It should also define a main() function that outputs the initial - lines of the assembler input and of the test control file, that - also contains the disassembler output. The main() funcion may - optionally set skip_list too, before calling output_groups() or - output_insns(). */ - -/* Define to 1 to avoid repeating instructions and to use a simpler - register/constant generation mechanism. This makes it much easier - to verify that the generated bit patterns are correct. */ -#ifndef SIMPLIFY_OUTPUT -#define SIMPLIFY_OUTPUT 0 -#endif - -/* Define to 0 to avoid generating disassembler tests. */ -#ifndef DISASSEMBLER_TEST -#define DISASSEMBLER_TEST 1 -#endif - -/* Define to the number of times to repeat the generation of each - insn. It's best to use prime numbers, to improve randomization. */ -#ifndef INSN_REPEAT -#define INSN_REPEAT 5 -#endif - -/* Define in order to get randomization_counter printed, as a comment, - in the disassembler output, after each insn is emitted. */ -#ifndef OUTPUT_RANDOMIZATION_COUNTER -#define OUTPUT_RANDOMIZATION_COUNTER 0 -#endif - -/* Other configuration macros are DEFINED_WORD and DEFINED_FUNC_ARG, - see below. */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -/* It is expected that the main program defines the type `word' before - includeing this. */ -#ifndef DEFINED_WORD -typedef unsigned long long word; -#endif - -/* This struct is used as the output area for each function. It - should store in as_in a pointer to the string to be output to the - assembler; in dis_out, the string to be expected in return from the - disassembler, and in bits the bits of the instruction word that are - enabled by the assembly fragment. */ -typedef struct -{ - char * as_in; - char * dis_out; - word bits; -} insn_data; - -#ifndef DEFINED_FUNC_ARG -/* This is the struct that feeds information to each function. You're - free to extend it, by `typedef'ing it before including this file, - and defining DEFINED_FUNC_ARG. You may even reorder the fields, - but do not remove any of the existing fields. */ -typedef struct -{ - int i1; - int i2; - int i3; - void * p1; - void * p2; - word w; -} func_arg; -#endif - -/* This is the struct whose arrays define insns. Each func in the - array will be called, in sequence, being given a pointer to the - associated arg and a pointer to a zero-initialized output area, - that it may fill in. */ -typedef struct -{ - int (* func) (func_arg *, insn_data *); - func_arg arg; -} func; - -/* Use this to group insns under a name. */ -typedef struct -{ - const char * name; - func ** insns; -} group_t; - -/* This is the size of each instruction. Use `insn_size_bits' instead - of `insn_bits' in an insn defition to modify it. */ -int insn_size = 4; - -/* The offset of the next insn, as expected in the disassembler - output. */ -int current_offset = 0; - -/* The offset and name of the last label to be emitted. */ -int last_label_offset = 0; -const char * last_label_name = 0; - -/* This variable may be initialized in main() to `argv+1', if - `argc>1', so that tests are emitted only for instructions that - match exactly one of the given command-line arguments. If it is - NULL, tests for all instructions are emitted. It must be a - NULL-terminated array of pointers to strings (just like - `argv+1'). */ -char ** skip_list = 0; - -/* This is a counter used to walk the various arrays of ``random'' - operand generation. In simplified output mode, it is zeroed after - each insn, otherwise it just keeps growing. */ -unsigned randomization_counter = 0; - -/* Use `define_insn' to create an array of funcs to define an insn, - then `insn' to refer to that insn when defining an insn group. */ -#define define_insn(insname, funcs...) \ - func i_ ## insname[] = { funcs, { 0 } } -#define insn(insname) (i_ ## insname) - -/* Use these to output a comma followed by an optional space, a single - space, a plus sign, left and right square brackets and parentheses, - all of them properly quoted. */ -#define comma literal_q (", ", ", ?") -#define space literal (" ") -#define tab literal ("\t") -#define plus literal_q ("+", "\\+") -#define lsqbkt literal_q ("[", "\\[") -#define rsqbkt literal_q ("]", "\\]") -#define lparen literal_q ("(", "\\(") -#define rparen literal_q (")", "\\)") - -/* Use this as a placeholder when you define a macro that expects an - argument, but you don't have anything to output there. */ -int -nothing (func_arg *arg, insn_data *data) -#define nothing { nothing } -{ - return 0; -} - -/* This is to be used in the argument list of define_insn, causing a - string to be copied into both the assembly and the expected - disassembler output. It is assumed not to modify the binary - encoding of the insn. */ -int -literal (func_arg *arg, insn_data *data) -#define literal(s) { literal, { p1: (s) } } -{ - data->as_in = data->dis_out = strdup ((char *) arg->p1); - return 0; -} - -/* The characters `[', `]', `\\' and `^' must be quoted in the - disassembler-output matcher. If a literal string contains any of - these characters, use literal_q instead of literal, and specify the - unquoted version (for as input) as the first argument, and the - quoted version (for expected disassembler output) as the second - one. */ -int -literal_q (func_arg *arg, insn_data *data) -#define literal_q(s,q) { literal_q, { p1: (s), p2: (q) } } -{ - data->as_in = strdup ((char *) arg->p1); - data->dis_out = strdup ((char *) arg->p2); - return 0; -} - -/* Given an insn name, check whether it should be skipped or not, - depending on skip_list. Return non-zero if the insn is to be - skipped. */ -int -skip_insn (char *name) -{ - char **test; - - if (! skip_list) - return 0; - - for (test = skip_list; * test; ++ test) - if (strcmp (name, * test) == 0) - return 0; - - return 1; -} - -/* Use this to emit the actual insn name, with its opcode, in - architectures with fixed-length instructions. */ -int -insn_bits (func_arg *arg, insn_data *data) -#define insn_bits(name,bits) \ - { insn_bits, { p1: # name, w: bits } } -{ - if (skip_insn ((char *) arg->p1)) - return 1; - data->as_in = data->dis_out = strdup ((char *) arg->p1); - data->bits = arg->w; - return 0; -} - -/* Use this to emit the insn name and its opcode in architectures - without a variable instruction length. */ -int -insn_size_bits (func_arg *arg, insn_data *data) -#define insn_size_bits(name,size,bits) \ - { insn_size_bits, { p1: # name, i1: size, w: bits } } -{ - if (skip_insn ((char *) arg->p1)) - return 1; - data->as_in = data->dis_out = strdup ((char *) arg->p1); - data->bits = arg->w; - insn_size = arg->i1; - return 0; -} - -/* Use this to advance the random generator by one, in case it is - generating repetitive patterns. It is usually good to arrange that - each insn consumes a prime number of ``random'' numbers, or, at - least, that it does not consume an exact power of two ``random'' - numbers. */ -int -tick_random (func_arg *arg, insn_data *data) -#define tick_random { tick_random } -{ - ++ randomization_counter; - return 0; -} - -/* Select the next ``random'' number from the array V of size S, and - advance the counter. */ -#define get_bits_from_size(V,S) \ - ((V)[randomization_counter ++ % (S)]) - -/* Utility macros. `_get_bits_var', used in some macros below, assume - the names of the arrays used to define the ``random'' orders start - with `random_order_'. */ -#define _get_bits_var(N) (random_order_ ## N) -#define _get_bits_size(V) (sizeof (V) / sizeof * (V)) - -/* Use this within a `func_arg' to select one of the arrays below (or - any other array that starts with random_order_N. */ -#define mk_get_bits(N) \ - p2: _get_bits_var (N), i3: _get_bits_size (_get_bits_var (N)) - -/* Simplified versions of get_bits_from_size for when you have access - to the array, so that its size can be implicitly calculated. */ -#define get_bits_from(V) get_bits_from_size ((V),_get_bits_size ((V))) -#define get_bits(N) get_bits_from (_get_bits_var (N)) - - -/* Use `2u' to generate 2-bit unsigned values. Good for selecting - registers randomly from a set of 4 registers. */ -unsigned random_order_2u[] = - { - /* This sequence was generated by hand so that no digit appers more - than once in any horizontal or vertical line. */ - 0, 1, 3, 2, - 2, 0, 1, 3, - 1, 3, 2, 0, - 3, 2, 0, 1 - }; - -/* Use `3u' to generate 3-bit unsigned values. Good for selecting - registers randomly from a set of 8 registers. */ -unsigned random_order_3u[] = - { - /* This sequence was generated by: - f(k) = 3k mod 8 - except that the middle pairs were swapped. */ - 0, 6, 3, 1, 4, 2, 7, 5, - /* This sequence was generated by: - f(k) = 5k mod 8 - except that the middle pairs were swapped. */ - 0, 2, 5, 7, 4, 6, 1, 3, - }; - -/* Use `4u' to generate 4-bit unsigned values. Good for selecting - registers randomly from a set of 16 registers. */ -unsigned random_order_4u[] = - { - /* This sequence was generated by: - f(k) = 5k mod 16 - except that the middle pairs were swapped. */ - 0, 5, 15, 10, 9, 4, 14, 3, - 8, 13, 7, 2, 1, 12, 6, 11, - /* This sequence was generated by: - f(k) = 7k mod 16 - except that the middle pairs were swapped. */ - 0, 7, 5, 14, 3, 12, 10, 1, - 8, 15, 13, 6, 11, 4, 2, 9, - }; - -/* Use `5u' to generate 5-bit unsigned values. Good for selecting - registers randomly from a set of 32 registers. */ -unsigned random_order_5u[] = - { - /* This sequence was generated by: - f(k) = (13k) mod 32 - except that the middle pairs were swapped. */ - 0, 26, 13, 7, 20, 14, 1, 27, - 8, 2, 21, 15, 28, 22, 9, 3, - 16, 10, 29, 23, 4, 30, 17, 11, - 24, 18, 5, 31, 12, 6, 25, 19 - }; - -/* Use `7s' to generate 7-bit signed values. Good for selecting - ``interesting'' constants from -64 to +63. */ -int random_order_7s[] = - { - /* Sequence generated by hand, to explore limit values and a few - intermediate values selected by chance. Keep the number of - intermediate values low, to ensure that the limit values are - generated often enough. */ - 0, -1, -64, 63, -32, 32, 24, -20, - 9, -27, -31, 33, 40, -2, -5, 1 - }; - -/* Use `8s' to generate 8-bit signed values. Good for selecting - ``interesting'' constants from -128 to +127. */ -int random_order_8s[] = - { - /* Sequence generated by hand, to explore limit values and a few - intermediate values selected by chance. Keep the number of - intermediate values low, to ensure that the limit values are - generated often enough. */ - 0, -1, -128, 127, -32, 32, 24, -20, - 73, -27, -95, 33, 104, -2, -69, 1 - }; - -/* Use `9s' to generate 9-bit signed values. Good for selecting - ``interesting'' constants from -256 to +255. */ -int random_order_9s[] = - { - /* Sequence generated by hand, to explore limit values and a few - intermediate values selected by chance. Keep the number of - intermediate values low, to ensure that the limit values are - generated often enough. */ - 0, -1, -256, 255, -64, 64, 72, -40, - 73, -137, -158, 37, 104, -240, -69, 1 - }; - -/* Use `16s' to generate 16-bit signed values. Good for selecting - ``interesting'' constants from -32768 to +32767. */ -int random_order_16s[] = - { - /* Sequence generated by hand, to explore limit values and a few - intermediate values selected by chance. Keep the number of - intermediate values low, to ensure that the limit values are - generated often enough. */ - -32768, - 32767, - (-1 << 15) | (64 << 8) | 32, - (64 << 8) | 32, - 0x1234, - (-1 << 15) | 0x8765, - 0x0180, - (-1 << 15) | 0x8001 -}; - -/* Use `24s' to generate 24-bit signed values. Good for selecting - ``interesting'' constants from -2^23 to 2^23-1. */ -int random_order_24s[] = - { - /* Sequence generated by hand, to explore limit values and a few - intermediate values selected by chance. Keep the number of - intermediate values low, to ensure that the limit values are - generated often enough. */ - -1 << 23, - 1 << 23 -1, - (-1 << 23) | (((64 << 8) | 32) << 8) | 16, - (((64 << 8) | 32) << 8) | 16, - 0x123456, - (-1 << 23) | 0x876543, - 0x01ff80, - (-1 << 23) | 0x80ff01 -}; - -/* Use `32s' to generate 32-bit signed values. Good for selecting - ``interesting'' constants from -2^31 to 2^31-1. */ -int random_order_32s[] = - { - /* Sequence generated by hand, to explore limit values and a few - intermediate values selected by chance. Keep the number of - intermediate values low, to ensure that the limit values are - generated often enough. */ - -1 << 31, - 1 << 31 - 1, - (-1 << 31) | (((((64 << 8) | 32) << 8) | 16) << 8) | 8, - (((((64 << 8) | 32) << 8) | 16) << 8) | 8, - 0x12345678, - (-1 << 31) | 0x87654321, - 0x01ffff80, - (-1 << 31) | 0x80ffff01 - }; - -/* This function computes the number of digits needed to represent a - given number. */ -unsigned long -ulen (unsigned long i, unsigned base) -{ - int count = 0; - - if (i == 0) - return 1; - for (; i > 0; ++ count) - i /= base; - return count; -} - -/* Use this to generate a signed constant of the given size, shifted - by the given amount, with the specified endianness. */ -int -signed_constant (func_arg * arg, insn_data * data) -#define signed_constant(bits, shift, revert) \ - { signed_constant, { i1: shift, i2: bits * (revert ? -1 : 1), \ - mk_get_bits (bits ## s) } } -{ - long val = get_bits_from_size ((unsigned *) arg->p2, arg->i3); - int len = (val >= 0 ? ulen (val, 10) : (1 + ulen (-val, 10))); - int nbits = (arg->i2 >= 0 ? arg->i2 : -arg->i2); - word bits = ((word) val) & (((((word) 1) << (nbits - 1)) << 1) - 1); - - data->as_in = data->dis_out = malloc (len + 1); - sprintf (data->as_in, "%ld", val); - if (arg->i2 < 0) - { - word rbits = 0; - - do - { - rbits <<= 8; - rbits |= bits & 0xff; - bits >>= 8; - nbits -= 8; - } - while (nbits > 0); - - bits = rbits; - } - data->bits = bits << arg->i1; - - return 0; -} - -/* Use this to generate a unsigned constant of the given size, shifted - by the given amount, with the specified endianness. */ -int -unsigned_constant (func_arg * arg, insn_data * data) -#define unsigned_constant(bits, shift, revert) \ - { unsigned_constant, { i1: shift, i2: bits * (revert ? -1 : 1), \ - mk_get_bits (bits ## s) } } -{ - int nbits = (arg->i2 >= 0 ? arg->i2 : -arg->i2); - unsigned long val = - get_bits_from_size ((unsigned *) arg->p2, arg->i3) - & (((((word) 1) << (nbits - 1)) << 1) - 1); - int len = ulen (val, 10); - word bits = val; - - data->as_in = data->dis_out = malloc (len + 1); - sprintf (data->as_in, "%lu", val); - if (arg->i2 < 0) - { - word rbits = 0; - - do - { - rbits <<= 8; - rbits |= bits & 0xff; - bits >>= 8; - nbits -= 8; - } - while (nbits > 0); - - bits = rbits; - } - data->bits = bits << arg->i1; - - return 0; -} - -/* Use this to generate an absolute address of the given size, shifted - by the given amount, with the specified endianness. */ -int -absolute_address (func_arg *arg, insn_data *data) -#define absolute_address (bits, shift, revert) \ - { absolute_address, { i1: shift, i2: bits * (revert ? -1 : 1), \ - mk_get_bits (bits ## s) } } -{ - int nbits = (arg->i2 >= 0 ? arg->i2 : -arg->i2); - unsigned long val = - get_bits_from_size ((unsigned *) arg->p2, arg->i3) - & (((((word) 1) << (nbits - 1)) << 1) - 1); - word bits = val; - - data->as_in = malloc (ulen (val, 10) + 1); - sprintf (data->as_in, "%lu", val); - data->dis_out = malloc (nbits / 4 + 11); - sprintf (data->dis_out, "0*%0*lx <[^>]*>", nbits / 4, val); - if (arg->i2 < 0) - { - word rbits = 0; - - do - { - rbits <<= 8; - rbits |= bits & 0xff; - bits >>= 8; - nbits -= 8; - } - while (nbits > 0); - - bits = rbits; - } - data->bits = bits << arg->i1; - - return 0; -} - -/* Use this to generate a register name that starts with a given - prefix, and is followed by a number generated by `gen' (see - mk_get_bits below). The register number is shifted `shift' bits - left before being stored in the binary insn. */ -int -reg_p (func_arg *arg, insn_data *data) -#define reg_p(prefix,shift,gen) \ - { reg_p, { i1: (shift), p1: (prefix), gen } } -{ - unsigned reg = get_bits_from_size ((unsigned *) arg->p2, arg->i3); - char *regname = (char *) arg->p1; - - data->as_in = data->dis_out = malloc (strlen (regname) + ulen (reg, 10) + 1); - sprintf (data->as_in, "%s%u", regname, reg); - data->bits = reg; - data->bits <<= arg->i1; - return 0; -} - -/* Use this to generate a register name taken from an array. The - index into the array `names' is to be produced by `gen', but `mask' - may be used to filter out some of the bits before choosing the - disassembler output and the bits for the binary insn, shifted left - by `shift'. For example, if registers have canonical names, but - can also be referred to by aliases, the array can be n times larger - than the actual number of registers, and the mask is then used to - pick the canonical name for the disassembler output, and to - eliminate the extra bits from the binary output. */ -int -reg_r (func_arg *arg, insn_data *data) -#define reg_r(names,shift,mask,gen) \ - { reg_r, { i1: (shift), i2: (mask), p1: (names), gen } } -{ - unsigned reg = get_bits_from_size ((unsigned *) arg->p2, arg->i3); - - data->as_in = strdup (((const char **) arg->p1)[reg]); - reg &= arg->i2; - data->dis_out = strdup (((const char **) arg->p1)[reg]); - data->bits = reg; - data->bits <<= arg->i1; - return 0; -} - -/* Given a NULL-terminated array of insns-definitions (pointers to - arrays of funcs), output test code for the insns to as_in (assembly - input) and dis_out (expected disassembler output). */ -void -output_insns (func **insn, FILE *as_in, FILE *dis_out) -{ - for (; *insn; ++insn) - { - insn_data *data; - func *parts = *insn; - int part_count = 0, r; - - /* Figure out how many funcs have to be called. */ - while (parts[part_count].func) - ++part_count; - - /* Allocate storage for the output area of each func. */ - data = (insn_data*) malloc (part_count * sizeof (insn_data)); - -#if SIMPLIFY_OUTPUT - randomization_counter = 0; -#else - /* Repeat each insn several times. */ - for (r = 0; r < INSN_REPEAT; ++r) -#endif - { - unsigned saved_rc = randomization_counter; - int part; - word bits = 0; - - for (part = 0; part < part_count; ++part) - { - /* Zero-initialize the storage. */ - data[part].as_in = data[part].dis_out = 0; - data[part].bits = 0; - /* If a func returns non-zero, skip this line. */ - if (parts[part].func (&parts[part].arg, &data[part])) - goto skip; - /* Otherwise, get its output bit pattern into the total - bit pattern. */ - bits |= data[part].bits; - } - - if (as_in) - { - /* Output the whole assembly line. */ - fputc ('\t', as_in); - for (part = 0; part < part_count; ++part) - if (data[part].as_in) - fputs (data[part].as_in, as_in); - fputc ('\n', as_in); - } - - if (dis_out) - { - /* Output the disassembler expected output line, - starting with the offset and the insn binary pattern, - just like objdump outputs. Because objdump sometimes - inserts spaces between each byte in the insn binary - pattern, make the space optional. */ - fprintf (dis_out, "0*%x <", current_offset); - if (last_label_name) - if (current_offset == last_label_offset) - fputs (last_label_name, dis_out); - else - fprintf (dis_out, "%s\\+0x%x", last_label_name, - current_offset - last_label_offset); - else - fputs ("[^>]*", dis_out); - fputs ("> ", dis_out); - for (part = insn_size; part-- > 0; ) - fprintf (dis_out, "%02x ?", (int)(bits >> (part * 8)) & 0xff); - fputs (" *\t", dis_out); - -#if DISASSEMBLER_TEST - for (part = 0; part < part_count; ++part) - if (data[part].dis_out) - fputs (data[part].dis_out, dis_out); -#else - /* If we're not testing the DISASSEMBLER, just match - anything. */ - fputs (".*", dis_out); -#endif - fputc ('\n', dis_out); -#if OUTPUT_RANDOMIZATION_COUNTER - fprintf (dis_out, "# %i\n", randomization_counter); -#endif - } - - /* Account for the insn_size bytes we've just output. */ - current_offset += insn_size; - - /* Release the memory that each func may have allocated. */ - for (; part-- > 0;) - { - skip: - if (data[part].as_in) - free (data[part].as_in); - if (data[part].dis_out - && data[part].dis_out != data[part].as_in) - free (data[part].dis_out); - } - - /* There's nothing random here, don't repeat this insn. */ - if (randomization_counter == saved_rc) - break; - } - - free (data); - } -} - -/* For each group, output an asm label and the insns of the group. */ -void -output_groups (group_t group[], FILE *as_in, FILE *dis_out) -{ - for (; group->name; ++group) - { - fprintf (as_in, "%s:\n", group->name); - fprintf (dis_out, "# %s:\n", group->name); - last_label_offset = current_offset; - last_label_name = group->name; - output_insns (group->insns, as_in, dis_out); - } -} - -#endif |