Home | History | Annotate | Line # | Download | only in rx
      1 /* main.c --- main function for stand-alone RX simulator.
      2 
      3 Copyright (C) 2005-2024 Free Software Foundation, Inc.
      4 Contributed by Red Hat, Inc.
      5 
      6 This file is part of the GNU simulators.
      7 
      8 This program is free software; you can redistribute it and/or modify
      9 it under the terms of the GNU General Public License as published by
     10 the Free Software Foundation; either version 3 of the License, or
     11 (at your option) any later version.
     12 
     13 This program is distributed in the hope that it will be useful,
     14 but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 GNU General Public License for more details.
     17 
     18 You should have received a copy of the GNU General Public License
     19 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20 
     21 /* This must come before any other includes.  */
     22 #include "defs.h"
     23 
     24 #include <stdio.h>
     25 #include <string.h>
     26 #include <stdlib.h>
     27 #include <unistd.h>
     28 #include <assert.h>
     29 #include <setjmp.h>
     30 #include <signal.h>
     31 #include <getopt.h>
     32 
     33 #include "bfd.h"
     34 
     35 #include "cpu.h"
     36 #include "mem.h"
     37 #include "misc.h"
     38 #include "load.h"
     39 #include "trace.h"
     40 #include "err.h"
     41 
     42 static int disassemble = 0;
     43 
     44 /* This must be higher than any other option index.  */
     45 #define OPT_ACT 400
     46 
     47 #define ACT(E,A) (OPT_ACT + SIM_ERR_##E * SIM_ERRACTION_NUM_ACTIONS + SIM_ERRACTION_##A)
     48 
     49 static struct option sim_options[] =
     50 {
     51   { "end-sim-args", 0, NULL, 'E' },
     52   { "exit-null-deref", 0, NULL, ACT(NULL_POINTER_DEREFERENCE,EXIT) },
     53   { "warn-null-deref", 0, NULL, ACT(NULL_POINTER_DEREFERENCE,WARN) },
     54   { "ignore-null-deref", 0, NULL, ACT(NULL_POINTER_DEREFERENCE,IGNORE) },
     55   { "exit-unwritten-pages", 0, NULL, ACT(READ_UNWRITTEN_PAGES,EXIT) },
     56   { "warn-unwritten-pages", 0, NULL, ACT(READ_UNWRITTEN_PAGES,WARN) },
     57   { "ignore-unwritten-pages", 0, NULL, ACT(READ_UNWRITTEN_PAGES,IGNORE) },
     58   { "exit-unwritten-bytes", 0, NULL, ACT(READ_UNWRITTEN_BYTES,EXIT) },
     59   { "warn-unwritten-bytes", 0, NULL, ACT(READ_UNWRITTEN_BYTES,WARN) },
     60   { "ignore-unwritten-bytes", 0, NULL, ACT(READ_UNWRITTEN_BYTES,IGNORE) },
     61   { "exit-corrupt-stack", 0, NULL, ACT(CORRUPT_STACK,EXIT) },
     62   { "warn-corrupt-stack", 0, NULL, ACT(CORRUPT_STACK,WARN) },
     63   { "ignore-corrupt-stack", 0, NULL, ACT(CORRUPT_STACK,IGNORE) },
     64   { 0, 0, 0, 0 }
     65 };
     66 
     67 static void
     68 done (int exit_code)
     69 {
     70   if (verbose)
     71     {
     72       stack_heap_stats ();
     73       mem_usage_stats ();
     74       /* Only use comma separated numbers when being very verbose.
     75 	 Comma separated numbers are hard to parse in awk scripts.  */
     76       if (verbose > 1)
     77 	printf ("insns: %14s\n", comma (rx_cycles));
     78       else
     79 	printf ("insns: %u\n", rx_cycles);
     80 
     81       pipeline_stats ();
     82     }
     83   exit (exit_code);
     84 }
     85 
     86 int
     87 main (int argc, char **argv)
     88 {
     89   int o;
     90   int save_trace;
     91   bfd *prog;
     92   int rc;
     93 
     94   /* By default, we exit when an execution error occurs.  */
     95   execution_error_init_standalone ();
     96 
     97   while ((o = getopt_long (argc, argv, "tvdeEwi", sim_options, NULL)) != -1)
     98     {
     99       if (o == 'E')
    100 	/* Stop processing the command line. This is so that any remaining
    101 	   words on the command line that look like arguments will be passed
    102 	   on to the program being simulated.  */
    103 	break;
    104 
    105       if (o >= OPT_ACT)
    106 	{
    107 	  int e, a;
    108 
    109 	  o -= OPT_ACT;
    110 	  e = o / SIM_ERRACTION_NUM_ACTIONS;
    111 	  a = o % SIM_ERRACTION_NUM_ACTIONS;
    112 	  execution_error_set_action (e, a);
    113 	}
    114       else switch (o)
    115 	{
    116 	case 't':
    117 	  trace++;
    118 	  break;
    119 	case 'v':
    120 	  verbose++;
    121 	  break;
    122 	case 'd':
    123 	  disassemble++;
    124 	  break;
    125 	case 'e':
    126 	  execution_error_init_standalone ();
    127 	  break;
    128 	case 'w':
    129 	  execution_error_warn_all ();
    130 	  break;
    131 	case 'i':
    132 	  execution_error_ignore_all ();
    133 	  break;
    134 	case '?':
    135 	  {
    136 	    int i;
    137 	    fprintf (stderr,
    138 		     "usage: run [options] program [arguments]\n");
    139 	    fprintf (stderr,
    140 		     "\t-v\t- increase verbosity.\n"
    141 		     "\t-t\t- trace.\n"
    142 		     "\t-d\t- disassemble.\n"
    143 		     "\t-E\t- stop processing sim args\n"
    144 		     "\t-e\t- exit on all execution errors.\n"
    145 		     "\t-w\t- warn (do not exit) on all execution errors.\n"
    146 		     "\t-i\t- ignore all execution errors.\n");
    147 	    for (i=0; sim_options[i].name; i++)
    148 	      fprintf (stderr, "\t--%s\n", sim_options[i].name);
    149 	    exit (1);
    150 	  }
    151 	}
    152     }
    153 
    154   prog = bfd_openr (argv[optind], 0);
    155   if (!prog)
    156     {
    157       fprintf (stderr, "Can't read %s\n", argv[optind]);
    158       exit (1);
    159     }
    160 
    161   if (!bfd_check_format (prog, bfd_object))
    162     {
    163       fprintf (stderr, "%s not a rx program\n", argv[optind]);
    164       exit (1);
    165     }
    166 
    167   init_regs ();
    168 
    169   rx_in_gdb = 0;
    170   save_trace = trace;
    171   trace = 0;
    172   rx_load (prog, NULL);
    173   trace = save_trace;
    174 
    175   sim_disasm_init (prog);
    176 
    177   enable_counting = verbose;
    178 
    179   rc = setjmp (decode_jmp_buf);
    180 
    181   if (rc == 0)
    182     {
    183       if (!trace && !disassemble)
    184 	{
    185 	  /* This will longjmp to the above if an exception
    186 	     happens.  */
    187 	  for (;;)
    188 	    decode_opcode ();
    189 	}
    190       else
    191 	while (1)
    192 	  {
    193 
    194 	    if (trace)
    195 	      printf ("\n");
    196 
    197 	    if (disassemble)
    198 	      {
    199 		enable_counting = 0;
    200 		sim_disasm_one ();
    201 		enable_counting = verbose;
    202 	      }
    203 
    204 	    rc = decode_opcode ();
    205 
    206 	    if (trace)
    207 	      trace_register_changes ();
    208 	  }
    209     }
    210 
    211   if (RX_HIT_BREAK (rc))
    212     done (1);
    213   else if (RX_EXITED (rc))
    214     done (RX_EXIT_STATUS (rc));
    215   else if (RX_STOPPED (rc))
    216     {
    217       if (verbose)
    218 	printf("Stopped on signal %d\n", RX_STOP_SIG (rc));
    219       exit(1);
    220     }
    221   done (0);
    222   exit (0);
    223 }
    224