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(®[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