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