Correct check for endianness
[external/binutils.git] / sim / erc32 / interf.c
1 /* This file is part of SIS (SPARC instruction simulator)
2
3    Copyright (C) 1995-2017 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 * const *argv;
166 {
167
168     int             argc = 0;
169     int             stat = 1;
170     int             freq = 0;
171
172     sim_callback = callback;
173
174     argc = countargv (argv);
175     while (stat < argc) {
176         if (argv[stat][0] == '-') {
177             if (strcmp(argv[stat], "-v") == 0) {
178                 sis_verbose++;
179             } else
180             if (strcmp(argv[stat], "-nfp") == 0) {
181                 nfp = 1;
182             } else
183             if (strcmp(argv[stat], "-ift") == 0) {
184                 ift = 1;
185             } else
186             if (strcmp(argv[stat], "-sparclite") == 0) {
187                 sparclite = 1;
188             } else
189             if (strcmp(argv[stat], "-sparclite-board") == 0) {
190                 sparclite_board = 1;
191             } else 
192             if (strcmp(argv[stat], "-dumbio") == 0) {
193                 dumbio = 1;
194             } else
195             if (strcmp(argv[stat], "-wrp") == 0) {
196                 wrp = 1;
197             } else
198             if (strcmp(argv[stat], "-rom8") == 0) {
199                 rom8 = 1;
200             } else 
201             if (strcmp(argv[stat], "-uben") == 0) {
202                 uben = 1;
203             } else 
204             if (strcmp(argv[stat], "-uart1") == 0) {
205                 if ((stat + 1) < argc)
206                     strcpy(uart_dev1, argv[++stat]);
207             } else
208             if (strcmp(argv[stat], "-uart2") == 0) {
209                 if ((stat + 1) < argc)
210                     strcpy(uart_dev2, argv[++stat]);
211             } else
212             if (strcmp(argv[stat], "-nogdb") == 0) {
213                 sis_gdb_break = 0;
214             } else
215             if (strcmp(argv[stat], "-freq") == 0) {
216                 if ((stat + 1) < argc) {
217                     freq = strtol(argv[++stat], (char **)NULL, 0);
218                 }
219             } else
220             if (strncmp(argv[stat], "--sysroot=", sizeof("--sysroot=") - 1) == 0) {
221                 /* Ignore until we start to support this.  */
222             } else {
223                 (*sim_callback->printf_filtered) (sim_callback,
224                                                   "unknown option %s\n",
225                                                   argv[stat]);
226             }
227         } else
228             bfd_load(argv[stat]);
229         stat++;
230     }
231
232     if (sis_verbose) {
233         (*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
234         (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
235         if (nfp)
236           (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
237         if (sparclite)
238           (*sim_callback->printf_filtered) (sim_callback, "simulating Sparclite\n");
239         if (dumbio)
240           (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
241         if (sis_gdb_break == 0)
242           (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
243         if (freq)
244           (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
245     }
246
247     sregs.freq = freq ? freq : 15;
248     termsave = fcntl(0, F_GETFL, 0);
249     INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
250 #ifdef HOST_LITTLE_ENDIAN
251     dinfo.endian = BFD_ENDIAN_LITTLE;
252 #else
253     dinfo.endian = BFD_ENDIAN_BIG;
254 #endif
255     reset_all();
256     ebase.simtime = 0;
257     init_sim();
258     init_bpt(&sregs);
259     reset_stat(&sregs);
260
261     /* Fudge our descriptor for now.  */
262     return (SIM_DESC) 1;
263 }
264
265 void
266 sim_close(sd, quitting)
267      SIM_DESC sd;
268      int quitting;
269 {
270
271     exit_sim();
272     fcntl(0, F_SETFL, termsave);
273
274 };
275
276 SIM_RC
277 sim_load(sd, prog, abfd, from_tty)
278      SIM_DESC sd;
279      const char *prog;
280      bfd *abfd;
281      int from_tty;
282 {
283     bfd_load (prog);
284     return SIM_RC_OK;
285 }
286
287 SIM_RC
288 sim_create_inferior(sd, abfd, argv, env)
289      SIM_DESC sd;
290      struct bfd *abfd;
291      char * const *argv;
292      char * const *env;
293 {
294     bfd_vma start_address = 0;
295     if (abfd != NULL)
296       start_address = bfd_get_start_address (abfd);
297
298     ebase.simtime = 0;
299     reset_all();
300     reset_stat(&sregs);
301     sregs.pc = start_address & ~3;
302     sregs.npc = sregs.pc + 4;
303     return SIM_RC_OK;
304 }
305
306 int
307 sim_store_register(sd, regno, value, length)
308     SIM_DESC sd;
309     int             regno;
310     unsigned char  *value;
311     int length;
312 {
313     int regval;
314
315     regval = (value[0] << 24) | (value[1] << 16)
316                  | (value[2] << 8) | value[3];
317     set_regi(&sregs, regno, regval);
318     return length;
319 }
320
321
322 int
323 sim_fetch_register(sd, regno, buf, length)
324      SIM_DESC sd;
325     int             regno;
326     unsigned char  *buf;
327      int length;
328 {
329     get_regi(&sregs, regno, buf);
330     return -1;
331 }
332
333 int
334 sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length)
335 {
336     int i, len;
337
338     for (i = 0; i < length; i++) {
339         sis_memory_write ((mem + i) ^ EBT, &buf[i], 1);
340     }
341     return length;
342 }
343
344 int
345 sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
346 {
347     int i, len;
348
349     for (i = 0; i < length; i++) {
350         sis_memory_read ((mem + i) ^ EBT, &buf[i], 1);
351     }
352     return length;
353 }
354
355 void
356 sim_info(sd, verbose)
357      SIM_DESC sd;
358      int verbose;
359 {
360     show_stat(&sregs);
361 }
362
363 int             simstat = OK;
364
365 void
366 sim_stop_reason(sd, reason, sigrc)
367      SIM_DESC sd;
368      enum sim_stop * reason;
369      int *sigrc;
370 {
371
372     switch (simstat) {
373         case CTRL_C:
374         *reason = sim_stopped;
375         *sigrc = GDB_SIGNAL_INT;
376         break;
377     case OK:
378     case TIME_OUT:
379     case BPT_HIT:
380         *reason = sim_stopped;
381         *sigrc = GDB_SIGNAL_TRAP;
382         break;
383     case ERROR:
384         *sigrc = 0;
385         *reason = sim_exited;
386     }
387     ctrl_c = 0;
388     simstat = OK;
389 }
390
391 /* Flush all register windows out to the stack.  Starting after the invalid
392    window, flush all windows up to, and including the current window.  This
393    allows GDB to do backtraces and look at local variables for frames that
394    are still in the register windows.  Note that strictly speaking, this
395    behavior is *wrong* for several reasons.  First, it doesn't use the window
396    overflow handlers.  It therefore assumes standard frame layouts and window
397    handling policies.  Second, it changes system state behind the back of the
398    target program.  I expect this to mainly pose problems when debugging trap
399    handlers.
400 */
401
402 static void
403 flush_windows ()
404 {
405   int invwin;
406   int cwp;
407   int win;
408   int ws;
409
410   /* Keep current window handy */
411
412   cwp = sregs.psr & PSR_CWP;
413
414   /* Calculate the invalid window from the wim. */
415
416   for (invwin = 0; invwin <= PSR_CWP; invwin++)
417     if ((sregs.wim >> invwin) & 1)
418       break;
419
420   /* Start saving with the window after the invalid window. */
421
422   invwin = (invwin - 1) & PSR_CWP;
423
424   for (win = invwin; ; win = (win - 1) & PSR_CWP)
425     {
426       uint32 sp;
427       int i;
428
429       sp = sregs.r[(win * 16 + 14) & 0x7f];
430 #if 1
431       if (sis_verbose > 2) {
432         uint32 fp = sregs.r[(win * 16 + 30) & 0x7f];
433         printf("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
434       }
435 #endif
436
437       for (i = 0; i < 16; i++)
438         memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
439                       &ws);
440
441       if (win == cwp)
442         break;
443     }
444 }
445
446 void
447 sim_resume(SIM_DESC sd, int step, int siggnal)
448 {
449     simstat = run_sim(&sregs, UINT64_MAX, 0);
450
451     if (sis_gdb_break) flush_windows ();
452 }
453
454 void
455 sim_do_command(sd, cmd)
456      SIM_DESC sd;
457      const char *cmd;
458 {
459     exec_cmd(&sregs, cmd);
460 }
461
462 char **
463 sim_complete_command (SIM_DESC sd, const char *text, const char *word)
464 {
465   return NULL;
466 }
467
468 #if 0 /* FIXME: These shouldn't exist.  */
469
470 int
471 sim_insert_breakpoint(int addr)
472 {
473     if (sregs.bptnum < BPT_MAX) {
474         sregs.bpts[sregs.bptnum] = addr & ~0x3;
475         sregs.bptnum++;
476         if (sis_verbose)
477             (*sim_callback->printf_filtered) (sim_callback, "inserted HW BP at %x\n", addr);
478         return 0;
479     } else
480         return 1;
481 }
482
483 int
484 sim_remove_breakpoint(int addr)
485 {
486     int             i = 0;
487
488     while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
489         i++;
490     if (addr == sregs.bpts[i]) {
491         for (; i < sregs.bptnum - 1; i++)
492             sregs.bpts[i] = sregs.bpts[i + 1];
493         sregs.bptnum -= 1;
494         if (sis_verbose)
495             (*sim_callback->printf_filtered) (sim_callback, "removed HW BP at %x\n", addr);
496         return 0;
497     }
498     return 1;
499 }
500
501 #endif