Fix sim build when configured with --enable-plugins
[external/binutils.git] / sim / erc32 / func.c
1 /*
2  * func.c, misc simulator functions. This file is part of SIS.
3  * 
4  * SIS, SPARC instruction simulator V1.8 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 <ctype.h>
29 #include "sis.h"
30 #include "end.h"
31 #include <dis-asm.h>
32 #include "sim-config.h"
33
34
35 #define VAL(x)  strtoul(x,(char **)NULL,0)
36
37 extern int      current_target_byte_order;
38 struct disassemble_info dinfo;
39 struct pstate   sregs;
40 extern struct estate ebase;
41 int             ctrl_c = 0;
42 int             sis_verbose = 0;
43 char           *sis_version = "2.7.5";
44 int             nfp = 0;
45 int             ift = 0;
46 int             wrp = 0;
47 int             rom8 = 0;
48 int             uben = 0;
49 int             termsave;
50 int             sparclite = 0;          /* emulating SPARClite instructions? */
51 int             sparclite_board = 0;    /* emulating SPARClite board RAM? */
52 char            uart_dev1[128] = "";
53 char            uart_dev2[128] = "";
54 extern  int     ext_irl;
55 uint32          last_load_addr = 0;
56
57 #ifdef ERRINJ
58 uint32          errcnt = 0;
59 uint32          errper = 0;
60 uint32          errtt = 0;
61 uint32          errftt = 0;
62 uint32          errmec = 0;
63 #endif
64
65 /* Forward declarations */
66
67 static int      batch PARAMS ((struct pstate *sregs, char *fname));
68 static void     set_rega PARAMS ((struct pstate *sregs, char *reg, uint32 rval));
69 static void     disp_reg PARAMS ((struct pstate *sregs, char *reg));
70 static uint32   limcalc PARAMS ((float32 freq));
71 static void     int_handler PARAMS ((int32 sig));
72 static void     init_event PARAMS ((void));
73 static int      disp_fpu PARAMS ((struct pstate  *sregs));
74 static void     disp_regs PARAMS ((struct pstate  *sregs, int cwp));
75 static void     disp_ctrl PARAMS ((struct pstate *sregs));
76 static void     disp_mem PARAMS ((uint32 addr, uint32 len));
77
78 static int 
79 batch(sregs, fname)
80     struct pstate  *sregs;
81     char           *fname;
82 {
83     FILE           *fp;
84     char            lbuf[1024];
85
86     if ((fp = fopen(fname, "r")) == NULL) {
87         fprintf(stderr, "couldn't open batch file %s\n", fname);
88         return (0);
89     }
90     while (!feof(fp)) {
91         lbuf[0] = 0;
92         fgets(lbuf, 1023, fp);
93         if ((strlen(lbuf) > 0) && (lbuf[strlen(lbuf) - 1] == '\n'))
94             lbuf[strlen(lbuf) - 1] = 0;
95         printf("sis> %s\n", lbuf);
96         exec_cmd(sregs, lbuf);
97     }
98     fclose(fp);
99     return (1);
100 }
101
102 void
103 set_regi(sregs, reg, rval)
104     struct pstate  *sregs;
105     int32           reg;
106     uint32          rval;
107 {
108     uint32          cwp;
109
110     cwp = ((sregs->psr & 0x7) << 4);
111     if ((reg > 0) && (reg < 8)) {
112         sregs->g[reg] = rval;
113     } else if ((reg >= 8) && (reg < 32)) {
114         sregs->r[(cwp + reg) & 0x7f] = rval;
115     } else if ((reg >= 32) && (reg < 64)) {
116         sregs->fsi[reg - 32] = rval;
117     } else {
118         switch (reg) {
119         case 64:
120             sregs->y = rval;
121             break;
122         case 65:
123             sregs->psr = rval;
124             break;
125         case 66:
126             sregs->wim = rval;
127             break;
128         case 67:
129             sregs->tbr = rval;
130             break;
131         case 68:
132             sregs->pc = rval;
133             break;
134         case 69:
135             sregs->npc = rval;
136             break;
137         case 70:
138             sregs->fsr = rval;
139             set_fsr(rval);
140             break;
141     default:break;
142         }
143     }
144 }
145
146 void
147 get_regi(struct pstate * sregs, int32 reg, char *buf)
148 {
149     uint32          cwp;
150     uint32          rval = 0;
151
152     cwp = ((sregs->psr & 0x7) << 4);
153     if ((reg >= 0) && (reg < 8)) {
154         rval = sregs->g[reg];
155     } else if ((reg >= 8) && (reg < 32)) {
156         rval = sregs->r[(cwp + reg) & 0x7f];
157     } else if ((reg >= 32) && (reg < 64)) {
158         rval = sregs->fsi[reg - 32];
159     } else {
160         switch (reg) {
161         case 64:
162             rval = sregs->y;
163             break;
164         case 65:
165             rval = sregs->psr;
166             break;
167         case 66:
168             rval = sregs->wim;
169             break;
170         case 67:
171             rval = sregs->tbr;
172             break;
173         case 68:
174             rval = sregs->pc;
175             break;
176         case 69:
177             rval = sregs->npc;
178             break;
179         case 70:
180             rval = sregs->fsr;
181             break;
182     default:break;
183         }
184     }
185     if (current_target_byte_order == BIG_ENDIAN) {
186         buf[0] = (rval >> 24) & 0x0ff;
187         buf[1] = (rval >> 16) & 0x0ff;
188         buf[2] = (rval >> 8) & 0x0ff;
189         buf[3] = rval & 0x0ff;
190     }
191     else {
192         buf[3] = (rval >> 24) & 0x0ff;
193         buf[2] = (rval >> 16) & 0x0ff;
194         buf[1] = (rval >> 8) & 0x0ff;
195         buf[0] = rval & 0x0ff;
196     }
197 }
198
199
200 static void
201 set_rega(sregs, reg, rval)
202     struct pstate  *sregs;
203     char           *reg;
204     uint32          rval;
205 {
206     uint32          cwp;
207     int32           err = 0;
208
209     cwp = ((sregs->psr & 0x7) << 4);
210     if (strcmp(reg, "psr") == 0)
211         sregs->psr = (rval = (rval & 0x00f03fff));
212     else if (strcmp(reg, "tbr") == 0)
213         sregs->tbr = (rval = (rval & 0xfffffff0));
214     else if (strcmp(reg, "wim") == 0)
215         sregs->wim = (rval = (rval & 0x0ff));
216     else if (strcmp(reg, "y") == 0)
217         sregs->y = rval;
218     else if (strcmp(reg, "pc") == 0)
219         sregs->pc = rval;
220     else if (strcmp(reg, "npc") == 0)
221         sregs->npc = rval;
222     else if (strcmp(reg, "fsr") == 0) {
223         sregs->fsr = rval;
224         set_fsr(rval);
225     } else if (strcmp(reg, "g0") == 0)
226         err = 2;
227     else if (strcmp(reg, "g1") == 0)
228         sregs->g[1] = rval;
229     else if (strcmp(reg, "g2") == 0)
230         sregs->g[2] = rval;
231     else if (strcmp(reg, "g3") == 0)
232         sregs->g[3] = rval;
233     else if (strcmp(reg, "g4") == 0)
234         sregs->g[4] = rval;
235     else if (strcmp(reg, "g5") == 0)
236         sregs->g[5] = rval;
237     else if (strcmp(reg, "g6") == 0)
238         sregs->g[6] = rval;
239     else if (strcmp(reg, "g7") == 0)
240         sregs->g[7] = rval;
241     else if (strcmp(reg, "o0") == 0)
242         sregs->r[(cwp + 8) & 0x7f] = rval;
243     else if (strcmp(reg, "o1") == 0)
244         sregs->r[(cwp + 9) & 0x7f] = rval;
245     else if (strcmp(reg, "o2") == 0)
246         sregs->r[(cwp + 10) & 0x7f] = rval;
247     else if (strcmp(reg, "o3") == 0)
248         sregs->r[(cwp + 11) & 0x7f] = rval;
249     else if (strcmp(reg, "o4") == 0)
250         sregs->r[(cwp + 12) & 0x7f] = rval;
251     else if (strcmp(reg, "o5") == 0)
252         sregs->r[(cwp + 13) & 0x7f] = rval;
253     else if (strcmp(reg, "o6") == 0)
254         sregs->r[(cwp + 14) & 0x7f] = rval;
255     else if (strcmp(reg, "o7") == 0)
256         sregs->r[(cwp + 15) & 0x7f] = rval;
257     else if (strcmp(reg, "l0") == 0)
258         sregs->r[(cwp + 16) & 0x7f] = rval;
259     else if (strcmp(reg, "l1") == 0)
260         sregs->r[(cwp + 17) & 0x7f] = rval;
261     else if (strcmp(reg, "l2") == 0)
262         sregs->r[(cwp + 18) & 0x7f] = rval;
263     else if (strcmp(reg, "l3") == 0)
264         sregs->r[(cwp + 19) & 0x7f] = rval;
265     else if (strcmp(reg, "l4") == 0)
266         sregs->r[(cwp + 20) & 0x7f] = rval;
267     else if (strcmp(reg, "l5") == 0)
268         sregs->r[(cwp + 21) & 0x7f] = rval;
269     else if (strcmp(reg, "l6") == 0)
270         sregs->r[(cwp + 22) & 0x7f] = rval;
271     else if (strcmp(reg, "l7") == 0)
272         sregs->r[(cwp + 23) & 0x7f] = rval;
273     else if (strcmp(reg, "i0") == 0)
274         sregs->r[(cwp + 24) & 0x7f] = rval;
275     else if (strcmp(reg, "i1") == 0)
276         sregs->r[(cwp + 25) & 0x7f] = rval;
277     else if (strcmp(reg, "i2") == 0)
278         sregs->r[(cwp + 26) & 0x7f] = rval;
279     else if (strcmp(reg, "i3") == 0)
280         sregs->r[(cwp + 27) & 0x7f] = rval;
281     else if (strcmp(reg, "i4") == 0)
282         sregs->r[(cwp + 28) & 0x7f] = rval;
283     else if (strcmp(reg, "i5") == 0)
284         sregs->r[(cwp + 29) & 0x7f] = rval;
285     else if (strcmp(reg, "i6") == 0)
286         sregs->r[(cwp + 30) & 0x7f] = rval;
287     else if (strcmp(reg, "i7") == 0)
288         sregs->r[(cwp + 31) & 0x7f] = rval;
289     else
290         err = 1;
291     switch (err) {
292     case 0:
293         printf("%s = %d (0x%08x)\n", reg, rval, rval);
294         break;
295     case 1:
296         printf("no such regiser: %s\n", reg);
297         break;
298     case 2:
299         printf("cannot set g0\n");
300         break;
301     default:
302         break;
303     }
304
305 }
306
307 static void
308 disp_reg(sregs, reg)
309     struct pstate  *sregs;
310     char           *reg;
311 {
312     if (strncmp(reg, "w",1) == 0)
313         disp_regs(sregs, VAL(&reg[1]));
314 }
315
316 #ifdef ERRINJ
317
318 void
319 errinj()
320 {
321     int err;
322
323     switch (err = (random() % 12)) {
324         case 0: errtt = 0x61; break;
325         case 1: errtt = 0x62; break;
326         case 2: errtt = 0x63; break;
327         case 3: errtt = 0x64; break;
328         case 4: errtt = 0x65; break;
329         case 5: 
330         case 6: 
331         case 7: errftt = err; 
332                 break;
333         case 8: errmec = 1; break;
334         case 9: errmec = 2; break;
335         case 10: errmec = 5; break;
336         case 11: errmec = 6; break;
337     }
338     errcnt++;
339     if (errper) event(errinj, 0, (random()%errper));
340 }
341
342 void
343 errinjstart()
344 {
345     if (errper) event(errinj, 0, (random()%errper));
346 }
347
348 #endif
349
350 static uint32
351 limcalc (freq)
352     float32             freq;
353 {
354     uint32          unit, lim;
355     double          flim;
356     char           *cmd1, *cmd2;
357
358     unit = 1;
359     lim = -1;
360     if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
361         lim = VAL(cmd1);
362         if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
363             if (strcmp(cmd2,"us")==0) unit = 1;
364             if (strcmp(cmd2,"ms")==0) unit = 1000;
365             if (strcmp(cmd2,"s")==0)  unit = 1000000;
366         }
367         flim = (double) lim * (double) unit * (double) freq + 
368            (double) ebase.simtime;
369         if ((flim > ebase.simtime) && (flim < 4294967296.0)) {
370             lim = (uint32) flim;
371         } else  {
372             printf("error in expression\n");
373             lim = -1;
374         }
375     }
376     return (lim);
377 }
378     
379 int
380 exec_cmd(sregs, cmd)
381     char           *cmd;
382     struct pstate  *sregs;
383 {
384     char           *cmd1, *cmd2;
385     int32           stat;
386     uint32          len, i, clen, j;
387     static uint32   daddr = 0;
388     char           *cmdsave;
389
390     stat = OK;
391     cmdsave = strdup(cmd);
392     if ((cmd1 = strtok(cmd, " \t")) != NULL) {
393         clen = strlen(cmd1);
394         if (strncmp(cmd1, "bp", clen) == 0) {
395             for (i = 0; i < sregs->bptnum; i++) {
396                 printf("  %d : 0x%08x\n", i + 1, sregs->bpts[i]);
397             }
398         } else if (strncmp(cmd1, "+bp", clen) == 0) {
399             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
400                 sregs->bpts[sregs->bptnum] = VAL(cmd1) & ~0x3;
401                 printf("added breakpoint %d at 0x%08x\n",
402                        sregs->bptnum + 1, sregs->bpts[sregs->bptnum]);
403                 sregs->bptnum += 1;
404             }
405         } else if (strncmp(cmd1, "-bp", clen) == 0) {
406             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
407                 i = VAL(cmd1) - 1;
408                 if ((i >= 0) && (i < sregs->bptnum)) {
409                     printf("deleted breakpoint %d at 0x%08x\n", i + 1,
410                            sregs->bpts[i]);
411                     for (; i < sregs->bptnum - 1; i++) {
412                         sregs->bpts[i] = sregs->bpts[i + 1];
413                     }
414                     sregs->bptnum -= 1;
415                 }
416             }
417         } else if (strncmp(cmd1, "batch", clen) == 0) {
418             if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
419                 printf("no file specified\n");
420             } else {
421                 batch(sregs, cmd1);
422             }
423         } else if (strncmp(cmd1, "cont", clen) == 0) {
424             if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
425                 stat = run_sim(sregs, UINT64_MAX, 0);
426             } else {
427                 stat = run_sim(sregs, VAL(cmd1), 0);
428             }
429             daddr = sregs->pc;
430             sim_halt();
431         } else if (strncmp(cmd1, "debug", clen) == 0) {
432             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
433                 sis_verbose = VAL(cmd1);
434             }
435             printf("Debug level = %d\n",sis_verbose);
436         } else if (strncmp(cmd1, "dis", clen) == 0) {
437             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
438                 daddr = VAL(cmd1);
439             }
440             if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
441                 len = VAL(cmd2);
442             } else
443                 len = 16;
444             printf("\n");
445             dis_mem(daddr, len, &dinfo);
446             printf("\n");
447             daddr += len * 4;
448         } else if (strncmp(cmd1, "echo", clen) == 0) {
449             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
450                 printf("%s\n", (&cmdsave[clen+1]));
451             }
452 #ifdef ERRINJ
453         } else if (strncmp(cmd1, "error", clen) == 0) {
454             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
455                 errper = VAL(cmd1);
456                 if (errper) {
457                     event(errinj, 0, (len = (random()%errper)));
458                     printf("Error injection started with period %d\n",len);
459                 } 
460              } else printf("Injected errors: %d\n",errcnt);
461 #endif
462         } else if (strncmp(cmd1, "float", clen) == 0) {
463             stat = disp_fpu(sregs);
464         } else if (strncmp(cmd1, "go", clen) == 0) {
465             if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
466                 len = last_load_addr;
467             } else {
468                 len = VAL(cmd1);
469             }
470             sregs->pc = len & ~3;
471             sregs->npc = sregs->pc + 4;
472             printf("resuming at 0x%08x\n",sregs->pc);
473             if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
474                 stat = run_sim(sregs, VAL(cmd2), 0);
475             } else {
476                 stat = run_sim(sregs, UINT64_MAX, 0);
477             }
478             daddr = sregs->pc;
479             sim_halt();
480         } else if (strncmp(cmd1, "help", clen) == 0) {
481             gen_help();
482         } else if (strncmp(cmd1, "history", clen) == 0) {
483             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
484                 sregs->histlen = VAL(cmd1);
485                 if (sregs->histbuf != NULL)
486                     free(sregs->histbuf);
487                 sregs->histbuf = (struct histype *) calloc(sregs->histlen, sizeof(struct histype));
488                 printf("trace history length = %d\n\r", sregs->histlen);
489                 sregs->histind = 0;
490
491             } else {
492                 j = sregs->histind;
493                 for (i = 0; i < sregs->histlen; i++) {
494                     if (j >= sregs->histlen)
495                         j = 0;
496                     printf(" %8d ", sregs->histbuf[j].time);
497                     dis_mem(sregs->histbuf[j].addr, 1, &dinfo);
498                     j++;
499                 }
500             }
501
502         } else if (strncmp(cmd1, "load", clen) == 0) {
503             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
504                 last_load_addr = bfd_load(cmd1);
505                 while ((cmd1 = strtok(NULL, " \t\n\r")) != NULL)
506                     last_load_addr = bfd_load(cmd1);
507             } else {
508                 printf("load: no file specified\n");
509             }
510         } else if (strncmp(cmd1, "mem", clen) == 0) {
511             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL)
512                 daddr = VAL(cmd1);
513             if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL)
514                 len = VAL(cmd2);
515             else
516                 len = 64;
517             disp_mem(daddr, len);
518             daddr += len;
519         } else if (strncmp(cmd1, "perf", clen) == 0) {
520             cmd1 = strtok(NULL, " \t\n\r");
521             if ((cmd1 != NULL) &&
522                 (strncmp(cmd1, "reset", strlen(cmd1)) == 0)) {
523                 reset_stat(sregs);
524             } else
525                 show_stat(sregs);
526         } else if (strncmp(cmd1, "quit", clen) == 0) {
527             exit(0);
528         } else if (strncmp(cmd1, "reg", clen) == 0) {
529             cmd1 = strtok(NULL, " \t\n\r");
530             cmd2 = strtok(NULL, " \t\n\r");
531             if (cmd2 != NULL)
532                 set_rega(sregs, cmd1, VAL(cmd2));
533             else if (cmd1 != NULL)
534                 disp_reg(sregs, cmd1);
535             else {
536                 disp_regs(sregs,sregs->psr);
537                 disp_ctrl(sregs);
538             }
539         } else if (strncmp(cmd1, "reset", clen) == 0) {
540             ebase.simtime = 0;
541             reset_all();
542             reset_stat(sregs);
543         } else if (strncmp(cmd1, "run", clen) == 0) {
544             ebase.simtime = 0;
545             reset_all();
546             reset_stat(sregs);
547             if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
548                 stat = run_sim(sregs, UINT64_MAX, 0);
549             } else {
550                 stat = run_sim(sregs, VAL(cmd1), 0);
551             }
552             daddr = sregs->pc;
553             sim_halt();
554         } else if (strncmp(cmd1, "shell", clen) == 0) {
555             if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
556                 system(&cmdsave[clen]);
557             }
558         } else if (strncmp(cmd1, "step", clen) == 0) {
559             stat = run_sim(sregs, 1, 1);
560             daddr = sregs->pc;
561             sim_halt();
562         } else if (strncmp(cmd1, "tcont", clen) == 0) {
563             sregs->tlimit = limcalc(sregs->freq);
564             stat = run_sim(sregs, UINT64_MAX, 0);
565             daddr = sregs->pc;
566             sim_halt();
567         } else if (strncmp(cmd1, "tgo", clen) == 0) {
568             if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
569                 len = last_load_addr;
570             } else {
571                 len = VAL(cmd1);
572                 sregs->tlimit = limcalc(sregs->freq);
573             }
574             sregs->pc = len & ~3;
575             sregs->npc = sregs->pc + 4;
576             printf("resuming at 0x%08x\n",sregs->pc);
577             stat = run_sim(sregs, UINT64_MAX, 0);
578             daddr = sregs->pc;
579             sim_halt();
580         } else if (strncmp(cmd1, "tlimit", clen) == 0) {
581            sregs->tlimit = limcalc(sregs->freq);
582            if (sregs->tlimit != (uint32) -1)
583               printf("simulation limit = %u (%.3f ms)\n",(uint32) sregs->tlimit,
584                 sregs->tlimit / sregs->freq / 1000);
585         } else if (strncmp(cmd1, "tra", clen) == 0) {
586             if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
587                 stat = run_sim(sregs, UINT64_MAX, 1);
588             } else {
589                 stat = run_sim(sregs, VAL(cmd1), 1);
590             }
591             printf("\n");
592             daddr = sregs->pc;
593             sim_halt();
594         } else if (strncmp(cmd1, "trun", clen) == 0) {
595             ebase.simtime = 0;
596             reset_all();
597             reset_stat(sregs);
598             sregs->tlimit = limcalc(sregs->freq);
599             stat = run_sim(sregs, UINT64_MAX, 0);
600             daddr = sregs->pc;
601             sim_halt();
602         } else
603             printf("syntax error\n");
604     }
605     if (cmdsave != NULL)
606         free(cmdsave);
607     return (stat);
608 }
609
610
611 void
612 reset_stat(sregs)
613     struct pstate  *sregs;
614 {
615     sregs->tottime = 0;
616     sregs->pwdtime = 0;
617     sregs->ninst = 0;
618     sregs->fholdt = 0;
619     sregs->holdt = 0;
620     sregs->icntt = 0;
621     sregs->finst = 0;
622     sregs->nstore = 0;
623     sregs->nload = 0;
624     sregs->nbranch = 0;
625     sregs->simstart = ebase.simtime;
626
627 }
628
629 void
630 show_stat(sregs)
631     struct pstate  *sregs;
632 {
633     uint32          iinst;
634     uint32          stime, tottime;
635
636     if (sregs->tottime == 0) tottime = 1; else tottime = sregs->tottime;
637     stime = ebase.simtime - sregs->simstart;    /* Total simulated time */
638 #ifdef STAT
639
640     iinst = sregs->ninst - sregs->finst - sregs->nload - sregs->nstore -
641         sregs->nbranch;
642 #endif
643
644     printf("\n Cycles       : %9d\n\r", ebase.simtime - sregs->simstart);
645     printf(" Instructions : %9d\n", sregs->ninst);
646
647 #ifdef STAT
648     printf("   integer    : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst);
649     printf("   load       : %9.2f %%\n",
650            100.0 * (float) sregs->nload / (float) sregs->ninst);
651     printf("   store      : %9.2f %%\n",
652            100.0 * (float) sregs->nstore / (float) sregs->ninst);
653     printf("   branch     : %9.2f %%\n",
654            100.0 * (float) sregs->nbranch / (float) sregs->ninst);
655     printf("   float      : %9.2f %%\n",
656            100.0 * (float) sregs->finst / (float) sregs->ninst);
657     printf(" Integer CPI  : %9.2f\n",
658            ((float) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst))
659            /
660            (float) (sregs->ninst - sregs->finst));
661     printf(" Float CPI    : %9.2f\n",
662            ((float) sregs->fholdt / (float) sregs->finst) + 1.0);
663 #endif
664     printf(" Overall CPI  : %9.2f\n",
665            (float) (stime - sregs->pwdtime) / (float) sregs->ninst);
666     printf("\n ERC32 performance (%4.1f MHz): %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n",
667            sregs->freq, sregs->freq * (float) sregs->ninst / (float) (stime - sregs->pwdtime),
668            sregs->freq * (float) (sregs->ninst - sregs->finst) /
669            (float) (stime - sregs->pwdtime),
670      sregs->freq * (float) sregs->finst / (float) (stime - sregs->pwdtime));
671     printf(" Simulated ERC32 time        : %5.2f ms\n", (float) (ebase.simtime - sregs->simstart) / 1000.0 / sregs->freq);
672     printf(" Processor utilisation       : %5.2f %%\n", 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime)));
673     printf(" Real-time / simulator-time  : 1/%.2f \n",
674       ((float) sregs->tottime) / ((float) (stime) / (sregs->freq * 1.0E6)));
675     printf(" Simulator performance       : %d KIPS\n",sregs->ninst/tottime/1000);
676     printf(" Used time (sys + user)      : %3d s\n\n", sregs->tottime);
677 }
678
679
680
681 void
682 init_bpt(sregs)
683     struct pstate  *sregs;
684 {
685     sregs->bptnum = 0;
686     sregs->histlen = 0;
687     sregs->histind = 0;
688     sregs->histbuf = NULL;
689     sregs->tlimit = -1;
690 }
691
692 static void
693 int_handler(sig)
694     int32           sig;
695 {
696     if (sig != 2)
697         printf("\n\n Signal handler error  (%d)\n\n", sig);
698     ctrl_c = 1;
699 }
700
701 void
702 init_signals()
703 {
704     typedef void    (*PFI) ();
705     static PFI      int_tab[2];
706
707     int_tab[0] = signal(SIGTERM, int_handler);
708     int_tab[1] = signal(SIGINT, int_handler);
709 }
710
711
712 extern struct disassemble_info dinfo;
713
714 struct estate   ebase;
715 struct evcell   evbuf[EVENT_MAX];
716 struct irqcell  irqarr[16];
717
718 static int
719 disp_fpu(sregs)
720     struct pstate  *sregs;
721 {
722
723     int         i;
724     float       t;
725
726     printf("\n fsr: %08X\n\n", sregs->fsr);
727
728 #ifdef HOST_LITTLE_ENDIAN_FLOAT
729     for (i = 0; i < 32; i++)
730       sregs->fdp[i ^ 1] = sregs->fs[i];
731 #endif
732
733     for (i = 0; i < 32; i++) {
734         t = sregs->fs[i];
735         printf(" f%02d  %08x  %14e  ", i, sregs->fsi[i], sregs->fs[i]);
736         if (!(i & 1))
737             printf("%14e\n", sregs->fd[i >> 1]);
738         else
739             printf("\n");
740     }
741     printf("\n");
742     return (OK);
743 }
744
745 static void
746 disp_regs(sregs,cwp)
747     struct pstate  *sregs;
748     int cwp;
749 {
750
751     int           i;
752
753     cwp = ((cwp & 0x7) << 4);
754     printf("\n\t  INS       LOCALS      OUTS     GLOBALS\n");
755     for (i = 0; i < 8; i++) {
756         printf("   %d:  %08X   %08X   %08X   %08X\n", i,
757                sregs->r[(cwp + i + 24) & 0x7f],
758             sregs->r[(cwp + i + 16) & 0x7f], sregs->r[(cwp + i + 8) & 0x7f],
759                sregs->g[i]);
760     }
761 }
762
763 static void
764 disp_ctrl(sregs)
765     struct pstate  *sregs;
766 {
767
768     unsigned char           i[4];
769
770     printf("\n psr: %08X   wim: %08X   tbr: %08X   y: %08X\n",
771            sregs->psr, sregs->wim, sregs->tbr, sregs->y);
772     sis_memory_read(sregs->pc, i, 4);
773     printf("\n  pc: %08X = %02X%02X%02X%02X    ", sregs->pc,i[0],i[1],i[2],i[3]);
774     print_insn_sparc(sregs->pc, &dinfo);
775     sis_memory_read(sregs->npc, i, 4);
776     printf("\n npc: %08X = %02X%02X%02X%02X    ",sregs->npc,i[0],i[1],i[2],i[3]);
777     print_insn_sparc(sregs->npc, &dinfo);
778     if (sregs->err_mode)
779         printf("\n IU in error mode");
780     printf("\n\n");
781 }
782
783 static void
784 disp_mem(addr, len)
785     uint32          addr;
786     uint32          len;
787 {
788
789     uint32          i;
790     unsigned char   data[4];
791     uint32          mem[4], j;
792     char           *p;
793
794     for (i = addr & ~3; i < ((addr + len) & ~3); i += 16) {
795         printf("\n %8X  ", i);
796         for (j = 0; j < 4; j++) {
797             sis_memory_read((i + (j * 4)), data, 4);
798             printf("%02x%02x%02x%02x  ", data[0],data[1],data[2],data[3]);
799             mem[j] = *((int *) &data);
800         }
801         printf("  ");
802         p = (char *) mem;
803         for (j = 0; j < 16; j++) {
804             if (isprint(p[j]))
805                 putchar(p[j]);
806             else
807                 putchar('.');
808         }
809     }
810     printf("\n\n");
811 }
812
813 void
814 dis_mem(addr, len, info)
815     uint32          addr;
816     uint32          len;
817     struct disassemble_info *info;
818 {
819     uint32          i;
820     unsigned char   data[4];
821
822     for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) {
823         sis_memory_read(i, data, 4);
824         printf(" %08x  %02x%02x%02x%02x  ", i, data[0],data[1],data[2],data[3]);
825         print_insn_sparc(i, info);
826         if (i >= 0xfffffffc) break;
827         printf("\n");
828     }
829 }
830
831 /* Add event to event queue */
832
833 void
834 event(cfunc, arg, delta)
835     void            (*cfunc) ();
836     int32           arg;
837     uint64          delta;
838 {
839     struct evcell  *ev1, *evins;
840
841     if (ebase.freeq == NULL) {
842         printf("Error, too many events in event queue\n");
843         return;
844     }
845     ev1 = &ebase.eq;
846     delta += ebase.simtime;
847     while ((ev1->nxt != NULL) && (ev1->nxt->time <= delta)) {
848         ev1 = ev1->nxt;
849     }
850     if (ev1->nxt == NULL) {
851         ev1->nxt = ebase.freeq;
852         ebase.freeq = ebase.freeq->nxt;
853         ev1->nxt->nxt = NULL;
854     } else {
855         evins = ebase.freeq;
856         ebase.freeq = ebase.freeq->nxt;
857         evins->nxt = ev1->nxt;
858         ev1->nxt = evins;
859     }
860     ev1->nxt->time = delta;
861     ev1->nxt->cfunc = cfunc;
862     ev1->nxt->arg = arg;
863 }
864
865 #if 0   /* apparently not used */
866 void
867 stop_event()
868 {
869 }
870 #endif
871
872 void
873 init_event()
874 {
875     int32           i;
876
877     ebase.eq.nxt = NULL;
878     ebase.freeq = evbuf;
879     for (i = 0; i < EVENT_MAX; i++) {
880         evbuf[i].nxt = &evbuf[i + 1];
881     }
882     evbuf[EVENT_MAX - 1].nxt = NULL;
883 }
884
885 void
886 set_int(level, callback, arg)
887     int32           level;
888     void            (*callback) ();
889     int32           arg;
890 {
891     irqarr[level & 0x0f].callback = callback;
892     irqarr[level & 0x0f].arg = arg;
893 }
894
895 /* Advance simulator time */
896
897 void
898 advance_time(sregs)
899     struct pstate  *sregs;
900 {
901
902     struct evcell  *evrem;
903     void            (*cfunc) ();
904     uint32          arg;
905     uint64          endtime;
906
907 #ifdef STAT
908     sregs->fholdt += sregs->fhold;
909     sregs->holdt += sregs->hold;
910     sregs->icntt += sregs->icnt;
911 #endif
912
913     endtime = ebase.simtime + sregs->icnt + sregs->hold + sregs->fhold;
914
915     while ((ebase.eq.nxt->time <= (endtime)) && (ebase.eq.nxt != NULL)) {
916         ebase.simtime = ebase.eq.nxt->time;
917         cfunc = ebase.eq.nxt->cfunc;
918         arg = ebase.eq.nxt->arg;
919         evrem = ebase.eq.nxt;
920         ebase.eq.nxt = ebase.eq.nxt->nxt;
921         evrem->nxt = ebase.freeq;
922         ebase.freeq = evrem;
923         cfunc(arg);
924     }
925     ebase.simtime = endtime;
926
927 }
928
929 uint32
930 now()
931 {
932     return(ebase.simtime);
933 }
934
935
936 /* Advance time until an external interrupt is seen */
937
938 int
939 wait_for_irq()
940 {
941     struct evcell  *evrem;
942     void            (*cfunc) ();
943     int32           arg;
944     uint64          endtime;
945
946     if (ebase.eq.nxt == NULL)
947         printf("Warning: event queue empty - power-down mode not entered\n");
948     endtime = ebase.simtime;
949     while (!ext_irl && (ebase.eq.nxt != NULL)) {
950         ebase.simtime = ebase.eq.nxt->time;
951         cfunc = ebase.eq.nxt->cfunc;
952         arg = ebase.eq.nxt->arg;
953         evrem = ebase.eq.nxt;
954         ebase.eq.nxt = ebase.eq.nxt->nxt;
955         evrem->nxt = ebase.freeq;
956         ebase.freeq = evrem;
957         cfunc(arg);
958         if (ctrl_c) {
959             printf("\bwarning: power-down mode interrupted\n");
960             break;
961         }
962     }
963     sregs.pwdtime += ebase.simtime - endtime;
964     return (ebase.simtime - endtime);
965 }
966
967 int
968 check_bpt(sregs)
969     struct pstate  *sregs;
970 {
971     int32           i;
972
973     if ((sregs->bphit) || (sregs->annul))
974         return (0);
975     for (i = 0; i < (int32) sregs->bptnum; i++) {
976         if (sregs->pc == sregs->bpts[i])
977             return (BPT_HIT);
978     }
979     return (0);
980 }
981
982 void
983 reset_all()
984 {
985     init_event();               /* Clear event queue */
986     init_regs(&sregs);
987     reset();
988 #ifdef ERRINJ
989     errinjstart();
990 #endif
991 }
992
993 void
994 sys_reset()
995 {
996     reset_all();
997     sregs.trap = 256;           /* Force fake reset trap */
998 }
999
1000 void
1001 sys_halt()
1002 {
1003     sregs.trap = 257;           /* Force fake halt trap */
1004 }
1005
1006 #include "ansidecl.h"
1007
1008 #include <stdarg.h>
1009
1010 #include "libiberty.h"
1011 #include "bfd.h"
1012
1013 #define min(A, B) (((A) < (B)) ? (A) : (B))
1014 #define LOAD_ADDRESS 0
1015
1016 int
1017 bfd_load(fname)
1018     char           *fname;
1019 {
1020     asection       *section;
1021     bfd            *pbfd;
1022     const bfd_arch_info_type *arch;
1023
1024     pbfd = bfd_openr(fname, 0);
1025
1026     if (pbfd == NULL) {
1027         printf("open of %s failed\n", fname);
1028         return (-1);
1029     }
1030     if (!bfd_check_format(pbfd, bfd_object)) {
1031         printf("file %s  doesn't seem to be an object file\n", fname);
1032         return (-1);
1033     }
1034
1035     arch = bfd_get_arch_info (pbfd);
1036     if (bfd_little_endian (pbfd) || arch->mach == bfd_mach_sparc_sparclite_le)
1037         current_target_byte_order = LITTLE_ENDIAN;
1038     else
1039         current_target_byte_order = BIG_ENDIAN;
1040     if (sis_verbose)
1041         printf("file %s is %s-endian.\n", fname,
1042                current_target_byte_order == BIG_ENDIAN ? "big" : "little");
1043
1044     if (sis_verbose)
1045         printf("loading %s:", fname);
1046     for (section = pbfd->sections; section; section = section->next) {
1047         if (bfd_get_section_flags(pbfd, section) & SEC_ALLOC) {
1048             bfd_vma         section_address;
1049             unsigned long   section_size;
1050             const char     *section_name;
1051
1052             section_name = bfd_get_section_name(pbfd, section);
1053
1054             section_address = bfd_get_section_vma(pbfd, section);
1055             /*
1056              * Adjust sections from a.out files, since they don't carry their
1057              * addresses with.
1058              */
1059             if (bfd_get_flavour(pbfd) == bfd_target_aout_flavour) {
1060                 if (strcmp (section_name, ".text") == 0)
1061                     section_address = bfd_get_start_address (pbfd);
1062                 else if (strcmp (section_name, ".data") == 0) {
1063                     /* Read the first 8 bytes of the data section.
1064                        There should be the string 'DaTa' followed by
1065                        a word containing the actual section address. */
1066                     struct data_marker
1067                     {
1068                         char signature[4];      /* 'DaTa' */
1069                         unsigned char sdata[4]; /* &sdata */
1070                     } marker;
1071                     bfd_get_section_contents (pbfd, section, &marker, 0,
1072                                               sizeof (marker));
1073                     if (strncmp (marker.signature, "DaTa", 4) == 0)
1074                       {
1075                         if (current_target_byte_order == BIG_ENDIAN)
1076                           section_address = bfd_getb32 (marker.sdata);
1077                         else
1078                           section_address = bfd_getl32 (marker.sdata);
1079                       }
1080                 }
1081             }
1082
1083             section_size = bfd_section_size(pbfd, section);
1084
1085             if (sis_verbose)
1086                 printf("\nsection %s at 0x%08lx (0x%lx bytes)",
1087                        section_name, section_address, section_size);
1088
1089             /* Text, data or lit */
1090             if (bfd_get_section_flags(pbfd, section) & SEC_LOAD) {
1091                 file_ptr        fptr;
1092
1093                 fptr = 0;
1094
1095                 while (section_size > 0) {
1096                     char            buffer[1024];
1097                     int             count;
1098
1099                     count = min(section_size, 1024);
1100
1101                     bfd_get_section_contents(pbfd, section, buffer, fptr, count);
1102
1103                     sis_memory_write(section_address, buffer, count);
1104
1105                     section_address += count;
1106                     fptr += count;
1107                     section_size -= count;
1108                 }
1109             } else              /* BSS */
1110                 if (sis_verbose)
1111                     printf("(not loaded)");
1112         }
1113     }
1114     if (sis_verbose)
1115         printf("\n");
1116
1117     return(bfd_get_start_address (pbfd));
1118 }