/* Copyright (c) 1992-1993 The Regents of the University of California. All rights reserved. See copyright.h for copyright notice and limitation of liability and disclaimer of warranty provisions. */ #include "copyright.h" #include #include "instr.h" #include "encode.h" #include "int.h" #define FAST 0 #define true 1 #define false 0 extern char mem[]; extern int TRACE, Regtrace; /* Machine registers */ int Reg[32]; /* GPR's */ int HI, LO; /* mul/div machine registers */ /* statistics gathering places */ int numjmpls; int arch1cycles; /* Condition-code calculations */ #define b31(z) (((z) >>31 )&0x1) /* extract bit 31 */ /* code looks funny but is fast thanx to MIPS! */ #define cc_add(rr, op1, op2) \ N = (rr < 0); \ Z = (rr == 0); \ C = ((unsigned) rr < (unsigned) op2); \ V = ((op1^op2) >= 0 && (op1^rr) < 0); #define cc_sub(rr, op1, op2) \ N = (rr < 0); \ Z = (rr == 0); \ V = b31((op1 & ~op2 & ~rr) | (~op1 & op2 & rr)); \ C = ((unsigned) op1 < (unsigned) op2); /* C = b31((~op1 & op2) | (rr & (~op1 | op2))); /* */ #define cc_logic(rr) \ N = (rr < 0); \ Z = (rr == 0); \ V = 0; \ C = 0; #define cc_mulscc(rr, op1, op2) \ N = (rr < 0); \ Z = (rr == 0); \ V = b31((op1 & op2 & ~rr) | (~op1 & ~op2 & rr)); \ C = b31((op1 & op2) | (~rr & (op1 | op2))); runprogram(startpc, argc, argv) int startpc, argc; char *argv[]; { int aci, ai, j; register int instr, pc, xpc, npc; register int i; /* temporary for local stuff */ register int icount; extern char *strcpy(); icount = 0; pc = startpc; npc = pc + 4; i = MEMSIZE - 1024 + memoffset; /* Initial SP value */ Reg[29] = i; /* Initialize SP */ /* setup argc and argv stuff (icky!) */ store(i, argc); aci = i + 4; ai = aci + 32; for ( j=0; j>26) & 0x0000003f) { case I_SPECIAL: { switch ( instr & 0x0000003f ) { case I_SLL: Reg[rd(instr)] = Reg[rt(instr)] << shamt(instr); break; case I_SRL: Reg[rd(instr)] = (unsigned) Reg[rt(instr)] >> shamt(instr); break; case I_SRA: Reg[rd(instr)] = Reg[rt(instr)] >> shamt(instr); break; case I_SLLV: Reg[rd(instr)] = Reg[rt(instr)] << Reg[rs(instr)]; break; case I_SRLV: Reg[rd(instr)] = (unsigned) Reg[rt(instr)] >> Reg[rs(instr)]; break; case I_SRAV: Reg[rd(instr)] = Reg[rt(instr)] >> Reg[rs(instr)]; break; case I_JR: npc = Reg[rs(instr)]; break; case I_JALR: npc = Reg[rs(instr)]; Reg[rd(instr)] = xpc + 8; break; case I_SYSCALL: system_trap(); break; case I_BREAK: system_break(); break; case I_MFHI: Reg[rd(instr)] = HI; break; case I_MTHI: HI = Reg[rs(instr)]; break; case I_MFLO: Reg[rd(instr)] = LO; break; case I_MTLO: LO = Reg[rs(instr)]; break; case I_MULT: { int t1, t2; int t1l, t1h, t2l, t2h; int neg; t1 = Reg[rs(instr)]; t2 = Reg[rt(instr)]; neg = 0; if ( t1 < 0 ) { t1 = -t1 ; neg = !neg; } if ( t2 < 0 ) { t2 = -t2 ; neg = !neg; } LO = t1 * t2; t1l = t1 & 0xffff; t1h = (t1 >> 16) & 0xffff; t2l = t2 & 0xffff; t2h = (t2 >> 16) & 0xffff; HI = t1h*t2h+((t1h*t2l)>>16)+((t2h*t1l)>>16); if ( neg ) { LO = ~LO; HI = ~HI; LO = LO + 1; if ( LO == 0 ) HI = HI + 1; } } break; case I_MULTU: { int t1, t2; int t1l, t1h, t2l, t2h; t1 = Reg[rs(instr)]; t2 = Reg[rt(instr)]; t1l = t1 & 0xffff; t1h = (t1 >> 16) & 0xffff; t2l = t2 & 0xffff; t2h = (t2 >> 16) & 0xffff; LO = t1*t2; HI = t1h*t2h+((t1h*t2l)>>16)+((t2h*t1l)>>16); }break; case I_DIV: LO = Reg[rs(instr)] / Reg[rt(instr)]; HI = Reg[rs(instr)] % Reg[rt(instr)]; break; case I_DIVU: LO = (unsigned)Reg[rs(instr)] / (unsigned)Reg[rt(instr)]; HI = (unsigned)Reg[rs(instr)] % (unsigned)Reg[rt(instr)]; break; case I_ADD: case I_ADDU: Reg[rd(instr)] = Reg[rs(instr)] + Reg[rt(instr)]; break; case I_SUB: case I_SUBU: Reg[rd(instr)] = Reg[rs(instr)] - Reg[rt(instr)]; break; case I_AND: Reg[rd(instr)] = Reg[rs(instr)] & Reg[rt(instr)]; break; case I_OR: Reg[rd(instr)] = Reg[rs(instr)] | Reg[rt(instr)]; break; case I_XOR: Reg[rd(instr)] = Reg[rs(instr)] ^ Reg[rt(instr)]; break; case I_NOR: Reg[rd(instr)] = ~(Reg[rs(instr)] | Reg[rt(instr)]); break; case I_SLT: Reg[rd(instr)] = (Reg[rs(instr)] < Reg[rt(instr)]); break; case I_SLTU: Reg[rd(instr)] = ((unsigned) Reg[rs(instr)] < (unsigned) Reg[rt(instr)]); break; default: u(); break; } } break; case I_BCOND: { switch ( rt(instr) ) /* this field encodes the op */ { case I_BLTZ: if ( Reg[rs(instr)] < 0 ) npc = xpc + 4 + (immed(instr)<<2); break; case I_BGEZ: if ( Reg[rs(instr)] >= 0 ) npc = xpc + 4 + (immed(instr)<<2); break; case I_BLTZAL: Reg[31] = xpc + 8; if ( Reg[rs(instr)] < 0 ) npc = xpc + 4 + (immed(instr)<<2); break; case I_BGEZAL: Reg[31] = xpc + 8; if ( Reg[rs(instr)] >= 0 ) npc = xpc + 4 + (immed(instr)<<2); break; default: u(); break; } } break; case I_J: npc = (xpc & 0xf0000000) | ((instr & 0x03ffffff) << 2); break; case I_JAL: Reg[31] = xpc + 8; npc = (xpc & 0xf0000000) | ((instr & 0x03ffffff) << 2); break; case I_BEQ: if ( Reg[rs(instr)] == Reg[rt(instr)] ) npc = xpc + 4 + (immed(instr) << 2); break; case I_BNE: if ( Reg[rs(instr)] != Reg[rt(instr)] ) npc = xpc + 4 + (immed(instr) << 2); break; case I_BLEZ: if ( Reg[rs(instr)] <= 0 ) npc = xpc + 4 + (immed(instr) << 2); break; case I_BGTZ: if ( Reg[rs(instr)] > 0 ) npc = xpc + 4 + (immed(instr) << 2); break; case I_ADDI: Reg[rt(instr)] = Reg[rs(instr)] + immed(instr); break; case I_ADDIU: Reg[rt(instr)] = Reg[rs(instr)] + immed(instr); break; case I_SLTI: Reg[rt(instr)] = (Reg[rs(instr)] < immed(instr)); break; case I_SLTIU: Reg[rt(instr)] = ((unsigned) Reg[rs(instr)] < (unsigned) immed(instr)); break; case I_ANDI: Reg[rt(instr)] = Reg[rs(instr)] & immed(instr); break; case I_ORI: Reg[rt(instr)] = Reg[rs(instr)] | immed(instr); break; case I_XORI: Reg[rt(instr)] = Reg[rs(instr)] ^ immed(instr); break; case I_LUI: Reg[rt(instr)] = instr << 16; break; case I_LB: Reg[rt(instr)] = cfetch(Reg[rs(instr)] + immed(instr)); break; case I_LH: Reg[rt(instr)] = sfetch(Reg[rs(instr)] + immed(instr)); break; case I_LWL: i = Reg[rs(instr)] + immed(instr); Reg[rt(instr)] &= (-1 >> 8*((-i) & 0x03)); Reg[rt(instr)] |= ((fetch(i & 0xfffffffc)) << 8*(i & 0x03)); break; case I_LW: Reg[rt(instr)] = fetch(Reg[rs(instr)] + immed(instr)); break; case I_LBU: Reg[rt(instr)] = ucfetch(Reg[rs(instr)] + immed(instr)); break; case I_LHU: Reg[rt(instr)] = usfetch(Reg[rs(instr)] + immed(instr)); break; case I_LWR: i = Reg[rs(instr)] + immed(instr); Reg[rt(instr)] &= (-1 << 8*(i & 0x03)); if ( (i & 0x03)== 0 ) Reg[rt(instr)] = 0; Reg[rt(instr)] |= ((fetch(i & 0xfffffffc)) >> 8*((-i) & 0x03)); break; case I_SB: cstore(Reg[rs(instr)] + immed(instr), Reg[rt(instr)]); break; case I_SH: sstore(Reg[rs(instr)] + immed(instr), Reg[rt(instr)]); break; case I_SWL: fprintf(stderr, "sorry, no SWL yet.\n"); u(); break; case I_SW: store(Reg[rs(instr)] + immed(instr), Reg[rt(instr)]); break; case I_SWR: fprintf(stderr, "sorry, no SWR yet.\n"); u(); break; case I_LWC0: case I_LWC1: case I_LWC2: case I_LWC3: case I_SWC0: case I_SWC1: case I_SWC2: case I_SWC3: case I_COP0: case I_COP1: case I_COP2: case I_COP3: fprintf(stderr, "Sorry, no coprocessors.\n"); exit(2); break; default: u(); break; } } #ifdef DEBUG /* printf(" %d(%x) = %d(%x) op %d(%x)\n", Reg[rd], Reg[rd], op1, op1, op2, op2); /* */ #endif #if !FAST if ( TRACE ) { dump_ascii(instr, xpc); printf("\n"); /* */ if ( Regtrace ) dump_reg(); } #endif } } u() /* unimplemented */ { printf("Unimplemented Instruction\n"); exit(2); } ny() { printf("This opcode not implemeted yet.\n"); exit(2); } /* debug aids */ RS(i) int i; { return rs(i); } RT(i) int i; { return rt(i); } RD(i) int i; { return rd(i); } IM(i) int i; { return immed(i); } dump_reg() { int j; printf(" 0:"); for ( j=0; j<8; ++j ) printf(" %08x", Reg[j]); printf("\n"); printf(" 8:"); for ( ; j<16; ++j ) printf(" %08x", Reg[j]); printf("\n"); printf("16:"); for ( ; j<24; ++j ) printf(" %08x", Reg[j]); printf("\n"); printf("24:"); for ( ; j<32; ++j ) printf(" %08x", Reg[j]); printf("\n"); } /* 0 -> 0 1 -> 1 2 -> 1 3 -> 2 4 -> 2 5 -> 2 6 -> 2 7 -> 3 8 -> 3 9 -> 3 ... Treats all ints as unsigned numbers. */ ilog2(i) int i; { int j, l; if ( i == 0 ) return 0; j = 0; l = 1; if ( (j=(i&0xffff0000)) != 0 ) { i = j; l += 16; } if ( (j=(i&0xff00ff00)) != 0 ) { i = j; l += 8; } if ( (j=(i&0xf0f0f0f0)) != 0 ) { i = j; l += 4; } if ( (j=(i&0xcccccccc)) != 0 ) { i = j; l += 2; } if ( (j=(i&0xaaaaaaaa)) != 0 ) { i = j; l += 1; } return l; } #define NH 32 #define NNN 33 static int hists[NH][NNN]; int hoflo[NH], htotal[NH]; void henters(n, hist) int n, hist; { if ( 0 <= n && n < NNN ) ++hists[hist][n]; else ++hoflo[hist]; ++htotal[hist]; } hprint() { int h, i; double I; for ( h=0; h<=NH; ++h ) if ( htotal[h] > 0 ) { printf("\nhisto %d:\n", h); I = 0.0; for ( i=0; i