2 * func.c, misc simulator functions. This file is part of SIS.
4 * SIS, SPARC instruction simulator V1.8 Copyright (C) 1995 Jiri Gaisler,
5 * European Space Agency
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 675
19 * Mass Ave, Cambridge, MA 02139, USA.
31 #define VAL(x) strtol(x,(char *)NULL,0)
33 extern char *readline(char *prompt); /* GNU readline function */
35 struct disassemble_info dinfo;
37 extern struct estate ebase;
40 char *sis_version = "2.1";
42 char uart_dev1[128] = "/dev/ptypc";
43 char uart_dev2[128] = "/dev/ptypd";
60 if ((fp = fopen(fname, "r")) == NULL) {
61 fprintf(stderr, "couldn't open batch file %s\n", fname);
66 fgets(lbuf, 1023, fp);
67 if ((strlen(lbuf) > 0) && (lbuf[strlen(lbuf) - 1] == '\n'))
68 lbuf[strlen(lbuf) - 1] = 0;
69 printf("sis> %s\n", lbuf);
70 exec_cmd(sregs, lbuf);
76 set_regi(sregs, reg, rval)
84 cwp = ((sregs->psr & 0x7) << 4);
85 if ((reg > 0) && (reg < 8)) {
87 } else if ((reg >= 8) && (reg < 32)) {
88 sregs->r[(cwp + reg) & 0x7f] = rval;
89 } else if ((reg >= 32) && (reg < 64)) {
90 sregs->fsi[reg - 32] = rval;
121 get_regi(struct pstate * sregs, int32 reg, char *buf)
126 cwp = ((sregs->psr & 0x7) << 4);
127 if ((reg >= 0) && (reg < 8)) {
128 rval = sregs->g[reg];
129 } else if ((reg >= 8) && (reg < 32)) {
130 rval = sregs->r[(cwp + reg) & 0x7f];
131 } else if ((reg >= 32) && (reg < 64)) {
132 rval = sregs->fsi[reg - 32];
159 buf[0] = (rval >> 24) & 0x0ff;
160 buf[1] = (rval >> 16) & 0x0ff;
161 buf[2] = (rval >> 8) & 0x0ff;
162 buf[3] = rval & 0x0ff;
166 set_rega(sregs, reg, rval)
167 struct pstate *sregs;
174 cwp = ((sregs->psr & 0x7) << 4);
175 if (strcmp(reg, "psr") == 0)
176 sregs->psr = (rval = (rval & 0x00f03fff));
177 else if (strcmp(reg, "tbr") == 0)
178 sregs->tbr = (rval = (rval & 0xfffffff0));
179 else if (strcmp(reg, "wim") == 0)
180 sregs->wim = (rval = (rval & 0x0ff));
181 else if (strcmp(reg, "y") == 0)
183 else if (strcmp(reg, "pc") == 0)
185 else if (strcmp(reg, "npc") == 0)
187 else if (strcmp(reg, "fsr") == 0) {
190 } else if (strcmp(reg, "g0") == 0)
192 else if (strcmp(reg, "g1") == 0)
194 else if (strcmp(reg, "g2") == 0)
196 else if (strcmp(reg, "g3") == 0)
198 else if (strcmp(reg, "g4") == 0)
200 else if (strcmp(reg, "g5") == 0)
202 else if (strcmp(reg, "g6") == 0)
204 else if (strcmp(reg, "g7") == 0)
206 else if (strcmp(reg, "o0") == 0)
207 sregs->r[(cwp + 8) & 0x7f] = rval;
208 else if (strcmp(reg, "o1") == 0)
209 sregs->r[(cwp + 9) & 0x7f] = rval;
210 else if (strcmp(reg, "o2") == 0)
211 sregs->r[(cwp + 10) & 0x7f] = rval;
212 else if (strcmp(reg, "o3") == 0)
213 sregs->r[(cwp + 11) & 0x7f] = rval;
214 else if (strcmp(reg, "o4") == 0)
215 sregs->r[(cwp + 12) & 0x7f] = rval;
216 else if (strcmp(reg, "o5") == 0)
217 sregs->r[(cwp + 13) & 0x7f] = rval;
218 else if (strcmp(reg, "o6") == 0)
219 sregs->r[(cwp + 14) & 0x7f] = rval;
220 else if (strcmp(reg, "o7") == 0)
221 sregs->r[(cwp + 15) & 0x7f] = rval;
222 else if (strcmp(reg, "l0") == 0)
223 sregs->r[(cwp + 16) & 0x7f] = rval;
224 else if (strcmp(reg, "l1") == 0)
225 sregs->r[(cwp + 17) & 0x7f] = rval;
226 else if (strcmp(reg, "l2") == 0)
227 sregs->r[(cwp + 18) & 0x7f] = rval;
228 else if (strcmp(reg, "l3") == 0)
229 sregs->r[(cwp + 19) & 0x7f] = rval;
230 else if (strcmp(reg, "l4") == 0)
231 sregs->r[(cwp + 20) & 0x7f] = rval;
232 else if (strcmp(reg, "l5") == 0)
233 sregs->r[(cwp + 21) & 0x7f] = rval;
234 else if (strcmp(reg, "l6") == 0)
235 sregs->r[(cwp + 22) & 0x7f] = rval;
236 else if (strcmp(reg, "l7") == 0)
237 sregs->r[(cwp + 23) & 0x7f] = rval;
238 else if (strcmp(reg, "i0") == 0)
239 sregs->r[(cwp + 24) & 0x7f] = rval;
240 else if (strcmp(reg, "i1") == 0)
241 sregs->r[(cwp + 25) & 0x7f] = rval;
242 else if (strcmp(reg, "i2") == 0)
243 sregs->r[(cwp + 26) & 0x7f] = rval;
244 else if (strcmp(reg, "i3") == 0)
245 sregs->r[(cwp + 27) & 0x7f] = rval;
246 else if (strcmp(reg, "i4") == 0)
247 sregs->r[(cwp + 28) & 0x7f] = rval;
248 else if (strcmp(reg, "i5") == 0)
249 sregs->r[(cwp + 29) & 0x7f] = rval;
250 else if (strcmp(reg, "i6") == 0)
251 sregs->r[(cwp + 30) & 0x7f] = rval;
252 else if (strcmp(reg, "i7") == 0)
253 sregs->r[(cwp + 31) & 0x7f] = rval;
258 printf("%s = %d (0x%08x)\n", reg, rval, rval);
261 printf("no such regiser: %s\n", reg);
264 printf("cannot set g0\n");
273 struct pstate *sregs;
276 if (strncmp(reg, "w",1) == 0)
277 disp_regs(sregs, VAL(®[1]));
282 struct pstate *sregs;
286 int32 len, i, clen, j;
291 cmdsave = strdup(cmd);
292 if ((cmd1 = strtok(cmd, " \t")) != NULL) {
294 if (strncmp(cmd1, "bp", clen) == 0) {
295 for (i = 0; i < sregs->bptnum; i++) {
296 printf(" %d : 0x%08x\n", i + 1, sregs->bpts[i]);
298 } else if (strncmp(cmd1, "+bp", clen) == 0) {
299 if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
300 sregs->bpts[sregs->bptnum] = VAL(cmd1) & ~0x3;
301 printf("added breakpoint %d at 0x%08x\n",
302 sregs->bptnum + 1, sregs->bpts[sregs->bptnum]);
305 } else if (strncmp(cmd1, "-bp", clen) == 0) {
306 if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
308 if ((i >= 0) && (i < sregs->bptnum)) {
309 printf("deleted breakpoint %d at 0x%08x\n", i + 1,
311 for (; i < sregs->bptnum - 1; i++) {
312 sregs->bpts[i] = sregs->bpts[i + 1];
317 } else if (strncmp(cmd1, "batch", clen) == 0) {
318 if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
319 printf("no file specified\n");
323 } else if (strncmp(cmd1, "cont", clen) == 0) {
324 if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
325 stat = run_sim(sregs, 1, 0, 0);
327 stat = run_sim(sregs, 0, VAL(cmd1), 0);
331 } else if (strncmp(cmd1, "dis", clen) == 0) {
332 if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
335 if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
340 dis_mem(daddr, len, &dinfo);
343 } else if (strncmp(cmd1, "echo", clen) == 0) {
344 if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
345 printf("%s\n", (&cmdsave[clen+1]));
347 } else if (strncmp(cmd1, "float", clen) == 0) {
348 stat = disp_fpu(sregs);
349 } else if (strncmp(cmd1, "go", clen) == 0) {
350 if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
351 printf("wrong syntax: go <address> [inst_count]\n");
354 sregs->pc = len & ~3;
355 sregs->npc = sregs->pc + 4;
356 if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
357 stat = run_sim(sregs, 0, VAL(cmd2), 0);
359 stat = run_sim(sregs, 1, 0, 0);
364 } else if (strncmp(cmd1, "help", clen) == 0) {
366 } else if (strncmp(cmd1, "history", clen) == 0) {
367 if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
368 sregs->histlen = VAL(cmd1);
369 if (sregs->histbuf != NULL)
370 free(sregs->histbuf);
371 sregs->histbuf = (struct histype *) calloc(sregs->histlen, sizeof(struct histype));
372 printf("trace history length = %d\n\r", sregs->histlen);
377 for (i = 0; i < sregs->histlen; i++) {
378 if (j >= sregs->histlen)
380 printf(" %8d ", sregs->histbuf[j].time);
381 dis_mem(sregs->histbuf[j].addr, 1, &dinfo);
386 } else if (strncmp(cmd1, "load", clen) == 0) {
387 if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
390 printf("load: no file specified\n");
392 } else if (strncmp(cmd1, "mem", clen) == 0) {
393 if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL)
395 if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL)
399 disp_mem(daddr, len);
401 } else if (strncmp(cmd1, "perf", clen) == 0) {
402 cmd1 = strtok(NULL, " \t\n\r");
403 if ((cmd1 != NULL) &&
404 (strncmp(cmd1, "reset", strlen(cmd1)) == 0)) {
408 } else if (strncmp(cmd1, "quit", clen) == 0) {
410 } else if (strncmp(cmd1, "reg", clen) == 0) {
411 cmd1 = strtok(NULL, " \t\n\r");
412 cmd2 = strtok(NULL, " \t\n\r");
414 set_rega(sregs, cmd1, VAL(cmd2));
415 else if (cmd1 != NULL)
416 disp_reg(sregs, cmd1);
418 disp_regs(sregs,sregs->psr);
421 } else if (strncmp(cmd1, "reset", clen) == 0) {
425 } else if (strncmp(cmd1, "run", clen) == 0) {
429 if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
430 stat = run_sim(sregs, 1, 0, 0);
432 stat = run_sim(sregs, 0, VAL(cmd1), 0);
436 } else if (strncmp(cmd1, "shell", clen) == 0) {
437 if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
438 system(&cmdsave[clen]);
440 } else if (strncmp(cmd1, "step", clen) == 0) {
441 stat = run_sim(sregs, 0, 1, 1);
444 } else if (strncmp(cmd1, "tra", clen) == 0) {
445 if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
446 stat = run_sim(sregs, 1, 0, 1);
448 stat = run_sim(sregs, 0, VAL(cmd1), 1);
454 printf("syntax error\n");
463 struct pstate *sregs;
475 sregs->simstart = ebase.simtime;
480 struct pstate *sregs;
486 stime = ebase.simtime - sregs->simstart; /* Total simulated time */
489 iinst = sregs->ninst - sregs->finst - sregs->nload - sregs->nstore -
493 printf("\n Cycles : %9d\n\r", ebase.simtime - sregs->simstart);
494 printf(" Instructions : %9d\n", sregs->ninst);
497 printf(" integer : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst);
498 printf(" load : %9.2f %%\n",
499 100.0 * (float) sregs->nload / (float) sregs->ninst);
500 printf(" store : %9.2f %%\n",
501 100.0 * (float) sregs->nstore / (float) sregs->ninst);
502 printf(" branch : %9.2f %%\n",
503 100.0 * (float) sregs->nbranch / (float) sregs->ninst);
504 printf(" float : %9.2f %%\n",
505 100.0 * (float) sregs->finst / (float) sregs->ninst);
506 printf(" Integer CPI : %9.2f\n",
507 ((float) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst))
509 (float) (sregs->ninst - sregs->finst));
510 printf(" Float CPI : %9.2f\n",
511 ((float) sregs->fholdt / (float) sregs->finst) + 1.0);
513 printf(" Overall CPI : %9.2f\n",
514 (float) (stime - sregs->pwdtime) / (float) sregs->ninst);
515 printf("\n ERC32 performance (%4.1f MHz): %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n",
516 sregs->freq, sregs->freq * (float) sregs->ninst / (float) (stime - sregs->pwdtime),
517 sregs->freq * (float) (sregs->ninst - sregs->finst) /
518 (float) (stime - sregs->pwdtime),
519 sregs->freq * (float) sregs->finst / (float) (stime - sregs->pwdtime));
520 printf(" Simulated ERC32 time : %5.2f ms\n", (float) (ebase.simtime - sregs->simstart) / 1000.0 / sregs->freq);
521 printf(" Processor utilisation : %5.2f %%\n", 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime)));
522 printf(" Real-time / simulator-time : %5.2f \n",
523 ((float) sregs->tottime) / ((float) (stime) / (sregs->freq * 1.0E6)));
524 printf(" Used time (sys + user) : %3d s\n\n", sregs->tottime);
530 struct pstate *sregs;
535 sregs->histbuf = NULL;
544 printf("\n\n Signal handler error (%d)\n\n", sig);
550 typedef void (*PFI) ();
551 static PFI int_tab[2];
553 int_tab[0] = signal(SIGTERM, int_handler);
554 int_tab[1] = signal(SIGINT, int_handler);
558 extern struct disassemble_info dinfo;
561 struct evcell evbuf[EVENT_MAX];
562 struct irqcell irqarr[16];
563 int32 irqpend, ext_irl = 0;
566 struct pstate *sregs;
572 printf("\n fsr: %08X\n\n", sregs->fsr);
574 #ifdef HOST_LITTLE_ENDIAN_FLOAT
575 for (i = 0; i < 32; i++) {
576 sregs->fdp[i ^ 1] = sregs->fs[i];
580 for (i = 0; i < 32; i++) {
582 printf(" f%02d %08x %14e ", i, sregs->fsi[i], sregs->fs[i]);
584 printf("%14e\n", sregs->fd[i >> 1]);
593 struct pstate *sregs;
599 cwp = ((cwp & 0x7) << 4);
600 printf("\n\t INS LOCALS OUTS GLOBALS\n");
601 for (i = 0; i < 8; i++) {
602 printf(" %d: %08X %08X %08X %08X\n", i,
603 sregs->r[(cwp + i + 24) & 0x7f],
604 sregs->r[(cwp + i + 16) & 0x7f], sregs->r[(cwp + i + 8) & 0x7f],
610 struct pstate *sregs;
615 printf("\n psr: %08X wim: %08X tbr: %08X y: %08X\n",
616 sregs->psr, sregs->wim, sregs->tbr, sregs->y);
617 sis_memory_read(sregs->pc, &i, 4);
618 printf("\n pc: %08X = %08X ", sregs->pc, i);
619 print_insn_sparc(sregs->pc, &dinfo);
620 sis_memory_read(sregs->npc, &i, 4);
621 printf("\n npc: %08X = %08X ", sregs->npc, i);
622 print_insn_sparc(sregs->npc, &dinfo);
624 printf("\n IU in error mode");
637 for (i = addr & ~3; i < ((addr + len) & ~3); i += 16) {
638 printf("\n %8X ", i);
639 for (j = 0; j < 4; j++) {
640 sis_memory_read((i + (j * 4)), &data, 4);
641 printf("%08x ", data);
646 for (j = 0; j < 16; j++) {
655 dis_mem(addr, len, info)
658 struct disassemble_info *info;
662 for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) {
663 sis_memory_read(i, &data, 4);
664 printf(" %08x %08x ", i, data);
665 print_insn_sparc(i, info);
672 buffer_read_memory(addr, buffer, size, info)
676 struct disassemble_info *info;
678 if (size == sis_memory_read(addr, buffer, size))
685 perror_memory(status, addr, info)
688 struct disassemble_info *info;
691 printf("Could not read address 0x%08x\n", addr);
695 generic_print_address(addr, info)
697 struct disassemble_info *info;
700 printf("0x%x", addr);
703 /* Add event to event queue */
705 event(cfunc, arg, delta)
710 struct evcell *ev1, *evins;
712 if (ebase.freeq == NULL) {
713 printf("Error, too many events in event queue\n");
717 delta += ebase.simtime;
718 while ((ev1->nxt != NULL) && (ev1->nxt->time <= delta)) {
721 if (ev1->nxt == NULL) {
722 ev1->nxt = ebase.freeq;
723 ebase.freeq = ebase.freeq->nxt;
724 ev1->nxt->nxt = NULL;
727 ebase.freeq = ebase.freeq->nxt;
728 evins->nxt = ev1->nxt;
731 ev1->nxt->time = delta;
732 ev1->nxt->cfunc = cfunc;
746 for (i = 0; i < EVENT_MAX; i++) {
747 evbuf[i].nxt = &evbuf[i + 1];
749 evbuf[EVENT_MAX - 1].nxt = NULL;
752 set_int(level, callback, arg)
757 irqarr[level & 0x0f].callback = callback;
758 irqarr[level & 0x0f].arg = arg;
759 irqpend |= (1 << level);
768 int32 tmpirq = irqpend;
770 irqpend &= ~(1 << level);
781 /* Advance simulator time */
784 struct pstate *sregs;
787 struct evcell *evrem;
789 uint32 arg, endtime, ws;
791 ws = sregs->icnt + sregs->hold + sregs->fhold;
794 sregs->fholdt += sregs->fhold;
795 sregs->holdt += sregs->hold;
796 sregs->icntt += sregs->icnt;
799 endtime = ebase.simtime += ws;
800 while ((ebase.eq.nxt != NULL) && (ebase.eq.nxt->time <= (endtime))) {
801 ebase.simtime = ebase.eq.nxt->time;
802 cfunc = ebase.eq.nxt->cfunc;
803 arg = ebase.eq.nxt->arg;
804 evrem = ebase.eq.nxt;
805 ebase.eq.nxt = ebase.eq.nxt->nxt;
806 evrem->nxt = ebase.freeq;
810 ebase.simtime = endtime;
814 /* Advance time until an external interrupt is seen */
819 struct evcell *evrem;
823 if (ebase.eq.nxt == NULL)
824 printf("Warning: event queue empty - power-down mode not entered\n");
825 endtime = ebase.simtime;
826 while (!ext_irl && (ebase.eq.nxt != NULL)) {
827 ebase.simtime = ebase.eq.nxt->time;
828 cfunc = ebase.eq.nxt->cfunc;
829 arg = ebase.eq.nxt->arg;
830 evrem = ebase.eq.nxt;
831 ebase.eq.nxt = ebase.eq.nxt->nxt;
832 evrem->nxt = ebase.freeq;
836 printf("\bwarning: power-down mode interrupted\n");
840 sregs.pwdtime += ebase.simtime - endtime;
841 return (ebase.simtime - endtime);
846 struct pstate *sregs;
850 if ((sregs->bphit) || (sregs->annul))
852 for (i = 0; i < sregs->bptnum; i++) {
853 if (sregs->pc == sregs->bpts[i])
861 init_event(); /* Clear event queue */
869 sregs.trap = 256; /* Force fake reset trap */
872 #include "ansidecl.h"
874 #ifdef ANSI_PROTOTYPES
880 #include "libiberty.h"
883 #define min(A, B) (((A) < (B)) ? (A) : (B))
884 #define LOAD_ADDRESS 0
891 unsigned char buf[10];
896 pbfd = bfd_openr(fname, 0);
899 printf("open of %s failed\n", fname);
902 if (!bfd_check_format(pbfd, bfd_object)) {
903 printf("file %s doesn't seem to be an object file\n", fname);
906 printf("loading %s:", fname);
907 for (section = pbfd->sections; section; section = section->next) {
908 if (bfd_get_section_flags(pbfd, section) & SEC_ALLOC) {
909 bfd_vma section_address;
910 unsigned long section_size;
911 const char *section_name;
913 section_name = bfd_get_section_name(pbfd, section);
915 section_address = bfd_get_section_vma(pbfd, section);
917 * Adjust sections from a.out files, since they don't carry their
920 if (bfd_get_flavour(pbfd) == bfd_target_aout_flavour)
921 section_address += bfd_get_start_address (pbfd);
922 section_size = bfd_section_size(pbfd, section);
924 printf("\nsection %s at 0x%08lx (%ld bytes)",
925 section_name, section_address, section_size);
927 /* Text, data or lit */
928 if (bfd_get_section_flags(pbfd, section) & SEC_LOAD) {
933 while (section_size > 0) {
937 count = min(section_size, 1024);
939 bfd_get_section_contents(pbfd, section, buffer, fptr, count);
941 sis_memory_write(section_address, buffer, count);
943 section_address += count;
945 section_size -= count;
948 printf("(not loaded)");
954 * entry = bfd_get_start_address (pbfd);
956 * printf ("[Starting %s at 0x%lx]\n", fname, entry);
963 sim_set_callbacks (ptr)
964 struct host_callback_struct *ptr;