1/*
2 * This file is part of SIS.
3 *
4 * SIS, SPARC instruction simulator. Copyright (C) 1995 Jiri Gaisler, European
5 * 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 "config.h"
24#include <signal.h>
25#include <string.h>
26#ifdef HAVE_STDLIB_H
27#include <stdlib.h>
28#endif
29#include <stdio.h>
30#include <time.h>
31#include <sys/fcntl.h>
32#include "sis.h"
33#include <dis-asm.h>
34#include "sim-config.h"
35
36#define	VAL(x)	strtol(x,(char **)NULL,0)
37
38/* Structures and functions from readline library */
39
40typedef struct {
41  char *line;
42  char *data;
43} HIST_ENTRY;
44
45extern char *	readline PARAMS ((char *prompt));
46extern void	using_history PARAMS ((void));
47extern void	add_history PARAMS ((char *string));
48extern HIST_ENTRY *remove_history PARAMS ((int which));
49
50
51
52/* Command history buffer length - MUST be binary */
53#define HIST_LEN	64
54
55extern struct disassemble_info dinfo;
56extern struct pstate sregs;
57extern struct estate ebase;
58
59extern int      ctrl_c;
60extern int      nfp;
61extern int      ift;
62extern int      wrp;
63extern int      rom8;
64extern int      uben;
65extern int      sis_verbose;
66extern char    *sis_version;
67extern struct estate ebase;
68extern struct evcell evbuf[];
69extern struct irqcell irqarr[];
70extern int      irqpend, ext_irl;
71extern int      termsave;
72extern int      sparclite;
73extern int      dumbio;
74extern char     uart_dev1[];
75extern char     uart_dev2[];
76extern uint32   last_load_addr;
77
78#ifdef ERA
79extern int era;
80#endif
81
82int
83run_sim(sregs, icount, dis)
84    struct pstate  *sregs;
85    unsigned int    icount;
86    int             dis;
87{
88    int             irq, mexc, deb, asi;
89
90    sregs->starttime = time(NULL);
91    init_stdio();
92    if (sregs->err_mode) icount = 0;
93    deb = dis || sregs->histlen || sregs->bptnum;
94    irq = 0;
95    while (icount > 0) {
96
97	if (sregs->psr & 0x080)
98	    asi = 9;
99   	else
100	    asi = 8;
101	mexc = memory_read(asi, sregs->pc, &sregs->inst, 2, &sregs->hold);
102	sregs->icnt = 1;
103	if (sregs->annul) {
104	    sregs->annul = 0;
105	    sregs->pc = sregs->npc;
106	    sregs->npc = sregs->npc + 4;
107	} else {
108	    sregs->fhold = 0;
109	    if (ext_irl) irq = check_interrupts(sregs);
110	    if (!irq) {
111		if (mexc) {
112		    sregs->trap = I_ACC_EXC;
113		} else {
114		    if (deb) {
115	    		if ((sregs->bphit = check_bpt(sregs)) != 0) {
116            		    restore_stdio();
117	    		    return (BPT_HIT);
118	    		}
119		        if (sregs->histlen) {
120			    sregs->histbuf[sregs->histind].addr = sregs->pc;
121			    sregs->histbuf[sregs->histind].time = ebase.simtime;
122			    sregs->histind++;
123			    if (sregs->histind >= sregs->histlen)
124			        sregs->histind = 0;
125		        }
126		        if (dis) {
127			    printf(" %8u ", ebase.simtime);
128			    dis_mem(sregs->pc, 1, &dinfo);
129		        }
130		    }
131		    dispatch_instruction(sregs);
132		    icount--;
133		}
134	    }
135	    if (sregs->trap) {
136		irq = 0;
137		sregs->err_mode = execute_trap(sregs);
138        	if (sregs->err_mode) {
139	            error_mode(sregs->pc);
140	            icount = 0;
141	        }
142	    }
143	}
144	advance_time(sregs);
145	if (ctrl_c || (sregs->tlimit <= ebase.simtime)) {
146	    icount = 0;
147	    if (sregs->tlimit <= ebase.simtime) sregs->tlimit = -1;
148	}
149    }
150    sregs->tottime += time(NULL) - sregs->starttime;
151    restore_stdio();
152    if (sregs->err_mode)
153	return (ERROR);
154    if (ctrl_c) {
155	ctrl_c = 0;
156	return (CTRL_C);
157    }
158    return (TIME_OUT);
159}
160
161int
162main(argc, argv)
163    int             argc;
164    char          **argv;
165{
166
167    int             cont = 1;
168    int             stat = 1;
169    int             freq = 14;
170    int             copt = 0;
171
172    char           *cfile, *bacmd;
173    char           *cmdq[HIST_LEN];
174    int             cmdi = 0;
175    int             i;
176
177    cfile = 0;
178    for (i = 0; i < 64; i++)
179	cmdq[i] = 0;
180    printf("\n SIS - SPARC intruction simulator %s,  copyright Jiri Gaisler 1995\n", sis_version);
181    printf(" Bug-reports to jgais@wd.estec.esa.nl\n\n");
182    while (stat < argc) {
183	if (argv[stat][0] == '-') {
184	    if (strcmp(argv[stat], "-v") == 0) {
185		sis_verbose = 1;
186	    } else if (strcmp(argv[stat], "-c") == 0) {
187		if ((stat + 1) < argc) {
188		    copt = 1;
189		    cfile = argv[++stat];
190		}
191	    } else if (strcmp(argv[stat], "-nfp") == 0)
192		nfp = 1;
193	    else if (strcmp(argv[stat], "-ift") == 0)
194		ift = 1;
195	    else if (strcmp(argv[stat], "-wrp") == 0)
196		wrp = 1;
197	    else if (strcmp(argv[stat], "-rom8") == 0)
198		rom8 = 1;
199	    else if (strcmp(argv[stat], "-uben") == 0)
200		uben = 1;
201	    else if (strcmp(argv[stat], "-uart1") == 0) {
202		if ((stat + 1) < argc)
203		    strcpy(uart_dev1, argv[++stat]);
204	    } else if (strcmp(argv[stat], "-uart2") == 0) {
205		if ((stat + 1) < argc)
206		    strcpy(uart_dev2, argv[++stat]);
207	    } else if (strcmp(argv[stat], "-freq") == 0) {
208		if ((stat + 1) < argc)
209		    freq = VAL(argv[++stat]);
210	    } else if (strcmp(argv[stat], "-sparclite") == 0) {
211		sparclite = 1;
212#ifdef ERA
213	    } else if (strcmp(argv[stat], "-era") == 0) {
214		era = 1;
215#endif
216            } else if (strcmp(argv[stat], "-dumbio") == 0) {
217		dumbio = 1;
218	    } else {
219		printf("unknown option %s\n", argv[stat]);
220		usage();
221		exit(1);
222	    }
223	} else {
224	    last_load_addr = bfd_load(argv[stat]);
225	}
226	stat++;
227    }
228    if (nfp)
229	printf("FPU disabled\n");
230#ifdef ERA
231    if (era)
232	printf("ERA ECC emulation enabled\n");
233#endif
234    sregs.freq = freq;
235
236    INIT_DISASSEMBLE_INFO(dinfo, stdout, (fprintf_ftype) fprintf);
237    dinfo.endian = BFD_ENDIAN_BIG;
238
239    termsave = fcntl(0, F_GETFL, 0);
240    using_history();
241    init_signals();
242    ebase.simtime = 0;
243    reset_all();
244    init_bpt(&sregs);
245    init_sim();
246#ifdef STAT
247    reset_stat(&sregs);
248#endif
249
250    if (copt) {
251	bacmd = (char *) malloc(256);
252	strcpy(bacmd, "batch ");
253	strcat(bacmd, cfile);
254	exec_cmd(&sregs, bacmd);
255    }
256    while (cont) {
257
258	if (cmdq[cmdi] != 0) {
259#if 0
260	    remove_history(cmdq[cmdi]);
261#else
262	    remove_history(cmdi);
263#endif
264	    free(cmdq[cmdi]);
265	    cmdq[cmdi] = 0;
266	}
267	cmdq[cmdi] = readline("sis> ");
268	if (cmdq[cmdi] && *cmdq[cmdi])
269	    add_history(cmdq[cmdi]);
270	if (cmdq[cmdi])
271	    stat = exec_cmd(&sregs, cmdq[cmdi]);
272	else {
273	    puts("\n");
274	    exit(0);
275	}
276	switch (stat) {
277	case OK:
278	    break;
279	case CTRL_C:
280	    printf("\b\bInterrupt!\n");
281	case TIME_OUT:
282	    printf(" Stopped at time %d (%.3f ms)\n", ebase.simtime,
283	      ((double) ebase.simtime / (double) sregs.freq) / 1000.0);
284	    break;
285	case BPT_HIT:
286	    printf("breakpoint at 0x%08x reached\n", sregs.pc);
287	    sregs.bphit = 1;
288	    break;
289	case ERROR:
290	    printf("IU in error mode (%d)\n", sregs.trap);
291	    stat = 0;
292	    printf(" %8d ", ebase.simtime);
293	    dis_mem(sregs.pc, 1, &dinfo);
294	    break;
295	default:
296	    break;
297	}
298	ctrl_c = 0;
299	stat = OK;
300
301	cmdi = (cmdi + 1) & (HIST_LEN - 1);
302
303    }
304    return 0;
305}
306
307