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