xref: /netbsd-src/external/gpl3/gdb/dist/sim/erc32/interf.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
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 2 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, write to the Free Software Foundation, Inc., 675
19  * Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22 
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 		(*sim_callback->printf_filtered) (sim_callback,
239 						  "unknown option %s\n",
240 						  argv[stat]);
241 	    }
242 	} else
243 	    bfd_load(argv[stat]);
244 	stat++;
245     }
246 
247     if (sis_verbose) {
248 	(*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
249 	(*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
250 	if (nfp)
251 	  (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
252 	if (sparclite)
253 	  (*sim_callback->printf_filtered) (sim_callback, "simulating Sparclite\n");
254 	if (dumbio)
255 	  (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
256 	if (sis_gdb_break == 0)
257 	  (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
258 	if (freq)
259 	  (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
260     }
261 
262     sregs.freq = freq ? freq : 15;
263     termsave = fcntl(0, F_GETFL, 0);
264     INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
265     dinfo.endian = BFD_ENDIAN_BIG;
266     reset_all();
267     ebase.simtime = 0;
268     init_sim();
269     init_bpt(&sregs);
270     reset_stat(&sregs);
271 
272     /* Fudge our descriptor for now.  */
273     return (SIM_DESC) 1;
274 }
275 
276 void
277 sim_close(sd, quitting)
278      SIM_DESC sd;
279      int quitting;
280 {
281 
282     exit_sim();
283     fcntl(0, F_SETFL, termsave);
284 
285 };
286 
287 SIM_RC
288 sim_load(sd, prog, abfd, from_tty)
289      SIM_DESC sd;
290      char *prog;
291      bfd *abfd;
292      int from_tty;
293 {
294     bfd_load (prog);
295     return SIM_RC_OK;
296 }
297 
298 SIM_RC
299 sim_create_inferior(sd, abfd, argv, env)
300      SIM_DESC sd;
301      struct bfd *abfd;
302      char **argv;
303      char **env;
304 {
305     bfd_vma start_address = 0;
306     if (abfd != NULL)
307       start_address = bfd_get_start_address (abfd);
308 
309     ebase.simtime = 0;
310     reset_all();
311     reset_stat(&sregs);
312     sregs.pc = start_address & ~3;
313     sregs.npc = sregs.pc + 4;
314     return SIM_RC_OK;
315 }
316 
317 int
318 sim_store_register(sd, regno, value, length)
319     SIM_DESC sd;
320     int             regno;
321     unsigned char  *value;
322     int length;
323 {
324     /* FIXME: Review the computation of regval.  */
325     int regval;
326     if (current_target_byte_order == BIG_ENDIAN)
327 	regval = (value[0] << 24) | (value[1] << 16)
328 		 | (value[2] << 8) | value[3];
329     else
330 	regval = (value[3] << 24) | (value[2] << 16)
331 		 | (value[1] << 8) | value[0];
332     set_regi(&sregs, regno, regval);
333     return length;
334 }
335 
336 
337 int
338 sim_fetch_register(sd, regno, buf, length)
339      SIM_DESC sd;
340     int             regno;
341     unsigned char  *buf;
342      int length;
343 {
344     get_regi(&sregs, regno, buf);
345     return -1;
346 }
347 
348 int
349 sim_write(sd, mem, buf, length)
350      SIM_DESC sd;
351     SIM_ADDR             mem;
352     const unsigned char  *buf;
353     int             length;
354 {
355     return (sis_memory_write(mem, buf, length));
356 }
357 
358 int
359 sim_read(sd, mem, buf, length)
360      SIM_DESC sd;
361      SIM_ADDR mem;
362      unsigned char *buf;
363      int length;
364 {
365     return (sis_memory_read(mem, buf, length));
366 }
367 
368 void
369 sim_info(sd, verbose)
370      SIM_DESC sd;
371      int verbose;
372 {
373     show_stat(&sregs);
374 }
375 
376 int             simstat = OK;
377 
378 void
379 sim_stop_reason(sd, reason, sigrc)
380      SIM_DESC sd;
381      enum sim_stop * reason;
382      int *sigrc;
383 {
384 
385     switch (simstat) {
386 	case CTRL_C:
387 	*reason = sim_stopped;
388 	*sigrc = TARGET_SIGNAL_INT;
389 	break;
390     case OK:
391     case TIME_OUT:
392     case BPT_HIT:
393 	*reason = sim_stopped;
394 	*sigrc = TARGET_SIGNAL_TRAP;
395 	break;
396     case ERROR:
397 	*sigrc = 0;
398 	*reason = sim_exited;
399     }
400     ctrl_c = 0;
401     simstat = OK;
402 }
403 
404 /* Flush all register windows out to the stack.  Starting after the invalid
405    window, flush all windows up to, and including the current window.  This
406    allows GDB to do backtraces and look at local variables for frames that
407    are still in the register windows.  Note that strictly speaking, this
408    behavior is *wrong* for several reasons.  First, it doesn't use the window
409    overflow handlers.  It therefore assumes standard frame layouts and window
410    handling policies.  Second, it changes system state behind the back of the
411    target program.  I expect this to mainly pose problems when debugging trap
412    handlers.
413 */
414 
415 static void
416 flush_windows ()
417 {
418   int invwin;
419   int cwp;
420   int win;
421   int ws;
422 
423   /* Keep current window handy */
424 
425   cwp = sregs.psr & PSR_CWP;
426 
427   /* Calculate the invalid window from the wim. */
428 
429   for (invwin = 0; invwin <= PSR_CWP; invwin++)
430     if ((sregs.wim >> invwin) & 1)
431       break;
432 
433   /* Start saving with the window after the invalid window. */
434 
435   invwin = (invwin - 1) & PSR_CWP;
436 
437   for (win = invwin; ; win = (win - 1) & PSR_CWP)
438     {
439       uint32 sp;
440       int i;
441 
442       sp = sregs.r[(win * 16 + 14) & 0x7f];
443 #if 1
444       if (sis_verbose > 2) {
445 	uint32 fp = sregs.r[(win * 16 + 30) & 0x7f];
446 	printf("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
447       }
448 #endif
449 
450       for (i = 0; i < 16; i++)
451 	memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
452 		      &ws);
453 
454       if (win == cwp)
455 	break;
456     }
457 }
458 
459 void
460 sim_resume(SIM_DESC sd, int step, int siggnal)
461 {
462     simstat = run_sim(&sregs, UINT64_MAX, 0);
463 
464     if (sis_gdb_break) flush_windows ();
465 }
466 
467 int
468 sim_trace (sd)
469      SIM_DESC sd;
470 {
471   /* FIXME: unfinished */
472   sim_resume (sd, 0, 0);
473   return 1;
474 }
475 
476 void
477 sim_do_command(sd, cmd)
478      SIM_DESC sd;
479     char           *cmd;
480 {
481     exec_cmd(&sregs, cmd);
482 }
483 
484 #if 0 /* FIXME: These shouldn't exist.  */
485 
486 int
487 sim_insert_breakpoint(int addr)
488 {
489     if (sregs.bptnum < BPT_MAX) {
490 	sregs.bpts[sregs.bptnum] = addr & ~0x3;
491 	sregs.bptnum++;
492 	if (sis_verbose)
493 	    (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr);
494 	return 0;
495     } else
496 	return 1;
497 }
498 
499 int
500 sim_remove_breakpoint(int addr)
501 {
502     int             i = 0;
503 
504     while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
505 	i++;
506     if (addr == sregs.bpts[i]) {
507 	for (; i < sregs.bptnum - 1; i++)
508 	    sregs.bpts[i] = sregs.bpts[i + 1];
509 	sregs.bptnum -= 1;
510 	if (sis_verbose)
511 	    (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr);
512 	return 0;
513     }
514     return 1;
515 }
516 
517 #endif
518