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