* erc32.c (mec_reset mec_read mec_write memory_read memory_write),
[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 "sis.h"
27 #include "bfd.h"
28 #include <dis-asm.h>
29
30 #ifndef fprintf
31 extern          fprintf();
32 #endif
33
34 #define VAL(x)  strtol(x,(char *)NULL,0)
35
36 extern char   **buildargv(char *input);
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      sis_verbose;
45 extern char    *sis_version;
46 extern struct estate ebase;
47 extern struct evcell evbuf[];
48 extern struct irqcell irqarr[];
49 extern int      irqpend, ext_irl;
50 extern char     uart_dev1[], uart_dev2[];
51
52 int             sis_gdb_break = 1;
53
54 #ifdef IUREV0
55 extern int      iurev0;
56 #endif
57
58 #ifdef MECREV0
59 extern int      mecrev0;
60 #endif
61
62 run_sim(sregs, go, icount, dis)
63     struct pstate  *sregs;
64     int             go;
65     unsigned int    icount;
66     int             dis;
67 {
68     int             mexc, ws;
69
70     if (sis_verbose)
71         printf_filtered("resuming at %x\n", sregs->pc);
72     sregs->starttime = time(NULL);
73     while ((!sregs->err_mode & (go || (icount > 0))) &&
74            ((sregs->bptnum == 0) || !(sregs->bphit = check_bpt(sregs)))) {
75
76         sregs->fhold = 0;
77         sregs->hold = 0;
78         sregs->icnt = 0;
79
80         check_interrupts(sregs);
81         if (sregs->trap) {
82             sregs->err_mode = execute_trap(sregs);
83         } else {
84             if (sregs->psr & 0x080)
85                 sregs->asi = 8;
86             else
87                 sregs->asi = 9;
88 #ifdef IUREV0
89             if (iurev0 && sregs->rett_err) {
90                 sregs->asi &= ~0x1;
91                 sregs->asi |= ((sregs->psr & 0x040) >> 6);
92             }
93 #endif
94
95             mexc = memory_read(sregs->asi, sregs->pc, &sregs->inst, &sregs->hold);
96             if (sregs->annul) {
97                 sregs->annul = 0;
98                 sregs->icnt = 1;
99                 sregs->pc = sregs->npc;
100                 sregs->npc = sregs->npc + 4;
101             } else {
102                 if (mexc) {
103                     sregs->trap = I_ACC_EXC;
104                 } else {
105                     if (sregs->histlen) {
106                         sregs->histbuf[sregs->histind].addr = sregs->pc;
107                         sregs->histbuf[sregs->histind].time = ebase.simtime;
108                         sregs->histind++;
109                         if (sregs->histind >= sregs->histlen)
110                             sregs->histind = 0;
111                     }
112                     if (dis) {
113                         printf(" %8d ", ebase.simtime);
114                         dis_mem(sregs->pc, 1, &dinfo);
115                     }
116                     if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) {
117                         if (sis_verbose)
118                             printf_filtered("SW BP hit at %x\n", sregs->pc);
119                         return (BPT_HIT);
120                     } else
121                         dispatch_instruction(sregs);
122                 }
123                 icount--;
124             }
125             if (sregs->trap) {
126                 sregs->err_mode = execute_trap(sregs);
127             }
128         }
129         advance_time(sregs);
130         if (ctrl_c) {
131             go = icount = 0;
132         }
133     }
134     sregs->tottime += time(NULL) - sregs->starttime;
135     if (sregs->err_mode)
136         error_mode(sregs->pc);
137     if (sregs->err_mode)
138         return (ERROR);
139     if (sregs->bphit) {
140         if (sis_verbose)
141             printf_filtered("HW BP hit at %x\n", sregs->pc);
142         return (BPT_HIT);
143     }
144     if (ctrl_c) {
145         ctrl_c = 0;
146         return (CTRL_C);
147     }
148     return (TIME_OUT);
149 }
150
151
152 void
153 sim_open(char *args)
154 {
155
156     int             argc = 0;
157     char          **argv;
158     int             cont = 1;
159     int             stat = 0;
160     int             grdl = 0;
161     int             freq = 15;
162
163     printf_filtered("\n SIS - SPARC instruction simulator %s\n", sis_version);
164     printf_filtered(" Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
165     argv = buildargv(args);
166     if (argv != NULL)
167         while (argv[argc])
168             argc++;
169     while (stat < argc) {
170         if (argv[stat][0] == '-') {
171             if (strcmp(argv[stat], "-v") == 0) {
172                 sis_verbose = 1;
173             }
174 #ifdef IUREV0
175             if (strcmp(argv[stat], "-iurev0") == 0) {
176                 iurev0 = 1;
177                 printf_filtered(" simulating IU rev.0 jmpl/restore bug\n");
178             }
179 #endif
180 #ifdef MECREV0
181             if (strcmp(argv[stat], "-mecrev0") == 0) {
182                 mecrev0 = 1;
183                 printf_filtered(" simulating MEC rev.0 timer and uart interrupt bug\n");
184             }
185 #endif
186             if (strcmp(argv[stat], "-nfp") == 0) {
187                 printf_filtered("no FPU\n");
188                 nfp = 1;
189             }
190             if (strcmp(argv[stat], "-uart1") == 0) {
191                 if ((stat + 1) < argc)
192                     strcpy(uart_dev1, argv[++stat]);
193             }
194             if (strcmp(argv[stat], "-uart2") == 0) {
195                 if ((stat + 1) < argc)
196                     strcpy(uart_dev2, argv[++stat]);
197             }
198             if (strcmp(argv[stat], "-nogdb") == 0) {
199                 printf_filtered("disabling GDB trap handling for breakpoints\n");
200                 sis_gdb_break = 0;
201             }
202             if (strcmp(argv[stat], "-freq") == 0)
203                 if ((stat + 1) < argc) {
204                     freq = VAL(argv[++stat]);
205                     printf_filtered(" ERC32 freq %d Mhz\n", freq);
206                 }
207         } else
208             bfd_load(argv[stat]);
209         stat++;
210     }
211     freeargv(argv);
212     sregs.freq = freq;
213
214     INIT_DISASSEMBLE_INFO(dinfo, stdout, fprintf);
215     init_signals();
216     reset_all();
217     ebase.simtime = 0;
218     init_sim();
219     init_bpt(&sregs);
220     reset_stat(&sregs);
221 }
222
223 void
224 sim_close(int quitting)
225 {
226
227     exit_sim();
228
229 };
230
231 /* Return non-zero if the caller should handle the load. Zero if
232      we have loaded the image. */
233 int
234 sim_load(char *prog, int from_tty)
235 {
236     bfd_load(prog);
237     return (0);
238 }
239
240 void
241 sim_create_inferior(int start_address, char **argv, char **env)
242 {
243     ebase.simtime = 0;
244     reset_all();
245     reset_stat(&sregs);
246     sregs.pc = start_address & ~3;
247     sregs.npc = sregs.pc + 4;
248
249 }
250
251 void
252 sim_store_register(regno, value)
253     int             regno;
254     unsigned char  *value;
255 {
256     /* FIXME: Review the computation of regval.  */
257     int             regval = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
258     set_regi(&sregs, regno, regval);
259 }
260
261
262 void
263 sim_fetch_register(regno, buf)
264     int             regno;
265     unsigned char  *buf;
266 {
267     get_regi(&sregs, regno, buf);
268 }
269
270 int
271 sim_write(mem, buf, length)
272     int             mem;
273     unsigned char  *buf;
274     int             length;
275 {
276     return (sis_memory_write(mem, buf, length));
277 }
278
279 int
280 sim_read(int mem, unsigned char *buf, int length)
281 {
282     return (sis_memory_read(mem, buf, length));
283 }
284
285 void
286 sim_info(int verbose)
287 {
288     show_stat(&sregs);
289
290
291 }
292
293 int             simstat = OK;
294
295 enum sim_stop {
296     sim_exited, sim_stopped, sim_signalled
297 };
298
299 void
300 sim_stop_reason(enum sim_stop * reason, int *sigrc)
301 {
302
303     switch (simstat) {
304         case CTRL_C:
305         *reason = sim_stopped;
306         *sigrc = SIGINT;
307         break;
308     case OK:
309     case TIME_OUT:
310     case BPT_HIT:
311         *reason = sim_stopped;
312         *sigrc = SIGTRAP;
313         break;
314     case ERROR:
315         *sigrc = 0;
316         *reason = sim_exited;
317     }
318     ctrl_c = 0;
319     simstat = OK;
320 }
321
322 /* Flush all register windows out to the stack.  Starting after the invalid
323    window, flush all windows up to, and including the current window.  This
324    allows GDB to do backtraces and look at local variables for frames that
325    are still in the register windows.  Note that strictly speaking, this
326    behavior is *wrong* for several reasons.  First, it doesn't use the window
327    overflow handlers.  It therefore assumes standard frame layouts and window
328    handling policies.  Second, it changes system state behind the back of the
329    target program.  I expect this to mainly pose problems when debugging trap
330    handlers.
331 */
332
333 #define PSR_CWP 0x7
334
335 static void
336 flush_windows ()
337 {
338   int invwin;
339   int cwp;
340   int win;
341   int ws;
342
343   /* Keep current window handy */
344
345   cwp = sregs.psr & PSR_CWP;
346
347   /* Calculate the invalid window from the wim. */
348
349   for (invwin = 0; invwin <= PSR_CWP; invwin++)
350     if ((sregs.wim >> invwin) & 1)
351       break;
352
353   /* Start saving with the window after the invalid window. */
354
355   invwin = (invwin - 1) & PSR_CWP;
356
357   for (win = invwin; ; win = (win - 1) & PSR_CWP)
358     {
359       uint32 sp;
360       int i;
361
362       sp = sregs.r[(win * 16 + 14) & 0x7f];
363
364       for (i = 0; i < 16; i++)
365         memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
366                       &ws);
367
368       if (win == cwp)
369         break;
370     }
371 }
372
373 void
374 sim_resume(int step, int siggnal)
375 {
376     simstat = run_sim(&sregs, 1, 0, 0);
377
378     flush_windows ();
379 }
380
381 void
382 sim_kill(void)
383 {
384 };
385
386
387
388 void
389 sim_do_command(cmd)
390     char           *cmd;
391 {
392     exec_cmd(&sregs, cmd);
393 }
394
395
396
397 int
398 sim_insert_breakpoint(int addr)
399 {
400     if (sregs.bptnum < BPT_MAX) {
401         sregs.bpts[sregs.bptnum] = addr & ~0x3;
402         sregs.bptnum++;
403         if (sis_verbose)
404             printf_filtered("inserted HW BP at %x\n", addr);
405         return 0;
406     } else
407         return 1;
408 }
409
410 int
411 sim_remove_breakpoint(int addr)
412 {
413     int             i = 0;
414
415     while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
416         i++;
417     if (addr == sregs.bpts[i]) {
418         for (; i < sregs.bptnum - 1; i++)
419             sregs.bpts[i] = sregs.bpts[i + 1];
420         sregs.bptnum -= 1;
421         if (sis_verbose)
422             printf_filtered("removed HW BP at %x\n", addr);
423         return 0;
424     }
425     return 1;
426 }