1 /* main.c --- main function for stand-alone M32C 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 <sys/types.h> 32 #include <getopt.h> 33 34 #ifdef HAVE_SYS_SOCKET_H 35 #ifdef HAVE_NETINET_IN_H 36 #ifdef HAVE_NETINET_TCP_H 37 #define HAVE_networking 38 #endif 39 #endif 40 #endif 41 42 #ifdef HAVE_networking 43 #include <sys/socket.h> 44 #include <netinet/in.h> 45 #include <netinet/tcp.h> 46 #endif 47 48 49 #include "bfd.h" 50 51 #include "cpu.h" 52 #include "mem.h" 53 #include "misc.h" 54 #include "load.h" 55 #include "trace.h" 56 #ifdef TIMER_A 57 #include "int.h" 58 #include "timer_a.h" 59 #endif 60 61 #ifdef HAVE_networking 62 extern int m32c_console_ofd; 63 extern int m32c_console_ifd; 64 #endif 65 66 int m32c_disassemble = 0; 67 static unsigned int cycles = 0; 68 69 static void 70 done (int exit_code) 71 { 72 if (verbose) 73 { 74 stack_heap_stats (); 75 mem_usage_stats (); 76 printf ("insns: %14s\n", comma (cycles)); 77 } 78 exit (exit_code); 79 } 80 81 #ifdef HAVE_networking 82 static void 83 setup_tcp_console (char *portname) 84 { 85 int port = atoi (portname); 86 struct sockaddr_in address; 87 int isocket; 88 socklen_t as; 89 unsigned char *a; 90 91 if (port < 1024) 92 { 93 printf ("invalid port number %d\n", port); 94 exit (1); 95 } 96 printf ("waiting for tcp console on port %d\n", port); 97 98 memset (&address, 0, sizeof (address)); 99 address.sin_family = AF_INET; 100 address.sin_port = htons (port); 101 102 isocket = socket (AF_INET, SOCK_STREAM, 0); 103 if (isocket == -1) 104 { 105 perror ("socket"); 106 exit (1); 107 } 108 109 if (bind (isocket, (struct sockaddr *) &address, sizeof (address))) 110 { 111 perror ("bind"); 112 exit (1); 113 } 114 listen (isocket, 2); 115 116 printf ("waiting for connection...\n"); 117 as = sizeof (address); 118 m32c_console_ifd = accept (isocket, (struct sockaddr *) &address, &as); 119 if (m32c_console_ifd == -1) 120 { 121 perror ("accept"); 122 exit (1); 123 } 124 a = (unsigned char *) (&address.sin_addr.s_addr); 125 printf ("connection from %d.%d.%d.%d\n", a[0], a[1], a[2], a[3]); 126 m32c_console_ofd = m32c_console_ifd; 127 } 128 #endif 129 130 int 131 main (int argc, char **argv) 132 { 133 int o; 134 int save_trace; 135 bfd *prog; 136 #ifdef HAVE_networking 137 char *console_port_s = 0; 138 #endif 139 static const struct option longopts[] = { { 0 } }; 140 141 setbuf (stdout, 0); 142 143 in_gdb = 0; 144 145 while ((o = getopt_long (argc, argv, "tc:vdm:C", longopts, NULL)) 146 != -1) 147 switch (o) 148 { 149 case 't': 150 trace++; 151 break; 152 case 'c': 153 #ifdef HAVE_networking 154 console_port_s = optarg; 155 #else 156 fprintf (stderr, "Nework console not available in this build.\n"); 157 #endif 158 break; 159 case 'C': 160 #ifdef HAVE_TERMIOS_H 161 m32c_use_raw_console = 1; 162 #else 163 fprintf (stderr, "Raw console not available in this build.\n"); 164 #endif 165 break; 166 case 'v': 167 verbose++; 168 break; 169 case 'd': 170 m32c_disassemble++; 171 break; 172 case 'm': 173 if (strcmp (optarg, "r8c") == 0 || strcmp (optarg, "m16c") == 0) 174 default_machine = bfd_mach_m16c; 175 else if (strcmp (optarg, "m32cm") == 0 176 || strcmp (optarg, "m32c") == 0) 177 default_machine = bfd_mach_m32c; 178 else 179 { 180 fprintf (stderr, "Invalid machine: %s\n", optarg); 181 exit (1); 182 } 183 break; 184 case '?': 185 fprintf (stderr, 186 "usage: run [-v] [-C] [-c port] [-t] [-d] [-m r8c|m16c|m32cm|m32c]" 187 " program\n"); 188 exit (1); 189 } 190 191 prog = bfd_openr (argv[optind], 0); 192 if (!prog) 193 { 194 fprintf (stderr, "Can't read %s\n", argv[optind]); 195 exit (1); 196 } 197 198 if (!bfd_check_format (prog, bfd_object)) 199 { 200 fprintf (stderr, "%s not a m32c program\n", argv[optind]); 201 exit (1); 202 } 203 204 save_trace = trace; 205 trace = 0; 206 m32c_load (prog); 207 trace = save_trace; 208 209 #ifdef HAVE_networking 210 if (console_port_s) 211 setup_tcp_console (console_port_s); 212 #endif 213 214 sim_disasm_init (prog); 215 216 while (1) 217 { 218 int rc; 219 220 if (trace) 221 printf ("\n"); 222 223 if (m32c_disassemble) 224 sim_disasm_one (); 225 226 enable_counting = verbose; 227 cycles++; 228 rc = decode_opcode (); 229 enable_counting = 0; 230 231 if (M32C_HIT_BREAK (rc)) 232 done (1); 233 else if (M32C_EXITED (rc)) 234 done (M32C_EXIT_STATUS (rc)); 235 else 236 assert (M32C_STEPPED (rc)); 237 238 trace_register_changes (); 239 240 #ifdef TIMER_A 241 update_timer_a (); 242 #endif 243 } 244 } 245