Line 16... |
Line 16... |
#include <string.h>
|
#include <string.h>
|
#include <ctype.h>
|
#include <ctype.h>
|
#include <assert.h>
|
#include <assert.h>
|
|
|
//#define ENABLE_CACHE
|
//#define ENABLE_CACHE
|
|
//#define SIMPLE_CACHE
|
|
|
#define MEM_SIZE (1024*1024*2)
|
#define MEM_SIZE (1024*1024*2)
|
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
|
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
|
#define htons(A) ntohs(A)
|
#define htons(A) ntohs(A)
|
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
|
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
|
#define htonl(A) ntohl(A)
|
#define htonl(A) ntohl(A)
|
|
|
#ifndef WIN32
|
#ifndef WIN32
|
#define getch getchar
|
//Support for Linux
|
void Sleep(unsigned long value)
|
#define putch putchar
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
void Sleep(unsigned int value)
|
|
{
|
|
usleep(value * 1000);
|
|
}
|
|
|
|
int kbhit(void)
|
|
{
|
|
struct termios oldt, newt;
|
|
struct timeval tv;
|
|
fd_set read_fd;
|
|
|
|
tcgetattr(STDIN_FILENO, &oldt);
|
|
newt = oldt;
|
|
newt.c_lflag &= ~(ICANON | ECHO);
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
|
tv.tv_sec=0;
|
|
tv.tv_usec=0;
|
|
FD_ZERO(&read_fd);
|
|
FD_SET(0,&read_fd);
|
|
if(select(1, &read_fd, NULL, NULL, &tv) == -1)
|
|
return 0;
|
|
//tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
|
if(FD_ISSET(0,&read_fd))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int getch(void)
|
{
|
{
|
volatile unsigned long count = value*1000000;
|
struct termios oldt, newt;
|
while(--count > 0) ;
|
int ch;
|
|
|
|
tcgetattr(STDIN_FILENO, &oldt);
|
|
newt = oldt;
|
|
newt.c_lflag &= ~(ICANON | ECHO);
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
|
ch = getchar();
|
|
//tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
|
return ch;
|
}
|
}
|
#else
|
#else
|
|
//Support for Windows
|
#include <conio.h>
|
#include <conio.h>
|
extern void __stdcall Sleep(unsigned long value);
|
extern void __stdcall Sleep(unsigned long value);
|
#endif
|
#endif
|
|
|
#define UART_WRITE 0x20000000
|
#define UART_WRITE 0x20000000
|
Line 54... |
Line 94... |
|
|
#define MMU_ENTRIES 4
|
#define MMU_ENTRIES 4
|
#define MMU_MASK (1024*4-1)
|
#define MMU_MASK (1024*4-1)
|
typedef struct
|
typedef struct
|
{
|
{
|
unsigned long virtualAddress;
|
unsigned int virtualAddress;
|
unsigned long physicalAddress;
|
unsigned int physicalAddress;
|
} MmuEntry;
|
} MmuEntry;
|
|
|
typedef struct {
|
typedef struct {
|
long r[32];
|
int r[32];
|
long pc, pc_next, epc;
|
int pc, pc_next, epc;
|
unsigned long hi;
|
unsigned int hi;
|
unsigned long lo;
|
unsigned int lo;
|
long status;
|
int status;
|
long userMode;
|
int userMode;
|
long processId;
|
int processId;
|
long exceptionId;
|
int exceptionId;
|
long faultAddr;
|
int faultAddr;
|
long irqStatus;
|
int irqStatus;
|
long skip;
|
int skip;
|
unsigned char *mem;
|
unsigned char *mem;
|
long wakeup;
|
int wakeup;
|
long big_endian;
|
int big_endian;
|
MmuEntry mmuEntry[MMU_ENTRIES];
|
MmuEntry mmuEntry[MMU_ENTRIES];
|
} State;
|
} State;
|
|
|
static char *opcode_string[]={
|
static char *opcode_string[]={
|
"SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
|
"SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
|
Line 105... |
Line 145... |
"TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
|
"TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
|
"BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
|
"BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
|
"?","?","?","?","?","?","?","?"
|
"?","?","?","?","?","?","?","?"
|
};
|
};
|
|
|
static unsigned long HWMemory[8];
|
static unsigned int HWMemory[8];
|
|
|
|
|
static long mem_read(State *s, long size, unsigned long address)
|
static int mem_read(State *s, int size, unsigned int address)
|
{
|
{
|
unsigned long value=0, ptr;
|
unsigned int value=0, ptr;
|
|
|
s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
|
s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
|
switch(address)
|
switch(address)
|
{
|
{
|
case UART_READ:
|
case UART_READ:
|
Line 135... |
Line 175... |
return s->processId;
|
return s->processId;
|
case MMU_FAULT_ADDR:
|
case MMU_FAULT_ADDR:
|
return s->faultAddr;
|
return s->faultAddr;
|
}
|
}
|
|
|
ptr = (unsigned long)s->mem + (address % MEM_SIZE);
|
ptr = (unsigned int)s->mem + (address % MEM_SIZE);
|
|
|
if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
|
if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
|
ptr = (unsigned long)s->mem + address - 0x10000000;
|
ptr = (unsigned int)s->mem + address - 0x10000000;
|
else if(address < 1024*8)
|
else if(address < 1024*8)
|
ptr += 1024*1024;
|
ptr += 1024*1024;
|
|
|
switch(size)
|
switch(size)
|
{
|
{
|
case 4:
|
case 4:
|
if(address & 3)
|
if(address & 3)
|
printf("Unaligned access PC=0x%x address=0x%x\n", s->pc, address);
|
printf("Unaligned access PC=0x%x address=0x%x\n", (int)s->pc, (int)address);
|
assert((address & 3) == 0);
|
assert((address & 3) == 0);
|
value = *(long*)ptr;
|
value = *(int*)ptr;
|
if(s->big_endian)
|
if(s->big_endian)
|
value = ntohl(value);
|
value = ntohl(value);
|
break;
|
break;
|
case 2:
|
case 2:
|
assert((address & 1) == 0);
|
assert((address & 1) == 0);
|
Line 167... |
Line 207... |
printf("ERROR");
|
printf("ERROR");
|
}
|
}
|
return(value);
|
return(value);
|
}
|
}
|
|
|
static void mem_write(State *s, long size, long unsigned address, unsigned long value)
|
static void mem_write(State *s, int size, int unsigned address, unsigned int value)
|
{
|
{
|
static char_count=0;
|
unsigned int ptr;
|
unsigned long ptr;
|
|
|
|
switch(address)
|
switch(address)
|
{
|
{
|
case UART_WRITE:
|
case UART_WRITE:
|
putch(value);
|
putch(value);
|
|
fflush(stdout);
|
return;
|
return;
|
case IRQ_MASK:
|
case IRQ_MASK:
|
HWMemory[1] = value;
|
HWMemory[1] = value;
|
return;
|
return;
|
case IRQ_STATUS:
|
case IRQ_STATUS:
|
Line 190... |
Line 230... |
case MMU_PROCESS_ID:
|
case MMU_PROCESS_ID:
|
//printf("processId=%d\n", value);
|
//printf("processId=%d\n", value);
|
s->processId = value;
|
s->processId = value;
|
return;
|
return;
|
}
|
}
|
|
|
if(MMU_TLB <= address && address <= MMU_TLB+MMU_ENTRIES * 8)
|
if(MMU_TLB <= address && address <= MMU_TLB+MMU_ENTRIES * 8)
|
{
|
{
|
//printf("TLB 0x%x 0x%x\n", address - MMU_TLB, value);
|
//printf("TLB 0x%x 0x%x\n", address - MMU_TLB, value);
|
ptr = (unsigned long)s->mmuEntry + address - MMU_TLB;
|
ptr = (unsigned int)s->mmuEntry + address - MMU_TLB;
|
*(int*)ptr = value;
|
*(int*)ptr = value;
|
s->irqStatus &= ~IRQ_MMU;
|
s->irqStatus &= ~IRQ_MMU;
|
return;
|
return;
|
}
|
}
|
|
|
ptr = (unsigned long)s->mem + (address % MEM_SIZE);
|
ptr = (unsigned int)s->mem + (address % MEM_SIZE);
|
|
|
if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
|
if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
|
ptr = (unsigned long)s->mem + address - 0x10000000;
|
ptr = (unsigned int)s->mem + address - 0x10000000;
|
else if(address < 1024*8)
|
else if(address < 1024*8)
|
ptr += 1024*1024;
|
ptr += 1024*1024;
|
|
|
switch(size)
|
switch(size)
|
{
|
{
|
case 4:
|
case 4:
|
assert((address & 3) == 0);
|
assert((address & 3) == 0);
|
if(s->big_endian)
|
if(s->big_endian)
|
value = htonl(value);
|
value = htonl(value);
|
*(long*)ptr = value;
|
*(int*)ptr = value;
|
break;
|
break;
|
case 2:
|
case 2:
|
assert((address & 1) == 0);
|
assert((address & 1) == 0);
|
if(s->big_endian)
|
if(s->big_endian)
|
value = htons((unsigned short)value);
|
value = htons((unsigned short)value);
|
Line 231... |
Line 272... |
}
|
}
|
|
|
#ifdef ENABLE_CACHE
|
#ifdef ENABLE_CACHE
|
/************* Optional MMU and cache implementation *************/
|
/************* Optional MMU and cache implementation *************/
|
/* TAG = VirtualAddress | ProcessId | WriteableBit */
|
/* TAG = VirtualAddress | ProcessId | WriteableBit */
|
unsigned long mmu_lookup(State *s, unsigned long processId,
|
unsigned int mmu_lookup(State *s, unsigned int processId,
|
unsigned long address, int write)
|
unsigned int address, int write)
|
{
|
{
|
int i;
|
int i;
|
unsigned long compare, tag;
|
unsigned int compare, tag;
|
|
|
if(processId == 0 || s->userMode == 0)
|
if(processId == 0 || s->userMode == 0)
|
return address;
|
return address;
|
//if(address < 0x30000000)
|
//if(address < 0x30000000)
|
// return address;
|
// return address;
|
Line 262... |
Line 303... |
|
|
#define CACHE_SET_ASSOC_LN2 0
|
#define CACHE_SET_ASSOC_LN2 0
|
#define CACHE_SET_ASSOC (1 << CACHE_SET_ASSOC_LN2)
|
#define CACHE_SET_ASSOC (1 << CACHE_SET_ASSOC_LN2)
|
#define CACHE_SIZE_LN2 (13 - CACHE_SET_ASSOC_LN2) //8 KB
|
#define CACHE_SIZE_LN2 (13 - CACHE_SET_ASSOC_LN2) //8 KB
|
#define CACHE_SIZE (1 << CACHE_SIZE_LN2)
|
#define CACHE_SIZE (1 << CACHE_SIZE_LN2)
|
#define CACHE_LINE_SIZE_LN2 5 //32 bytes
|
#define CACHE_LINE_SIZE_LN2 2 //4 bytes
|
#define CACHE_LINE_SIZE (1 << CACHE_LINE_SIZE_LN2)
|
#define CACHE_LINE_SIZE (1 << CACHE_LINE_SIZE_LN2)
|
|
|
static long cacheData[CACHE_SET_ASSOC][CACHE_SIZE/sizeof(long)];
|
static int cacheData[CACHE_SET_ASSOC][CACHE_SIZE/sizeof(int)];
|
static long cacheAddr[CACHE_SET_ASSOC][CACHE_SIZE/CACHE_LINE_SIZE];
|
static int cacheAddr[CACHE_SET_ASSOC][CACHE_SIZE/CACHE_LINE_SIZE];
|
static long cacheSetNext;
|
static int cacheSetNext;
|
static long cacheMiss, cacheWriteBack, cacheCount;
|
static int cacheMiss, cacheWriteBack, cacheCount;
|
|
|
static void cache_init(void)
|
static void cache_init(void)
|
{
|
{
|
int set, i;
|
int set, i;
|
for(set = 0; set < CACHE_SET_ASSOC; ++set)
|
for(set = 0; set < CACHE_SET_ASSOC; ++set)
|
Line 282... |
Line 323... |
}
|
}
|
}
|
}
|
|
|
/* Write-back cache memory tagged by virtual address and processId */
|
/* Write-back cache memory tagged by virtual address and processId */
|
/* TAG = virtualAddress | processId | dirtyBit */
|
/* TAG = virtualAddress | processId | dirtyBit */
|
static int cache_load(State *s, unsigned long address, int write)
|
static int cache_load(State *s, unsigned int address, int write)
|
{
|
{
|
int set, i, pid, miss, offsetAddr, offsetData, offsetMem;
|
int set, i, pid, miss, offsetAddr, offsetData, offsetMem;
|
unsigned long addrTagMatch, addrPrevMatch=0;
|
unsigned int addrTagMatch, addrPrevMatch=0;
|
unsigned long addrPrev;
|
unsigned int addrPrev;
|
unsigned long addressPhysical, tag;
|
unsigned int addressPhysical, tag;
|
|
|
++cacheCount;
|
++cacheCount;
|
addrTagMatch = address & ~(CACHE_SIZE-1);
|
addrTagMatch = address & ~(CACHE_SIZE-1);
|
offsetAddr = (address & (CACHE_SIZE-1)) >> CACHE_LINE_SIZE_LN2;
|
offsetAddr = (address & (CACHE_SIZE-1)) >> CACHE_LINE_SIZE_LN2;
|
|
|
Line 312... |
Line 353... |
{
|
{
|
++cacheMiss;
|
++cacheMiss;
|
set = cacheSetNext;
|
set = cacheSetNext;
|
cacheSetNext = (cacheSetNext + 1) & (CACHE_SET_ASSOC-1);
|
cacheSetNext = (cacheSetNext + 1) & (CACHE_SET_ASSOC-1);
|
}
|
}
|
else if(write || (address >> 28) != 0x1)
|
//else if(write || (address >> 28) != 0x1)
|
{
|
//{
|
tag = cacheAddr[set][offsetAddr];
|
// tag = cacheAddr[set][offsetAddr];
|
pid = (tag & (CACHE_SIZE-1)) >> 1;
|
// pid = (tag & (CACHE_SIZE-1)) >> 1;
|
if(pid != s->processId)
|
// if(pid != s->processId)
|
miss = 1;
|
// miss = 1;
|
}
|
//}
|
|
|
if(miss)
|
if(miss)
|
{
|
{
|
offsetData = address & (CACHE_SIZE-1) & ~(CACHE_LINE_SIZE-1);
|
offsetData = address & (CACHE_SIZE-1) & ~(CACHE_LINE_SIZE-1);
|
|
|
Line 354... |
Line 395... |
}
|
}
|
cacheAddr[set][offsetAddr] |= write;
|
cacheAddr[set][offsetAddr] |= write;
|
return set;
|
return set;
|
}
|
}
|
|
|
static long cache_read(State *s, long size, unsigned long address)
|
static int cache_read(State *s, int size, unsigned int address)
|
{
|
{
|
int set, offset;
|
int set, offset;
|
long value;
|
int value;
|
|
|
if((address >> 28) == 0x2) // && (s->processId == 0 || s->userMode == 0))
|
if((address & 0xfe000000) != 0x10000000)
|
return mem_read(s, size, address);
|
return mem_read(s, size, address);
|
|
|
set = cache_load(s, address, 0);
|
set = cache_load(s, address, 0);
|
if(s->exceptionId)
|
if(s->exceptionId)
|
return 0;
|
return 0;
|
Line 381... |
Line 422... |
break;
|
break;
|
}
|
}
|
return value;
|
return value;
|
}
|
}
|
|
|
static void cache_write(State *s, long size, long unsigned address, unsigned long value)
|
static void cache_write(State *s, int size, int unsigned address, unsigned int value)
|
{
|
{
|
int set, offset;
|
int set, offset;
|
unsigned long mask;
|
unsigned int mask;
|
|
|
if((address >> 28) == 0x2) // && (s->processId == 0 || s->userMode == 0))
|
if((address >> 28) != 0x1) // && (s->processId == 0 || s->userMode == 0))
|
{
|
{
|
mem_write(s, size, address, value);
|
mem_write(s, size, address, value);
|
return;
|
return;
|
}
|
}
|
|
|
Line 420... |
Line 461... |
cacheData[set][offset] = (value & mask) | (cacheData[set][offset] & ~mask);
|
cacheData[set][offset] = (value & mask) | (cacheData[set][offset] & ~mask);
|
}
|
}
|
|
|
#define mem_read cache_read
|
#define mem_read cache_read
|
#define mem_write cache_write
|
#define mem_write cache_write
|
/************* End optional cache implementation *************/
|
|
#else
|
#else
|
static void cache_init(void) {}
|
static void cache_init(void) {}
|
#endif
|
#endif
|
|
|
void mult_big(unsigned long a,
|
#ifdef SIMPLE_CACHE
|
unsigned long b,
|
|
unsigned long *hi,
|
//Write through direct mapped 8KB cache
|
unsigned long *lo)
|
#define CACHE_MISS 0x1ff
|
{
|
static int cacheData[2048];
|
unsigned long ahi, alo, bhi, blo;
|
static int cacheAddr[2048]; //9-bit addresses
|
unsigned long c0, c1, c2;
|
static int cacheTry, cacheMiss, cacheInit;
|
unsigned long c1_a, c1_b;
|
|
|
static int cache_read(State *s, int size, unsigned int address)
|
|
{
|
|
int offset;
|
|
unsigned int value, value2, address2=address;
|
|
|
|
if(cacheInit == 0)
|
|
{
|
|
cacheInit = 1;
|
|
for(offset = 0; offset < 2048; ++offset)
|
|
cacheAddr[offset] = CACHE_MISS;
|
|
}
|
|
|
|
if(address & 0xefc00000)
|
|
return mem_read(s, size, address);
|
|
|
|
++cacheTry;
|
|
offset = (address >> 2) & 0x7ff;
|
|
if(cacheAddr[offset] != (address >> 13) || cacheAddr[offset] == CACHE_MISS)
|
|
{
|
|
++cacheMiss;
|
|
cacheAddr[offset] = address >> 13;
|
|
cacheData[offset] = mem_read(s, 4, address & ~3);
|
|
}
|
|
value = cacheData[offset];
|
|
if(s->big_endian)
|
|
address ^= 3;
|
|
switch(size)
|
|
{
|
|
case 2:
|
|
value = (value >> ((address & 2) << 3)) & 0xffff;
|
|
break;
|
|
case 1:
|
|
value = (value >> ((address & 3) << 3)) & 0xff;
|
|
break;
|
|
}
|
|
value2 = mem_read(s, size, address2);
|
|
if(value != value2)
|
|
printf("miss match\n");
|
|
//if((cacheTry & 0xffff) == 0) printf("cache(%d,%d) ", cacheMiss, cacheTry);
|
|
return value;
|
|
}
|
|
|
|
static void cache_write(State *s, int size, int unsigned address, unsigned int value)
|
|
{
|
|
int offset;
|
|
|
|
mem_write(s, size, address, value);
|
|
if(address & 0xefc00000)
|
|
return;
|
|
|
|
offset = (address >> 2) & 0x7ff;
|
|
if(size != 4)
|
|
{
|
|
cacheAddr[offset] = CACHE_MISS;
|
|
return;
|
|
}
|
|
cacheAddr[offset] = address >> 13;
|
|
cacheData[offset] = value;
|
|
}
|
|
|
|
#define mem_read cache_read
|
|
#define mem_write cache_write
|
|
#endif
|
|
/************* End optional cache implementation *************/
|
|
|
|
|
|
void mult_big(unsigned int a,
|
|
unsigned int b,
|
|
unsigned int *hi,
|
|
unsigned int *lo)
|
|
{
|
|
unsigned int ahi, alo, bhi, blo;
|
|
unsigned int c0, c1, c2;
|
|
unsigned int c1_a, c1_b;
|
|
|
ahi = a >> 16;
|
ahi = a >> 16;
|
alo = a & 0xffff;
|
alo = a & 0xffff;
|
bhi = b >> 16;
|
bhi = b >> 16;
|
blo = b & 0xffff;
|
blo = b & 0xffff;
|
Line 452... |
Line 567... |
c0 = (c1 << 16) + (c0 & 0xffff);
|
c0 = (c1 << 16) + (c0 & 0xffff);
|
*hi = c2;
|
*hi = c2;
|
*lo = c0;
|
*lo = c0;
|
}
|
}
|
|
|
void mult_big_signed(long a,
|
void mult_big_signed(int a,
|
long b,
|
int b,
|
unsigned long *hi,
|
unsigned int *hi,
|
unsigned long *lo)
|
unsigned int *lo)
|
{
|
{
|
unsigned long ahi, alo, bhi, blo;
|
unsigned int ahi, alo, bhi, blo;
|
unsigned long c0, c1, c2;
|
unsigned int c0, c1, c2;
|
unsigned long c1_a, c1_b;
|
unsigned int c1_a, c1_b;
|
|
|
ahi = a >> 16;
|
ahi = a >> 16;
|
alo = a & 0xffff;
|
alo = a & 0xffff;
|
bhi = b >> 16;
|
bhi = b >> 16;
|
blo = b & 0xffff;
|
blo = b & 0xffff;
|
Line 482... |
Line 597... |
}
|
}
|
|
|
//execute one cycle of a Plasma CPU
|
//execute one cycle of a Plasma CPU
|
void cycle(State *s, int show_mode)
|
void cycle(State *s, int show_mode)
|
{
|
{
|
unsigned long opcode;
|
unsigned int opcode;
|
unsigned long op, rs, rt, rd, re, func, imm, target;
|
unsigned int op, rs, rt, rd, re, func, imm, target;
|
long imm_shift, branch=0, lbranch=2, skip2=0;
|
int imm_shift, branch=0, lbranch=2, skip2=0;
|
long *r=s->r;
|
int *r=s->r;
|
unsigned long *u=(unsigned long*)s->r;
|
unsigned int *u=(unsigned int*)s->r;
|
unsigned long ptr, epc, rSave;
|
unsigned int ptr, epc, rSave;
|
|
|
opcode = mem_read(s, 4, s->pc);
|
opcode = mem_read(s, 4, s->pc);
|
op = (opcode >> 26) & 0x3f;
|
op = (opcode >> 26) & 0x3f;
|
rs = (opcode >> 21) & 0x1f;
|
rs = (opcode >> 21) & 0x1f;
|
rt = (opcode >> 16) & 0x1f;
|
rt = (opcode >> 16) & 0x1f;
|
rd = (opcode >> 11) & 0x1f;
|
rd = (opcode >> 11) & 0x1f;
|
re = (opcode >> 6) & 0x1f;
|
re = (opcode >> 6) & 0x1f;
|
func = opcode & 0x3f;
|
func = opcode & 0x3f;
|
imm = opcode & 0xffff;
|
imm = opcode & 0xffff;
|
imm_shift = (((long)(short)imm) << 2) - 4;
|
imm_shift = (((int)(short)imm) << 2) - 4;
|
target = (opcode << 6) >> 4;
|
target = (opcode << 6) >> 4;
|
ptr = (short)imm + r[rs];
|
ptr = (short)imm + r[rs];
|
r[0] = 0;
|
r[0] = 0;
|
if(show_mode)
|
if(show_mode)
|
{
|
{
|
printf("%8.8lx %8.8lx ", s->pc, opcode);
|
printf("%8.8x %8.8x ", s->pc, opcode);
|
if(op == 0)
|
if(op == 0)
|
printf("%8s ", special_string[func]);
|
printf("%8s ", special_string[func]);
|
else if(op == 1)
|
else if(op == 1)
|
printf("%8s ", regimm_string[rt]);
|
printf("%8s ", regimm_string[rt]);
|
else
|
else
|
printf("%8s ", opcode_string[op]);
|
printf("%8s ", opcode_string[op]);
|
printf("$%2.2ld $%2.2ld $%2.2ld $%2.2ld ", rs, rt, rd, re);
|
printf("$%2.2d $%2.2d $%2.2d $%2.2d ", rs, rt, rd, re);
|
printf("%4.4lx", imm);
|
printf("%4.4x", imm);
|
if(show_mode == 1)
|
if(show_mode == 1)
|
printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
|
printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
|
printf("\n");
|
printf("\n");
|
}
|
}
|
if(show_mode > 5)
|
if(show_mode > 5)
|
Line 597... |
Line 712... |
case 0x06:/*BLEZ*/ branch=r[rs]<=0; break;
|
case 0x06:/*BLEZ*/ branch=r[rs]<=0; break;
|
case 0x07:/*BGTZ*/ branch=r[rs]>0; break;
|
case 0x07:/*BGTZ*/ branch=r[rs]>0; break;
|
case 0x08:/*ADDI*/ r[rt]=r[rs]+(short)imm; break;
|
case 0x08:/*ADDI*/ r[rt]=r[rs]+(short)imm; break;
|
case 0x09:/*ADDIU*/ u[rt]=u[rs]+(short)imm; break;
|
case 0x09:/*ADDIU*/ u[rt]=u[rs]+(short)imm; break;
|
case 0x0a:/*SLTI*/ r[rt]=r[rs]<(short)imm; break;
|
case 0x0a:/*SLTI*/ r[rt]=r[rs]<(short)imm; break;
|
case 0x0b:/*SLTIU*/ u[rt]=u[rs]<(unsigned long)(short)imm; break;
|
case 0x0b:/*SLTIU*/ u[rt]=u[rs]<(unsigned int)(short)imm; break;
|
case 0x0c:/*ANDI*/ r[rt]=r[rs]&imm; break;
|
case 0x0c:/*ANDI*/ r[rt]=r[rs]&imm; break;
|
case 0x0d:/*ORI*/ r[rt]=r[rs]|imm; break;
|
case 0x0d:/*ORI*/ r[rt]=r[rs]|imm; break;
|
case 0x0e:/*XORI*/ r[rt]=r[rs]^imm; break;
|
case 0x0e:/*XORI*/ r[rt]=r[rs]^imm; break;
|
case 0x0f:/*LUI*/ r[rt]=(imm<<16); break;
|
case 0x0f:/*LUI*/ r[rt]=(imm<<16); break;
|
case 0x10:/*COP0*/
|
case 0x10:/*COP0*/
|
Line 641... |
Line 756... |
case 0x23:/*LW*/ r[rt]=mem_read(s,4,ptr); break;
|
case 0x23:/*LW*/ r[rt]=mem_read(s,4,ptr); break;
|
case 0x24:/*LBU*/ r[rt]=(unsigned char)mem_read(s,1,ptr); break;
|
case 0x24:/*LBU*/ r[rt]=(unsigned char)mem_read(s,1,ptr); break;
|
case 0x25:/*LHU*/ r[rt]=(unsigned short)mem_read(s,2,ptr); break;
|
case 0x25:/*LHU*/ r[rt]=(unsigned short)mem_read(s,2,ptr); break;
|
case 0x26:/*LWR*/
|
case 0x26:/*LWR*/
|
//target=32-8*(ptr&3);
|
//target=32-8*(ptr&3);
|
//r[rt]=(r[rt]&~((unsigned long)0xffffffff>>target))|
|
//r[rt]=(r[rt]&~((unsigned int)0xffffffff>>target))|
|
//((unsigned long)mem_read(s,4,ptr&~3)>>target);
|
//((unsigned int)mem_read(s,4,ptr&~3)>>target);
|
break;
|
break;
|
case 0x28:/*SB*/ mem_write(s,1,ptr,r[rt]); break;
|
case 0x28:/*SB*/ mem_write(s,1,ptr,r[rt]); break;
|
case 0x29:/*SH*/ mem_write(s,2,ptr,r[rt]); break;
|
case 0x29:/*SH*/ mem_write(s,2,ptr,r[rt]); break;
|
case 0x2a:/*SWL*/
|
case 0x2a:/*SWL*/
|
//mem_write(s,1,ptr,r[rt]>>24);
|
//mem_write(s,1,ptr,r[rt]>>24);
|
Line 661... |
Line 776... |
// case 0x32:/*LWC2*/ break;
|
// case 0x32:/*LWC2*/ break;
|
// case 0x33:/*LWC3*/ break;
|
// case 0x33:/*LWC3*/ break;
|
// case 0x35:/*LDC1*/ break;
|
// case 0x35:/*LDC1*/ break;
|
// case 0x36:/*LDC2*/ break;
|
// case 0x36:/*LDC2*/ break;
|
// case 0x37:/*LDC3*/ break;
|
// case 0x37:/*LDC3*/ break;
|
// case 0x38:/*SC*/ *(long*)ptr=r[rt]; r[rt]=1; break;
|
// case 0x38:/*SC*/ *(int*)ptr=r[rt]; r[rt]=1; break;
|
case 0x38:/*SC*/ mem_write(s,4,ptr,r[rt]); r[rt]=1; break;
|
case 0x38:/*SC*/ mem_write(s,4,ptr,r[rt]); r[rt]=1; break;
|
// case 0x39:/*SWC1*/ break;
|
// case 0x39:/*SWC1*/ break;
|
// case 0x3a:/*SWC2*/ break;
|
// case 0x3a:/*SWC2*/ break;
|
// case 0x3b:/*SWC3*/ break;
|
// case 0x3b:/*SWC3*/ break;
|
// case 0x3d:/*SDC1*/ break;
|
// case 0x3d:/*SDC1*/ break;
|
Line 691... |
Line 806... |
}
|
}
|
}
|
}
|
|
|
void show_state(State *s)
|
void show_state(State *s)
|
{
|
{
|
long i,j;
|
int i,j;
|
printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
|
printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
|
for(i = 0; i < 4; ++i)
|
for(i = 0; i < 4; ++i)
|
{
|
{
|
printf("%2.2ld ", i * 8);
|
printf("%2.2d ", i * 8);
|
for(j = 0; j < 8; ++j)
|
for(j = 0; j < 8; ++j)
|
{
|
{
|
printf("%8.8lx ", s->r[i*8+j]);
|
printf("%8.8x ", s->r[i*8+j]);
|
}
|
}
|
printf("\n");
|
printf("\n");
|
}
|
}
|
//printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
|
//printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
|
j = s->pc;
|
j = s->pc;
|
Line 716... |
Line 831... |
}
|
}
|
|
|
void do_debug(State *s)
|
void do_debug(State *s)
|
{
|
{
|
int ch;
|
int ch;
|
long i, j=0, watch=0, addr;
|
int i, j=0, watch=0, addr;
|
s->pc_next = s->pc + 4;
|
s->pc_next = s->pc + 4;
|
s->skip = 0;
|
s->skip = 0;
|
s->wakeup = 0;
|
s->wakeup = 0;
|
show_state(s);
|
show_state(s);
|
ch = ' ';
|
ch = ' ';
|
for(;;)
|
for(;;)
|
{
|
{
|
if(ch != 'n')
|
if(ch != 'n')
|
{
|
{
|
if(watch)
|
if(watch)
|
printf("0x%8.8lx=0x%8.8lx\n", watch, mem_read(s, 4, watch));
|
printf("0x%8.8x=0x%8.8x\n", watch, mem_read(s, 4, watch));
|
printf("1=Debug 2=Trace 3=Step 4=BreakPt 5=Go 6=Memory ");
|
printf("1=Debug 2=Trace 3=Step 4=BreakPt 5=Go 6=Memory ");
|
printf("7=Watch 8=Jump 9=Quit> ");
|
printf("7=Watch 8=Jump 9=Quit> ");
|
}
|
}
|
ch = getch();
|
ch = getch();
|
if(ch != 'n')
|
if(ch != 'n')
|
Line 744... |
Line 859... |
cycle(s, 1); break;
|
cycle(s, 1); break;
|
case '2': case 't':
|
case '2': case 't':
|
cycle(s, 0); printf("*"); cycle(s, 10); break;
|
cycle(s, 0); printf("*"); cycle(s, 10); break;
|
case '3': case 's':
|
case '3': case 's':
|
printf("Count> ");
|
printf("Count> ");
|
scanf("%ld", &j);
|
scanf("%d", &j);
|
for(i = 0; i < j; ++i)
|
for(i = 0; i < j; ++i)
|
cycle(s, 1);
|
cycle(s, 1);
|
show_state(s);
|
show_state(s);
|
break;
|
break;
|
case '4': case 'b':
|
case '4': case 'b':
|
printf("Line> ");
|
printf("Line> ");
|
scanf("%lx", &j);
|
scanf("%x", &j);
|
printf("break point=0x%x\n", j);
|
printf("break point=0x%x\n", j);
|
break;
|
break;
|
case '5': case 'g':
|
case '5': case 'g':
|
s->wakeup = 0;
|
s->wakeup = 0;
|
cycle(s, 0);
|
cycle(s, 0);
|
Line 778... |
Line 893... |
}
|
}
|
show_state(s);
|
show_state(s);
|
break;
|
break;
|
case '6': case 'm':
|
case '6': case 'm':
|
printf("Memory> ");
|
printf("Memory> ");
|
scanf("%lx", &j);
|
scanf("%x", &j);
|
for(i = 0; i < 8; ++i)
|
for(i = 0; i < 8; ++i)
|
{
|
{
|
printf("%8.8lx ", mem_read(s, 4, j+i*4));
|
printf("%8.8x ", mem_read(s, 4, j+i*4));
|
}
|
}
|
printf("\n");
|
printf("\n");
|
break;
|
break;
|
case '7': case 'w':
|
case '7': case 'w':
|
printf("Watch> ");
|
printf("Watch> ");
|
scanf("%lx", &watch);
|
scanf("%x", &watch);
|
break;
|
break;
|
case '8': case 'j':
|
case '8': case 'j':
|
printf("Jump> ");
|
printf("Jump> ");
|
scanf("%lx", &addr);
|
scanf("%x", &addr);
|
s->pc = addr;
|
s->pc = addr;
|
s->pc_next = addr + 4;
|
s->pc_next = addr + 4;
|
show_state(s);
|
show_state(s);
|
break;
|
break;
|
case '9': case 'q':
|
case '9': case 'q':
|
Line 807... |
Line 922... |
|
|
int main(int argc,char *argv[])
|
int main(int argc,char *argv[])
|
{
|
{
|
State state, *s=&state;
|
State state, *s=&state;
|
FILE *in;
|
FILE *in;
|
long bytes, index;
|
int bytes, index;
|
printf("Plasma emulator\n");
|
printf("Plasma emulator\n");
|
memset(s, 0, sizeof(State));
|
memset(s, 0, sizeof(State));
|
s->big_endian = 1;
|
s->big_endian = 1;
|
s->mem = (unsigned char*)malloc(MEM_SIZE);
|
s->mem = (unsigned char*)malloc(MEM_SIZE);
|
memset(s->mem, 0, MEM_SIZE);
|
memset(s->mem, 0, MEM_SIZE);
|
Line 833... |
Line 948... |
return(0);
|
return(0);
|
}
|
}
|
bytes = fread(s->mem, 1, MEM_SIZE, in);
|
bytes = fread(s->mem, 1, MEM_SIZE, in);
|
fclose(in);
|
fclose(in);
|
memcpy(s->mem + 1024*1024, s->mem, 1024*8); //internal 8KB SRAM
|
memcpy(s->mem + 1024*1024, s->mem, 1024*8); //internal 8KB SRAM
|
printf("Read %ld bytes.\n", bytes);
|
printf("Read %d bytes.\n", bytes);
|
cache_init();
|
cache_init();
|
if(argc == 3 && argv[2][0] == 'B')
|
if(argc == 3 && argv[2][0] == 'B')
|
{
|
{
|
printf("Big Endian\n");
|
printf("Big Endian\n");
|
s->big_endian = 1;
|
s->big_endian = 1;
|
Line 851... |
Line 966... |
if(argc == 3 && argv[2][0] == 'S')
|
if(argc == 3 && argv[2][0] == 'S')
|
{ /*make big endian*/
|
{ /*make big endian*/
|
printf("Big Endian\n");
|
printf("Big Endian\n");
|
for(index = 0; index < bytes+3; index += 4)
|
for(index = 0; index < bytes+3; index += 4)
|
{
|
{
|
*(unsigned long*)&s->mem[index] = htonl(*(unsigned long*)&s->mem[index]);
|
*(unsigned int*)&s->mem[index] = htonl(*(unsigned int*)&s->mem[index]);
|
}
|
}
|
in = fopen("big.exe", "wb");
|
in = fopen("big.exe", "wb");
|
fwrite(s->mem, bytes, 1, in);
|
fwrite(s->mem, bytes, 1, in);
|
fclose(in);
|
fclose(in);
|
return(0);
|
return(0);
|