home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "register.h"
- #include "symtab.h"
- #include "diblock.h"
- #include "instrn.h"
- #include "process.h"
- #include "nels.h"
-
- #define TWOTIMES(s) s;s
- #define FOURTIMES(s) TWOTIMES(s);TWOTIMES(s)
- #define EIGHTTIMES(s) FOURTIMES(s);FOURTIMES(s)
- #define SIXTEENTIMES(s) EIGHTTIMES(s);EIGHTTIMES(s)
-
- extern void histo_log();
- extern void hist_log();
- extern instrn *getip();
- extern char *say_pg_register();
-
- extern FILE *outfp;
- extern int Bflag;
- extern int Hflag;
- extern int Iflag;
- extern int Nflag;
- extern unsigned long instruction_count;
- extern unsigned long instruction_count_since_last_syscall;
- extern int hist_length;
-
- static instrn *ip;
- static unsigned long i;
-
- int compile_ok;
-
- void
- unrecognised(dipc)
- dinstrn *dipc;
- {
- GLOBALdipc = dipc;
- vcouldnot("execute unrecognised instruction: <0x%x> \"%s\" [p.%s]", i, ip->i_name, ip->i_pageno);
- }
-
- /*
- * Execute the next instruction.
- */
- static
- dinstrn *
- i_execute(dipc)
- dinstrn *dipc;
- {
- unsigned long opcodesPC;
- unsigned int rs;
- unsigned int rt;
- unsigned int immediate;
- unsigned long target;
- unsigned int rd;
- unsigned int shamt;
- unsigned int funct;
- unsigned int fmt;
- unsigned int ft;
- unsigned int fs;
- unsigned int fd;
-
- /*
- * Signals to be delivered?
- */
- if (sigs_pending > 0)
- {
- dipc = deliver_signal(dipc);
-
- return dipc;
- }
-
- /*
- * Get the current pc.
- */
- opcodesPC = dipc->di_addr;
-
- /*
- * Check for an unaligned pc.
- */
- if ((opcodesPC % 4) != 0)
- {
- GLOBALdipc = dipc;
- vcouldnot("fetch instruction at unaligned address");
- return dipc;
- }
-
- if (Hflag)
- histo_log(opcodesPC);
-
- if (hist_length > 0)
- hist_log(opcodesPC);
-
- /*
- * Put into 'i' the instruction word found
- * at address 'opcodesPC' in the address space of
- * process 'P' and make 'ip' point to
- * a description of that instruction.
- */
- if (procmget(dipc, opcodesPC, (unsigned char *)&i, sizeof(i)) == -1)
- return dipc;
-
- if ((ip = getip(i)) == (instrn *)0)
- return dipc;
-
- /*
- * Now,
- * 'i' contains a copy of the current instruction,
- * 'ip' points to a description of the current instruction
- * and
- * 'pc' contains the address of the first byte of the
- * next instruction.
- */
-
- if (Iflag)
- fprintf(outfp, "\t%s:\t%s\t", proc_text_address(opcodesPC), ip->i_name);
-
- switch (ip->i_format)
- {
- case IF_I:
- /*
- * Immediate.
- */
- rs = i_to_rs(i);
- rt = i_to_rt(i);
- immediate = i_to_immediate(i);
- if (Iflag)
- {
- fprintf(outfp, "rs=%s,", say_pg_register(rs));
- fprintf(outfp, "rt=%s,", say_pg_register(rt));
- fprintf(outfp, "immediate=%d", immediate);
- if (Bflag)
- fprintf(outfp, "\t[p.%s]", ip->i_pageno);
- fprintf(outfp, "\n");
- }
- dipc = (*(ip->i_handler))(dipc, rs, rt, (short)immediate);
- break;
-
- case IF_I1:
- /*
- * Immediate (cop1).
- */
- immediate = i_to_immediate(i);
- if (Iflag)
- {
- fprintf(outfp, "immediate=%d", immediate);
- if (Bflag)
- fprintf(outfp, "\t[p.%s]", ip->i_pageno);
- fprintf(outfp, "\n");
- }
- dipc = (*(ip->i_handler))(dipc, (short)immediate);
- break;
-
- case IF_J:
- /*
- * Jump.
- */
- target = i_to_target(i);
- if (Iflag)
- {
- fprintf(outfp, "target=%s", proc_text_address((opcodesPC & 0xF0000000) | (target << 2)));
-
- if (Bflag)
- fprintf(outfp, "\t[p.%s]", ip->i_pageno);
- fprintf(outfp, "\n");
- }
- dipc = (*(ip->i_handler))(dipc, target);
- break;
-
- case IF_M1:
- /*
- * Move (cop1).
- */
- rt = i_to_rt(i);
- fs = i_to_fs(i);
- if (Iflag)
- {
- fprintf(outfp, "rt=%s,", say_pg_register(rt));
- fprintf(outfp, "fs=%s", say_fg_register(fs));
- if (Bflag)
- fprintf(outfp, "\t[p.%s]", ip->i_pageno);
- fprintf(outfp, "\n");
- }
- dipc = (*(ip->i_handler))(dipc, rt, fs);
- break;
-
- case IF_C1:
- /*
- * Control (cop1).
- */
- rt = i_to_rt(i);
- fs = i_to_fs(i);
- if (Iflag)
- {
- fprintf(outfp, "rt=%s,", say_pg_register(rt));
- fprintf(outfp, "fs=%s", say_fc_register(fs));
- if (Bflag)
- fprintf(outfp, "\t[p.%s]", ip->i_pageno);
- fprintf(outfp, "\n");
- }
- dipc = (*(ip->i_handler))(dipc, rt, fs);
- break;
-
- case IF_R:
- /*
- * Register.
- */
- rs = i_to_rs(i);
- rt = i_to_rt(i);
- rd = i_to_rd(i);
- shamt = i_to_shamt(i);
- funct = i_to_funct(i);
- if (Iflag)
- {
- fprintf(outfp, "rs=%s,", say_pg_register(rs));
- fprintf(outfp, "rt=%s,", say_pg_register(rt));
- fprintf(outfp, "rd=%s,", say_pg_register(rd));
- fprintf(outfp, "shamt=%d,funct=%d", shamt, funct);
- if (Bflag)
- fprintf(outfp, "\t[p.%s]", ip->i_pageno);
- fprintf(outfp, "\n");
- }
- dipc = (*(ip->i_handler))(dipc, rs, rt, rd, shamt, funct);
- break;
-
- case IF_R1:
- /*
- * Register (cop1).
- */
- fmt = i_to_fmt(i);
- ft = i_to_ft(i);
- fs = i_to_fs(i);
- fd = i_to_fd(i);
- if (Iflag)
- {
- fprintf(outfp, "fmt=%d,", fmt);
- fprintf(outfp, "ft=%s,", say_fg_register(ft));
- fprintf(outfp, "fs=%s,", say_fg_register(fs));
- fprintf(outfp, "fd=%s", say_fg_register(fd));
- if (Bflag)
- fprintf(outfp, "\t[p.%s]", ip->i_pageno);
- fprintf(outfp, "\n");
- }
- dipc = (*(ip->i_handler))(dipc, fmt, ft, fs, fd);
- break;
-
- case IF_U:
- default:
- /*
- * Undefined.
- */
- if (Iflag)
- fprintf(outfp, "\n");
- unrecognised(dipc);
- break;
- }
-
- if (Nflag)
- {
- instruction_count++;
- instruction_count_since_last_syscall++;
- }
-
- return dipc;
- }
-
- static
- dinstrn *
- i_end_of_block(dipc)
- dinstrn *dipc;
- {
- dinstrn *olddipc;
- int saved_compile_ok;
-
- olddipc = dipc;
-
- saved_compile_ok = compile_ok;
- compile_ok = 0;
-
- dipc = i_execute(dipc);
-
- compile_ok = saved_compile_ok;
-
- if (dipc == olddipc)
- {
- dipc = addr_to_decoded_instrnp(dipc, dipc->di_addr + sizeof(unsigned long));
-
- dipc--;
- }
-
- return dipc;
- }
-
- static unsigned long lastpageno;
- static unsigned long lastaddr;
- static dinstrn *lastresult;
-
- dinstrn *
- addr_to_decoded_instrnp(dipc, addr)
- dinstrn *dipc;
- unsigned long addr;
- {
- unsigned long pageno;
- diblock *bp;
-
- if ((pageno = addr / SIMULATED_PAGE_SIZE) == lastpageno)
- return lastresult + ((long)addr - (long)lastaddr) / sizeof(unsigned long);
-
- lastpageno = pageno;
- lastaddr = addr;
-
- if ((bp = addr_to_decoded_block(dipc, addr)) == (diblock *)0)
- return (dinstrn *)0;
-
- if (bp->dib_want_init)
- {
- int i;
- unsigned long a;
-
- bp->dib_want_init = 0;
-
- for (i = 0, a = bp->dib_first_addr; i < nels(bp->dib_instrn) - 1; i++, a += sizeof(unsigned long))
- {
- bp->dib_instrn[i].di_handler = i_execute;
- bp->dib_instrn[i].di_addr = a;
- }
-
- bp->dib_instrn[nels(bp->dib_instrn) - 1].di_handler = i_end_of_block;
- bp->dib_instrn[nels(bp->dib_instrn) - 1].di_addr = a;
- }
-
- return lastresult = &bp->dib_instrn[(addr - bp->dib_first_addr) / sizeof(unsigned long)];
- }
-
- int
- clear_decoded_page(dipc, addr, remainderp)
- dinstrn *dipc;
- unsigned long addr;
- int *remainderp;
- {
- unsigned long pageno;
- diblock *bp;
-
- if ((pageno = addr / SIMULATED_PAGE_SIZE) == lastpageno)
- lastpageno = 0;
-
- if ((bp = addr_to_decoded_block(dipc, addr)) == (diblock *)0)
- return -1;
-
- bp->dib_want_init = 1;
-
- *remainderp = bp->dib_first_addr + SIMULATED_PAGE_SIZE - addr;
-
- return 0;
- }
-
- int
- compile_known_delayed_branch(dipc, target)
- dinstrn *dipc;
- unsigned long target;
- {
- dinstrn *dp;
-
- if ((dp = addr_to_decoded_instrnp(dipc, dipc->di_addr + sizeof(unsigned long))) == (dinstrn *)0)
- return -1;
-
- dipc->di_2 = (unsigned long *)dp;
-
- if ((dipc->di_3 = (unsigned long *)addr_to_decoded_instrnp(dipc, target)) == (unsigned long *)0)
- return -1;
-
- dipc->di_3 = (unsigned long *)(((dinstrn *)dipc->di_3) - 1);
-
- return 0;
- }
-
- int
- compile_unknown_delayed_branch(dipc)
- dinstrn *dipc;
- {
- dinstrn *dp;
-
- if ((dp = addr_to_decoded_instrnp(dipc, dipc->di_addr + sizeof(unsigned long))) == (dinstrn *)0)
- return -1;
-
- dipc->di_1 = (unsigned long *)dp;
-
- return 0;
- }
-
- dinstrn *
- do_delayed_branch(dipc, target)
- dinstrn *dipc;
- unsigned long target;
- {
- dipc = addr_to_decoded_instrnp(dipc, dipc->di_addr + sizeof(unsigned long));
-
- (void)(*dipc->di_handler)(dipc);
-
- dipc = addr_to_decoded_instrnp(dipc, target);
-
- dipc--;
-
- return dipc;
- }
-
- #if 0
- #define DIPC_TRACE 1
- #endif /* 0 */
-
- static
- void
- interpret(dipc)
- dinstrn *dipc;
- {
- for (;;)
- {
- #if DIPC_TRACE
- printf("0x%08x: ", dipc);
- fflush(stdout);
- printf("0x%08x\n", dipc->di_handler);
- fflush(stdout);
- dipc = (*dipc->di_handler)(dipc) + 1;
- #else /* DIPC_TRACE */
- SIXTEENTIMES(dipc = (*dipc->di_handler)(dipc) + 1);
- #endif /* DIPC_TRACE */
- }
- }
-
- /*
- * Commence simulation of the process.
- */
- int
- go()
- {
- dinstrn *idipc;
-
- if (hist_length > 0 || Bflag || Hflag || Iflag || Mflag || Nflag || Rflag)
- compile_ok = 0;
- else
- compile_ok = 1;
-
- if ((idipc = addr_to_decoded_instrnp((dinstrn *)0, P.p_entry_point)) == (dinstrn *)0)
- return -1;
-
- interpret(idipc);
- }
-