]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/cris/rvdummy.c
sim: rename tconfig.in to tconfig.h
[thirdparty/binutils-gdb.git] / sim / cris / rvdummy.c
CommitLineData
aad3b3cb
HPN
1/* Test-driver for the remote-virtual-component simulator framework
2 for GDB, the GNU Debugger.
3
32d0add0 4 Copyright 2006-2015 Free Software Foundation, Inc.
aad3b3cb
HPN
5
6 This file is part of GDB.
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
4744ac1b 10 the Free Software Foundation; either version 3 of the License, or
aad3b3cb
HPN
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
4744ac1b 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
aad3b3cb
HPN
20
21/* Avoid any problems whatsoever building this program if we're not
22 also building hardware support. */
23
24#if !WITH_HW
25int
26main (int argc, char *argv[])
27{
28 return 2;
29}
30#else
31
32#ifdef HAVE_CONFIG_H
33#include "cconfig.h"
aad3b3cb
HPN
34#endif
35
36#include "getopt.h"
37#include "libiberty.h"
38
39#define _GNU_SOURCE
40#include <stdio.h>
41
42#ifdef HAVE_UNISTD_H
43#include <unistd.h>
44#endif
45#ifdef HAVE_STDLIB_H
46#include <stdlib.h>
47#endif
48#ifdef HAVE_STRING_H
49#include <string.h>
50#endif
51
52#ifdef HAVE_SYS_TYPES_H
53#include <sys/types.h>
54#endif
55
56#ifdef HAVE_SYS_TIME_H
57#include <sys/time.h>
58#endif
59
60#ifdef HAVE_SYS_SELECT_H
61#include <sys/select.h>
62#endif
63
64#ifdef HAVE_ERRNO_H
65#include <errno.h>
66#endif
67
68/* Not guarded in dv-sockser.c, so why here. */
69#include <netinet/in.h>
70#include <arpa/inet.h>
71#include <netdb.h>
72#include <sys/socket.h>
73
74enum rv_command {
75 RV_READ_CMD = 0,
76 RV_WRITE_CMD = 1,
77 RV_IRQ_CMD = 2,
78 RV_MEM_RD_CMD = 3,
79 RV_MEM_WR_CMD = 4,
80 RV_MBOX_HANDLE_CMD = 5,
81 RV_MBOX_PUT_CMD = 6,
82 RV_WATCHDOG_CMD = 7
83};
84
85enum opts { OPT_PORT = 1, OPT_TIMEOUT, OPT_VERBOSE };
86
87struct option longopts[] =
88 {
89 {"port", required_argument, NULL, OPT_PORT},
90 {"timeout", required_argument, NULL, OPT_TIMEOUT},
91 {"verbose", no_argument, NULL, OPT_VERBOSE},
92 {NULL, 0, NULL, 0}
93 };
94
95int port = 10000;
96time_t timeout = 30000;
97char *progname = "(unknown)";
98int verbose = 0;
99
100/* Required forward-declarations. */
101static void handle_input_file (int, char *);
102
103/* Set up a "server" listening to the port in PORT for a raw TCP
104 connection. Return a file descriptor for the connection or -1 on
105 error. */
106
107int setupsocket (void)
108{
109 int s;
110 socklen_t len;
111 int reuse = 1;
112 struct sockaddr_in sa_in;
113 struct sockaddr_in from;
114
115 len = sizeof (from);
116 memset (&from, 0, len);
117 memset (&sa_in, 0, sizeof (sa_in));
118
119 s = socket (AF_INET, SOCK_STREAM, 0);
363a6e9f 120 if (s == -1)
aad3b3cb
HPN
121 return -1;
122
123 if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse) != 0)
124 return -1;
125
126 sa_in.sin_port = htons (port);
127 sa_in.sin_family = AF_INET;
128
129 if (bind (s, (struct sockaddr *) & sa_in, sizeof sa_in) < 0)
130 return -1;
131
132 if (listen (s, 1) < 0)
133 return -1;
134
135 return accept (s, (struct sockaddr *) &from, &len);
136}
137
138/* Basic host-to-little-endian 32-bit value. Could use the BFD
139 machinery, but let's avoid it for this only dependency. */
140
141static void
142h2le32 (unsigned char *dest, unsigned int val)
143{
144 dest[0] = val & 255;
145 dest[1] = (val >> 8) & 255;
146 dest[2] = (val >> 16) & 255;
147 dest[3] = (val >> 24) & 255;
148}
149
150/* Send a blob of data. */
151
152static void
153send_output (int fd, unsigned char *buf, int nbytes)
154{
155 while (nbytes > 0)
156 {
157 ssize_t written = write (fd, buf, nbytes);
158 if (written < 0)
159 {
160 fprintf (stderr, "%s: write to socket failed: %s\n",
161 progname, strerror (errno));
162 exit (2);
163 }
164 nbytes -= written;
165 }
166}
167
168/* Receive a blob of data, NBYTES large. Compare to the first NCOMP
169 bytes of BUF; if not a match, write error message to stderr and
170 exit (2). Else put it in buf. */
171
172static void
173expect_input (int fd, unsigned char *buf, int nbytes, int ncomp)
174{
175 unsigned char byt;
176 int i;
177
178 for (i = 0; i < nbytes; i++)
179 {
180 int r;
181
182 do
183 {
184 errno = 0;
185 r = read (fd, &byt, 1);
186 }
187 while (r <= 0 && (r == 0 || errno == EAGAIN));
188
189 if (r != 1)
190 {
191 fprintf (stderr, "%s: read from socket failed: %s",
192 progname, strerror (errno));
193 exit (2);
194 }
195
196 if (i < ncomp && byt != buf[i])
197 {
198 int j;
199 fprintf (stderr, "%s: unexpected input,\n ", progname);
200 if (i == 0)
201 fprintf (stderr, "nothing,");
202 else
203 for (j = 0; j < i; j++)
204 fprintf (stderr, "%02x", buf[j]);
205 fprintf (stderr, "\nthen %02x instead of %02x\n", byt, buf[i]);
206 exit (2);
207 }
208 else
209 buf[i] = byt;
210 }
211}
212
213/* Handle everything about a nil-terminated line of input.
214 Call exit (2) on error with error text on stderr. */
215
216static void
217handle_input (int fd, char *buf, char *fname, int lineno)
218{
219 int nbytes = 0;
220 int n = -1;
221 char *s = buf + 2;
222 unsigned int data;
223 static unsigned char bytes[1024];
224 int i;
225
226 memset (bytes, 0, sizeof bytes);
227 lineno++;
228
229 if (buf[1] != ',')
230 goto syntax_error;
231
232 switch (buf[0])
233 {
234 /* Comment characters and empty lines. */
235 case 0: case '!': case '#':
236 break;
237
238 /* Include another file. */
239 case '@':
240 handle_input_file (fd, s);
241 break;
242
243 /* Raw input (to be expected). */
244 case 'i':
245 do
246 {
247 n = -1;
248 sscanf (s, "%02x%n", &data, &n);
249 s += n;
250 if (n > 0)
251 bytes[nbytes++] = data;
252 }
253 while (n > 0);
254 expect_input (fd, bytes, nbytes, nbytes);
255 if (verbose)
256 {
257 printf ("i,");
258 for (i = 0; i < nbytes; i++)
259 printf ("%02x", bytes[i]);
260 printf ("\n");
261 }
262 break;
263
264 /* Raw output (to be written). */
265 case 'o':
266 do
267 {
268 n = -1;
269 sscanf (s, "%02x%n", &data, &n);
270 if (n > 0)
271 {
272 s += n;
273 bytes[nbytes++] = data;
274 }
275 }
276 while (n > 0);
277 if (*s != 0)
278 goto syntax_error;
279 send_output (fd, bytes, nbytes);
280 if (verbose)
281 {
282 printf ("o,");
283 for (i = 0; i < nbytes; i++)
284 printf ("%02x", bytes[i]);
285 printf ("\n");
286 }
287 break;
288
289 /* Read a register. */
290 case 'r':
291 {
292 unsigned int addr;
293 sscanf (s, "%x,%x%n", &addr, &data, &n);
294 if (n < 0 || s[n] != 0)
295 goto syntax_error;
296 bytes[0] = 11;
297 bytes[1] = 0;
298 bytes[2] = RV_READ_CMD;
299 h2le32 (bytes + 3, addr);
300 expect_input (fd, bytes, 11, 7);
301 h2le32 (bytes + 7, data);
302 send_output (fd, bytes, 11);
303 if (verbose)
304 printf ("r,%x,%x\n", addr, data);
305 }
306 break;
307
308 /* Write a register. */
309 case 'w':
310 {
311 unsigned int addr;
312 sscanf (s, "%x,%x%n", &addr, &data, &n);
313 if (n < 0 || s[n] != 0)
314 goto syntax_error;
315 bytes[0] = 11;
316 bytes[1] = 0;
317 bytes[2] = RV_WRITE_CMD;
318 h2le32 (bytes + 3, addr);
319 h2le32 (bytes + 7, data);
320 expect_input (fd, bytes, 11, 11);
321 send_output (fd, bytes, 11);
322 if (verbose)
323 printf ("w,%x,%x\n", addr, data);
324 }
325 break;
326
327 /* Wait for some milliseconds. */
328 case 't':
329 {
330 int del = 0;
331 struct timeval to;
332 sscanf (s, "%d%n", &del, &n);
333 if (n < 0 || s[n] != 0 || del == 0)
334 goto syntax_error;
335
336 to.tv_sec = del / 1000;
337 to.tv_usec = (del % 1000) * 1000;
338
339 if (select (0, NULL, NULL, NULL, &to) != 0)
340 {
341 fprintf (stderr, "%s: problem waiting for %d ms:\n %s\n",
342 progname, del, strerror (errno));
343 exit (2);
344 }
345 if (verbose)
346 printf ("t,%d\n", del);
347 }
348 break;
349
350 /* Expect a watchdog command. */
351 case 'W':
352 if (*s != 0)
353 goto syntax_error;
354 bytes[0] = 3;
355 bytes[1] = 0;
356 bytes[2] = RV_WATCHDOG_CMD;
357 expect_input (fd, bytes, 3, 3);
358 if (verbose)
359 printf ("W\n");
360 break;
361
362 /* Send an IRQ notification. */
363 case 'I':
364 sscanf (s, "%x%n", &data, &n);
365 if (n < 0 || s[n] != 0)
366 goto syntax_error;
367 bytes[0] = 7;
368 bytes[1] = 0;
369 bytes[2] = RV_IRQ_CMD;
370 h2le32 (bytes + 3, data);
371 send_output (fd, bytes, 7);
372 if (verbose)
373 printf ("I,%x\n", data);
374 break;
375
376 /* DMA store (to CPU). */
377 case 's':
378 {
379 unsigned int addr;
380 sscanf (s, "%x,%n", &addr, &n);
381
382 if (n < 0 || s[n] == 0)
383 goto syntax_error;
384 s += n;
385 do
386 {
387 n = -1;
388 sscanf (s, "%02x%n", &data, &n);
389 if (n > 0)
390 {
391 s += n;
392 bytes[11 + nbytes++] = data;
393 }
394 }
395 while (n > 0);
396
397 if (*s != 0)
398 goto syntax_error;
399 h2le32 (bytes, nbytes + 11);
400 bytes[2] = RV_MEM_WR_CMD;
401 h2le32 (bytes + 3, addr);
402 h2le32 (bytes + 7, nbytes);
403 send_output (fd, bytes, nbytes + 11);
404 if (verbose)
405 {
406 printf ("s,%x,", addr);
407 for (i = 0; i < nbytes; i++)
408 printf ("%02x", bytes[i]);
409 printf ("\n");
410 }
411 }
412 break;
413
414 /* DMA load (from CPU). */
415 case 'l':
416 {
417 unsigned int addr;
418 sscanf (s, "%x,%n", &addr, &n);
419
420 if (n < 0 || s[n] == 0)
421 goto syntax_error;
422 s += n;
423 do
424 {
425 n = -1;
426 sscanf (s, "%02x%n", &data, &n);
427 if (n > 0)
428 {
429 s += n;
430 bytes[11 + nbytes++] = data;
431 }
432 }
433 while (n > 0);
434
435 if (*s != 0)
436 goto syntax_error;
437 h2le32 (bytes, nbytes + 11);
438 bytes[0] = 11;
439 bytes[1] = 0;
440 bytes[2] = RV_MEM_RD_CMD;
441 h2le32 (bytes + 3, addr);
442 h2le32 (bytes + 7, nbytes);
443 send_output (fd, bytes, 11);
444 bytes[0] = (nbytes + 11) & 255;
445 bytes[1] = ((nbytes + 11) >> 8) & 255;
446 expect_input (fd, bytes, nbytes + 11, nbytes + 11);
447 if (verbose)
448 {
449 printf ("l,%x,", addr);
450 for (i = 0; i < nbytes; i++)
451 printf ("%02x", bytes[i]);
452 printf ("\n");
453 }
454 }
455 break;
456
457 syntax_error:
458 default:
459 fprintf (stderr, "%s: invalid command line in %s:%d:\n %s",
460 progname, fname, lineno, strerror (errno));
461 exit (2);
462 }
463}
464
465/* Loop over the contents of FNAME, using handle_input to parse each line.
466 Errors to stderr, exit (2). */
467
468static void
469handle_input_file (int fd, char *fname)
470{
471 static char buf[2048] = {0};
472 int lineno = 0;
473 FILE *f = fopen (fname, "r");
474
475 if (f == NULL)
476 {
477 fprintf (stderr, "%s: problem opening %s: %s\n",
478 progname, fname, strerror (errno));
479 exit (2);
480 }
481
482 /* Let's cut the buffer short, so we always get a newline. */
483 while (fgets (buf, sizeof (buf) - 1, f) != NULL)
484 {
485 buf[strlen (buf) - 1] = 0;
486 lineno++;
487 handle_input (fd, buf, fname, lineno);
488 }
489
490 fclose (f);
491}
492
493int
494main (int argc, char *argv[])
495{
496 int optc;
497 int fd;
498 FILE *f;
499 int i;
500
501 progname = argv[0];
502 while ((optc = getopt_long (argc, argv, "", longopts, NULL)) != -1)
503 switch (optc)
504 {
505 case OPT_PORT:
506 port = atoi (optarg);
507 break;
508
509 case OPT_TIMEOUT:
510 timeout = (time_t) atoi (optarg);
511 break;
512
513 case OPT_VERBOSE:
514 verbose = 1;
515 break;
516 }
517
518 fd = setupsocket ();
363a6e9f 519 if (fd == -1)
aad3b3cb
HPN
520 {
521 fprintf (stderr, "%s: problem setting up the connection: %s\n",
522 progname, strerror (errno));
523 exit (2);
524 }
525
526 for (i = optind; i < argc; i++)
527 handle_input_file (fd, argv[i]);
528
529 /* FIXME: option-controlled test for remaining input? */
530 close (fd);
531 return 1;
532}
533#endif