interf.c revision 1.1.1.5
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
36extern struct disassemble_info dinfo;
37extern struct pstate sregs;
38extern struct estate ebase;
39
40extern int      ctrl_c;
41extern int      nfp;
42extern int      ift;
43extern int      rom8;
44extern int      wrp;
45extern int      uben;
46extern int      sis_verbose;
47extern char    *sis_version;
48extern struct estate ebase;
49extern struct evcell evbuf[];
50extern struct irqcell irqarr[];
51extern int      irqpend, ext_irl;
52extern int      sparclite;
53extern int      dumbio;
54extern int      sparclite_board;
55extern int      termsave;
56extern char     uart_dev1[], uart_dev2[];
57
58int             sis_gdb_break = 1;
59
60host_callback *sim_callback;
61
62int
63run_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
160SIM_DESC
161sim_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
266void
267sim_close(sd, quitting)
268     SIM_DESC sd;
269     int quitting;
270{
271
272    exit_sim();
273    fcntl(0, F_SETFL, termsave);
274
275};
276
277SIM_RC
278sim_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
288SIM_RC
289sim_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
307int
308sim_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
323int
324sim_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
334int
335sim_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
345int
346sim_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
356void
357sim_info(sd, verbose)
358     SIM_DESC sd;
359     int verbose;
360{
361    show_stat(&sregs);
362}
363
364int             simstat = OK;
365
366void
367sim_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
403static void
404flush_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
447void
448sim_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
455void
456sim_do_command(sd, cmd)
457     SIM_DESC sd;
458     const char *cmd;
459{
460    exec_cmd(&sregs, cmd);
461}
462
463char **
464sim_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
471int
472sim_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
484int
485sim_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