interf.c revision 1.1.1.4
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
40extern struct disassemble_info dinfo;
41extern struct pstate sregs;
42extern struct estate ebase;
43
44extern int	current_target_byte_order;
45extern int      ctrl_c;
46extern int      nfp;
47extern int      ift;
48extern int      rom8;
49extern int      wrp;
50extern int      uben;
51extern int      sis_verbose;
52extern char    *sis_version;
53extern struct estate ebase;
54extern struct evcell evbuf[];
55extern struct irqcell irqarr[];
56extern int      irqpend, ext_irl;
57extern int      sparclite;
58extern int      dumbio;
59extern int      sparclite_board;
60extern int      termsave;
61extern char     uart_dev1[], uart_dev2[];
62
63int             sis_gdb_break = 1;
64
65host_callback *sim_callback;
66
67int
68run_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
164void
165sim_set_callbacks (ptr)
166     host_callback *ptr;
167{
168  sim_callback = ptr;
169}
170
171void
172sim_size (memsize)
173     int memsize;
174{
175}
176
177SIM_DESC
178sim_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
279void
280sim_close(sd, quitting)
281     SIM_DESC sd;
282     int quitting;
283{
284
285    exit_sim();
286    fcntl(0, F_SETFL, termsave);
287
288};
289
290SIM_RC
291sim_load(sd, prog, abfd, from_tty)
292     SIM_DESC sd;
293     const char *prog;
294     bfd *abfd;
295     int from_tty;
296{
297    bfd_load (prog);
298    return SIM_RC_OK;
299}
300
301SIM_RC
302sim_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
320int
321sim_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
340int
341sim_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
351int
352sim_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
361int
362sim_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
371void
372sim_info(sd, verbose)
373     SIM_DESC sd;
374     int verbose;
375{
376    show_stat(&sregs);
377}
378
379int             simstat = OK;
380
381void
382sim_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
418static void
419flush_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
462void
463sim_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
470int
471sim_trace (sd)
472     SIM_DESC sd;
473{
474  /* FIXME: unfinished */
475  sim_resume (sd, 0, 0);
476  return 1;
477}
478
479void
480sim_do_command(sd, cmd)
481     SIM_DESC sd;
482     const char *cmd;
483{
484    exec_cmd(&sregs, cmd);
485}
486
487char **
488sim_complete_command (SIM_DESC sd, const char *text, const char *word)
489{
490  return NULL;
491}
492
493#if 0 /* FIXME: These shouldn't exist.  */
494
495int
496sim_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
508int
509sim_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