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 32struct disassemble_info dinfo; 33struct pstate sregs; 34extern struct estate ebase; 35int ctrl_c = 0; 36int sis_verbose = 0; 37char *sis_version = "2.7.5"; 38int nfp = 0; 39int ift = 0; 40int wrp = 0; 41int rom8 = 0; 42int uben = 0; 43int termsave; 44int sparclite = 0; /* emulating SPARClite instructions? */ 45int sparclite_board = 0; /* emulating SPARClite board RAM? */ 46char uart_dev1[128] = ""; 47char uart_dev2[128] = ""; 48extern int ext_irl; 49uint32 last_load_addr = 0; 50 51#ifdef ERRINJ 52uint32 errcnt = 0; 53uint32 errper = 0; 54uint32 errtt = 0; 55uint32 errftt = 0; 56uint32 errmec = 0; 57#endif 58 59/* Forward declarations */ 60 61static int batch (struct pstate *sregs, char *fname); 62static void set_rega (struct pstate *sregs, char *reg, uint32 rval); 63static void disp_reg (struct pstate *sregs, char *reg); 64static uint32 limcalc (float32 freq); 65static void int_handler (int32 sig); 66static void init_event (void); 67static int disp_fpu (struct pstate *sregs); 68static void disp_regs (struct pstate *sregs, int cwp); 69static void disp_ctrl (struct pstate *sregs); 70static void disp_mem (uint32 addr, uint32 len); 71 72static int 73batch(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 99void 100set_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 143void 144get_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 189static void 190set_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 296static void 297disp_reg(sregs, reg) 298 struct pstate *sregs; 299 char *reg; 300{ 301 if (strncmp(reg, "w",1) == 0) 302 disp_regs(sregs, VAL(®[1])); 303} 304 305#ifdef ERRINJ 306 307void 308errinj() 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 331void 332errinjstart() 333{ 334 if (errper) event(errinj, 0, (random()%errper)); 335} 336 337#endif 338 339static uint32 340limcalc (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 368int 369exec_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 605void 606reset_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 623void 624show_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 679void 680init_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 690static void 691int_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 699void 700init_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 710extern struct disassemble_info dinfo; 711 712struct estate ebase; 713struct evcell evbuf[EVENT_MAX]; 714struct irqcell irqarr[16]; 715 716static int 717disp_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 743static void 744disp_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 761static 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 772static void 773disp_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 792static void 793disp_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 825void 826dis_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 848void 849event(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 */ 881void 882stop_event() 883{ 884} 885#endif 886 887void 888init_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 900void 901set_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 912void 913advance_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 944uint32 945now() 946{ 947 return ebase.simtime; 948} 949 950 951/* Advance time until an external interrupt is seen */ 952 953int 954wait_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 982int 983check_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 997void 998reset_all() 999{ 1000 init_event(); /* Clear event queue */ 1001 init_regs(&sregs); 1002 reset(); 1003#ifdef ERRINJ 1004 errinjstart(); 1005#endif 1006} 1007 1008void 1009sys_reset() 1010{ 1011 reset_all(); 1012 sregs.trap = 256; /* Force fake reset trap */ 1013} 1014 1015void 1016sys_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 1031int 1032bfd_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 1125double 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