home *** CD-ROM | disk | FTP | other *** search
- /* AEC, the AE Compiler.
- Copyright (C) 1989, 1990 by James R. Larus (larus@cs.wisc.edu)
-
- AE and AEC are 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 1, or (at your option) any
- later version.
-
- AE and AEC are 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 GNU CC; see the file COPYING. If not, write to James R.
- Larus, Computer Sciences Department, University of Wisconsin--Madison,
- 1210 West Dayton Street, Madison, WI 53706, USA or to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
- /* $Header: /var/home/larus/AE/AEC/RCS/aec.c,v 2.0 90/02/09 17:23:41 larus Exp Locker: larus $ */
-
-
- /* Syntax is:
- aec -x a.out -o aec.out {-q, -d} f1.sma ... fn.sma
-
- -x a.out (Mandatory) Executable: Name of the executable file a.out.
- -o aec.out (Mandatory) Output: Name of the output file.
- -q (Optional) Quiet: do not write information.
- -d (Optional) Debug: produce safer, but slower code.
- -m (Optional) Multiple inst.: treat consecutive inst.
- together
- */
-
-
- #include <stdio.h>
- #include <strings.h>
- #include <varargs.h>
- #include "config.h"
- #include "rtl.h"
- #include "ae.h"
- #include "ae-machine.h"
- #include "aec.h"
-
- #ifdef ECOFF_AOUT
- #include <filehdr.h>
- #include <syms.h>
- #include <ldfcn.h>
- #endif
- #ifdef BSD_AOUT
- #include <nlist.h>
- #endif
-
-
- #define streq(s1,s2) !strcmp((s1),(s2))
-
-
- struct symbol
- {
- struct symbol *next; /* Next structure in the bucket. */
- char *name; /* Name. */
- int used_in_call; /* Non-zero if symbol referenced in call */
- int schema_seen_p; /* Non-zero if schema processed. */
- unsigned long address; /* Address in core. */
- int addr_missing_warning; /* Non-zero if complained about unknown addr */
- };
-
- /* From rtl.c: */
- #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) \
- (SIZE*UNITS_PER_WORD+3)/4,
-
- int mode_size[] = {
- #include "machmode.def"
- };
-
-
- void add_hash ();
- void annotate_loop_edges ();
- char *arg_out ();
- void block_end ();
- void block_end_cjump ();
- void block_end_jump ();
- void block_start ();
- void block_start_target ();
- void call_indirect_inst ();
- void call_inst ();
- void copy_file_to_out_file ();
- void end_block_common ();
- void fatal_error ();
- void free_list ();
- void function_end ();
- void function_start ();
- void indirect_call_code ();
- void initialize_scanner ();
- void issue_instruction ();
- struct symbol *lookup_symbol ();
- void make_dummy_function ();
- void non_fatal_error ();
- void output_preface ();
- void output_reg_decl ();
- void output_set_value ();
- int nlist_addr_cmp ();
- void printf_out ();
- void report_statistics ();
- void schema_for_absent_functions ();
- char *string_cat ();
- void switch_error ();
- unsigned long symbol_address ();
- unsigned long symbol_address_or_die ();
- unsigned long symbol_address_or_warn ();
- void uneventful_inst ();
- void yyerror ();
- int yyparse ();
-
-
- void bzero ();
- void exit ();
- void free ();
- void fprintf ();
- void fclose ();
- int fread ();
- void fwrite ();
- char *malloc ();
-
-
- char *input_file_name; /* Input file name */
- static char *executable_file_name = NULL; /* Executable file name */
-
- static FILE *out_file = NULL; /* */
-
-
- #ifdef ECOFF_AOUT
- LDFILE *ex_file;
- #endif
-
- static int indirect_call_seen = 0; /* */
-
-
- #define GLOBAL_HASH_TBL_SIZE 8191
-
- static struct symbol *global_hash_tbl [GLOBAL_HASH_TBL_SIZE];
-
-
- /* Counters to collect statistics: */
-
- static int quiet = 0; /* Zero => statistics printed */
- static int debug = 0; /* Non-zero => safer and slower code */
- static int multiple_inst = 0; /* Non-zero => multiple insts together */
-
- static int function_cnt = 0; /* Number of functions */
- static int dummy_function_cnt = 0; /* Number of dummy functions */
- static int block_cnt = 0; /* Number of basic blocks */
- static int target_block_cnt = 0; /* Number of blocks that are targets */
- static int fall_block_cnt = 0; /* Number of blocks that fall thru */
- static int cjump_block_cnt = 0; /* Number of blocks that end with cjump */
- static int jump_block_cnt = 0; /* Number of blocks that end with jump */
- static int loop_cnt = 0; /* Number of loops */
- static int inst_cnt = 0; /* Number of instructions */
- static int store_cnt = 0; /* Number of stores */
- static int unknown_store_cnt = 0; /* Number of stores where data is read */
- static int load_cnt = 0; /* Number of loads */
- static int unknown_load_cnt = 0; /* Number of loads where data is read */
- static int known_def_cnt = 0; /* Number of def w/ known operands */
- static int unknown_def_cnt = 0; /* Number of def w/ known operands */
- static int call_cnt = 0; /* Number of function calls */
- static int indirect_call_cnt = 0; /* Number of indirect function calls */
-
- static int loops_in_function = 0; /* Number of loops in current function */
-
- extern int line_no;
-
-
-
- void
- main (argc, argv)
- int argc;
- char *argv[];
- {
- register int i;
- char *out_file_name = NULL;
- FILE *in_file;
-
- if (argc == 1)
- switch_error ("");
-
- for (i = 1; i < argc; i++)
- {
- if (*argv [i] == '-')
- {
- if (streq (argv [i], "-o"))
- {
- out_file_name = argv [i + 1];
- i ++;
- }
- else if (streq (argv [i], "-x"))
- {
- executable_file_name = argv [i + 1];
- i ++;
- }
- else if (streq (argv [i], "-q"))
- quiet = 1;
- else if (streq (argv [i], "-d"))
- debug = 1;
- else if (streq (argv [i], "-m"))
- multiple_inst = 1;
- else
- switch_error ("aec: Unknown switch %s\n", argv [i]);
- }
- else
- {
- if (out_file_name == NULL)
- switch_error ("aec: No output file specified\n");
- else if (executable_file_name == NULL)
- switch_error ("aec: No executable specified\n");
- else if (out_file == NULL)
- {
- out_file = fopen (out_file_name, "w");
- #ifdef ECOFF_AOUT
- ex_file = ldopen (executable_file_name, NULL);
- #endif
- output_preface ();
- }
-
- input_file_name = argv [i];
- in_file = fopen (input_file_name, "r");
- if (in_file == NULL)
- fatal_error ("Input file %s cannot be opened\n", input_file_name);
- initialize_scanner (in_file);
- while (yyparse () == 1) ;
- }
- }
-
- schema_for_absent_functions ();
- indirect_call_code ();
- fprintf (out_file, "int max_loops = %d;\n", loop_cnt);
- copy_file_to_out_file (string_cat (LIBRARY_PATH, "aec-file-epilogue"));
- fclose (out_file);
- #ifdef ECOFF_AOUT
- ldclose (ex_file);
- #endif
- if (!quiet)
- report_statistics ();
- exit (0);
- }
-
-
- void
- switch_error (message, x)
- char *message;
- int x;
- {
- fprintf (stderr, message, x);
- fprintf (stderr, "aec -x a.out -o aec.out {-q, -d} f1.sma ... fn.sma\n");
- fprintf (stderr, "-x a.out (Mandatory) Executable: name of executable a.out\n");
- fprintf (stderr, "-o aec.out (Mandatory) Output: name of the output file\n");
- fprintf (stderr, "-q (Optional) Quiet: do not write information\n");
- fprintf (stderr, "-d (Optional) Debug: produce safer, but slower code\n");
- fprintf (stderr, "-m (Optional) Multiple inst: treat consecutive inst\n");
- exit (-1);
- }
-
-
- void
- non_fatal_error (message, x)
- char *message;
- int x;
- {
- fprintf (stderr, "aec: In file %s, line %d: ", input_file_name, line_no);
- fprintf (stderr, message, x);
- }
-
-
- void
- fatal_error (message, x)
- char *message;
- int x;
- {
- fprintf (stderr, "aec: In file %s, line %d: ", input_file_name, line_no);
- fprintf (stderr, message, x);
- exit (-1);
- }
-
-
- #define PER(x,y) ((x * 100) / y)
-
- void
- report_statistics ()
- {
- fprintf (stderr, "\n\n%d functions w/ schemas %d functions w/o schemas\n",
- function_cnt, dummy_function_cnt);
-
- fprintf (stderr, "\n%d basic blocks:\n", block_cnt);
- fprintf (stderr, " %6d (%d %%) targets\n", target_block_cnt,
- PER (target_block_cnt, block_cnt));
- fprintf (stderr, " %6d (%d %%) fall thru\n", fall_block_cnt,
- PER (fall_block_cnt, block_cnt));
- fprintf (stderr, " %6d (%d %%) end w/ cjump\n", cjump_block_cnt,
- PER (cjump_block_cnt, block_cnt));
- fprintf (stderr, " %6d (%d %%) end w/ jump\n", jump_block_cnt,
- PER (jump_block_cnt, block_cnt));
-
- fprintf (stderr, "\n%d loops\n", loop_cnt);
-
- fprintf (stderr, "\n%d instructions:\n", inst_cnt);
-
- fprintf (stderr, " %6d (%d %%) stores\n", store_cnt,
- PER (store_cnt, inst_cnt));
- if (store_cnt > 0)
- fprintf (stderr, " %6d (%d %%) unknown stores\n", unknown_store_cnt,
- PER (unknown_store_cnt, store_cnt));
-
- fprintf (stderr, " %6d (%d %%) loads\n", load_cnt,
- PER (load_cnt, inst_cnt));
- if (load_cnt > 0)
- fprintf (stderr, " %6d (%d %%) unknown loads\n", unknown_load_cnt,
- PER (unknown_load_cnt, load_cnt));
-
- fprintf (stderr, " %6d (%d %%) known defs\n", known_def_cnt,
- PER (known_def_cnt, inst_cnt));
- fprintf (stderr, " %6d (%d %%) unknown defs\n", unknown_def_cnt,
- PER (unknown_def_cnt, inst_cnt));
-
- fprintf (stderr, " %6d (%d %%) calls\n", call_cnt,
- PER (call_cnt, inst_cnt));
- if (call_cnt > 0)
- fprintf (stderr, " %6d (%d %%) indirect calls\n", indirect_call_cnt,
- PER (indirect_call_cnt, call_cnt));
- }
-
-
-
-
- /* List data structure routines. */
-
- list
- cons (head, tail)
- int head;
- list tail;
- {
- list x = (list) malloc (sizeof (list_cell));
- CAR (x) = head;
- CDR (x) = tail;
- return (x);
- }
-
-
- void
- free_list (lst)
- list lst;
- {
- while (lst != NULL)
- {
- list next = CDR (lst);
- free (lst);
- lst = next;
- }
- }
-
-
-
- static int call_used_regs [] = CALL_USED_REGISTERS;
-
-
- void
- output_preface ()
- {
- int i;
-
- copy_file_to_out_file (string_cat (LIBRARY_PATH, "aec-file-prologue"));
- copy_file_to_out_file (string_cat (LIBRARY_PATH, "aec.h"));
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
- if (!REG_LOCAL_TO_FUNCTION (i))
- if (HARD_REGNO_MODE_OK (i, SImode))
- output_reg_decl ("static", "int", i);
- else if (HARD_REGNO_MODE_OK (i, SFmode))
- output_reg_decl ("static", "float", i);
- else if (HARD_REGNO_MODE_OK (i, DFmode))
- output_reg_decl ("static", "double", i);
-
- #ifdef PC_REGNUM
- printf_out ("#define PC R%d\n\n", PC_REGNUM);
- #else
- printf_out ("static int PC;\n\n");
- #endif
-
- printf_out ("static void __aec_global_reg_init ()\n{\n");
- INITIALIZE_REGISTERS ();
- printf_out ("}\n\n");
- }
-
-
- void
- output_reg_decl (preface, type, regno)
- char *preface, *type;
- int regno;
- {
- if (debug)
- printf_out ("%s %s *R%d = (%s *) -1;\n", preface, type, regno,
- type);
- else
- printf_out ("%s %s R%d;\n", preface, type, regno);
- }
-
-
- void
- schema_for_absent_functions ()
- {
- register int i, error_head_output_p = 0;
- struct symbol *idp;
-
- for (i = 0; i < GLOBAL_HASH_TBL_SIZE; i++)
- for (idp = global_hash_tbl [i]; idp; idp = idp-> next)
- if (idp->used_in_call && !idp->schema_seen_p)
- {
- if (!error_head_output_p)
- {
- fprintf (stdout, "aec: These functions are called but have no schemas.\n");
- fprintf (stdout, "They must not produce events.\n");
- }
- error_head_output_p = 1;
- fprintf (stdout, " %s\n", idp->name);
- make_dummy_function (idp->name);
- idp->schema_seen_p = 1;
- dummy_function_cnt ++;
- }
- }
-
-
- void
- indirect_call_code ()
- {
- printf_out ("static unsigned long func_tbl[] = {\n");
- if (indirect_call_seen)
- {
- #ifdef ECOFF_AOUT
- int i;
- PDR ppd;
- unsigned long addr;
- char *name;
- SYMR sym;
-
- for (i = 0; i < SYMHEADER (ex_file).ipdMax - 1; i++)
- if (ldgetpd (ex_file, i, &ppd) != 0)
- {
- struct symbol *idp;
-
- addr = ppd.adr;
- ldtbread (ex_file, ppd.isym, &sym);
- name = (char *) ldgetname (ex_file, &sym);
- idp = lookup_symbol (name);
- if (idp->schema_seen_p)
- /* Program could invoke any function, but we can only follow
- execution through those for which we have a schema. */
- printf_out ("0x%x, (unsigned long) __ae_%s,\n", addr, name);
- }
- #endif
- #ifdef BSD_AOUT
- register int i;
- register struct symbol *idp;
- register int count = 0;
- struct nlist *names;
-
- for (i = 0; i < GLOBAL_HASH_TBL_SIZE; i ++)
- for (idp = global_hash_tbl [i]; idp != NULL; idp = idp->next)
- if (idp->schema_seen_p)
- /* Program could invoke any function, but we can only follow
- execution through those for which we have a schema. */
- count += 1;
-
- names = (struct nlist *) malloc ((count + 1) * sizeof (struct nlist));
- names [count].n_name = NULL;
- count = 0;
- for (i = 0; i < GLOBAL_HASH_TBL_SIZE; i ++)
- for (idp = global_hash_tbl [i]; idp != NULL; idp = idp->next)
- if (idp->schema_seen_p)
- names [count ++].n_name = idp->name;
-
- nlist (executable_file_name, names);
- /* Sort names by address so can do binary search */
- qsort (names, count, sizeof (struct nlist), nlist_addr_cmp);
- for (i = 0; i < count; i++)
- if (names[i].n_type != 0)
- printf_out ("0x%x, (unsigned long) __ae_%s,\n",
- names [i].n_value, names [i].n_name);
- #endif
- }
- printf_out ("0};\n\n");
- }
-
-
- #ifndef mips
- nlist_addr_cmp (n1, n2)
- struct nlist *n1, *n2;
- {return (n1->n_value - n2->n_value);}
- #endif
-
-
- void
- copy_file_to_out_file (path)
- char *path;
- {
- int n;
- FILE *pfd = fopen (path, "r", 0);
- char buffer[4096];
-
- if (pfd == NULL)
- fatal_error ("Cannot open file: %s\n", path);
- while ((n = fread (buffer, sizeof (char), 4096, pfd)) > 0)
- fwrite (buffer, sizeof (char), n, out_file);
- fclose (pfd);
- }
-
-
- char *
- string_cat (s1, s2)
- char *s1, *s2;
- {
- int l = strlen (s1) + strlen (s2);
- char *r = (char *) malloc (l + 1);
-
- strcpy (r, s1);
- return strcat (r, s2);
- }
-
-
- /* Return the address of global identifier from the core file or 0 if
- the identifier is not defined. */
-
- unsigned long
- symbol_address (name)
- char *name;
- {
- struct symbol *idp = lookup_symbol (name);
-
- if (idp->address) /* Cache address since lookup is expensive */
- return idp->address;
-
- #ifdef ECOFF_AOUT
- {
- register int i;
- SYMR sym;
-
- for (i = 0; i <= SYMHEADER (ex_file).isymMax + SYMHEADER (ex_file).iextMax;
- i++)
- if (ldtbread (ex_file, i, &sym))
- if (streq (name, ldgetname (ex_file, &sym)))
- return (idp->address = sym.value);
- }
- #endif
- #ifdef BSD_AOUT
- {
- struct nlist names [2];
-
- names [0].n_name = name;
- names [1].n_name = NULL;
- if (nlist (executable_file_name, names) == -1)
- fatal_error ("Error reading symbol table for %s\n", name);
- return (idp->address = names [0].n_value);
- }
- #endif
- }
-
-
- /* Find and return a symbol's address or die horribly. */
-
- unsigned long
- symbol_address_or_die (name)
- char *name;
- {
- unsigned long addr = symbol_address (name);
-
- if (addr == 0)
- fatal_error ("Cannot find address of `%s' in %s\n", name,
- executable_file_name);
-
- return addr;
- }
-
-
- /* Complain about a symbol not having an address and return 0. */
-
- unsigned long
- symbol_address_or_warn (name)
- char *name;
- {
- unsigned long addr = symbol_address (name);
-
- if (addr == 0)
- {
- struct symbol *idp = lookup_symbol (name);
- if (!idp->addr_missing_warning && !quiet)
- fprintf (stderr, "aec: Cannot find address of '%s' in %s\n", name,
- executable_file_name);
- idp->addr_missing_warning = 1;
- }
-
- return addr;
- }
-
-
-
- static char* open_function_name = NULL;
-
-
- static int pc_offset = 0;
-
-
- /* Non-zero if block numbers are encode in a byte, not a half-word. */
-
- static int read_byte_p = 0;
-
-
- void
- function_start (name, num_blocks)
- char *name;
- int num_blocks;
- {
- int i;
- unsigned long addr;
-
- if (open_function_name != NULL)
- non_fatal_error ("function %s is not terminated.\n", open_function_name);
-
- printf_out ("static int __ae_%s()\n{\n", name);
-
- printf_out (" int in_pc;\n");
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
- if (REG_LOCAL_TO_FUNCTION(i))
- if (HARD_REGNO_MODE_OK (i, SImode))
- output_reg_decl (" register", "int", i);
- else if (HARD_REGNO_MODE_OK (i, SFmode))
- output_reg_decl (" register", "float", i);
- else if (HARD_REGNO_MODE_OK (i, DFmode))
- output_reg_decl (" register", "double", i);
-
- printf_out ("\n");
-
- addr = symbol_address_or_warn (name);
- if (addr != 0)
- printf_out (" PC=0x%x;\n", addr);
- printf_out (" in_pc = PC;\n");
-
- open_function_name = name;
- pc_offset = 0;
- read_byte_p = (num_blocks < 256);
- lookup_symbol (name)->schema_seen_p = 1;
- function_cnt ++;
- loops_in_function = 0;
- }
-
-
- void
- make_dummy_function (name)
- char *name;
- {
- /* exit and _exit have predefined functions because they do not obey
- the usual call/return convention. */
- if (!streq (name, "exit") && !streq (name, "_exit"))
- printf_out ("static int __ae_%s(){}\n\n", name);
- }
-
-
- void
- function_end (name)
- char *name;
- {
- register int i;
-
- if (debug)
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
- if (REG_LOCAL_TO_FUNCTION (i))
- if (HARD_REGNO_MODE_OK (i, SImode))
- printf_out (" if (R%d != (int *) -1) free(R%d);\n", i, i);
- else if (HARD_REGNO_MODE_OK (i, SFmode))
- printf_out (" if (R%d != (float *) -1) free(R%d);\n", i, i);
- else if (HARD_REGNO_MODE_OK (i, DFmode))
- printf_out (" if (R%d != (double *) -1) free(R%d);\n", i, i);
-
- printf_out ("}\n\n");
- if (open_function_name == NULL || !streq (name, open_function_name))
- yyerror ("Function name mismatch");
- free (open_function_name);
- open_function_name = NULL;
- free (name);
- loop_cnt += loops_in_function;
- }
-
-
- static int open_bid = -1;
-
-
- void
- block_start (bid)
- int bid;
- {
- if (open_bid != -1)
- non_fatal_error ("block %d is not terminated.\n", open_bid);
- printf_out ("/* Start of block %d */\n", bid);
- printf_out (" L%d:\n", bid);
- printf_out (" PC = in_pc+%d;\n", pc_offset);
- open_bid = bid;
- block_cnt ++;
- }
-
-
- void
- block_start_target (bid)
- int bid;
- {
- block_start (bid);
- target_block_cnt ++;
- }
-
-
- void
- end_block_common (bid)
- int bid;
- {
- if (bid != open_bid)
- yyerror ("Block id's mismatched");
- open_bid = -1;
- printf_out ("/* End of block %d */\n", bid);
- }
-
-
- void
- block_end (bid, fall_thru_p, loop_anno)
- int bid, fall_thru_p;
- list loop_anno;
- {
- if (fall_thru_p) /* Falling into target of conditional. */
- printf_out (" %s();\n", (read_byte_p ? "EAT_BYTE" : "EAT_HALF"));
- annotate_loop_edges (loop_anno, bid + 1, 1);
- end_block_common (bid);
- fall_block_cnt ++;
- free_list (loop_anno);
- }
-
-
- void
- block_end_jump (bid, target_bid, jump_to_cjump_target_p, loop_anno)
- int bid, target_bid, jump_to_cjump_target_p;
- list loop_anno;
- {
- #ifdef JUMP_DELAY_SLOTS
- int i;
-
- for (i = 0; i < JUMP_DELAY_SLOTS; i ++)
- yyparse (); /* Put delayed instruction first */
- #endif
-
- issue_instruction ();
- if (jump_to_cjump_target_p) /* Jump to target of conditional. */
- printf_out (" %s();\n", (read_byte_p ? "EAT_BYTE" : "EAT_HALF"));
- annotate_loop_edges (loop_anno, target_bid, 1);
- printf_out (" goto L%d;\n", target_bid);
- end_block_common (bid);
- jump_block_cnt ++;
- free_list (loop_anno);
- }
-
-
- void
- block_end_cjump (bid, targets, loop_anno)
- int bid;
- list targets;
- list loop_anno;
- {
- list t = targets;
- int hi = 0;
- char *seen_label;
- #ifdef CJUMP_DELAY_SLOTS
- int i;
-
- for (i = 0; i < CJUMP_DELAY_SLOTS; i ++)
- yyparse (); /* Put delayed instruction first */
- #endif
-
- for (t = targets; t!= NULL; t = CDR (t))
- if (CAR (t) > hi) hi = CAR (t);
-
- seen_label = (char *) malloc ((hi + 1) * sizeof (char));
- bzero (seen_label, (hi + 1) * sizeof (char));
-
- issue_instruction ();
- printf_out (" %s(temp);\n", (read_byte_p ? "GET_BYTE" : "GET_HALF"));
- printf_out (" switch(temp)\n {\n");
- for (t = targets; t != NULL; t = CDR (t))
- if (!seen_label [CAR (t)])
- {
- printf_out (" case %d:", CAR (t));
- annotate_loop_edges (loop_anno, CAR (t), CDR (t) == NULL);
- printf_out (" goto L%d;\n", CAR (t));
- seen_label [CAR (t)] = 1;
- }
- printf_out (" default: cjump_err();\n }\n");
-
- free_list (targets);
- end_block_common (bid);
-
- cjump_block_cnt ++;
- free_list (loop_anno);
- }
-
-
- void
- uneventful_inst (num_inst, size_inst)
- int num_inst, size_inst;
- {
- int i;
-
- for (i = 0; i < num_inst; i ++)
- issue_instruction ();
- }
-
-
- void
- store_inst (base, offset)
- char *base, *offset;
- {
- char buf1 [80], buf2 [80];
-
- issue_instruction ();
- printf_out (" WRITE_MEM(%s+%s);\n",
- arg_out (base, buf1), arg_out (offset, buf2));
- store_cnt ++;
- free (base);
- free (offset);
- }
-
-
- void
- store_d_inst (base, offset)
- char *base, *offset;
- {
- char buf1 [80], buf2 [80];
-
- issue_instruction ();
- printf_out (" WRITE_MEM(%s+%s);\n",
- arg_out (base, buf1), arg_out (offset, buf2));
- printf_out (" WRITE_MEM(%s+%d+4);\n",
- arg_out (base, buf1), arg_out (offset, buf2));
- store_cnt ++;
- free (base);
- free (offset);
- }
-
-
- void
- store_symbol_inst (offset, id)
- int offset;
- char *id;
- {
- issue_instruction ();
- printf_out (" WRITE_MEM(0x%x);\n", symbol_address_or_warn (id) + offset);
- free (id);
- store_cnt ++;
- }
-
-
- void
- store_unknown_inst ()
- {
- issue_instruction ();
- printf_out (" GET_WORD(temp);\n");
- printf_out (" WRITE_MEM(temp);\n");
- store_cnt ++;
- unknown_store_cnt ++;
- }
-
-
- void
- load_inst (base, offset)
- char *base, *offset;
- {
- char buf1 [80], buf2[80];
-
- issue_instruction ();
- printf_out (" READ_MEM(%s+%s);\n",
- arg_out (base, buf1), arg_out(offset, buf2));
- load_cnt ++;
- free (base);
- free (offset);
- }
-
-
- void
- load_d_inst (base, offset)
- char *base, *offset;
- {
- char buf1 [80], buf2 [80];
-
- issue_instruction ();
- printf_out (" READ_MEM(%s+%s);\n",
- arg_out (base, buf1), arg_out (offset, buf2));
- printf_out (" READ_MEM(%s+%s+4);\n",
- arg_out (base, buf1), arg_out (offset, buf2));
- load_cnt ++;
- free (base);
- free (offset);
- }
-
-
- void
- load_unknown_inst ()
- {
- issue_instruction ();
- printf_out (" GET_WORD(temp);\n");
- printf_out (" READ_MEM(temp);\n");
- load_cnt ++;
- unknown_load_cnt ++;
- }
-
-
- void
- compute_defn (num_operands, dest_reg, operator, arg1, arg2)
- int num_operands;
- int dest_reg;
- char *operator;
- char *arg1, *arg2;
- {
- char buf1 [80], buf2 [80], buf3 [80];
- char *a1, *a2, *a3;
-
- issue_instruction ();
-
- if (num_operands == 0)
- a1 = arg_out (arg1, buf1),
- a2 = a3 = "";
- else if (num_operands == 1)
- a1 = operator,
- a2 = arg_out (arg1, buf1),
- a3 = "";
- else
- a1 = arg_out (arg1, buf1),
- a2 = operator,
- a3 = arg_out (arg2, buf2);
-
- sprintf (buf3, "%s%s%s", a1, a2, a3);
- output_set_value (dest_reg, buf3);
-
- known_def_cnt ++;
-
- if (operator) free (operator);
- free (arg1);
- if (arg2) free (arg2);
- }
-
-
- void
- unknown_defn (reg)
- int reg;
- {
- issue_instruction ();
- if (debug)
- printf_out (" GET_WORD(temp); SVI(R%d,temp);\n", reg);
- else
- printf_out (" GET_WORD(R%d);\n", reg);
- unknown_def_cnt ++;
- }
-
-
- void
- call_inst (callee)
- char *callee;
- {
- char buf [80];
- #ifdef CALL_DELAY_SLOTS
- int i;
-
- for (i = 0; i < CALL_DELAY_SLOTS; i ++)
- yyparse (); /* Put delayed instruction first */
- #endif
-
- issue_instruction ();
- printf_out (" __ae_%s();\n", callee);
- printf_out (" PC = in_pc+%d+%d;\n", pc_offset, PC_OFFSET_AFTER_CALL);
-
- lookup_symbol (callee)->used_in_call = 1; /* Create entry for callee */
- free (callee);
- call_cnt ++;
- }
-
-
- void
- call_indirect_inst (reg)
- int reg;
- {
- char buf [80];
- #ifdef CALL_DELAY_SLOTS
- int i;
-
- for (i = 0; i < CALL_DELAY_SLOTS; i++)
- yyparse (); /* Put delayed instruction first */
- #endif
-
- indirect_call_seen = 1;
- issue_instruction ();
- printf_out (" (address_to_callee(R%d))();\n", reg);
- printf_out (" PC = in_pc+%d+%d;\n", pc_offset, PC_OFFSET_AFTER_CALL);
- indirect_call_cnt ++;
- }
-
-
-
- static int pending_instructions = 0;
-
- void
- issue_instruction ()
- {
- pc_offset += 4;
- inst_cnt += 1;
- if (multiple_inst)
- pending_instructions += 1;
- else
- fprintf (out_file, " ISSUE_INST(%d);\n", 1);
- }
-
-
- /*VARARGS0*/
- void
- printf_out (va_alist)
- va_dcl
- {
- va_list args;
- char *fmt;
-
- if (multiple_inst && pending_instructions > 0)
- fprintf (out_file, " ISSUE_INST(%d);\n", pending_instructions);
- pending_instructions = 0;
-
- va_start(args);
- fmt = va_arg (args, char *);
- vfprintf (out_file, fmt, args);
- }
-
-
- char *
- arg_out (arg, buf)
- char *arg, *buf;
- {
- switch (*(arg + 1))
- {
- case 'R':
- if (debug)
- {
- *arg = '*'; /* -> *Rn */
- return arg;
- }
- else
- return arg + 1;
-
- case 'S':
- sprintf (buf, "0x%x", symbol_address_or_warn (arg + 2));
- return buf;
-
- case 'I':
- return arg + 2;
-
- default:
- fatal_error ("Unknown arg to output: %s\n", arg);
- }
- }
-
-
- void
- output_set_value (dest_reg, value)
- int dest_reg;
- char *value;
- {
- if (debug)
- printf_out (" SVI(R%d, %s);\n", dest_reg, value);
- else
- printf_out (" R%d = %s;\n", dest_reg, value);
- }
-
-
- /* Loop through the list of loop annotations to find those applying to
- the edge that goes to block BID. If this is the LAST_TIME, then free
- the list of annotations. */
-
- void
- annotate_loop_edges (loop_anno, bid, last_time)
- register list loop_anno;
- int bid;
- int last_time;
- {
- register list tmp = loop_anno;
- register char *start_seen, *cont_seen, *end_seen;
-
- while (tmp != NULL)
- {
- list entry = (list) CAR (tmp);
- int code = (int) CAR (entry);
- int target_bid = (int) CAR (CDR (entry));
- int loop_no = (int) CDR (CDR (entry));
-
- if (loop_no + 1 > loops_in_function)
- loops_in_function = loop_no + 1;
- tmp = CDR (tmp);
- }
-
- /* Watch out for duplicate annotations */
- start_seen = malloc (loops_in_function * sizeof (char));
- bzero (start_seen, loops_in_function * sizeof (char));
- cont_seen = malloc (loops_in_function * sizeof (char));
- bzero (cont_seen, loops_in_function * sizeof (char));
- end_seen = malloc (loops_in_function * sizeof (char));
- bzero (end_seen, loops_in_function * sizeof (char));
-
- while (loop_anno != NULL)
- {
- list entry = (list) CAR (loop_anno);
- int code = (int) CAR (entry);
- int target_bid = (int) CAR (CDR (entry));
- int loop_no = (int) CDR (CDR (entry));
- int real_loop_no = loop_cnt + loop_no;
-
- if (target_bid == bid)
- {
- switch (code)
- {
- case START_LOOP:
- if (!start_seen [loop_no])
- printf_out (" LOOP_START(%d);", real_loop_no);
- start_seen [loop_no] = 1;
- break;
-
- case CONT_LOOP:
- if (!cont_seen [loop_no])
- printf_out (" LOOP_CONT(%d);", real_loop_no);
- cont_seen [loop_no] = 1;
- break;
-
- case END_LOOP:
- if (!end_seen [loop_no])
- printf_out (" LOOP_END(%d);", real_loop_no);
- end_seen [loop_no] = 1;
- break;
- };
- }
- if (last_time)
- {
- free (CDR (entry));
- free (entry);
- }
- loop_anno = CDR (loop_anno);
- }
-
- if (start_seen != NULL) /* NULL if loops_in_function == 0 */
- {
- free (start_seen);
- free (cont_seen);
- free (end_seen);
- }
- }
-
-
-
- #define HASHBITS 30
-
- /* Return a SYMBOL whose name is TEXT (a null-terminated string). If
- an identifier with that name has previously been looked-up, the same
- node is returned this time. */
-
-
- struct symbol *
- lookup_symbol (text)
- register char *text;
- {
- register int hi;
- register int i;
- register struct symbol *idp;
- register int len;
-
- /* Compute length of text in len. */
- for (len = 0; text[len]; len++);
-
- /* Compute hash code */
- hi = len;
- for (i = 0; i < len; i++)
- hi = ((hi * 613) + (unsigned)(text[i]));
-
- hi &= (1 << HASHBITS) - 1;
- hi %= GLOBAL_HASH_TBL_SIZE;
-
- /* Search table for identifier */
- for (idp = global_hash_tbl [hi]; idp; idp = idp->next)
- if (streq (idp->name, text))
- return idp; /* <-- return if found */
-
- /* Not found, create one, add to chain */
- idp = (struct symbol *) malloc (sizeof (struct symbol));
- idp->name = (char *) strcpy (malloc (strlen (text) + 1), text);
- idp->used_in_call = 0;
- idp->schema_seen_p = 0;
- idp->address = 0;
- idp->addr_missing_warning = 0;
-
- idp->next = global_hash_tbl [hi];
- global_hash_tbl [hi] = idp;
- return idp; /* <-- return if created */
- }
-