1 /* main.c --- main function for stand-alone RL78 simulator. 2 3 Copyright (C) 2011-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 22 /* This must come before any other includes. */ 23 #include "defs.h" 24 25 #include <stdio.h> 26 #include <string.h> 27 #include <stdlib.h> 28 #include <unistd.h> 29 #include <assert.h> 30 #include <setjmp.h> 31 #include <signal.h> 32 #include <getopt.h> 33 34 #include "libiberty.h" 35 #include "bfd.h" 36 37 #include "cpu.h" 38 #include "mem.h" 39 #include "load.h" 40 #include "trace.h" 41 42 static int disassemble = 0; 43 static const char * dump_counts_filename = NULL; 44 45 static void 46 done (int exit_code) 47 { 48 if (verbose) 49 { 50 printf ("Exit code: %d\n", exit_code); 51 printf ("total clocks: %lld\n", total_clocks); 52 } 53 if (dump_counts_filename) 54 dump_counts_per_insn (dump_counts_filename); 55 exit (exit_code); 56 } 57 58 int 59 main (int argc, char **argv) 60 { 61 int o; 62 int save_trace; 63 bfd *prog; 64 int rc; 65 static const struct option longopts[] = { { 0 } }; 66 67 xmalloc_set_program_name (argv[0]); 68 69 while ((o = getopt_long (argc, argv, "tvdr:D:M:", longopts, NULL)) 70 != -1) 71 { 72 switch (o) 73 { 74 case 't': 75 trace ++; 76 break; 77 case 'v': 78 verbose ++; 79 break; 80 case 'd': 81 disassemble ++; 82 break; 83 case 'r': 84 mem_ram_size (atoi (optarg)); 85 break; 86 case 'D': 87 dump_counts_filename = optarg; 88 break; 89 case 'M': 90 if (strcmp (optarg, "g10") == 0) 91 { 92 rl78_g10_mode = 1; 93 g13_multiply = 0; 94 g14_multiply = 0; 95 mem_set_mirror (0, 0xf8000, 4096); 96 } 97 if (strcmp (optarg, "g13") == 0) 98 { 99 rl78_g10_mode = 0; 100 g13_multiply = 1; 101 g14_multiply = 0; 102 } 103 if (strcmp (optarg, "g14") == 0) 104 { 105 rl78_g10_mode = 0; 106 g13_multiply = 0; 107 g14_multiply = 1; 108 } 109 break; 110 case '?': 111 { 112 fprintf (stderr, 113 "usage: run [options] program [arguments]\n"); 114 fprintf (stderr, 115 "\t-v\t\t- increase verbosity.\n" 116 "\t-t\t\t- trace.\n" 117 "\t-d\t\t- disassemble.\n" 118 "\t-r <bytes>\t- ram size.\n" 119 "\t-M <mcu>\t- mcu type, default none, allowed: g10,g13,g14\n" 120 "\t-D <filename>\t- dump cycle count histogram\n"); 121 exit (1); 122 } 123 } 124 } 125 126 prog = bfd_openr (argv[optind], 0); 127 if (!prog) 128 { 129 fprintf (stderr, "Can't read %s\n", argv[optind]); 130 exit (1); 131 } 132 133 if (!bfd_check_format (prog, bfd_object)) 134 { 135 fprintf (stderr, "%s not a rl78 program\n", argv[optind]); 136 exit (1); 137 } 138 139 init_cpu (); 140 141 rl78_in_gdb = 0; 142 save_trace = trace; 143 trace = 0; 144 rl78_load (prog, 0, argv[0]); 145 trace = save_trace; 146 147 sim_disasm_init (prog); 148 149 rc = setjmp (decode_jmp_buf); 150 151 if (rc == 0) 152 { 153 if (!trace && !disassemble) 154 { 155 /* This will longjmp to the above if an exception 156 happens. */ 157 for (;;) 158 decode_opcode (); 159 } 160 else 161 while (1) 162 { 163 164 if (trace) 165 printf ("\n"); 166 167 if (disassemble) 168 sim_disasm_one (); 169 170 rc = decode_opcode (); 171 172 if (trace) 173 trace_register_changes (); 174 } 175 } 176 177 if (RL78_HIT_BREAK (rc)) 178 done (1); 179 else if (RL78_EXITED (rc)) 180 done (RL78_EXIT_STATUS (rc)); 181 else if (RL78_STOPPED (rc)) 182 { 183 if (verbose) 184 printf ("Stopped on signal %d\n", RL78_STOP_SIG (rc)); 185 exit (1); 186 } 187 done (0); 188 exit (0); 189 } 190