1 /* main.c --- main function for stand-alone M32C simulator. 2 3 Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 4 Free Software Foundation, Inc. 5 Contributed by Red Hat, Inc. 6 7 This file is part of the GNU simulators. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 22 23 #include "config.h" 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 33 #ifdef HAVE_SYS_SOCKET_H 34 #ifdef HAVE_NETINET_IN_H 35 #ifdef HAVE_NETINET_TCP_H 36 #define HAVE_networking 37 #endif 38 #endif 39 #endif 40 41 #ifdef HAVE_networking 42 #include <sys/socket.h> 43 #include <netinet/in.h> 44 #include <netinet/tcp.h> 45 #endif 46 47 48 #include "bfd.h" 49 50 #include "cpu.h" 51 #include "mem.h" 52 #include "misc.h" 53 #include "load.h" 54 #include "trace.h" 55 #ifdef TIMER_A 56 #include "int.h" 57 #include "timer_a.h" 58 #endif 59 60 #ifdef HAVE_networking 61 extern int m32c_console_ofd; 62 extern int m32c_console_ifd; 63 #endif 64 65 int m32c_disassemble = 0; 66 static unsigned int cycles = 0; 67 68 static void 69 done (int exit_code) 70 { 71 if (verbose) 72 { 73 stack_heap_stats (); 74 mem_usage_stats (); 75 printf ("insns: %14s\n", comma (cycles)); 76 } 77 exit (exit_code); 78 } 79 80 #ifdef HAVE_networking 81 static void 82 setup_tcp_console (char *portname) 83 { 84 int port = atoi (portname); 85 struct sockaddr_in address; 86 int isocket; 87 socklen_t as; 88 unsigned char *a; 89 90 if (port < 1024) 91 { 92 printf ("invalid port number %d\n", port); 93 exit (1); 94 } 95 printf ("waiting for tcp console on port %d\n", port); 96 97 memset (&address, 0, sizeof (address)); 98 address.sin_family = AF_INET; 99 address.sin_port = htons (port); 100 101 isocket = socket (AF_INET, SOCK_STREAM, 0); 102 if (isocket == -1) 103 { 104 perror ("socket"); 105 exit (1); 106 } 107 108 if (bind (isocket, (struct sockaddr *) &address, sizeof (address))) 109 { 110 perror ("bind"); 111 exit (1); 112 } 113 listen (isocket, 2); 114 115 printf ("waiting for connection...\n"); 116 as = sizeof (address); 117 m32c_console_ifd = accept (isocket, (struct sockaddr *) &address, &as); 118 if (m32c_console_ifd == -1) 119 { 120 perror ("accept"); 121 exit (1); 122 } 123 a = (unsigned char *) (&address.sin_addr.s_addr); 124 printf ("connection from %d.%d.%d.%d\n", a[0], a[1], a[2], a[3]); 125 m32c_console_ofd = m32c_console_ifd; 126 } 127 #endif 128 129 int 130 main (int argc, char **argv) 131 { 132 int o; 133 int save_trace; 134 bfd *prog; 135 #ifdef HAVE_networking 136 char *console_port_s = 0; 137 #endif 138 139 setbuf (stdout, 0); 140 141 in_gdb = 0; 142 143 while ((o = getopt (argc, argv, "tc:vdm:C")) != -1) 144 switch (o) 145 { 146 case 't': 147 trace++; 148 break; 149 case 'c': 150 #ifdef HAVE_networking 151 console_port_s = optarg; 152 #else 153 fprintf (stderr, "Nework console not available in this build.\n"); 154 #endif 155 break; 156 case 'C': 157 #ifdef HAVE_TERMIOS_H 158 m32c_use_raw_console = 1; 159 #else 160 fprintf (stderr, "Raw console not available in this build.\n"); 161 #endif 162 break; 163 case 'v': 164 verbose++; 165 break; 166 case 'd': 167 m32c_disassemble++; 168 break; 169 case 'm': 170 if (strcmp (optarg, "r8c") == 0 || strcmp (optarg, "m16c") == 0) 171 default_machine = bfd_mach_m16c; 172 else if (strcmp (optarg, "m32cm") == 0 173 || strcmp (optarg, "m32c") == 0) 174 default_machine = bfd_mach_m32c; 175 else 176 { 177 fprintf (stderr, "Invalid machine: %s\n", optarg); 178 exit (1); 179 } 180 break; 181 case '?': 182 fprintf (stderr, 183 "usage: run [-v] [-C] [-c port] [-t] [-d] [-m r8c|m16c|m32cm|m32c]" 184 " program\n"); 185 exit (1); 186 } 187 188 prog = bfd_openr (argv[optind], 0); 189 if (!prog) 190 { 191 fprintf (stderr, "Can't read %s\n", argv[optind]); 192 exit (1); 193 } 194 195 if (!bfd_check_format (prog, bfd_object)) 196 { 197 fprintf (stderr, "%s not a m32c program\n", argv[optind]); 198 exit (1); 199 } 200 201 save_trace = trace; 202 trace = 0; 203 m32c_load (prog); 204 trace = save_trace; 205 206 #ifdef HAVE_networking 207 if (console_port_s) 208 setup_tcp_console (console_port_s); 209 #endif 210 211 sim_disasm_init (prog); 212 213 while (1) 214 { 215 int rc; 216 217 if (trace) 218 printf ("\n"); 219 220 if (m32c_disassemble) 221 sim_disasm_one (); 222 223 enable_counting = verbose; 224 cycles++; 225 rc = decode_opcode (); 226 enable_counting = 0; 227 228 if (M32C_HIT_BREAK (rc)) 229 done (1); 230 else if (M32C_EXITED (rc)) 231 done (M32C_EXIT_STATUS (rc)); 232 else 233 assert (M32C_STEPPED (rc)); 234 235 trace_register_changes (); 236 237 #ifdef TIMER_A 238 update_timer_a (); 239 #endif 240 } 241 } 242