xref: /netbsd-src/external/gpl3/gdb/dist/sim/m32c/main.c (revision 5bbd2a12505d72a8177929a37b5cee489d0a1cfd)
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