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