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