xref: /netbsd-src/external/gpl3/gdb/dist/sim/erc32/interf.c (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
1 /* This file is part of SIS (SPARC instruction simulator)
2 
3    Copyright (C) 1995-2017 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 * const *argv;
166 {
167 
168     int             argc = 0;
169     int             stat = 1;
170     int             freq = 0;
171 
172     sim_callback = callback;
173 
174     argc = countargv (argv);
175     while (stat < argc) {
176 	if (argv[stat][0] == '-') {
177 	    if (strcmp(argv[stat], "-v") == 0) {
178 		sis_verbose++;
179 	    } else
180 	    if (strcmp(argv[stat], "-nfp") == 0) {
181 		nfp = 1;
182 	    } else
183             if (strcmp(argv[stat], "-ift") == 0) {
184                 ift = 1;
185 	    } else
186 	    if (strcmp(argv[stat], "-sparclite") == 0) {
187 		sparclite = 1;
188 	    } else
189 	    if (strcmp(argv[stat], "-sparclite-board") == 0) {
190 		sparclite_board = 1;
191             } else
192             if (strcmp(argv[stat], "-dumbio") == 0) {
193 		dumbio = 1;
194 	    } else
195             if (strcmp(argv[stat], "-wrp") == 0) {
196                 wrp = 1;
197 	    } else
198             if (strcmp(argv[stat], "-rom8") == 0) {
199                 rom8 = 1;
200 	    } else
201             if (strcmp(argv[stat], "-uben") == 0) {
202                 uben = 1;
203 	    } else
204 	    if (strcmp(argv[stat], "-uart1") == 0) {
205 		if ((stat + 1) < argc)
206 		    strcpy(uart_dev1, argv[++stat]);
207 	    } else
208 	    if (strcmp(argv[stat], "-uart2") == 0) {
209 		if ((stat + 1) < argc)
210 		    strcpy(uart_dev2, argv[++stat]);
211 	    } else
212 	    if (strcmp(argv[stat], "-nogdb") == 0) {
213 		sis_gdb_break = 0;
214 	    } else
215 	    if (strcmp(argv[stat], "-freq") == 0) {
216 		if ((stat + 1) < argc) {
217 		    freq = strtol(argv[++stat], (char **)NULL, 0);
218 		}
219 	    } else
220 	    if (strncmp(argv[stat], "--sysroot=", sizeof("--sysroot=") - 1) == 0) {
221 		/* Ignore until we start to support this.  */
222 	    } else {
223 		(*sim_callback->printf_filtered) (sim_callback,
224 						  "unknown option %s\n",
225 						  argv[stat]);
226 	    }
227 	} else
228 	    bfd_load(argv[stat]);
229 	stat++;
230     }
231 
232     if (sis_verbose) {
233 	(*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
234 	(*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
235 	if (nfp)
236 	  (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
237 	if (sparclite)
238 	  (*sim_callback->printf_filtered) (sim_callback, "simulating Sparclite\n");
239 	if (dumbio)
240 	  (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
241 	if (sis_gdb_break == 0)
242 	  (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
243 	if (freq)
244 	  (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
245     }
246 
247     sregs.freq = freq ? freq : 15;
248     termsave = fcntl(0, F_GETFL, 0);
249     INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
250 #ifdef HOST_LITTLE_ENDIAN
251     dinfo.endian = BFD_ENDIAN_LITTLE;
252 #else
253     dinfo.endian = BFD_ENDIAN_BIG;
254 #endif
255     reset_all();
256     ebase.simtime = 0;
257     init_sim();
258     init_bpt(&sregs);
259     reset_stat(&sregs);
260 
261     /* Fudge our descriptor for now.  */
262     return (SIM_DESC) 1;
263 }
264 
265 void
266 sim_close(sd, quitting)
267      SIM_DESC sd;
268      int quitting;
269 {
270 
271     exit_sim();
272     fcntl(0, F_SETFL, termsave);
273 
274 };
275 
276 SIM_RC
277 sim_load(sd, prog, abfd, from_tty)
278      SIM_DESC sd;
279      const char *prog;
280      bfd *abfd;
281      int from_tty;
282 {
283     bfd_load (prog);
284     return SIM_RC_OK;
285 }
286 
287 SIM_RC
288 sim_create_inferior(sd, abfd, argv, env)
289      SIM_DESC sd;
290      struct bfd *abfd;
291      char * const *argv;
292      char * const *env;
293 {
294     bfd_vma start_address = 0;
295     if (abfd != NULL)
296       start_address = bfd_get_start_address (abfd);
297 
298     ebase.simtime = 0;
299     reset_all();
300     reset_stat(&sregs);
301     sregs.pc = start_address & ~3;
302     sregs.npc = sregs.pc + 4;
303     return SIM_RC_OK;
304 }
305 
306 int
307 sim_store_register(sd, regno, value, length)
308     SIM_DESC sd;
309     int             regno;
310     unsigned char  *value;
311     int length;
312 {
313     int regval;
314 
315     regval = (value[0] << 24) | (value[1] << 16)
316 		 | (value[2] << 8) | value[3];
317     set_regi(&sregs, regno, regval);
318     return length;
319 }
320 
321 
322 int
323 sim_fetch_register(sd, regno, buf, length)
324      SIM_DESC sd;
325     int             regno;
326     unsigned char  *buf;
327      int length;
328 {
329     get_regi(&sregs, regno, buf);
330     return -1;
331 }
332 
333 int
334 sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length)
335 {
336     int i, len;
337 
338     for (i = 0; i < length; i++) {
339 	sis_memory_write ((mem + i) ^ EBT, &buf[i], 1);
340     }
341     return length;
342 }
343 
344 int
345 sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
346 {
347     int i, len;
348 
349     for (i = 0; i < length; i++) {
350 	sis_memory_read ((mem + i) ^ EBT, &buf[i], 1);
351     }
352     return length;
353 }
354 
355 void
356 sim_info(sd, verbose)
357      SIM_DESC sd;
358      int verbose;
359 {
360     show_stat(&sregs);
361 }
362 
363 int             simstat = OK;
364 
365 void
366 sim_stop_reason(sd, reason, sigrc)
367      SIM_DESC sd;
368      enum sim_stop * reason;
369      int *sigrc;
370 {
371 
372     switch (simstat) {
373 	case CTRL_C:
374 	*reason = sim_stopped;
375 	*sigrc = GDB_SIGNAL_INT;
376 	break;
377     case OK:
378     case TIME_OUT:
379     case BPT_HIT:
380 	*reason = sim_stopped;
381 	*sigrc = GDB_SIGNAL_TRAP;
382 	break;
383     case ERROR:
384 	*sigrc = 0;
385 	*reason = sim_exited;
386     }
387     ctrl_c = 0;
388     simstat = OK;
389 }
390 
391 /* Flush all register windows out to the stack.  Starting after the invalid
392    window, flush all windows up to, and including the current window.  This
393    allows GDB to do backtraces and look at local variables for frames that
394    are still in the register windows.  Note that strictly speaking, this
395    behavior is *wrong* for several reasons.  First, it doesn't use the window
396    overflow handlers.  It therefore assumes standard frame layouts and window
397    handling policies.  Second, it changes system state behind the back of the
398    target program.  I expect this to mainly pose problems when debugging trap
399    handlers.
400 */
401 
402 static void
403 flush_windows ()
404 {
405   int invwin;
406   int cwp;
407   int win;
408   int ws;
409 
410   /* Keep current window handy */
411 
412   cwp = sregs.psr & PSR_CWP;
413 
414   /* Calculate the invalid window from the wim. */
415 
416   for (invwin = 0; invwin <= PSR_CWP; invwin++)
417     if ((sregs.wim >> invwin) & 1)
418       break;
419 
420   /* Start saving with the window after the invalid window. */
421 
422   invwin = (invwin - 1) & PSR_CWP;
423 
424   for (win = invwin; ; win = (win - 1) & PSR_CWP)
425     {
426       uint32 sp;
427       int i;
428 
429       sp = sregs.r[(win * 16 + 14) & 0x7f];
430 #if 1
431       if (sis_verbose > 2) {
432 	uint32 fp = sregs.r[(win * 16 + 30) & 0x7f];
433 	printf("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
434       }
435 #endif
436 
437       for (i = 0; i < 16; i++)
438 	memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
439 		      &ws);
440 
441       if (win == cwp)
442 	break;
443     }
444 }
445 
446 void
447 sim_resume(SIM_DESC sd, int step, int siggnal)
448 {
449     simstat = run_sim(&sregs, UINT64_MAX, 0);
450 
451     if (sis_gdb_break) flush_windows ();
452 }
453 
454 void
455 sim_do_command(sd, cmd)
456      SIM_DESC sd;
457      const char *cmd;
458 {
459     exec_cmd(&sregs, cmd);
460 }
461 
462 char **
463 sim_complete_command (SIM_DESC sd, const char *text, const char *word)
464 {
465   return NULL;
466 }
467 
468 #if 0 /* FIXME: These shouldn't exist.  */
469 
470 int
471 sim_insert_breakpoint(int addr)
472 {
473     if (sregs.bptnum < BPT_MAX) {
474 	sregs.bpts[sregs.bptnum] = addr & ~0x3;
475 	sregs.bptnum++;
476 	if (sis_verbose)
477 	    (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr);
478 	return 0;
479     } else
480 	return 1;
481 }
482 
483 int
484 sim_remove_breakpoint(int addr)
485 {
486     int             i = 0;
487 
488     while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
489 	i++;
490     if (addr == sregs.bpts[i]) {
491 	for (; i < sregs.bptnum - 1; i++)
492 	    sregs.bpts[i] = sregs.bpts[i + 1];
493 	sregs.bptnum -= 1;
494 	if (sis_verbose)
495 	    (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr);
496 	return 0;
497     }
498     return 1;
499 }
500 
501 #endif
502