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