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