xref: /netbsd-src/external/gpl3/gdb/dist/sim/erc32/interf.c (revision a24efa7dea9f1f56c3bdb15a927d3516792ace1c)
1 /* This file is part of SIS (SPARC instruction simulator)
2 
3    Copyright (C) 1995-2015 Free Software Foundation, Inc.
4    Contributed by Jiri Gaisler, European Space Agency
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 #include "config.h"
20 #include <signal.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/fcntl.h>
25 #include "sis.h"
26 #include "libiberty.h"
27 #include "bfd.h"
28 #include <dis-asm.h>
29 #include "sim-config.h"
30 
31 #include "gdb/remote-sim.h"
32 #include "gdb/signals.h"
33 
34 #define PSR_CWP 0x7
35 
36 extern struct disassemble_info dinfo;
37 extern struct pstate sregs;
38 extern struct estate ebase;
39 
40 extern int      ctrl_c;
41 extern int      nfp;
42 extern int      ift;
43 extern int      rom8;
44 extern int      wrp;
45 extern int      uben;
46 extern int      sis_verbose;
47 extern char    *sis_version;
48 extern struct estate ebase;
49 extern struct evcell evbuf[];
50 extern struct irqcell irqarr[];
51 extern int      irqpend, ext_irl;
52 extern int      sparclite;
53 extern int      dumbio;
54 extern int      sparclite_board;
55 extern int      termsave;
56 extern char     uart_dev1[], uart_dev2[];
57 
58 int             sis_gdb_break = 1;
59 
60 host_callback *sim_callback;
61 
62 int
63 run_sim(sregs, icount, dis)
64     struct pstate  *sregs;
65     uint64          icount;
66     int             dis;
67 {
68     int             mexc, irq;
69 
70     if (sis_verbose)
71 	(*sim_callback->printf_filtered) (sim_callback, "resuming at %x\n",
72 					  sregs->pc);
73    init_stdio();
74    sregs->starttime = get_time();
75    irq = 0;
76    if ((sregs->pc != 0) && (ebase.simtime == 0))
77 	boot_init();
78    while (!sregs->err_mode & (icount > 0)) {
79 
80 	sregs->fhold = 0;
81 	sregs->hold = 0;
82 	sregs->icnt = 1;
83 
84         if (sregs->psr & 0x080)
85             sregs->asi = 8;
86         else
87             sregs->asi = 9;
88 
89 #if 0	/* DELETE ME! for debugging purposes only */
90         if (sis_verbose > 1)
91             if (sregs->pc == 0 || sregs->npc == 0)
92                 printf ("bogus pc or npc\n");
93 #endif
94         mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
95 #if 0	/* DELETE ME! for debugging purposes only */
96         if (sis_verbose > 2)
97             printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
98                    sregs->pc, sregs->npc,
99                    sregs->r[(((sregs->psr & 7) << 4) + 14) & 0x7f],
100                    sregs->r[(((sregs->psr & 7) << 4) + 30) & 0x7f],
101                    sregs->wim,
102                    sregs->psr & 7,
103                    sregs->inst);
104 #endif
105         if (sregs->annul) {
106             sregs->annul = 0;
107             sregs->icnt = 1;
108             sregs->pc = sregs->npc;
109             sregs->npc = sregs->npc + 4;
110         } else {
111 	    if (ext_irl) irq = check_interrupts(sregs);
112 	    if (!irq) {
113 		if (mexc) {
114 		    sregs->trap = I_ACC_EXC;
115 		} else {
116 		    if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) {
117 			if (sis_verbose)
118 			    (*sim_callback->printf_filtered) (sim_callback,
119 							      "SW BP hit at %x\n", sregs->pc);
120                         sim_halt();
121 			restore_stdio();
122 			clearerr(stdin);
123 			return BPT_HIT;
124 		    } else
125 			dispatch_instruction(sregs);
126 		}
127 		icount--;
128 	    }
129 	    if (sregs->trap) {
130                 irq = 0;
131 		sregs->err_mode = execute_trap(sregs);
132 	    }
133 	}
134 	advance_time(sregs);
135 	if (ctrl_c) {
136 	    icount = 0;
137 	}
138     }
139     sim_halt();
140     sregs->tottime += get_time() - sregs->starttime;
141     restore_stdio();
142     clearerr(stdin);
143     if (sregs->err_mode)
144 	error_mode(sregs->pc);
145     if (sregs->err_mode)
146 	return ERROR;
147     if (sregs->bphit) {
148 	if (sis_verbose)
149 	    (*sim_callback->printf_filtered) (sim_callback,
150 					      "HW BP hit at %x\n", sregs->pc);
151 	return BPT_HIT;
152     }
153     if (ctrl_c) {
154 	ctrl_c = 0;
155 	return CTRL_C;
156     }
157     return TIME_OUT;
158 }
159 
160 SIM_DESC
161 sim_open (kind, callback, abfd, argv)
162      SIM_OPEN_KIND kind;
163      struct host_callback_struct *callback;
164      struct bfd *abfd;
165      char **argv;
166 {
167 
168     int             argc = 0;
169     int             stat = 1;
170     int             freq = 0;
171 
172     sim_callback = callback;
173 
174     while (argv[argc])
175       argc++;
176     while (stat < argc) {
177 	if (argv[stat][0] == '-') {
178 	    if (strcmp(argv[stat], "-v") == 0) {
179 		sis_verbose++;
180 	    } else
181 	    if (strcmp(argv[stat], "-nfp") == 0) {
182 		nfp = 1;
183 	    } else
184             if (strcmp(argv[stat], "-ift") == 0) {
185                 ift = 1;
186 	    } else
187 	    if (strcmp(argv[stat], "-sparclite") == 0) {
188 		sparclite = 1;
189 	    } else
190 	    if (strcmp(argv[stat], "-sparclite-board") == 0) {
191 		sparclite_board = 1;
192             } else
193             if (strcmp(argv[stat], "-dumbio") == 0) {
194 		dumbio = 1;
195 	    } else
196             if (strcmp(argv[stat], "-wrp") == 0) {
197                 wrp = 1;
198 	    } else
199             if (strcmp(argv[stat], "-rom8") == 0) {
200                 rom8 = 1;
201 	    } else
202             if (strcmp(argv[stat], "-uben") == 0) {
203                 uben = 1;
204 	    } else
205 	    if (strcmp(argv[stat], "-uart1") == 0) {
206 		if ((stat + 1) < argc)
207 		    strcpy(uart_dev1, argv[++stat]);
208 	    } else
209 	    if (strcmp(argv[stat], "-uart2") == 0) {
210 		if ((stat + 1) < argc)
211 		    strcpy(uart_dev2, argv[++stat]);
212 	    } else
213 	    if (strcmp(argv[stat], "-nogdb") == 0) {
214 		sis_gdb_break = 0;
215 	    } else
216 	    if (strcmp(argv[stat], "-freq") == 0) {
217 		if ((stat + 1) < argc) {
218 		    freq = strtol(argv[++stat], (char **)NULL, 0);
219 		}
220 	    } else
221 	    if (strncmp(argv[stat], "--sysroot=", sizeof("--sysroot=") - 1) == 0) {
222 		/* Ignore until we start to support this.  */
223 	    } else {
224 		(*sim_callback->printf_filtered) (sim_callback,
225 						  "unknown option %s\n",
226 						  argv[stat]);
227 	    }
228 	} else
229 	    bfd_load(argv[stat]);
230 	stat++;
231     }
232 
233     if (sis_verbose) {
234 	(*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
235 	(*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
236 	if (nfp)
237 	  (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
238 	if (sparclite)
239 	  (*sim_callback->printf_filtered) (sim_callback, "simulating Sparclite\n");
240 	if (dumbio)
241 	  (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
242 	if (sis_gdb_break == 0)
243 	  (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
244 	if (freq)
245 	  (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
246     }
247 
248     sregs.freq = freq ? freq : 15;
249     termsave = fcntl(0, F_GETFL, 0);
250     INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
251 #ifdef HOST_LITTLE_ENDIAN
252     dinfo.endian = BFD_ENDIAN_LITTLE;
253 #else
254     dinfo.endian = BFD_ENDIAN_BIG;
255 #endif
256     reset_all();
257     ebase.simtime = 0;
258     init_sim();
259     init_bpt(&sregs);
260     reset_stat(&sregs);
261 
262     /* Fudge our descriptor for now.  */
263     return (SIM_DESC) 1;
264 }
265 
266 void
267 sim_close(sd, quitting)
268      SIM_DESC sd;
269      int quitting;
270 {
271 
272     exit_sim();
273     fcntl(0, F_SETFL, termsave);
274 
275 };
276 
277 SIM_RC
278 sim_load(sd, prog, abfd, from_tty)
279      SIM_DESC sd;
280      const char *prog;
281      bfd *abfd;
282      int from_tty;
283 {
284     bfd_load (prog);
285     return SIM_RC_OK;
286 }
287 
288 SIM_RC
289 sim_create_inferior(sd, abfd, argv, env)
290      SIM_DESC sd;
291      struct bfd *abfd;
292      char **argv;
293      char **env;
294 {
295     bfd_vma start_address = 0;
296     if (abfd != NULL)
297       start_address = bfd_get_start_address (abfd);
298 
299     ebase.simtime = 0;
300     reset_all();
301     reset_stat(&sregs);
302     sregs.pc = start_address & ~3;
303     sregs.npc = sregs.pc + 4;
304     return SIM_RC_OK;
305 }
306 
307 int
308 sim_store_register(sd, regno, value, length)
309     SIM_DESC sd;
310     int             regno;
311     unsigned char  *value;
312     int length;
313 {
314     int regval;
315 
316     regval = (value[0] << 24) | (value[1] << 16)
317 		 | (value[2] << 8) | value[3];
318     set_regi(&sregs, regno, regval);
319     return length;
320 }
321 
322 
323 int
324 sim_fetch_register(sd, regno, buf, length)
325      SIM_DESC sd;
326     int             regno;
327     unsigned char  *buf;
328      int length;
329 {
330     get_regi(&sregs, regno, buf);
331     return -1;
332 }
333 
334 int
335 sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length)
336 {
337     int i, len;
338 
339     for (i = 0; i < length; i++) {
340 	sis_memory_write ((mem + i) ^ EBT, &buf[i], 1);
341     }
342     return length;
343 }
344 
345 int
346 sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
347 {
348     int i, len;
349 
350     for (i = 0; i < length; i++) {
351 	sis_memory_read ((mem + i) ^ EBT, &buf[i], 1);
352     }
353     return length;
354 }
355 
356 void
357 sim_info(sd, verbose)
358      SIM_DESC sd;
359      int verbose;
360 {
361     show_stat(&sregs);
362 }
363 
364 int             simstat = OK;
365 
366 void
367 sim_stop_reason(sd, reason, sigrc)
368      SIM_DESC sd;
369      enum sim_stop * reason;
370      int *sigrc;
371 {
372 
373     switch (simstat) {
374 	case CTRL_C:
375 	*reason = sim_stopped;
376 	*sigrc = GDB_SIGNAL_INT;
377 	break;
378     case OK:
379     case TIME_OUT:
380     case BPT_HIT:
381 	*reason = sim_stopped;
382 	*sigrc = GDB_SIGNAL_TRAP;
383 	break;
384     case ERROR:
385 	*sigrc = 0;
386 	*reason = sim_exited;
387     }
388     ctrl_c = 0;
389     simstat = OK;
390 }
391 
392 /* Flush all register windows out to the stack.  Starting after the invalid
393    window, flush all windows up to, and including the current window.  This
394    allows GDB to do backtraces and look at local variables for frames that
395    are still in the register windows.  Note that strictly speaking, this
396    behavior is *wrong* for several reasons.  First, it doesn't use the window
397    overflow handlers.  It therefore assumes standard frame layouts and window
398    handling policies.  Second, it changes system state behind the back of the
399    target program.  I expect this to mainly pose problems when debugging trap
400    handlers.
401 */
402 
403 static void
404 flush_windows ()
405 {
406   int invwin;
407   int cwp;
408   int win;
409   int ws;
410 
411   /* Keep current window handy */
412 
413   cwp = sregs.psr & PSR_CWP;
414 
415   /* Calculate the invalid window from the wim. */
416 
417   for (invwin = 0; invwin <= PSR_CWP; invwin++)
418     if ((sregs.wim >> invwin) & 1)
419       break;
420 
421   /* Start saving with the window after the invalid window. */
422 
423   invwin = (invwin - 1) & PSR_CWP;
424 
425   for (win = invwin; ; win = (win - 1) & PSR_CWP)
426     {
427       uint32 sp;
428       int i;
429 
430       sp = sregs.r[(win * 16 + 14) & 0x7f];
431 #if 1
432       if (sis_verbose > 2) {
433 	uint32 fp = sregs.r[(win * 16 + 30) & 0x7f];
434 	printf("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
435       }
436 #endif
437 
438       for (i = 0; i < 16; i++)
439 	memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
440 		      &ws);
441 
442       if (win == cwp)
443 	break;
444     }
445 }
446 
447 void
448 sim_resume(SIM_DESC sd, int step, int siggnal)
449 {
450     simstat = run_sim(&sregs, UINT64_MAX, 0);
451 
452     if (sis_gdb_break) flush_windows ();
453 }
454 
455 void
456 sim_do_command(sd, cmd)
457      SIM_DESC sd;
458      const char *cmd;
459 {
460     exec_cmd(&sregs, cmd);
461 }
462 
463 char **
464 sim_complete_command (SIM_DESC sd, const char *text, const char *word)
465 {
466   return NULL;
467 }
468 
469 #if 0 /* FIXME: These shouldn't exist.  */
470 
471 int
472 sim_insert_breakpoint(int addr)
473 {
474     if (sregs.bptnum < BPT_MAX) {
475 	sregs.bpts[sregs.bptnum] = addr & ~0x3;
476 	sregs.bptnum++;
477 	if (sis_verbose)
478 	    (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr);
479 	return 0;
480     } else
481 	return 1;
482 }
483 
484 int
485 sim_remove_breakpoint(int addr)
486 {
487     int             i = 0;
488 
489     while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
490 	i++;
491     if (addr == sregs.bpts[i]) {
492 	for (; i < sregs.bptnum - 1; i++)
493 	    sregs.bpts[i] = sregs.bpts[i + 1];
494 	sregs.bptnum -= 1;
495 	if (sis_verbose)
496 	    (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr);
497 	return 0;
498     }
499     return 1;
500 }
501 
502 #endif
503