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