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