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