574 lines
11 KiB
C
574 lines
11 KiB
C
/*
|
|
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 <stdio.h>
|
|
#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<argc; ++j )
|
|
{
|
|
strcpy((mem-memoffset)+ai, argv[j]);
|
|
store(aci, ai);
|
|
aci += 4;
|
|
ai += strlen(argv[j]) + 1;
|
|
}
|
|
|
|
|
|
for ( ; ; )
|
|
{
|
|
++icount;
|
|
xpc = pc; pc = npc; npc = pc + 4;
|
|
instr = ifetch(xpc);
|
|
Reg[0] = 0; /* Force r0 = 0 */
|
|
|
|
if ( instr != 0 ) /* eliminate no-ops */
|
|
{
|
|
switch ( (instr>>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<NNN; ++i )
|
|
{
|
|
I += hists[h][i];
|
|
printf("%d\t%d\t%5.2f%%\t%5.2f%%\n",
|
|
i, hists[h][i],
|
|
(double) 100*hists[h][i] / htotal[h],
|
|
(double) 100*I/htotal[h]);
|
|
}
|
|
printf("oflo %d:\t%d/%d\t%5.2f%%\n",
|
|
h, hoflo[h], htotal[h],
|
|
(double) 100*hoflo[h] / htotal[h]);
|
|
}
|
|
}
|
|
|
|
int numadds=1, numsubs=1, numsuccesses, numcarries;
|
|
int addtable[33][33];
|
|
int subtable[33][33];
|
|
|
|
char fmt[] = "%6d";
|
|
char fmt2[] = "------";
|
|
|
|
patable(tab)
|
|
int tab[33][33];
|
|
{
|
|
int i, j;
|
|
|
|
printf(" |");
|
|
for ( j=0; j<33; ++j )
|
|
printf(fmt, j);
|
|
putchar('\n');
|
|
printf(" |");
|
|
for ( j=0; j<33; ++j )
|
|
printf(fmt2);
|
|
putchar('\n');
|
|
for ( i=0; i<33; ++i )
|
|
{
|
|
printf("%2d|", i);
|
|
for ( j=0; j<33; ++j )
|
|
printf(fmt, tab[i][j]);
|
|
putchar('\n');
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
printstatistics()
|
|
{
|
|
/*
|
|
printhist();
|
|
/*
|
|
printf("numjmpls = %d / %d = %5.2f%%\n",
|
|
numjmpls, arch1cycles, 100.0*numjmpls/arch1cycles);
|
|
printf("numadds = %d, numsubs = %d, numcycles = %d, frac = %5.2f%%\n",
|
|
numadds, numsubs,
|
|
arch1cycles, (double) 100 * (numadds+numsubs) / arch1cycles);
|
|
printf("numsuccesses = %d (%5.2f%%) numcarries = %d\n",
|
|
numsuccesses, 100.0*numsuccesses/(numadds+numsubs), numcarries);
|
|
|
|
/*
|
|
hprint();
|
|
printf("\nADD table:\n");patable(addtable);
|
|
printf("\nSUB table:\n");patable(subtable);
|
|
*/
|
|
}
|
|
|
|
|
|
|
|
#define NNNN (64)
|
|
|
|
static int hist[NNNN];
|
|
|
|
henter(n)
|
|
int n;
|
|
{
|
|
if ( 0 <= n && n < NNNN )
|
|
++hist[n];
|
|
}
|
|
|
|
printhist()
|
|
{
|
|
int i;
|
|
|
|
for ( i=0; i<NNNN; ++i )
|
|
printf("%d %d\n", i, hist[i]);
|
|
}
|
|
|
|
|