home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / ae / AEC / aec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  27.5 KB  |  1,205 lines

  1. /* AEC, the AE Compiler.
  2.    Copyright (C) 1989, 1990 by James R. Larus (larus@cs.wisc.edu)
  3.  
  4.    AE and AEC are free software; you can redistribute it and/or modify it
  5.    under the terms of the GNU General Public License as published by the
  6.    Free Software Foundation; either version 1, or (at your option) any
  7.    later version.
  8.  
  9.    AE and AEC are 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 GNU CC; see the file COPYING.  If not, write to James R.
  16.    Larus, Computer Sciences Department, University of Wisconsin--Madison,
  17.    1210 West Dayton Street, Madison, WI 53706, USA or to the Free
  18.    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  19.  
  20.  
  21. /* $Header: /var/home/larus/AE/AEC/RCS/aec.c,v 2.0 90/02/09 17:23:41 larus Exp Locker: larus $ */
  22.  
  23.  
  24. /* Syntax is:
  25.    aec -x a.out -o aec.out {-q, -d} f1.sma ... fn.sma
  26.  
  27.    -x a.out    (Mandatory)    Executable:  Name of the executable file a.out.
  28.    -o aec.out    (Mandatory)    Output:  Name of the output file.
  29.    -q        (Optional)    Quiet: do not write information.
  30.    -d        (Optional)    Debug: produce safer, but slower code.
  31.    -m        (Optional)    Multiple inst.: treat consecutive inst.
  32.                 together
  33.  */
  34.  
  35.  
  36. #include <stdio.h>
  37. #include <strings.h>
  38. #include <varargs.h>
  39. #include "config.h"
  40. #include "rtl.h"
  41. #include "ae.h"
  42. #include "ae-machine.h"
  43. #include "aec.h"
  44.  
  45. #ifdef ECOFF_AOUT
  46. #include <filehdr.h>
  47. #include <syms.h>
  48. #include <ldfcn.h>
  49. #endif
  50. #ifdef BSD_AOUT
  51. #include <nlist.h>
  52. #endif
  53.  
  54.  
  55. #define streq(s1,s2) !strcmp((s1),(s2))
  56.  
  57.  
  58. struct symbol
  59. {
  60.   struct symbol *next;        /* Next structure in the bucket.  */
  61.   char *name;            /* Name. */
  62.   int used_in_call;        /* Non-zero if symbol referenced in call */
  63.   int schema_seen_p;        /* Non-zero if schema processed. */
  64.   unsigned long address;    /* Address in core. */
  65.   int addr_missing_warning;    /* Non-zero if complained about unknown addr */
  66. };
  67.  
  68. /* From rtl.c: */
  69. #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
  70.   (SIZE*UNITS_PER_WORD+3)/4,
  71.  
  72. int mode_size[] = {
  73. #include "machmode.def"
  74. };
  75.  
  76.  
  77. void add_hash ();
  78. void annotate_loop_edges ();
  79. char *arg_out ();
  80. void block_end ();
  81. void block_end_cjump ();
  82. void block_end_jump ();
  83. void block_start ();
  84. void block_start_target ();
  85. void call_indirect_inst ();
  86. void call_inst ();
  87. void copy_file_to_out_file ();
  88. void end_block_common ();
  89. void fatal_error ();
  90. void free_list ();
  91. void function_end ();
  92. void function_start ();
  93. void indirect_call_code ();
  94. void initialize_scanner ();
  95. void issue_instruction ();
  96. struct symbol *lookup_symbol ();
  97. void make_dummy_function ();
  98. void non_fatal_error ();
  99. void output_preface ();
  100. void output_reg_decl ();
  101. void output_set_value ();
  102. int nlist_addr_cmp ();
  103. void printf_out ();
  104. void report_statistics ();
  105. void schema_for_absent_functions ();
  106. char *string_cat ();
  107. void switch_error ();
  108. unsigned long symbol_address ();
  109. unsigned long symbol_address_or_die ();
  110. unsigned long symbol_address_or_warn ();
  111. void uneventful_inst ();
  112. void yyerror ();
  113. int yyparse ();
  114.  
  115.  
  116. void bzero ();
  117. void exit ();
  118. void free ();
  119. void fprintf ();
  120. void fclose ();
  121. int fread ();
  122. void fwrite ();
  123. char *malloc ();
  124.  
  125.  
  126. char *input_file_name;    /* Input file name */
  127. static char *executable_file_name = NULL; /* Executable file name */
  128.  
  129. static FILE *out_file = NULL;    /*  */
  130.  
  131.  
  132. #ifdef ECOFF_AOUT
  133. LDFILE *ex_file;
  134. #endif
  135.  
  136. static int indirect_call_seen = 0; /*  */
  137.  
  138.  
  139. #define GLOBAL_HASH_TBL_SIZE 8191
  140.  
  141. static struct symbol *global_hash_tbl [GLOBAL_HASH_TBL_SIZE];
  142.  
  143.  
  144. /* Counters to collect statistics: */
  145.  
  146. static int quiet = 0;        /* Zero => statistics printed */
  147. static int debug = 0;        /* Non-zero => safer and slower code */
  148. static int multiple_inst = 0;    /* Non-zero => multiple insts together */
  149.  
  150. static int function_cnt = 0;    /* Number of functions */
  151. static int dummy_function_cnt = 0; /* Number of dummy functions */
  152. static int block_cnt = 0;    /* Number of basic blocks */
  153. static int target_block_cnt = 0; /* Number of blocks that are targets */
  154. static int fall_block_cnt = 0;    /* Number of blocks that fall thru */
  155. static int cjump_block_cnt = 0;    /* Number of blocks that end with cjump */
  156. static int jump_block_cnt = 0;    /* Number of blocks that end with jump */
  157. static int loop_cnt = 0;    /* Number of loops */
  158. static int inst_cnt = 0;    /* Number of instructions */
  159. static int store_cnt = 0;    /* Number of stores */
  160. static int unknown_store_cnt = 0; /* Number of stores where data is read */
  161. static int load_cnt = 0;    /* Number of loads */
  162. static int unknown_load_cnt = 0; /* Number of loads where data is read */
  163. static int known_def_cnt = 0;    /* Number of def w/ known operands */
  164. static int unknown_def_cnt = 0;    /* Number of def w/ known operands */
  165. static int call_cnt = 0;    /* Number of function calls */
  166. static int indirect_call_cnt = 0; /* Number of indirect function calls */
  167.  
  168. static int loops_in_function = 0; /* Number of loops in current function */
  169.  
  170. extern int line_no;
  171.  
  172.  
  173.  
  174. void
  175. main (argc, argv)
  176.      int argc;
  177.      char *argv[];
  178. {
  179.   register int i;
  180.   char *out_file_name = NULL;
  181.   FILE *in_file;
  182.  
  183.   if (argc == 1)
  184.     switch_error ("");
  185.  
  186.   for (i = 1; i < argc; i++)
  187.     {
  188.       if (*argv [i] == '-')
  189.     {
  190.       if (streq (argv [i], "-o"))
  191.         {
  192.           out_file_name = argv [i + 1];
  193.           i ++;
  194.         }
  195.       else if (streq (argv [i], "-x"))
  196.         {
  197.           executable_file_name = argv [i + 1];
  198.           i ++;
  199.         }
  200.       else if (streq (argv [i], "-q"))
  201.         quiet = 1;
  202.       else if (streq (argv [i], "-d"))
  203.         debug = 1;
  204.       else if (streq (argv [i], "-m"))
  205.         multiple_inst = 1;
  206.       else
  207.         switch_error ("aec: Unknown switch %s\n", argv [i]);
  208.     }
  209.       else
  210.     {
  211.       if (out_file_name == NULL)
  212.         switch_error ("aec: No output file specified\n");
  213.       else if (executable_file_name == NULL)
  214.         switch_error ("aec: No executable specified\n");
  215.       else if (out_file == NULL)
  216.         {
  217.           out_file = fopen (out_file_name, "w");
  218. #ifdef ECOFF_AOUT
  219.           ex_file = ldopen (executable_file_name, NULL);
  220. #endif
  221.           output_preface ();
  222.         }
  223.  
  224.       input_file_name = argv [i];
  225.       in_file = fopen (input_file_name, "r");
  226.       if (in_file == NULL)
  227.         fatal_error ("Input file %s cannot be opened\n", input_file_name);
  228.       initialize_scanner (in_file);
  229.       while (yyparse () == 1) ;
  230.     }
  231.     }
  232.  
  233.   schema_for_absent_functions ();
  234.   indirect_call_code ();
  235.   fprintf (out_file, "int max_loops = %d;\n", loop_cnt);
  236.   copy_file_to_out_file (string_cat (LIBRARY_PATH, "aec-file-epilogue"));
  237.   fclose (out_file);
  238. #ifdef ECOFF_AOUT
  239.   ldclose (ex_file);
  240. #endif
  241.   if (!quiet)
  242.     report_statistics ();
  243.   exit (0);
  244. }
  245.  
  246.  
  247. void
  248. switch_error (message, x)
  249.      char *message;
  250.      int x;
  251. {
  252.   fprintf (stderr, message, x);
  253.   fprintf (stderr, "aec -x a.out -o aec.out {-q, -d} f1.sma ... fn.sma\n");
  254.   fprintf (stderr, "-x a.out    (Mandatory) Executable: name of executable a.out\n");
  255.   fprintf (stderr, "-o aec.out    (Mandatory) Output: name of the output file\n");
  256.   fprintf (stderr, "-q        (Optional)  Quiet: do not write information\n");
  257.   fprintf (stderr, "-d        (Optional)  Debug: produce safer, but slower code\n");
  258.   fprintf (stderr, "-m        (Optional)  Multiple inst: treat consecutive inst\n");
  259.   exit (-1);
  260. }
  261.  
  262.  
  263. void
  264. non_fatal_error (message, x)
  265.      char *message;
  266.      int x;
  267. {
  268.   fprintf (stderr, "aec: In file %s, line %d: ", input_file_name, line_no);
  269.   fprintf (stderr, message, x);
  270. }
  271.  
  272.  
  273. void
  274. fatal_error (message, x)
  275.      char *message;
  276.      int x;
  277. {
  278.   fprintf (stderr, "aec: In file %s, line %d: ", input_file_name, line_no);
  279.   fprintf (stderr, message, x);
  280.   exit (-1);
  281. }
  282.  
  283.  
  284. #define PER(x,y) ((x * 100) / y)
  285.  
  286. void
  287. report_statistics ()
  288. {
  289.   fprintf (stderr, "\n\n%d functions w/ schemas  %d functions w/o schemas\n",
  290.        function_cnt, dummy_function_cnt);
  291.  
  292.   fprintf (stderr, "\n%d basic blocks:\n", block_cnt);
  293.   fprintf (stderr, "  %6d (%d %%) targets\n", target_block_cnt,
  294.        PER (target_block_cnt, block_cnt));
  295.   fprintf (stderr, "  %6d (%d %%) fall thru\n", fall_block_cnt,
  296.        PER (fall_block_cnt, block_cnt));
  297.   fprintf (stderr, "  %6d (%d %%) end w/ cjump\n", cjump_block_cnt,
  298.        PER (cjump_block_cnt, block_cnt));
  299.   fprintf (stderr, "  %6d (%d %%) end w/ jump\n", jump_block_cnt,
  300.        PER (jump_block_cnt, block_cnt));
  301.  
  302.   fprintf (stderr, "\n%d loops\n", loop_cnt);
  303.  
  304.   fprintf (stderr, "\n%d instructions:\n", inst_cnt);
  305.  
  306.   fprintf (stderr, "  %6d (%d %%) stores\n", store_cnt,
  307.        PER (store_cnt, inst_cnt));
  308.   if (store_cnt > 0)
  309.     fprintf (stderr, "    %6d (%d %%) unknown stores\n", unknown_store_cnt,
  310.          PER (unknown_store_cnt, store_cnt));
  311.  
  312.   fprintf (stderr, "  %6d (%d %%) loads\n", load_cnt,
  313.        PER (load_cnt, inst_cnt));
  314.   if (load_cnt > 0)
  315.     fprintf (stderr, "    %6d (%d %%) unknown loads\n", unknown_load_cnt,
  316.          PER (unknown_load_cnt, load_cnt));
  317.  
  318.   fprintf (stderr, "  %6d (%d %%) known defs\n", known_def_cnt,
  319.        PER (known_def_cnt, inst_cnt));
  320.   fprintf (stderr, "  %6d (%d %%) unknown defs\n", unknown_def_cnt,
  321.        PER (unknown_def_cnt, inst_cnt));
  322.  
  323.   fprintf (stderr, "  %6d (%d %%) calls\n", call_cnt,
  324.        PER (call_cnt, inst_cnt));
  325.   if (call_cnt > 0)
  326.     fprintf (stderr, "    %6d (%d %%) indirect calls\n", indirect_call_cnt,
  327.          PER (indirect_call_cnt, call_cnt));
  328. }
  329.  
  330.  
  331.  
  332.  
  333. /* List data structure routines. */
  334.  
  335. list
  336. cons (head, tail)
  337.      int head;
  338.      list tail;
  339. {
  340.   list x = (list) malloc (sizeof (list_cell));
  341.   CAR (x) = head;
  342.   CDR (x) = tail;
  343.   return (x);
  344. }
  345.  
  346.  
  347. void
  348. free_list (lst)
  349.      list lst;
  350. {
  351.   while (lst != NULL)
  352.     {
  353.       list next = CDR (lst);
  354.       free (lst);
  355.       lst = next;
  356.     }
  357. }
  358.  
  359.  
  360.  
  361. static int call_used_regs [] = CALL_USED_REGISTERS;
  362.  
  363.  
  364. void
  365. output_preface ()
  366. {
  367.   int i;
  368.  
  369.   copy_file_to_out_file (string_cat (LIBRARY_PATH, "aec-file-prologue"));
  370.   copy_file_to_out_file (string_cat (LIBRARY_PATH, "aec.h"));
  371.  
  372.   for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
  373.     if (!REG_LOCAL_TO_FUNCTION (i))
  374.       if (HARD_REGNO_MODE_OK (i, SImode))
  375.     output_reg_decl ("static", "int", i);
  376.       else if (HARD_REGNO_MODE_OK (i, SFmode))
  377.     output_reg_decl ("static",  "float", i);
  378.       else if (HARD_REGNO_MODE_OK (i, DFmode))
  379.     output_reg_decl ("static",  "double", i);
  380.  
  381. #ifdef PC_REGNUM
  382.   printf_out ("#define PC R%d\n\n", PC_REGNUM);
  383. #else
  384.   printf_out ("static int PC;\n\n");
  385. #endif
  386.  
  387.   printf_out ("static void __aec_global_reg_init ()\n{\n");
  388.   INITIALIZE_REGISTERS ();
  389.   printf_out ("}\n\n");
  390. }
  391.  
  392.  
  393. void
  394. output_reg_decl (preface, type, regno)
  395.      char *preface, *type;
  396.      int regno;
  397. {
  398.   if (debug)
  399.     printf_out ("%s %s *R%d = (%s *) -1;\n", preface, type, regno,
  400.          type);
  401.   else
  402.     printf_out ("%s %s R%d;\n", preface, type, regno);
  403. }
  404.  
  405.  
  406. void
  407. schema_for_absent_functions ()
  408. {
  409.   register int i, error_head_output_p = 0;
  410.   struct symbol *idp;
  411.  
  412.   for (i = 0; i < GLOBAL_HASH_TBL_SIZE; i++)
  413.     for (idp = global_hash_tbl [i]; idp; idp = idp-> next)
  414.       if (idp->used_in_call && !idp->schema_seen_p)
  415.     {
  416.       if (!error_head_output_p)
  417.         {
  418.           fprintf (stdout, "aec: These functions are called but have no schemas.\n");
  419.           fprintf (stdout, "They must not produce events.\n");
  420.         }
  421.       error_head_output_p = 1;
  422.       fprintf (stdout, "  %s\n", idp->name);
  423.       make_dummy_function (idp->name);
  424.       idp->schema_seen_p = 1;
  425.       dummy_function_cnt ++;
  426.     }
  427. }
  428.  
  429.  
  430. void
  431. indirect_call_code ()
  432. {
  433.   printf_out ("static unsigned long func_tbl[] = {\n");
  434.   if (indirect_call_seen)
  435.     {
  436. #ifdef ECOFF_AOUT
  437.       int i;
  438.       PDR ppd;
  439.       unsigned long addr;
  440.       char *name;
  441.       SYMR sym;
  442.  
  443.       for (i = 0; i < SYMHEADER (ex_file).ipdMax - 1; i++)
  444.     if (ldgetpd (ex_file, i, &ppd) != 0)
  445.       {
  446.         struct symbol *idp;
  447.  
  448.         addr = ppd.adr;
  449.         ldtbread (ex_file, ppd.isym, &sym);
  450.         name = (char *) ldgetname (ex_file, &sym);
  451.         idp = lookup_symbol (name);
  452.         if (idp->schema_seen_p)
  453.           /* Program could invoke any function, but we can only follow
  454.          execution through those for which we have a schema. */
  455.           printf_out ("0x%x, (unsigned long) __ae_%s,\n", addr, name);
  456.       }
  457. #endif
  458. #ifdef BSD_AOUT
  459.       register int i;
  460.       register struct symbol *idp;
  461.       register int count = 0;
  462.       struct nlist *names;
  463.  
  464.       for (i = 0; i < GLOBAL_HASH_TBL_SIZE; i ++)
  465.     for (idp = global_hash_tbl [i]; idp != NULL; idp = idp->next)
  466.       if (idp->schema_seen_p)
  467.         /* Program could invoke any function, but we can only follow
  468.            execution through those for which we have a schema. */
  469.         count += 1;
  470.  
  471.       names = (struct nlist *) malloc ((count + 1) * sizeof (struct nlist));
  472.       names [count].n_name = NULL;
  473.       count = 0;
  474.       for (i = 0; i < GLOBAL_HASH_TBL_SIZE; i ++)
  475.     for (idp = global_hash_tbl [i]; idp != NULL; idp = idp->next)
  476.       if (idp->schema_seen_p)
  477.         names [count ++].n_name = idp->name;
  478.  
  479.       nlist (executable_file_name, names);
  480.       /* Sort names by address so can do binary search */
  481.       qsort (names, count, sizeof (struct nlist), nlist_addr_cmp);
  482.       for (i = 0; i < count; i++)
  483.     if (names[i].n_type != 0)
  484.       printf_out ("0x%x, (unsigned long) __ae_%s,\n",
  485.               names [i].n_value, names [i].n_name);
  486. #endif
  487.     }
  488.   printf_out ("0};\n\n");
  489. }
  490.  
  491.  
  492. #ifndef mips
  493. nlist_addr_cmp (n1, n2)
  494.      struct nlist *n1, *n2;
  495. {return (n1->n_value - n2->n_value);}
  496. #endif
  497.  
  498.  
  499. void
  500. copy_file_to_out_file (path)
  501.      char *path;
  502. {
  503.   int n;
  504.   FILE *pfd = fopen (path, "r", 0);
  505.   char buffer[4096];
  506.  
  507.   if (pfd == NULL)
  508.     fatal_error ("Cannot open file: %s\n", path);
  509.   while ((n = fread (buffer, sizeof (char), 4096, pfd)) > 0)
  510.     fwrite (buffer, sizeof (char), n, out_file);
  511.   fclose (pfd);
  512. }
  513.  
  514.  
  515. char *
  516. string_cat (s1, s2)
  517.      char *s1, *s2;
  518. {
  519.   int l = strlen (s1) + strlen (s2);
  520.   char *r = (char *) malloc (l + 1);
  521.  
  522.   strcpy (r, s1);
  523.   return strcat (r, s2);
  524. }
  525.  
  526.  
  527. /* Return the address of global identifier from the core file or 0 if
  528.    the identifier is not defined. */
  529.  
  530. unsigned long
  531. symbol_address (name)
  532.      char *name;
  533. {
  534.   struct symbol *idp = lookup_symbol (name);
  535.  
  536.   if (idp->address)        /* Cache address since lookup is expensive */
  537.     return idp->address;
  538.  
  539. #ifdef ECOFF_AOUT
  540.   {
  541.     register int i;
  542.     SYMR sym;
  543.  
  544.     for (i = 0; i <= SYMHEADER (ex_file).isymMax + SYMHEADER (ex_file).iextMax;
  545.      i++)
  546.       if (ldtbread (ex_file, i, &sym))
  547.     if (streq (name, ldgetname (ex_file, &sym)))
  548.       return (idp->address = sym.value);
  549.   }
  550. #endif
  551. #ifdef BSD_AOUT
  552.   {
  553.     struct nlist names [2];
  554.  
  555.     names [0].n_name = name;
  556.     names [1].n_name = NULL;
  557.     if (nlist (executable_file_name, names) == -1)
  558.       fatal_error ("Error reading symbol table for %s\n", name);
  559.     return (idp->address = names [0].n_value);
  560.   }
  561. #endif
  562. }
  563.  
  564.  
  565. /* Find and return a symbol's address or die horribly. */
  566.  
  567. unsigned long
  568. symbol_address_or_die (name)
  569.      char *name;
  570. {
  571.   unsigned long addr = symbol_address (name);
  572.  
  573.   if (addr == 0)
  574.     fatal_error ("Cannot find address of `%s' in %s\n", name,
  575.          executable_file_name);
  576.  
  577.   return addr;
  578. }
  579.  
  580.  
  581. /* Complain about a symbol not having an address and return 0. */
  582.  
  583. unsigned long
  584. symbol_address_or_warn (name)
  585.      char *name;
  586. {
  587.   unsigned long addr = symbol_address (name);
  588.  
  589.   if (addr == 0)
  590.     {
  591.       struct symbol *idp = lookup_symbol (name);
  592.       if (!idp->addr_missing_warning && !quiet)
  593.     fprintf (stderr, "aec: Cannot find address of '%s' in %s\n", name,
  594.          executable_file_name);
  595.       idp->addr_missing_warning = 1;
  596.     }
  597.  
  598.   return addr;
  599. }
  600.  
  601.  
  602.  
  603. static char* open_function_name = NULL;
  604.  
  605.  
  606. static int pc_offset = 0;
  607.  
  608.  
  609. /* Non-zero if block numbers are encode in a byte, not a half-word. */
  610.  
  611. static int read_byte_p = 0;
  612.  
  613.  
  614. void
  615. function_start (name, num_blocks)
  616.      char *name;
  617.      int num_blocks;
  618. {
  619.   int i;
  620.   unsigned long addr;
  621.  
  622.   if (open_function_name != NULL)
  623.     non_fatal_error ("function %s is not terminated.\n", open_function_name);
  624.  
  625.   printf_out ("static int __ae_%s()\n{\n", name);
  626.  
  627.   printf_out ("  int in_pc;\n");
  628.   for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
  629.     if (REG_LOCAL_TO_FUNCTION(i))
  630.       if (HARD_REGNO_MODE_OK (i, SImode))
  631.     output_reg_decl ("  register",  "int", i);
  632.       else if (HARD_REGNO_MODE_OK (i, SFmode))
  633.     output_reg_decl ("  register",  "float", i);
  634.       else if (HARD_REGNO_MODE_OK (i, DFmode))
  635.     output_reg_decl ("  register",  "double", i);
  636.  
  637.   printf_out ("\n");
  638.  
  639.   addr = symbol_address_or_warn (name);
  640.   if (addr != 0)
  641.     printf_out ("  PC=0x%x;\n", addr);
  642.   printf_out ("  in_pc = PC;\n");
  643.  
  644.   open_function_name = name;
  645.   pc_offset = 0;
  646.   read_byte_p = (num_blocks < 256);
  647.   lookup_symbol (name)->schema_seen_p = 1;
  648.   function_cnt ++;
  649.   loops_in_function = 0;
  650. }
  651.  
  652.  
  653. void
  654. make_dummy_function (name)
  655.      char *name;
  656. {
  657.   /* exit and _exit have predefined functions because they do not obey
  658.    the usual call/return convention. */
  659.   if (!streq (name, "exit") && !streq (name, "_exit"))
  660.     printf_out ("static int __ae_%s(){}\n\n", name);
  661. }
  662.  
  663.  
  664. void
  665. function_end (name)
  666.      char *name;
  667. {
  668.   register int i;
  669.  
  670.   if (debug)
  671.     for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
  672.       if (REG_LOCAL_TO_FUNCTION (i))
  673.     if (HARD_REGNO_MODE_OK (i, SImode))
  674.       printf_out ("  if (R%d != (int *) -1) free(R%d);\n", i, i);
  675.     else if (HARD_REGNO_MODE_OK (i, SFmode))
  676.       printf_out ("  if (R%d != (float *) -1) free(R%d);\n", i, i);
  677.     else if (HARD_REGNO_MODE_OK (i, DFmode))
  678.       printf_out ("  if (R%d != (double *) -1) free(R%d);\n", i, i);
  679.  
  680.   printf_out ("}\n\n");
  681.   if (open_function_name == NULL || !streq (name, open_function_name))
  682.     yyerror ("Function name mismatch");
  683.   free (open_function_name);
  684.   open_function_name = NULL;
  685.   free (name);
  686.   loop_cnt += loops_in_function;
  687. }
  688.  
  689.  
  690. static int open_bid = -1;
  691.  
  692.  
  693. void
  694. block_start (bid)
  695.      int bid;
  696. {
  697.   if (open_bid != -1)
  698.     non_fatal_error ("block %d is not terminated.\n", open_bid);
  699.   printf_out ("/* Start of block %d */\n", bid);
  700.   printf_out ("  L%d:\n", bid);
  701.   printf_out ("  PC = in_pc+%d;\n", pc_offset);
  702.   open_bid = bid;
  703.   block_cnt ++;
  704. }
  705.  
  706.  
  707. void
  708. block_start_target (bid)
  709.      int bid;
  710. {
  711.   block_start (bid);
  712.   target_block_cnt ++;
  713. }
  714.  
  715.  
  716. void
  717. end_block_common (bid)
  718.      int bid;
  719. {
  720.   if (bid != open_bid)
  721.     yyerror ("Block id's mismatched");
  722.   open_bid = -1;
  723.   printf_out ("/* End of block %d */\n", bid);
  724. }
  725.  
  726.  
  727. void
  728. block_end (bid, fall_thru_p, loop_anno)
  729.      int bid, fall_thru_p;
  730.      list loop_anno;
  731. {
  732.   if (fall_thru_p)        /* Falling into target of conditional. */
  733.     printf_out ("  %s();\n", (read_byte_p ? "EAT_BYTE" : "EAT_HALF"));
  734.   annotate_loop_edges (loop_anno, bid + 1, 1);
  735.   end_block_common (bid);
  736.   fall_block_cnt ++;
  737.   free_list (loop_anno);
  738. }
  739.  
  740.  
  741. void
  742. block_end_jump (bid, target_bid, jump_to_cjump_target_p, loop_anno)
  743.      int bid, target_bid, jump_to_cjump_target_p;
  744.      list loop_anno;
  745. {
  746. #ifdef JUMP_DELAY_SLOTS
  747.   int i;
  748.  
  749.   for (i = 0; i < JUMP_DELAY_SLOTS; i ++)
  750.     yyparse ();            /* Put delayed instruction first */
  751. #endif
  752.  
  753.   issue_instruction ();
  754.   if (jump_to_cjump_target_p)    /* Jump to target of conditional. */
  755.     printf_out ("  %s();\n", (read_byte_p ? "EAT_BYTE" : "EAT_HALF"));
  756.   annotate_loop_edges (loop_anno, target_bid, 1);
  757.   printf_out ("  goto L%d;\n", target_bid);
  758.   end_block_common (bid);
  759.   jump_block_cnt ++;
  760.   free_list (loop_anno);
  761. }
  762.  
  763.  
  764. void
  765. block_end_cjump (bid, targets, loop_anno)
  766.      int bid;
  767.      list targets;
  768.      list loop_anno;
  769. {
  770.   list t = targets;
  771.   int hi = 0;
  772.   char *seen_label;
  773. #ifdef CJUMP_DELAY_SLOTS
  774.   int i;
  775.  
  776.   for (i = 0; i < CJUMP_DELAY_SLOTS; i ++)
  777.     yyparse ();            /* Put delayed instruction first */
  778. #endif
  779.  
  780.   for (t = targets; t!= NULL; t = CDR (t))
  781.     if (CAR (t) > hi) hi = CAR (t);
  782.  
  783.   seen_label = (char *) malloc ((hi + 1) * sizeof (char));
  784.   bzero (seen_label, (hi + 1) * sizeof (char));
  785.  
  786.   issue_instruction ();
  787.   printf_out ("  %s(temp);\n", (read_byte_p ? "GET_BYTE" : "GET_HALF"));
  788.   printf_out ("  switch(temp)\n    {\n");
  789.   for (t = targets; t != NULL; t = CDR (t))
  790.     if (!seen_label [CAR (t)])
  791.       {
  792.     printf_out ("    case %d:", CAR (t));
  793.     annotate_loop_edges (loop_anno, CAR (t), CDR (t) == NULL);
  794.     printf_out (" goto L%d;\n", CAR (t));
  795.     seen_label [CAR (t)] = 1;
  796.       }
  797.   printf_out ("    default: cjump_err();\n  }\n");
  798.  
  799.   free_list (targets);
  800.   end_block_common (bid);
  801.  
  802.   cjump_block_cnt ++;
  803.   free_list (loop_anno);
  804. }
  805.  
  806.  
  807. void
  808. uneventful_inst (num_inst, size_inst)
  809.      int num_inst, size_inst;
  810. {
  811.   int i;
  812.  
  813.   for (i = 0; i < num_inst; i ++)
  814.     issue_instruction ();
  815. }
  816.  
  817.  
  818. void
  819. store_inst (base, offset)
  820.      char *base, *offset;
  821. {
  822.   char buf1 [80], buf2 [80];
  823.  
  824.   issue_instruction ();
  825.   printf_out ("  WRITE_MEM(%s+%s);\n",
  826.           arg_out (base, buf1), arg_out (offset, buf2));
  827.   store_cnt ++;
  828.   free (base);
  829.   free (offset);
  830. }
  831.  
  832.  
  833. void
  834. store_d_inst (base, offset)
  835.      char *base, *offset;
  836. {
  837.   char buf1 [80], buf2 [80];
  838.  
  839.   issue_instruction ();
  840.   printf_out ("  WRITE_MEM(%s+%s);\n",
  841.           arg_out (base, buf1), arg_out (offset, buf2));
  842.   printf_out ("  WRITE_MEM(%s+%d+4);\n",
  843.           arg_out (base, buf1), arg_out (offset, buf2));
  844.   store_cnt ++;
  845.   free (base);
  846.   free (offset);
  847. }
  848.  
  849.  
  850. void
  851. store_symbol_inst (offset, id)
  852.      int offset;
  853.      char *id;
  854. {
  855.   issue_instruction ();
  856.   printf_out ("  WRITE_MEM(0x%x);\n", symbol_address_or_warn (id) + offset);
  857.   free (id);
  858.   store_cnt ++;
  859. }
  860.  
  861.  
  862. void
  863. store_unknown_inst ()
  864. {
  865.   issue_instruction ();
  866.   printf_out ("  GET_WORD(temp);\n");
  867.   printf_out ("  WRITE_MEM(temp);\n");
  868.   store_cnt ++;
  869.   unknown_store_cnt ++;
  870. }
  871.  
  872.  
  873. void
  874. load_inst (base, offset)
  875.      char *base, *offset;
  876. {
  877.   char buf1 [80], buf2[80];
  878.  
  879.   issue_instruction ();
  880.   printf_out ("  READ_MEM(%s+%s);\n",
  881.           arg_out (base, buf1), arg_out(offset, buf2));
  882.   load_cnt ++;
  883.   free (base);
  884.   free (offset);
  885. }
  886.  
  887.  
  888. void
  889. load_d_inst (base, offset)
  890.      char *base, *offset;
  891. {
  892.   char buf1 [80], buf2 [80];
  893.  
  894.   issue_instruction ();
  895.   printf_out ("  READ_MEM(%s+%s);\n",
  896.           arg_out (base, buf1), arg_out (offset, buf2));
  897.   printf_out ("  READ_MEM(%s+%s+4);\n",
  898.           arg_out (base, buf1), arg_out (offset, buf2));
  899.   load_cnt ++;
  900.   free (base);
  901.   free (offset);
  902. }
  903.  
  904.  
  905. void
  906. load_unknown_inst ()
  907. {
  908.   issue_instruction ();
  909.   printf_out ("  GET_WORD(temp);\n");
  910.   printf_out ("  READ_MEM(temp);\n");
  911.   load_cnt ++;
  912.   unknown_load_cnt ++;
  913. }
  914.  
  915.  
  916. void
  917. compute_defn (num_operands, dest_reg, operator, arg1, arg2)
  918.      int num_operands;
  919.      int dest_reg;
  920.      char *operator;
  921.      char *arg1, *arg2;
  922. {
  923.   char buf1 [80], buf2 [80], buf3 [80];
  924.   char *a1, *a2, *a3;
  925.  
  926.   issue_instruction ();
  927.  
  928.   if (num_operands == 0)
  929.     a1 = arg_out (arg1, buf1),
  930.     a2 = a3 = "";
  931.   else if (num_operands == 1)
  932.     a1 = operator,
  933.     a2 = arg_out (arg1, buf1),
  934.     a3 = "";
  935.   else
  936.     a1 = arg_out (arg1, buf1),
  937.     a2 = operator,
  938.     a3 = arg_out (arg2, buf2);
  939.  
  940.   sprintf (buf3, "%s%s%s", a1, a2, a3);
  941.   output_set_value (dest_reg, buf3);
  942.  
  943.   known_def_cnt ++;
  944.  
  945.   if (operator) free (operator);
  946.   free (arg1);
  947.   if (arg2) free (arg2);
  948. }
  949.  
  950.  
  951. void
  952. unknown_defn (reg)
  953.      int reg;
  954. {
  955.   issue_instruction ();
  956.   if (debug)
  957.     printf_out ("  GET_WORD(temp); SVI(R%d,temp);\n", reg);
  958.   else
  959.     printf_out ("  GET_WORD(R%d);\n", reg);
  960.   unknown_def_cnt ++;
  961. }
  962.  
  963.  
  964. void
  965. call_inst (callee)
  966.      char *callee;
  967. {
  968.   char buf [80];
  969. #ifdef CALL_DELAY_SLOTS
  970.   int i;
  971.  
  972.   for (i = 0; i < CALL_DELAY_SLOTS; i ++)
  973.     yyparse ();            /* Put delayed instruction first */
  974. #endif
  975.  
  976.   issue_instruction ();
  977.   printf_out ("  __ae_%s();\n", callee);
  978.   printf_out ("  PC = in_pc+%d+%d;\n", pc_offset, PC_OFFSET_AFTER_CALL);
  979.  
  980.   lookup_symbol (callee)->used_in_call = 1; /* Create entry for callee */
  981.   free (callee);
  982.   call_cnt ++;
  983. }
  984.  
  985.  
  986. void
  987. call_indirect_inst (reg)
  988.      int reg;
  989. {
  990.   char buf [80];
  991. #ifdef CALL_DELAY_SLOTS
  992.   int i;
  993.  
  994.   for (i = 0; i < CALL_DELAY_SLOTS; i++)
  995.     yyparse ();            /* Put delayed instruction first */
  996. #endif
  997.  
  998.   indirect_call_seen = 1;
  999.   issue_instruction ();
  1000.   printf_out ("  (address_to_callee(R%d))();\n", reg);
  1001.   printf_out ("  PC = in_pc+%d+%d;\n", pc_offset, PC_OFFSET_AFTER_CALL);
  1002.   indirect_call_cnt ++;
  1003. }
  1004.  
  1005.  
  1006.  
  1007. static int pending_instructions = 0;
  1008.  
  1009. void
  1010. issue_instruction ()
  1011. {
  1012.   pc_offset += 4;
  1013.   inst_cnt += 1;
  1014.   if (multiple_inst)
  1015.     pending_instructions += 1;
  1016.   else
  1017.     fprintf (out_file, "  ISSUE_INST(%d);\n", 1);
  1018. }
  1019.  
  1020.  
  1021. /*VARARGS0*/
  1022. void
  1023. printf_out (va_alist)
  1024. va_dcl
  1025. {
  1026.   va_list args;
  1027.   char *fmt;
  1028.  
  1029.   if (multiple_inst && pending_instructions > 0)
  1030.     fprintf (out_file, "  ISSUE_INST(%d);\n", pending_instructions);
  1031.   pending_instructions = 0;
  1032.  
  1033.   va_start(args);
  1034.   fmt = va_arg (args, char *);
  1035.   vfprintf (out_file, fmt, args);
  1036. }
  1037.  
  1038.  
  1039. char *
  1040. arg_out (arg, buf)
  1041.      char *arg, *buf;
  1042. {
  1043.   switch (*(arg + 1))
  1044.     {
  1045.     case 'R':
  1046.       if (debug)
  1047.     {
  1048.       *arg = '*';        /* -> *Rn */
  1049.       return arg;
  1050.     }
  1051.       else
  1052.     return arg + 1;
  1053.  
  1054.     case 'S':
  1055.       sprintf (buf, "0x%x", symbol_address_or_warn (arg + 2));
  1056.       return buf;
  1057.  
  1058.     case 'I':
  1059.       return arg + 2;
  1060.  
  1061.     default:
  1062.       fatal_error ("Unknown arg to output: %s\n", arg);
  1063.     }
  1064. }
  1065.  
  1066.  
  1067. void
  1068. output_set_value (dest_reg, value)
  1069.      int dest_reg;
  1070.      char *value;
  1071. {
  1072.   if (debug)
  1073.     printf_out ("  SVI(R%d, %s);\n", dest_reg, value);
  1074.   else
  1075.     printf_out ("  R%d = %s;\n", dest_reg, value);
  1076. }
  1077.  
  1078.  
  1079. /* Loop through the list of loop annotations to find those applying to
  1080.    the edge that goes to block BID.  If this is the LAST_TIME, then free
  1081.    the list of annotations. */
  1082.  
  1083. void
  1084. annotate_loop_edges (loop_anno, bid, last_time)
  1085.      register list loop_anno;
  1086.      int bid;
  1087.      int last_time;
  1088. {
  1089.   register list tmp = loop_anno;
  1090.   register char *start_seen, *cont_seen, *end_seen;
  1091.  
  1092.   while (tmp != NULL)
  1093.     {
  1094.       list entry = (list) CAR (tmp);
  1095.       int code = (int) CAR (entry);
  1096.       int target_bid = (int) CAR (CDR (entry));
  1097.       int loop_no = (int) CDR (CDR (entry));
  1098.  
  1099.       if (loop_no + 1 > loops_in_function)
  1100.     loops_in_function = loop_no + 1;
  1101.       tmp = CDR (tmp);
  1102.     }
  1103.  
  1104.   /* Watch out for duplicate annotations */
  1105.   start_seen = malloc (loops_in_function * sizeof (char));
  1106.   bzero (start_seen, loops_in_function * sizeof (char));
  1107.   cont_seen = malloc (loops_in_function * sizeof (char));
  1108.   bzero (cont_seen, loops_in_function * sizeof (char));
  1109.   end_seen = malloc (loops_in_function * sizeof (char));
  1110.   bzero (end_seen, loops_in_function * sizeof (char));
  1111.  
  1112.   while (loop_anno != NULL)
  1113.     {
  1114.       list entry = (list) CAR (loop_anno);
  1115.       int code = (int) CAR (entry);
  1116.       int target_bid = (int) CAR (CDR (entry));
  1117.       int loop_no = (int) CDR (CDR (entry));
  1118.       int real_loop_no = loop_cnt + loop_no;
  1119.  
  1120.       if (target_bid == bid)
  1121.     {
  1122.       switch (code)
  1123.         {
  1124.         case START_LOOP:
  1125.           if (!start_seen [loop_no])
  1126.         printf_out ("  LOOP_START(%d);", real_loop_no);
  1127.           start_seen [loop_no] = 1;
  1128.           break;
  1129.  
  1130.         case CONT_LOOP:
  1131.           if (!cont_seen [loop_no])
  1132.         printf_out ("  LOOP_CONT(%d);", real_loop_no);
  1133.           cont_seen [loop_no] = 1;
  1134.           break;
  1135.  
  1136.         case END_LOOP:
  1137.           if (!end_seen [loop_no])
  1138.         printf_out ("  LOOP_END(%d);", real_loop_no);
  1139.           end_seen [loop_no] = 1;
  1140.           break;
  1141.         };
  1142.     }
  1143.       if (last_time)
  1144.     {
  1145.       free (CDR (entry));
  1146.       free (entry);
  1147.     }
  1148.       loop_anno = CDR (loop_anno);
  1149.     }
  1150.  
  1151.   if (start_seen != NULL)    /* NULL if loops_in_function == 0 */
  1152.     {
  1153.       free (start_seen);
  1154.       free (cont_seen);
  1155.       free (end_seen);
  1156.     }
  1157. }
  1158.  
  1159.  
  1160.  
  1161. #define HASHBITS 30
  1162.  
  1163. /* Return a SYMBOL whose name is TEXT (a null-terminated string).  If
  1164.    an identifier with that name has previously been looked-up, the same
  1165.    node is returned this time.  */
  1166.  
  1167.  
  1168. struct symbol *
  1169. lookup_symbol (text)
  1170.      register char *text;
  1171. {
  1172.   register int hi;
  1173.   register int i;
  1174.   register struct symbol *idp;
  1175.   register int len;
  1176.  
  1177.   /* Compute length of text in len.  */
  1178.   for (len = 0; text[len]; len++);
  1179.  
  1180.   /* Compute hash code */
  1181.   hi = len;
  1182.   for (i = 0; i < len; i++)
  1183.     hi = ((hi * 613) + (unsigned)(text[i]));
  1184.  
  1185.   hi &= (1 << HASHBITS) - 1;
  1186.   hi %= GLOBAL_HASH_TBL_SIZE;
  1187.  
  1188.   /* Search table for identifier */
  1189.   for (idp = global_hash_tbl [hi]; idp; idp = idp->next)
  1190.     if (streq (idp->name, text))
  1191.       return idp;        /* <-- return if found */
  1192.  
  1193.   /* Not found, create one, add to chain */
  1194.   idp = (struct symbol *) malloc (sizeof (struct symbol));
  1195.   idp->name = (char *) strcpy (malloc (strlen (text) + 1), text);
  1196.   idp->used_in_call = 0;
  1197.   idp->schema_seen_p = 0;
  1198.   idp->address = 0;
  1199.   idp->addr_missing_warning = 0;
  1200.  
  1201.   idp->next = global_hash_tbl [hi];
  1202.   global_hash_tbl [hi] = idp;
  1203.   return idp;            /* <-- return if created */
  1204. }
  1205.