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