interf.c revision 1.1.1.7
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
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 * 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
265void
266sim_close(sd, quitting)
267     SIM_DESC sd;
268     int quitting;
269{
270
271    exit_sim();
272    fcntl(0, F_SETFL, termsave);
273
274};
275
276SIM_RC
277sim_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
287SIM_RC
288sim_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
306int
307sim_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
322int
323sim_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
333int
334sim_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
344int
345sim_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
355void
356sim_info(sd, verbose)
357     SIM_DESC sd;
358     int verbose;
359{
360    show_stat(&sregs);
361}
362
363int             simstat = OK;
364
365void
366sim_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
402static void
403flush_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
446void
447sim_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
454void
455sim_do_command(sd, cmd)
456     SIM_DESC sd;
457     const char *cmd;
458{
459    exec_cmd(&sregs, cmd);
460}
461
462char **
463sim_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
470int
471sim_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
483int
484sim_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