Back to index

cell-binutils  2.17cvs20070401
test-gen.c
Go to the documentation of this file.
00001 #ifndef TEST_GEN_C
00002 #define TEST_GEN_C 1
00003 
00004 /* Copyright (C) 2000, 2003 Free Software Foundation
00005    Contributed by Alexandre Oliva <aoliva@cygnus.com>
00006 
00007    This file is free software; you can redistribute it and/or modify it
00008    under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful, but
00013    WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 /* This is a source file with infra-structure to test generators for
00022    assemblers and disassemblers.
00023 
00024    The strategy to generate testcases is as follows.  We'll output to
00025    two streams: one will get the assembly source, and the other will
00026    get regexps that match the expected binary patterns.
00027 
00028    To generate each instruction, the functions of a func[] are called,
00029    each with the corresponding func_arg.  Each function should set
00030    members of insn_data, to decide what it's going to output to the
00031    assembly source, the corresponding output for the disassembler
00032    tester, and the bits to be set in the instruction word.  The
00033    strings to be output must have been allocated with strdup() or
00034    malloc(), so that they can be freed.  A function may also modify
00035    insn_size.  More details in test-gen.c
00036 
00037    Because this would have generated too many tests, we have chosen to
00038    define ``random'' sequences of numbers/registers, and simply
00039    generate each instruction a couple of times, which should get us
00040    enough coverage.
00041 
00042    In general, test generators should be compiled/run as follows:
00043   
00044    % gcc test.c -o test
00045    % ./test > test.s 2 > test.d
00046 
00047    Please note that this file contains a couple of GCC-isms, such as
00048    macro varargs (also available in C99, but with a difference syntax)
00049    and labeled elements in initializers (so that insn definitions are
00050    simpler and safer).
00051 
00052    It is assumed that the test generator #includes this file after
00053    defining any of the preprocessor macros documented below.  The test
00054    generator is supposed to define instructions, at least one group of
00055    instructions, optionally, a sequence of groups.
00056 
00057    It should also define a main() function that outputs the initial
00058    lines of the assembler input and of the test control file, that
00059    also contains the disassembler output.  The main() funcion may
00060    optionally set skip_list too, before calling output_groups() or
00061    output_insns().  */
00062 
00063 /* Define to 1 to avoid repeating instructions and to use a simpler
00064    register/constant generation mechanism.  This makes it much easier
00065    to verify that the generated bit patterns are correct.  */
00066 #ifndef SIMPLIFY_OUTPUT
00067 #define SIMPLIFY_OUTPUT 0
00068 #endif
00069 
00070 /* Define to 0 to avoid generating disassembler tests.  */
00071 #ifndef DISASSEMBLER_TEST
00072 #define DISASSEMBLER_TEST 1
00073 #endif
00074 
00075 /* Define to the number of times to repeat the generation of each
00076    insn.  It's best to use prime numbers, to improve randomization.  */
00077 #ifndef INSN_REPEAT
00078 #define INSN_REPEAT 5
00079 #endif
00080 
00081 /* Define in order to get randomization_counter printed, as a comment,
00082    in the disassembler output, after each insn is emitted.  */
00083 #ifndef OUTPUT_RANDOMIZATION_COUNTER
00084 #define OUTPUT_RANDOMIZATION_COUNTER 0
00085 #endif
00086 
00087 /* Other configuration macros are DEFINED_WORD and DEFINED_FUNC_ARG,
00088    see below.  */
00089 
00090 #include <stdio.h>
00091 #include <string.h>
00092 #include <stdlib.h>
00093 
00094 /* It is expected that the main program defines the type `word' before
00095    includeing this.  */
00096 #ifndef DEFINED_WORD
00097 typedef unsigned long long word;
00098 #endif
00099 
00100 /* This struct is used as the output area for each function.  It
00101    should store in as_in a pointer to the string to be output to the
00102    assembler; in dis_out, the string to be expected in return from the
00103    disassembler, and in bits the bits of the instruction word that are
00104    enabled by the assembly fragment.  */
00105 typedef struct
00106 {
00107   char * as_in;
00108   char * dis_out;
00109   word   bits;
00110 } insn_data;
00111 
00112 #ifndef DEFINED_FUNC_ARG
00113 /* This is the struct that feeds information to each function.  You're
00114    free to extend it, by `typedef'ing it before including this file,
00115    and defining DEFINED_FUNC_ARG.  You may even reorder the fields,
00116    but do not remove any of the existing fields.  */
00117 typedef struct
00118 {
00119   int    i1;
00120   int    i2;
00121   int    i3;
00122   void * p1;
00123   void * p2;
00124   word   w;
00125 } func_arg;
00126 #endif
00127 
00128 /* This is the struct whose arrays define insns.  Each func in the
00129    array will be called, in sequence, being given a pointer to the
00130    associated arg and a pointer to a zero-initialized output area,
00131    that it may fill in.  */
00132 typedef struct
00133 {
00134   int (*    func) (func_arg *, insn_data *);
00135   func_arg  arg;
00136 } func;
00137 
00138 /* Use this to group insns under a name.  */
00139 typedef struct
00140 {
00141   const char * name;
00142   func **      insns;
00143 } group_t;
00144 
00145 /* This is the size of each instruction.  Use `insn_size_bits' instead
00146    of `insn_bits' in an insn defition to modify it.  */
00147 int insn_size = 4;
00148 
00149 /* The offset of the next insn, as expected in the disassembler
00150    output.  */
00151 int current_offset = 0;
00152 
00153 /* The offset and name of the last label to be emitted.  */
00154 int last_label_offset = 0;
00155 const char * last_label_name = 0;
00156 
00157 /* This variable may be initialized in main() to `argv+1', if
00158    `argc>1', so that tests are emitted only for instructions that
00159    match exactly one of the given command-line arguments.  If it is
00160    NULL, tests for all instructions are emitted.  It must be a
00161    NULL-terminated array of pointers to strings (just like
00162    `argv+1').  */
00163 char ** skip_list = 0;
00164 
00165 /* This is a counter used to walk the various arrays of ``random''
00166    operand generation.  In simplified output mode, it is zeroed after
00167    each insn, otherwise it just keeps growing.  */
00168 unsigned randomization_counter = 0;
00169 
00170 /* Use `define_insn' to create an array of funcs to define an insn,
00171    then `insn' to refer to that insn when defining an insn group.  */
00172 #define define_insn(insname, funcs...) \
00173   func i_ ## insname[] = { funcs, { 0 } }
00174 #define insn(insname) (i_ ## insname)
00175 
00176 /* Use these to output a comma followed by an optional space, a single
00177    space, a plus sign, left and right square brackets and parentheses,
00178    all of them properly quoted.  */
00179 #define comma  literal_q (", ", ", ?")
00180 #define space  literal (" ")
00181 #define tab    literal ("\t")
00182 #define plus   literal_q ("+", "\\+")
00183 #define lsqbkt literal_q ("[", "\\[")
00184 #define rsqbkt literal_q ("]", "\\]")
00185 #define lparen literal_q ("(", "\\(")
00186 #define rparen literal_q (")", "\\)")
00187 
00188 /* Use this as a placeholder when you define a macro that expects an
00189    argument, but you don't have anything to output there.  */
00190 int
00191 nothing (func_arg *arg, insn_data *data)
00192 #define nothing { nothing }
00193 {
00194   return 0;
00195 }
00196 
00197 /* This is to be used in the argument list of define_insn, causing a
00198    string to be copied into both the assembly and the expected
00199    disassembler output.  It is assumed not to modify the binary
00200    encoding of the insn.  */
00201 int
00202 literal (func_arg *arg, insn_data *data)
00203 #define literal(s) { literal, { p1: (s) } }
00204 {
00205   data->as_in = data->dis_out = strdup ((char *) arg->p1);
00206   return 0;
00207 }
00208 
00209 /* The characters `[', `]', `\\' and `^' must be quoted in the
00210    disassembler-output matcher.  If a literal string contains any of
00211    these characters, use literal_q instead of literal, and specify the
00212    unquoted version (for as input) as the first argument, and the
00213    quoted version (for expected disassembler output) as the second
00214    one.  */
00215 int
00216 literal_q (func_arg *arg, insn_data *data)
00217 #define literal_q(s,q) { literal_q, { p1: (s), p2: (q) } }
00218 {
00219   data->as_in = strdup ((char *) arg->p1);
00220   data->dis_out = strdup ((char *) arg->p2);
00221   return 0;
00222 }
00223 
00224 /* Given an insn name, check whether it should be skipped or not,
00225    depending on skip_list.  Return non-zero if the insn is to be
00226    skipped.  */
00227 int
00228 skip_insn (char *name)
00229 {
00230   char **test;
00231 
00232   if (! skip_list)
00233     return 0;
00234 
00235   for (test = skip_list; * test; ++ test)
00236     if (strcmp (name, * test) == 0)
00237       return 0;
00238 
00239   return 1;
00240 }
00241 
00242 /* Use this to emit the actual insn name, with its opcode, in
00243    architectures with fixed-length instructions.  */
00244 int
00245 insn_bits (func_arg *arg, insn_data *data)
00246 #define insn_bits(name,bits) \
00247   { insn_bits, { p1: # name, w: bits } }
00248 {
00249   if (skip_insn ((char *) arg->p1))
00250     return 1;
00251   data->as_in = data->dis_out = strdup ((char *) arg->p1);
00252   data->bits = arg->w;
00253   return 0;
00254 }
00255 
00256 /* Use this to emit the insn name and its opcode in architectures
00257    without a variable instruction length.  */ 
00258 int
00259 insn_size_bits (func_arg *arg, insn_data *data)
00260 #define insn_size_bits(name,size,bits) \
00261   { insn_size_bits, { p1: # name, i1: size, w: bits } }
00262 {
00263   if (skip_insn ((char *) arg->p1))
00264     return 1;
00265   data->as_in = data->dis_out = strdup ((char *) arg->p1);
00266   data->bits = arg->w;
00267   insn_size = arg->i1;
00268   return 0;
00269 }
00270 
00271 /* Use this to advance the random generator by one, in case it is
00272    generating repetitive patterns.  It is usually good to arrange that
00273    each insn consumes a prime number of ``random'' numbers, or, at
00274    least, that it does not consume an exact power of two ``random''
00275    numbers.  */
00276 int
00277 tick_random (func_arg *arg, insn_data *data)
00278 #define tick_random { tick_random }
00279 {
00280   ++ randomization_counter;
00281   return 0;
00282 }
00283 
00284 /* Select the next ``random'' number from the array V of size S, and
00285    advance the counter.  */
00286 #define get_bits_from_size(V,S) \
00287   ((V)[randomization_counter ++ % (S)])
00288 
00289 /* Utility macros.  `_get_bits_var', used in some macros below, assume
00290    the names of the arrays used to define the ``random'' orders start
00291    with `random_order_'.  */
00292 #define _get_bits_var(N) (random_order_ ## N)
00293 #define _get_bits_size(V) (sizeof (V) / sizeof * (V))
00294 
00295 /* Use this within a `func_arg' to select one of the arrays below (or
00296    any other array that starts with random_order_N.  */
00297 #define mk_get_bits(N) \
00298   p2: _get_bits_var (N), i3: _get_bits_size (_get_bits_var (N))
00299 
00300 /* Simplified versions of get_bits_from_size for when you have access
00301    to the array, so that its size can be implicitly calculated.  */
00302 #define get_bits_from(V) get_bits_from_size ((V),_get_bits_size ((V)))
00303 #define get_bits(N)      get_bits_from (_get_bits_var (N))
00304 
00305 
00306 /* Use `2u' to generate 2-bit unsigned values.  Good for selecting
00307    registers randomly from a set of 4 registers.  */
00308 unsigned random_order_2u[] =
00309   {
00310     /* This sequence was generated by hand so that no digit appers more
00311        than once in any horizontal or vertical line.  */
00312     0, 1, 3, 2,
00313     2, 0, 1, 3,
00314     1, 3, 2, 0,
00315     3, 2, 0, 1
00316   };
00317 
00318 /* Use `3u' to generate 3-bit unsigned values.  Good for selecting
00319    registers randomly from a set of 8 registers.  */
00320 unsigned random_order_3u[] =
00321   {
00322     /* This sequence was generated by:
00323        f(k) = 3k mod 8
00324        except that the middle pairs were swapped.  */
00325     0, 6, 3, 1, 4, 2, 7, 5,
00326     /* This sequence was generated by:
00327        f(k) = 5k mod 8
00328        except that the middle pairs were swapped.  */
00329     0, 2, 5, 7, 4, 6, 1, 3,
00330   };
00331 
00332 /* Use `4u' to generate 4-bit unsigned values.  Good for selecting
00333    registers randomly from a set of 16 registers.  */
00334 unsigned random_order_4u[] =
00335   {
00336     /* This sequence was generated by:
00337        f(k) = 5k mod 16
00338        except that the middle pairs were swapped.  */
00339     0,  5, 15, 10, 9,  4, 14,  3,
00340     8, 13,  7,  2, 1, 12,  6, 11,
00341     /* This sequence was generated by:
00342        f(k) = 7k mod 16
00343        except that the middle pairs were swapped.  */
00344     0,  7,  5, 14,  3, 12, 10, 1,
00345     8, 15, 13,  6, 11,  4,  2, 9,
00346   };
00347 
00348 /* Use `5u' to generate 5-bit unsigned values.  Good for selecting
00349    registers randomly from a set of 32 registers.  */
00350 unsigned random_order_5u[] =
00351   {
00352     /* This sequence was generated by:
00353        f(k) = (13k) mod 32
00354        except that the middle pairs were swapped.  */
00355     0, 26, 13,  7, 20, 14,  1, 27,
00356     8, 2,  21, 15, 28, 22,  9,  3,
00357     16, 10, 29, 23,  4, 30, 17, 11,
00358     24,  18, 5, 31, 12, 6,  25, 19
00359   };
00360 
00361 /* Use `7s' to generate 7-bit signed values.  Good for selecting
00362    ``interesting'' constants from -64 to +63.  */
00363 int random_order_7s[] =
00364   {
00365     /* Sequence generated by hand, to explore limit values and a few
00366        intermediate values selected by chance.  Keep the number of
00367        intermediate values low, to ensure that the limit values are
00368        generated often enough.  */
00369     0, -1, -64, 63, -32, 32, 24, -20,
00370     9, -27, -31, 33, 40, -2, -5, 1
00371   };
00372 
00373 /* Use `8s' to generate 8-bit signed values.  Good for selecting
00374    ``interesting'' constants from -128 to +127.  */
00375 int random_order_8s[] =
00376   {
00377     /* Sequence generated by hand, to explore limit values and a few
00378        intermediate values selected by chance.  Keep the number of
00379        intermediate values low, to ensure that the limit values are
00380        generated often enough.  */
00381     0, -1, -128, 127, -32, 32, 24, -20,
00382     73, -27, -95, 33, 104, -2, -69, 1
00383   };
00384 
00385 /* Use `9s' to generate 9-bit signed values.  Good for selecting
00386    ``interesting'' constants from -256 to +255.  */
00387 int random_order_9s[] =
00388   {
00389     /* Sequence generated by hand, to explore limit values and a few
00390        intermediate values selected by chance.  Keep the number of
00391        intermediate values low, to ensure that the limit values are
00392        generated often enough.  */
00393     0, -1, -256, 255, -64, 64, 72, -40,
00394     73, -137, -158, 37, 104, -240, -69, 1
00395   };
00396 
00397 /* Use `16s' to generate 16-bit signed values.  Good for selecting
00398    ``interesting'' constants from -32768 to +32767.  */
00399 int random_order_16s[] =
00400   {
00401     /* Sequence generated by hand, to explore limit values and a few
00402        intermediate values selected by chance.  Keep the number of
00403        intermediate values low, to ensure that the limit values are
00404        generated often enough.  */
00405     -32768,
00406     32767,
00407     (-1 << 15) | (64 << 8) | 32,
00408     (64 << 8) | 32,
00409     0x1234,
00410     (-1 << 15) | 0x8765,
00411     0x0180,
00412     (-1 << 15) | 0x8001
00413 };
00414 
00415 /* Use `24s' to generate 24-bit signed values.  Good for selecting
00416    ``interesting'' constants from -2^23 to 2^23-1.  */
00417 int random_order_24s[] =
00418   {
00419     /* Sequence generated by hand, to explore limit values and a few
00420        intermediate values selected by chance.  Keep the number of
00421        intermediate values low, to ensure that the limit values are
00422        generated often enough.  */
00423     -1 << 23,
00424     1 << 23 -1,
00425     (-1 << 23) | (((64 << 8) | 32) << 8) | 16,
00426     (((64 << 8) | 32) << 8) | 16,
00427     0x123456,
00428     (-1 << 23) | 0x876543,
00429     0x01ff80,
00430     (-1 << 23) | 0x80ff01
00431 };
00432 
00433 /* Use `32s' to generate 32-bit signed values.  Good for selecting
00434    ``interesting'' constants from -2^31 to 2^31-1.  */
00435 int random_order_32s[] =
00436   {
00437     /* Sequence generated by hand, to explore limit values and a few
00438        intermediate values selected by chance.  Keep the number of
00439        intermediate values low, to ensure that the limit values are
00440        generated often enough.  */
00441     -1 << 31,
00442     1 << 31 - 1,
00443     (-1 << 31) | (((((64 << 8) | 32) << 8) | 16) << 8) | 8,
00444     (((((64 << 8) | 32) << 8) | 16) << 8) | 8,
00445     0x12345678,
00446     (-1 << 31) | 0x87654321,
00447     0x01ffff80,
00448     (-1 << 31) | 0x80ffff01
00449   };
00450 
00451 /* This function computes the number of digits needed to represent a
00452    given number.  */
00453 unsigned long
00454 ulen (unsigned long i, unsigned base)
00455 {
00456   int count = 0;
00457 
00458   if (i == 0)
00459     return 1;
00460   for (; i > 0; ++ count)
00461     i /= base;
00462   return count;
00463 }
00464 
00465 /* Use this to generate a signed constant of the given size, shifted
00466    by the given amount, with the specified endianness.  */
00467 int
00468 signed_constant (func_arg * arg, insn_data * data)
00469 #define signed_constant(bits, shift, revert) \
00470   { signed_constant, { i1: shift, i2: bits * (revert ? -1 : 1), \
00471                      mk_get_bits (bits ## s) } }
00472 {
00473   long val = get_bits_from_size ((unsigned *) arg->p2, arg->i3);
00474   int len = (val >= 0 ? ulen (val, 10) : (1 + ulen (-val, 10)));
00475   int nbits = (arg->i2 >= 0 ? arg->i2 : -arg->i2);
00476   word bits = ((word) val) & (((((word) 1) << (nbits - 1)) << 1) - 1);
00477 
00478   data->as_in = data->dis_out = malloc (len + 1);
00479   sprintf (data->as_in, "%ld", val);
00480   if (arg->i2 < 0)
00481     {
00482       word rbits = 0;
00483 
00484       do
00485        {
00486          rbits <<= 8;
00487          rbits |= bits & 0xff;
00488          bits >>= 8;
00489          nbits -= 8;
00490        }
00491       while (nbits > 0);
00492 
00493       bits = rbits;
00494     }
00495   data->bits = bits << arg->i1;
00496 
00497   return 0;
00498 }
00499 
00500 /* Use this to generate a unsigned constant of the given size, shifted
00501    by the given amount, with the specified endianness.  */
00502 int
00503 unsigned_constant (func_arg * arg, insn_data * data)
00504 #define unsigned_constant(bits, shift, revert) \
00505   { unsigned_constant, { i1: shift, i2: bits * (revert ? -1 : 1), \
00506                       mk_get_bits (bits ## s) } }
00507 {
00508   int nbits = (arg->i2 >= 0 ? arg->i2 : -arg->i2);
00509   unsigned long val =
00510     get_bits_from_size ((unsigned *) arg->p2, arg->i3)
00511     & (((((word) 1) << (nbits - 1)) << 1) - 1);
00512   int len = ulen (val, 10);
00513   word bits = val;
00514 
00515   data->as_in = data->dis_out = malloc (len + 1);
00516   sprintf (data->as_in, "%lu", val);
00517   if (arg->i2 < 0)
00518     {
00519       word rbits = 0;
00520 
00521       do
00522        {
00523          rbits <<= 8;
00524          rbits |= bits & 0xff;
00525          bits >>= 8;
00526          nbits -= 8;
00527        }
00528       while (nbits > 0);
00529 
00530       bits = rbits;
00531     }
00532   data->bits = bits << arg->i1;
00533 
00534   return 0;
00535 }
00536 
00537 /* Use this to generate an absolute address of the given size, shifted
00538    by the given amount, with the specified endianness.  */
00539 int
00540 absolute_address (func_arg *arg, insn_data *data)
00541 #define absolute_address (bits, shift, revert) \
00542   { absolute_address, { i1: shift, i2: bits * (revert ? -1 : 1), \
00543                      mk_get_bits (bits ## s) } }
00544 {
00545   int nbits = (arg->i2 >= 0 ? arg->i2 : -arg->i2);
00546   unsigned long val =
00547     get_bits_from_size ((unsigned *) arg->p2, arg->i3)
00548     & (((((word) 1) << (nbits - 1)) << 1) - 1);
00549   word bits = val;
00550 
00551   data->as_in = malloc (ulen (val, 10) + 1);
00552   sprintf (data->as_in, "%lu", val);
00553   data->dis_out = malloc (nbits / 4 + 11);
00554   sprintf (data->dis_out, "0*%0*lx <[^>]*>", nbits / 4, val);
00555   if (arg->i2 < 0)
00556     {
00557       word rbits = 0;
00558 
00559       do
00560        {
00561          rbits <<= 8;
00562          rbits |= bits & 0xff;
00563          bits >>= 8;
00564          nbits -= 8;
00565        }
00566       while (nbits > 0);
00567 
00568       bits = rbits;
00569     }
00570   data->bits = bits << arg->i1;
00571 
00572   return 0;
00573 }
00574 
00575 /* Use this to generate a register name that starts with a given
00576    prefix, and is followed by a number generated by `gen' (see
00577    mk_get_bits below).  The register number is shifted `shift' bits
00578    left before being stored in the binary insn.  */
00579 int
00580 reg_p (func_arg *arg, insn_data *data)
00581 #define reg_p(prefix,shift,gen) \
00582   { reg_p, { i1: (shift), p1: (prefix), gen } }
00583 {
00584   unsigned reg = get_bits_from_size ((unsigned *) arg->p2, arg->i3);
00585   char *regname = (char *) arg->p1;
00586 
00587   data->as_in = data->dis_out = malloc (strlen (regname) + ulen (reg, 10) + 1);
00588   sprintf (data->as_in, "%s%u", regname, reg);
00589   data->bits = reg;
00590   data->bits <<= arg->i1;
00591   return 0;
00592 }
00593 
00594 /* Use this to generate a register name taken from an array.  The
00595    index into the array `names' is to be produced by `gen', but `mask'
00596    may be used to filter out some of the bits before choosing the
00597    disassembler output and the bits for the binary insn, shifted left
00598    by `shift'.  For example, if registers have canonical names, but
00599    can also be referred to by aliases, the array can be n times larger
00600    than the actual number of registers, and the mask is then used to
00601    pick the canonical name for the disassembler output, and to
00602    eliminate the extra bits from the binary output.  */
00603 int
00604 reg_r (func_arg *arg, insn_data *data)
00605 #define reg_r(names,shift,mask,gen) \
00606   { reg_r, { i1: (shift), i2: (mask), p1: (names), gen } }
00607 {
00608   unsigned reg = get_bits_from_size ((unsigned *) arg->p2, arg->i3);
00609   
00610   data->as_in = strdup (((const char **) arg->p1)[reg]);
00611   reg &= arg->i2;
00612   data->dis_out = strdup (((const char **) arg->p1)[reg]);
00613   data->bits = reg;
00614   data->bits <<= arg->i1;
00615   return 0;
00616 }
00617 
00618 /* Given a NULL-terminated array of insns-definitions (pointers to
00619    arrays of funcs), output test code for the insns to as_in (assembly
00620    input) and dis_out (expected disassembler output).  */
00621 void
00622 output_insns (func **insn, FILE *as_in, FILE *dis_out)
00623 {
00624   for (; *insn; ++insn)
00625     {
00626       insn_data *data;
00627       func *parts = *insn;
00628       int part_count = 0, r;
00629 
00630       /* Figure out how many funcs have to be called.  */
00631       while (parts[part_count].func)
00632        ++part_count;
00633 
00634       /* Allocate storage for the output area of each func.  */
00635       data = (insn_data*) malloc (part_count * sizeof (insn_data));
00636 
00637 #if SIMPLIFY_OUTPUT
00638       randomization_counter = 0;
00639 #else
00640       /* Repeat each insn several times.  */
00641       for (r = 0; r < INSN_REPEAT; ++r)
00642 #endif
00643        {
00644          unsigned saved_rc = randomization_counter;
00645          int part;
00646          word bits = 0;
00647 
00648          for (part = 0; part < part_count; ++part)
00649            {
00650              /* Zero-initialize the storage.  */
00651              data[part].as_in = data[part].dis_out = 0;
00652              data[part].bits = 0;
00653              /* If a func returns non-zero, skip this line.  */
00654              if (parts[part].func (&parts[part].arg, &data[part]))
00655               goto skip;
00656              /* Otherwise, get its output bit pattern into the total
00657                 bit pattern.  */
00658              bits |= data[part].bits;
00659            }
00660          
00661          if (as_in)
00662            {
00663              /* Output the whole assembly line.  */
00664              fputc ('\t', as_in);
00665              for (part = 0; part < part_count; ++part)
00666               if (data[part].as_in)
00667                 fputs (data[part].as_in, as_in);
00668              fputc ('\n', as_in);
00669            }
00670 
00671          if (dis_out)
00672            {
00673              /* Output the disassembler expected output line,
00674                 starting with the offset and the insn binary pattern,
00675                 just like objdump outputs.  Because objdump sometimes
00676                 inserts spaces between each byte in the insn binary
00677                 pattern, make the space optional.  */
00678              fprintf (dis_out, "0*%x <", current_offset);
00679              if (last_label_name)
00680               if (current_offset == last_label_offset)
00681                 fputs (last_label_name, dis_out);
00682               else
00683                 fprintf (dis_out, "%s\\+0x%x", last_label_name,
00684                         current_offset - last_label_offset);
00685              else
00686               fputs ("[^>]*", dis_out);
00687              fputs ("> ", dis_out);
00688              for (part = insn_size; part-- > 0; )
00689               fprintf (dis_out, "%02x ?", (int)(bits >> (part * 8)) & 0xff);
00690              fputs (" *\t", dis_out);
00691              
00692 #if DISASSEMBLER_TEST
00693              for (part = 0; part < part_count; ++part)
00694               if (data[part].dis_out)
00695                 fputs (data[part].dis_out, dis_out);
00696 #else
00697              /* If we're not testing the DISASSEMBLER, just match
00698                 anything.  */
00699              fputs (".*", dis_out);
00700 #endif
00701              fputc ('\n', dis_out);
00702 #if OUTPUT_RANDOMIZATION_COUNTER
00703              fprintf (dis_out, "# %i\n", randomization_counter);
00704 #endif
00705            }
00706 
00707          /* Account for the insn_size bytes we've just output.  */
00708          current_offset += insn_size;
00709 
00710          /* Release the memory that each func may have allocated.  */
00711          for (; part-- > 0;)
00712            {
00713            skip:
00714              if (data[part].as_in)
00715               free (data[part].as_in);
00716              if (data[part].dis_out
00717                 && data[part].dis_out != data[part].as_in)
00718               free (data[part].dis_out);
00719            }
00720 
00721          /* There's nothing random here, don't repeat this insn.  */
00722          if (randomization_counter == saved_rc)
00723            break;
00724        }
00725 
00726       free (data);
00727     }
00728 }
00729 
00730 /* For each group, output an asm label and the insns of the group.  */
00731 void
00732 output_groups (group_t group[], FILE *as_in, FILE *dis_out)
00733 {
00734   for (; group->name; ++group)
00735     {
00736       fprintf (as_in, "%s:\n", group->name);
00737       fprintf (dis_out, "# %s:\n", group->name);
00738       last_label_offset = current_offset;
00739       last_label_name = group->name;
00740       output_insns (group->insns, as_in, dis_out);
00741     }
00742 }
00743 
00744 #endif