1/* This file is part of SIS (SPARC instruction simulator) 2 3 Copyright (C) 1995-2023 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 35struct disassemble_info dinfo; 36struct pstate sregs; 37extern struct estate ebase; 38int ctrl_c = 0; 39int sis_verbose = 0; 40char *sis_version = "2.7.5"; 41int nfp = 0; 42int ift = 0; 43int wrp = 0; 44int rom8 = 0; 45int uben = 0; 46int termsave; 47int sparclite = 0; /* emulating SPARClite instructions? */ 48int sparclite_board = 0; /* emulating SPARClite board RAM? */ 49char uart_dev1[128] = ""; 50char uart_dev2[128] = ""; 51extern int ext_irl; 52uint32_t last_load_addr = 0; 53 54#ifdef ERRINJ 55uint32_t errcnt = 0; 56uint32_t errper = 0; 57uint32_t errtt = 0; 58uint32_t errftt = 0; 59uint32_t errmec = 0; 60#endif 61 62/* Forward declarations */ 63 64static int batch (struct pstate *sregs, char *fname); 65static void set_rega (struct pstate *sregs, char *reg, uint32_t rval); 66static void disp_reg (struct pstate *sregs, char *reg); 67static uint32_t limcalc (float32 freq); 68static void int_handler (int32_t sig); 69static void init_event (void); 70static int disp_fpu (struct pstate *sregs); 71static void disp_regs (struct pstate *sregs, int cwp); 72static void disp_ctrl (struct pstate *sregs); 73static void disp_mem (uint32_t addr, uint32_t len); 74 75static int 76batch(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 100void 101set_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 141void 142get_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 187static void 188set_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 291static void 292disp_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 300void 301errinj (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 324void 325errinjstart (void) 326{ 327 if (errper) event(errinj, 0, (random()%errper)); 328} 329 330#endif 331 332static uint32_t 333limcalc (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 360int 361exec_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 597void 598reset_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 614void 615show_stat(struct pstate *sregs) 616{ 617 uint32_t iinst; 618 uint32_t stime; 619 620 if (sregs->tottime == 0.0) 621 sregs->tottime += 1E-6; 622 stime = ebase.simtime - sregs->simstart; /* Total simulated time */ 623#ifdef STAT 624 625 iinst = sregs->ninst - sregs->finst - sregs->nload - sregs->nstore - 626 sregs->nbranch; 627#endif 628 629 printf("\n Cycles : %9" PRIu64 "\n\r", ebase.simtime - sregs->simstart); 630 printf(" Instructions : %9" PRIu64 "\n", sregs->ninst); 631 632#ifdef STAT 633 printf(" integer : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst); 634 printf(" load : %9.2f %%\n", 635 100.0 * (float) sregs->nload / (float) sregs->ninst); 636 printf(" store : %9.2f %%\n", 637 100.0 * (float) sregs->nstore / (float) sregs->ninst); 638 printf(" branch : %9.2f %%\n", 639 100.0 * (float) sregs->nbranch / (float) sregs->ninst); 640 printf(" float : %9.2f %%\n", 641 100.0 * (float) sregs->finst / (float) sregs->ninst); 642 printf(" Integer CPI : %9.2f\n", 643 ((float) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst)) 644 / 645 (float) (sregs->ninst - sregs->finst)); 646 printf(" Float CPI : %9.2f\n", 647 ((float) sregs->fholdt / (float) sregs->finst) + 1.0); 648#endif 649 printf(" Overall CPI : %9.2f\n", 650 (float) (stime - sregs->pwdtime) / (float) sregs->ninst); 651 printf("\n ERC32 performance (%4.1f MHz): %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n", 652 sregs->freq, sregs->freq * (float) sregs->ninst / (float) (stime - sregs->pwdtime), 653 sregs->freq * (float) (sregs->ninst - sregs->finst) / 654 (float) (stime - sregs->pwdtime), 655 sregs->freq * (float) sregs->finst / (float) (stime - sregs->pwdtime)); 656 printf(" Simulated ERC32 time : %.2f s\n", 657 (float) (ebase.simtime - sregs->simstart) / 1000000.0 / sregs->freq); 658 printf(" Processor utilisation : %.2f %%\n", 659 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime))); 660 printf(" Real-time performance : %.2f %%\n", 661 100.0 / (sregs->tottime / ((double) (stime) / (sregs->freq * 1.0E6)))); 662 printf(" Simulator performance : %.2f MIPS\n", 663 (double)(sregs->ninst) / sregs->tottime / 1E6); 664 printf(" Used time (sys + user) : %.2f s\n\n", sregs->tottime); 665} 666 667 668 669void 670init_bpt(struct pstate *sregs) 671{ 672 sregs->bptnum = 0; 673 sregs->histlen = 0; 674 sregs->histind = 0; 675 sregs->histbuf = NULL; 676 sregs->tlimit = -1; 677} 678 679static void 680int_handler(int32_t sig) 681{ 682 if (sig != 2) 683 printf("\n\n Signal handler error (%d)\n\n", sig); 684 ctrl_c = 1; 685} 686 687void 688init_signals(void) 689{ 690 typedef void (*PFI) (); 691 static PFI int_tab[2]; 692 693 int_tab[0] = signal(SIGTERM, int_handler); 694 int_tab[1] = signal(SIGINT, int_handler); 695} 696 697 698extern struct disassemble_info dinfo; 699 700struct estate ebase; 701struct evcell evbuf[EVENT_MAX]; 702struct irqcell irqarr[16]; 703 704static int 705disp_fpu(struct pstate *sregs) 706{ 707 708 int i; 709 float t; 710 711 printf("\n fsr: %08X\n\n", sregs->fsr); 712 713#ifdef HOST_LITTLE_ENDIAN 714 for (i = 0; i < 32; i++) 715 sregs->fdp[i ^ 1] = sregs->fs[i]; 716#endif 717 718 for (i = 0; i < 32; i++) { 719 t = sregs->fs[i]; 720 printf(" f%02d %08x %14e ", i, sregs->fsi[i], sregs->fs[i]); 721 if (!(i & 1)) 722 printf("%14e\n", sregs->fd[i >> 1]); 723 else 724 printf("\n"); 725 } 726 printf("\n"); 727 return OK; 728} 729 730static void 731disp_regs(struct pstate *sregs, int cwp) 732{ 733 734 int i; 735 736 cwp = ((cwp & 0x7) << 4); 737 printf("\n\t INS LOCALS OUTS GLOBALS\n"); 738 for (i = 0; i < 8; i++) { 739 printf(" %d: %08X %08X %08X %08X\n", i, 740 sregs->r[(cwp + i + 24) & 0x7f], 741 sregs->r[(cwp + i + 16) & 0x7f], sregs->r[(cwp + i + 8) & 0x7f], 742 sregs->g[i]); 743 } 744} 745 746static void print_insn_sparc_sis(uint32_t addr, struct disassemble_info *info) 747{ 748 unsigned char i[4]; 749 750 sis_memory_read(addr, i, 4); 751 dinfo.buffer_vma = addr; 752 dinfo.buffer_length = 4; 753 dinfo.buffer = i; 754 print_insn_sparc(addr, info); 755} 756 757static void 758disp_ctrl(struct pstate *sregs) 759{ 760 761 uint32_t i; 762 763 printf("\n psr: %08X wim: %08X tbr: %08X y: %08X\n", 764 sregs->psr, sregs->wim, sregs->tbr, sregs->y); 765 sis_memory_read (sregs->pc, (char *) &i, 4); 766 printf ("\n pc: %08X = %08X ", sregs->pc, i); 767 print_insn_sparc_sis(sregs->pc, &dinfo); 768 sis_memory_read (sregs->npc, (char *) &i, 4); 769 printf ("\n npc: %08X = %08X ", sregs->npc, i); 770 print_insn_sparc_sis(sregs->npc, &dinfo); 771 if (sregs->err_mode) 772 printf("\n IU in error mode"); 773 printf("\n\n"); 774} 775 776static void 777disp_mem(uint32_t addr, uint32_t len) 778{ 779 780 uint32_t i; 781 union { 782 unsigned char u8[4]; 783 uint32_t u32; 784 } data; 785 uint32_t mem[4], j; 786 char *p; 787 788 for (i = addr & ~3; i < ((addr + len) & ~3); i += 16) { 789 printf("\n %8X ", i); 790 for (j = 0; j < 4; j++) { 791 sis_memory_read ((i + (j * 4)), data.u8, 4); 792 printf ("%08x ", data.u32); 793 mem[j] = data.u32; 794 } 795 printf(" "); 796 p = (char *) mem; 797 for (j = 0; j < 16; j++) { 798 if (isprint (p[j ^ EBT])) 799 putchar (p[j ^ EBT]); 800 else 801 putchar('.'); 802 } 803 } 804 printf("\n\n"); 805} 806 807void 808dis_mem(uint32_t addr, uint32_t len, struct disassemble_info *info) 809{ 810 uint32_t i; 811 union { 812 unsigned char u8[4]; 813 uint32_t u32; 814 } data; 815 816 for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) { 817 sis_memory_read (i, data.u8, 4); 818 printf (" %08x %08x ", i, data.u32); 819 print_insn_sparc_sis(i, info); 820 if (i >= 0xfffffffc) break; 821 printf("\n"); 822 } 823} 824 825/* Add event to event queue */ 826 827void 828event(void (*cfunc) (int32_t), int32_t arg, uint64_t delta) 829{ 830 struct evcell *ev1, *evins; 831 832 if (ebase.freeq == NULL) { 833 printf("Error, too many events in event queue\n"); 834 return; 835 } 836 ev1 = &ebase.eq; 837 delta += ebase.simtime; 838 while ((ev1->nxt != NULL) && (ev1->nxt->time <= delta)) { 839 ev1 = ev1->nxt; 840 } 841 if (ev1->nxt == NULL) { 842 ev1->nxt = ebase.freeq; 843 ebase.freeq = ebase.freeq->nxt; 844 ev1->nxt->nxt = NULL; 845 } else { 846 evins = ebase.freeq; 847 ebase.freeq = ebase.freeq->nxt; 848 evins->nxt = ev1->nxt; 849 ev1->nxt = evins; 850 } 851 ev1->nxt->time = delta; 852 ev1->nxt->cfunc = cfunc; 853 ev1->nxt->arg = arg; 854} 855 856#if 0 /* apparently not used */ 857void 858stop_event(void) 859{ 860} 861#endif 862 863void 864init_event(void) 865{ 866 int32_t i; 867 868 ebase.eq.nxt = NULL; 869 ebase.freeq = evbuf; 870 for (i = 0; i < EVENT_MAX; i++) { 871 evbuf[i].nxt = &evbuf[i + 1]; 872 } 873 evbuf[EVENT_MAX - 1].nxt = NULL; 874} 875 876void 877set_int(int32_t level, void (*callback) (int32_t), int32_t arg) 878{ 879 irqarr[level & 0x0f].callback = callback; 880 irqarr[level & 0x0f].arg = arg; 881} 882 883/* Advance simulator time */ 884 885void 886advance_time(struct pstate *sregs) 887{ 888 889 struct evcell *evrem; 890 void (*cfunc) (int32_t); 891 int32_t arg; 892 uint64_t endtime; 893 894#ifdef STAT 895 sregs->fholdt += sregs->fhold; 896 sregs->holdt += sregs->hold; 897 sregs->icntt += sregs->icnt; 898#endif 899 900 endtime = ebase.simtime + sregs->icnt + sregs->hold + sregs->fhold; 901 902 while ((ebase.eq.nxt->time <= (endtime)) && (ebase.eq.nxt != NULL)) { 903 ebase.simtime = ebase.eq.nxt->time; 904 cfunc = ebase.eq.nxt->cfunc; 905 arg = ebase.eq.nxt->arg; 906 evrem = ebase.eq.nxt; 907 ebase.eq.nxt = ebase.eq.nxt->nxt; 908 evrem->nxt = ebase.freeq; 909 ebase.freeq = evrem; 910 cfunc(arg); 911 } 912 ebase.simtime = endtime; 913 914} 915 916uint32_t 917now(void) 918{ 919 return ebase.simtime; 920} 921 922 923/* Advance time until an external interrupt is seen */ 924 925int 926wait_for_irq(void) 927{ 928 struct evcell *evrem; 929 void (*cfunc) (int32_t); 930 int32_t arg; 931 uint64_t endtime; 932 933 if (ebase.eq.nxt == NULL) 934 printf("Warning: event queue empty - power-down mode not entered\n"); 935 endtime = ebase.simtime; 936 while (!ext_irl && (ebase.eq.nxt != NULL)) { 937 ebase.simtime = ebase.eq.nxt->time; 938 cfunc = ebase.eq.nxt->cfunc; 939 arg = ebase.eq.nxt->arg; 940 evrem = ebase.eq.nxt; 941 ebase.eq.nxt = ebase.eq.nxt->nxt; 942 evrem->nxt = ebase.freeq; 943 ebase.freeq = evrem; 944 cfunc(arg); 945 if (ctrl_c) { 946 printf("\bwarning: power-down mode interrupted\n"); 947 break; 948 } 949 } 950 sregs.pwdtime += ebase.simtime - endtime; 951 return ebase.simtime - endtime; 952} 953 954int 955check_bpt(struct pstate *sregs) 956{ 957 int32_t i; 958 959 if ((sregs->bphit) || (sregs->annul)) 960 return 0; 961 for (i = 0; i < (int32_t) sregs->bptnum; i++) { 962 if (sregs->pc == sregs->bpts[i]) 963 return BPT_HIT; 964 } 965 return 0; 966} 967 968void 969reset_all(void) 970{ 971 init_event(); /* Clear event queue */ 972 init_regs(&sregs); 973 reset(); 974#ifdef ERRINJ 975 errinjstart(); 976#endif 977} 978 979void 980sys_reset(void) 981{ 982 reset_all(); 983 sregs.trap = 256; /* Force fake reset trap */ 984} 985 986void 987sys_halt(void) 988{ 989 sregs.trap = 257; /* Force fake halt trap */ 990} 991 992#include "ansidecl.h" 993 994#include <stdarg.h> 995 996#include "libiberty.h" 997#include "bfd.h" 998 999#ifndef min 1000#define min(A, B) (((A) < (B)) ? (A) : (B)) 1001#endif 1002#define LOAD_ADDRESS 0 1003 1004int 1005bfd_load (const char *fname) 1006{ 1007 asection *section; 1008 bfd *pbfd; 1009 const bfd_arch_info_type *arch; 1010 int i; 1011 1012 pbfd = bfd_openr(fname, 0); 1013 1014 if (pbfd == NULL) { 1015 printf("open of %s failed\n", fname); 1016 return -1; 1017 } 1018 if (!bfd_check_format(pbfd, bfd_object)) { 1019 printf("file %s doesn't seem to be an object file\n", fname); 1020 return -1; 1021 } 1022 1023 arch = bfd_get_arch_info (pbfd); 1024 if (sis_verbose) 1025 printf("loading %s:", fname); 1026 for (section = pbfd->sections; section; section = section->next) { 1027 if (bfd_section_flags (section) & SEC_ALLOC) { 1028 bfd_vma section_address; 1029 unsigned long section_size; 1030 const char *section_name; 1031 1032 section_name = bfd_section_name (section); 1033 1034 section_address = bfd_section_vma (section); 1035 /* 1036 * Adjust sections from a.out files, since they don't carry their 1037 * addresses with. 1038 */ 1039 if (bfd_get_flavour(pbfd) == bfd_target_aout_flavour) { 1040 if (strcmp (section_name, ".text") == 0) 1041 section_address = bfd_get_start_address (pbfd); 1042 else if (strcmp (section_name, ".data") == 0) { 1043 /* Read the first 8 bytes of the data section. 1044 There should be the string 'DaTa' followed by 1045 a word containing the actual section address. */ 1046 struct data_marker 1047 { 1048 char signature[4]; /* 'DaTa' */ 1049 unsigned char sdata[4]; /* &sdata */ 1050 } marker; 1051 bfd_get_section_contents (pbfd, section, &marker, 0, 1052 sizeof (marker)); 1053 if (strncmp (marker.signature, "DaTa", 4) == 0) 1054 { 1055 section_address = bfd_getb32 (marker.sdata); 1056 } 1057 } 1058 } 1059 1060 section_size = bfd_section_size (section); 1061 1062 if (sis_verbose) 1063 printf("\nsection %s at 0x%08" PRIx64 " (0x%lx bytes)", 1064 section_name, (uint64_t) section_address, section_size); 1065 1066 /* Text, data or lit */ 1067 if (bfd_section_flags (section) & SEC_LOAD) { 1068 file_ptr fptr; 1069 1070 fptr = 0; 1071 1072 while (section_size > 0) { 1073 char buffer[1024]; 1074 int count; 1075 1076 count = min(section_size, 1024); 1077 1078 bfd_get_section_contents(pbfd, section, buffer, fptr, count); 1079 1080 for (i = 0; i < count; i++) 1081 sis_memory_write ((section_address + i) ^ EBT, &buffer[i], 1); 1082 1083 section_address += count; 1084 fptr += count; 1085 section_size -= count; 1086 } 1087 } else /* BSS */ 1088 if (sis_verbose) 1089 printf("(not loaded)"); 1090 } 1091 } 1092 if (sis_verbose) 1093 printf("\n"); 1094 1095 return bfd_get_start_address (pbfd); 1096} 1097 1098double get_time (void) 1099{ 1100 double usec; 1101 1102 struct timeval tm; 1103 1104 gettimeofday (&tm, NULL); 1105 usec = ((double) tm.tv_sec) * 1E6 + ((double) tm.tv_usec); 1106 return usec / 1E6; 1107} 1108