sim: delete SIM_HAVE_FLATMEM support
[external/binutils.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