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