]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/erc32/interf.c
sim: common: change sim_read & sim_write to use void* buffers
[thirdparty/binutils-gdb.git] / sim / erc32 / interf.c
1 /* This file is part of SIS (SPARC instruction simulator)
2
3 Copyright (C) 1995-2022 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 <stdio.h>
25 #include <stdlib.h>
26 #include <sys/fcntl.h>
27 #include "sis.h"
28 #include "libiberty.h"
29 #include "bfd.h"
30 #include <dis-asm.h>
31 #include "sim-config.h"
32
33 #include "sim/sim.h"
34 #include "gdb/signals.h"
35
36 #define PSR_CWP 0x7
37
38 extern struct disassemble_info dinfo;
39 extern struct pstate sregs;
40 extern struct estate ebase;
41
42 extern int ctrl_c;
43 extern int nfp;
44 extern int ift;
45 extern int rom8;
46 extern int wrp;
47 extern int uben;
48 extern int sis_verbose;
49 extern char *sis_version;
50 extern struct estate ebase;
51 extern struct evcell evbuf[];
52 extern struct irqcell irqarr[];
53 extern int irqpend, ext_irl;
54 extern int sparclite;
55 extern int dumbio;
56 extern int sparclite_board;
57 extern int termsave;
58 extern char uart_dev1[], uart_dev2[];
59
60 int sis_gdb_break = 1;
61
62 host_callback *sim_callback;
63
64 int
65 run_sim(struct pstate *sregs, uint64_t icount, int dis)
66 {
67 int mexc, irq;
68
69 if (sis_verbose)
70 (*sim_callback->printf_filtered) (sim_callback, "resuming at %x\n",
71 sregs->pc);
72 init_stdio();
73 sregs->starttime = get_time();
74 irq = 0;
75 if ((sregs->pc != 0) && (ebase.simtime == 0))
76 boot_init();
77 while (!sregs->err_mode & (icount > 0)) {
78
79 sregs->fhold = 0;
80 sregs->hold = 0;
81 sregs->icnt = 1;
82
83 if (sregs->psr & 0x080)
84 sregs->asi = 8;
85 else
86 sregs->asi = 9;
87
88 #if 0 /* DELETE ME! for debugging purposes only */
89 if (sis_verbose > 1)
90 if (sregs->pc == 0 || sregs->npc == 0)
91 printf ("bogus pc or npc\n");
92 #endif
93 mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
94 #if 0 /* DELETE ME! for debugging purposes only */
95 if (sis_verbose > 2)
96 printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
97 sregs->pc, sregs->npc,
98 sregs->r[(((sregs->psr & 7) << 4) + 14) & 0x7f],
99 sregs->r[(((sregs->psr & 7) << 4) + 30) & 0x7f],
100 sregs->wim,
101 sregs->psr & 7,
102 sregs->inst);
103 #endif
104 if (sregs->annul) {
105 sregs->annul = 0;
106 sregs->icnt = 1;
107 sregs->pc = sregs->npc;
108 sregs->npc = sregs->npc + 4;
109 } else {
110 if (ext_irl) irq = check_interrupts(sregs);
111 if (!irq) {
112 if (mexc) {
113 sregs->trap = I_ACC_EXC;
114 } else {
115 if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) {
116 if (sis_verbose)
117 (*sim_callback->printf_filtered) (sim_callback,
118 "SW BP hit at %x\n", sregs->pc);
119 sim_halt();
120 restore_stdio();
121 clearerr(stdin);
122 return BPT_HIT;
123 } else
124 dispatch_instruction(sregs);
125 }
126 icount--;
127 }
128 if (sregs->trap) {
129 irq = 0;
130 sregs->err_mode = execute_trap(sregs);
131 }
132 }
133 advance_time(sregs);
134 if (ctrl_c) {
135 icount = 0;
136 }
137 }
138 sim_halt();
139 sregs->tottime += get_time() - sregs->starttime;
140 restore_stdio();
141 clearerr(stdin);
142 if (sregs->err_mode)
143 error_mode(sregs->pc);
144 if (sregs->err_mode)
145 return ERROR;
146 if (sregs->bphit) {
147 if (sis_verbose)
148 (*sim_callback->printf_filtered) (sim_callback,
149 "HW BP hit at %x\n", sregs->pc);
150 return BPT_HIT;
151 }
152 if (ctrl_c) {
153 ctrl_c = 0;
154 return CTRL_C;
155 }
156 return TIME_OUT;
157 }
158
159 static int ATTRIBUTE_PRINTF (3, 4)
160 fprintf_styled (void *stream, enum disassembler_style style,
161 const char *fmt, ...)
162 {
163 int ret;
164 FILE *out = (FILE *) stream;
165 va_list args;
166
167 va_start (args, fmt);
168 ret = vfprintf (out, fmt, args);
169 va_end (args);
170
171 return ret;
172 }
173
174 SIM_DESC
175 sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *callback,
176 struct bfd *abfd, char * const *argv)
177 {
178
179 int argc = 0;
180 int stat = 1;
181 int freq = 0;
182
183 sim_callback = callback;
184
185 argc = countargv (argv);
186 while (stat < argc) {
187 if (argv[stat][0] == '-') {
188 if (strcmp(argv[stat], "-v") == 0) {
189 sis_verbose++;
190 } else
191 if (strcmp(argv[stat], "-nfp") == 0) {
192 nfp = 1;
193 } else
194 if (strcmp(argv[stat], "-ift") == 0) {
195 ift = 1;
196 } else
197 if (strcmp(argv[stat], "-sparclite") == 0) {
198 sparclite = 1;
199 } else
200 if (strcmp(argv[stat], "-sparclite-board") == 0) {
201 sparclite_board = 1;
202 } else
203 if (strcmp(argv[stat], "-dumbio") == 0) {
204 dumbio = 1;
205 } else
206 if (strcmp(argv[stat], "-wrp") == 0) {
207 wrp = 1;
208 } else
209 if (strcmp(argv[stat], "-rom8") == 0) {
210 rom8 = 1;
211 } else
212 if (strcmp(argv[stat], "-uben") == 0) {
213 uben = 1;
214 } else
215 if (strcmp(argv[stat], "-uart1") == 0) {
216 if ((stat + 1) < argc)
217 strcpy(uart_dev1, argv[++stat]);
218 } else
219 if (strcmp(argv[stat], "-uart2") == 0) {
220 if ((stat + 1) < argc)
221 strcpy(uart_dev2, argv[++stat]);
222 } else
223 if (strcmp(argv[stat], "-nogdb") == 0) {
224 sis_gdb_break = 0;
225 } else
226 if (strcmp(argv[stat], "-freq") == 0) {
227 if ((stat + 1) < argc) {
228 freq = strtol(argv[++stat], (char **)NULL, 0);
229 }
230 } else
231 if (strncmp(argv[stat], "--sysroot=", sizeof("--sysroot=") - 1) == 0) {
232 /* Ignore until we start to support this. */
233 } else {
234 (*sim_callback->printf_filtered) (sim_callback,
235 "unknown option %s\n",
236 argv[stat]);
237 }
238 } else
239 bfd_load(argv[stat]);
240 stat++;
241 }
242
243 if (sis_verbose) {
244 (*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
245 (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
246 if (nfp)
247 (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
248 if (sparclite)
249 (*sim_callback->printf_filtered) (sim_callback, "simulating Sparclite\n");
250 if (dumbio)
251 (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
252 if (sis_gdb_break == 0)
253 (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
254 if (freq)
255 (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
256 }
257
258 sregs.freq = freq ? freq : 15;
259 #ifdef F_GETFL
260 termsave = fcntl(0, F_GETFL, 0);
261 #endif
262 INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf,
263 fprintf_styled);
264 #ifdef HOST_LITTLE_ENDIAN
265 dinfo.endian = BFD_ENDIAN_LITTLE;
266 #else
267 dinfo.endian = BFD_ENDIAN_BIG;
268 #endif
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
279 void
280 sim_close(SIM_DESC sd, int quitting)
281 {
282
283 exit_sim();
284 #ifdef F_SETFL
285 fcntl(0, F_SETFL, termsave);
286 #endif
287 }
288
289 SIM_RC
290 sim_load(SIM_DESC sd, const char *prog, bfd *abfd, int from_tty)
291 {
292 bfd_load (prog);
293 return SIM_RC_OK;
294 }
295
296 SIM_RC
297 sim_create_inferior(SIM_DESC sd, bfd *abfd, char * const *argv,
298 char * const *env)
299 {
300 bfd_vma start_address = 0;
301 if (abfd != NULL)
302 start_address = bfd_get_start_address (abfd);
303
304 ebase.simtime = 0;
305 reset_all();
306 reset_stat(&sregs);
307 sregs.pc = start_address & ~3;
308 sregs.npc = sregs.pc + 4;
309 return SIM_RC_OK;
310 }
311
312 int
313 sim_store_register(SIM_DESC sd, int regno, unsigned char *value, int length)
314 {
315 int regval;
316
317 regval = (value[0] << 24) | (value[1] << 16)
318 | (value[2] << 8) | value[3];
319 set_regi(&sregs, regno, regval);
320 return length;
321 }
322
323
324 int
325 sim_fetch_register(SIM_DESC sd, int regno, unsigned char *buf, int length)
326 {
327 get_regi(&sregs, regno, buf);
328 return -1;
329 }
330
331 int
332 sim_write (SIM_DESC sd, SIM_ADDR mem, const void *buffer, int length)
333 {
334 int i, len;
335 const unsigned char *data = buffer;
336
337 for (i = 0; i < length; i++) {
338 sis_memory_write ((mem + i) ^ EBT, &data[i], 1);
339 }
340 return length;
341 }
342
343 int
344 sim_read (SIM_DESC sd, SIM_ADDR mem, void *buffer, int length)
345 {
346 int i, len;
347 unsigned char *data = buffer;
348
349 for (i = 0; i < length; i++) {
350 sis_memory_read ((mem + i) ^ EBT, &data[i], 1);
351 }
352 return length;
353 }
354
355 void
356 sim_info(SIM_DESC sd, int verbose)
357 {
358 show_stat(&sregs);
359 }
360
361 int simstat = OK;
362
363 void
364 sim_stop_reason(SIM_DESC sd, enum sim_stop *reason, int *sigrc)
365 {
366
367 switch (simstat) {
368 case CTRL_C:
369 *reason = sim_stopped;
370 *sigrc = GDB_SIGNAL_INT;
371 break;
372 case OK:
373 case TIME_OUT:
374 case BPT_HIT:
375 *reason = sim_stopped;
376 *sigrc = GDB_SIGNAL_TRAP;
377 break;
378 case ERROR:
379 *sigrc = 0;
380 *reason = sim_exited;
381 }
382 ctrl_c = 0;
383 simstat = OK;
384 }
385
386 /* Flush all register windows out to the stack. Starting after the invalid
387 window, flush all windows up to, and including the current window. This
388 allows GDB to do backtraces and look at local variables for frames that
389 are still in the register windows. Note that strictly speaking, this
390 behavior is *wrong* for several reasons. First, it doesn't use the window
391 overflow handlers. It therefore assumes standard frame layouts and window
392 handling policies. Second, it changes system state behind the back of the
393 target program. I expect this to mainly pose problems when debugging trap
394 handlers.
395 */
396
397 static void
398 flush_windows (void)
399 {
400 int invwin;
401 int cwp;
402 int win;
403 int ws;
404
405 /* Keep current window handy */
406
407 cwp = sregs.psr & PSR_CWP;
408
409 /* Calculate the invalid window from the wim. */
410
411 for (invwin = 0; invwin <= PSR_CWP; invwin++)
412 if ((sregs.wim >> invwin) & 1)
413 break;
414
415 /* Start saving with the window after the invalid window. */
416
417 invwin = (invwin - 1) & PSR_CWP;
418
419 for (win = invwin; ; win = (win - 1) & PSR_CWP)
420 {
421 uint32_t sp;
422 int i;
423
424 sp = sregs.r[(win * 16 + 14) & 0x7f];
425 #if 1
426 if (sis_verbose > 2) {
427 uint32_t fp = sregs.r[(win * 16 + 30) & 0x7f];
428 printf("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
429 }
430 #endif
431
432 for (i = 0; i < 16; i++)
433 memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
434 &ws);
435
436 if (win == cwp)
437 break;
438 }
439 }
440
441 void
442 sim_resume(SIM_DESC sd, int step, int siggnal)
443 {
444 simstat = run_sim(&sregs, UINT64_MAX, 0);
445
446 if (sis_gdb_break) flush_windows ();
447 }
448
449 void
450 sim_do_command(SIM_DESC sd, const char *cmd)
451 {
452 exec_cmd(&sregs, cmd);
453 }
454
455 char **
456 sim_complete_command (SIM_DESC sd, const char *text, const char *word)
457 {
458 return NULL;
459 }
460
461 char *
462 sim_memory_map (SIM_DESC sd)
463 {
464 return NULL;
465 }
466
467 #if 0 /* FIXME: These shouldn't exist. */
468
469 int
470 sim_insert_breakpoint(int addr)
471 {
472 if (sregs.bptnum < BPT_MAX) {
473 sregs.bpts[sregs.bptnum] = addr & ~0x3;
474 sregs.bptnum++;
475 if (sis_verbose)
476 (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr);
477 return 0;
478 } else
479 return 1;
480 }
481
482 int
483 sim_remove_breakpoint(int addr)
484 {
485 int i = 0;
486
487 while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
488 i++;
489 if (addr == sregs.bpts[i]) {
490 for (; i < sregs.bptnum - 1; i++)
491 sregs.bpts[i] = sregs.bpts[i + 1];
492 sregs.bptnum -= 1;
493 if (sis_verbose)
494 (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr);
495 return 0;
496 }
497 return 1;
498 }
499
500 #endif