URL
https://opencores.org/ocsvn/ion/ion/trunk
Subversion Repositories ion
Compare Revisions
- This comparison shows the changes necessary to convert path
/ion/trunk/tools/slite
- from Rev 163 to Rev 166
- ↔ Reverse comparison
Rev 163 → Rev 166
/src/slite.c
39,7 → 39,8
* |
* IMPORTANT: Assumes host is little endian and target is big endian. |
*-----------------------------------------------------------------------------*/ |
|
|
#include <errno.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdint.h> |
127,8 → 128,8
{/* Bootstrap BRAM, read only */ |
{VECTOR_RESET, 0x00001000, 0xf8000000, 1, NULL, "Boot BRAM"}, |
/* main external ram block */ |
{0x80000000, 0x00200000, 0xf8000000, 0, NULL, "XRAM0"}, |
{0x00000000, 0x00400000, 0xf8000000, 0, NULL, "XRAM1"}, |
{0x80000000, 0x00800000, 0xf8000000, 0, NULL, "XRAM0"}, |
{0x00000000, 0x00800000, 0xf8000000, 0, NULL, "XRAM1"}, |
/* external flash block */ |
{0xb0000000, 0x00100000, 0xf8000000, 0, NULL, "Flash"}, |
} |
169,6 → 170,8
typedef struct s_args { |
/** !=0 to trap on unimplemented opcodes, 0 to print warning and NOP */ |
uint32_t trap_on_reserved; |
/** !=0 to emulate some common mips32 opcodes */ |
uint32_t emulate_some_mips32; |
/** address to start execution from (by default, reset vector) */ |
uint32_t start_addr; |
/** memory map to be used */ |
186,6 → 189,8
char *log_file_name; |
/** bin file to load to each area or null */ |
char *bin_filename[NUM_MEM_BLOCKS]; |
/** map file to be used for function call tracing, if any */ |
char *map_filename; |
/** offset into area (in bytes) where bin wile will be loaded */ |
uint32_t offset[NUM_MEM_BLOCKS]; |
} t_args; |
264,9 → 269,10
/* FIXME Refactor HW system params */ |
|
#define DBG_REGS (0x20010000) |
|
#define UART_WRITE 0x20000000 |
#define UART_READ 0x20000000 |
#define UART_WRITE (0x20000000) |
#define UART_READ (0x20000000) |
|
/* FIXME The following addresses are remnants of Plasma to be removed */ |
#define IRQ_MASK 0x20000010 |
#define IRQ_STATUS 0x20000020 |
#define CONFIG_REG 0x20000070 |
322,10 → 328,10
unsigned int hi; |
unsigned int lo; |
int status; |
int32_t trap_cause; /**< temporary trap code or <0 if no trap */ |
unsigned cp0_cause; |
int userMode; /**< DEPRECATED, to be removed */ |
int processId; /**< DEPRECATED, to be removed */ |
int exceptionId; /**< DEPRECATED, to be removed */ |
int faultAddr; /**< DEPRECATED, to be removed */ |
int irqStatus; /**< DEPRECATED, to be removed */ |
int skip; |
346,7 → 352,7
"0SPECIAL","0REGIMM","1J","1JAL","2BEQ","2BNE","3BLEZ","3BGTZ", |
"5ADDI","5ADDIU","5SLTI","5SLTIU","5ANDI","5ORI","5XORI","6LUI", |
"cCOP0","cCOP1","cCOP2","cCOP3","2BEQL","2BNEL","3BLEZL","3BGTZL", |
"0?","0?","0?","0?","0?","0?","0?","0?", |
"0?","0?","0?","0?","0SPECIAL2","0?","0?","0SPECIAL3", |
"8LB","8LH","8LWL","8LW","8LBU","8LHU","8LWR","0?", |
"8SB","8SH","8SWL","8SW","0?","0?","8SWR","0CACHE", |
"0LL","0LWC1","0LWC2","0LWC3","?","0LDC1","0LDC2","0LDC3" |
370,9 → 376,37
"9BLTZAL","9BEQZAL","9BLTZALL","9BGEZALL","0?","0?","0?","0?", |
"0?","0?","0?","0?","0?","0?","0?","0?" |
}; |
/* |
static char *special2_string[]={ |
"0MADD","0MADDU","0MUL","0?", "0?","0?","0?","0?", |
"0?","0?","0?","0?", "0?","0?","0?","0?", |
"0?","0?","0?","0?", "0?","0?","0?","0?", |
"0?","0?","0?","0?", "0?","0?","0?","0?", |
|
"0CLZ","0CLO","0?","0?", "0?","0?","0?","0?", |
"0?","0?","0?","0?", "0?","0?","0?","0?", |
"0?","0?","0?","0?", "0?","0?","0?","0?", |
"0?","0?","0?","0?", "0?","0?","0?","0?", |
}; |
*/ |
|
/** local memory used by the console simulation code */ |
static unsigned int HWMemory[8]; |
|
#define MAP_MAX_FUNCTIONS (400) |
#define MAP_MAX_NAME_LEN (80) |
|
/** Information extracted from the map file, if any */ |
typedef struct { |
uint32_t num_functions; /**< number of functions in the table */ |
FILE *log; /**< text log file or stdout */ |
char *log_filename; /**< name of log file or NULL */ |
uint32_t fn_address[MAP_MAX_FUNCTIONS]; |
char fn_name[MAP_MAX_FUNCTIONS][MAP_MAX_NAME_LEN]; |
} t_map_info; |
|
t_map_info map_info; |
|
/*---- Local function prototypes ---------------------------------------------*/ |
|
/* Debug and logging */ |
379,12 → 413,17
void init_trace_buffer(t_state *s, t_args *args); |
void close_trace_buffer(t_state *s); |
void dump_trace_buffer(t_state *s); |
void log_cycle(t_state *s); |
uint32_t log_cycle(t_state *s); |
void log_read(t_state *s, int full_address, int word_value, int size, int log); |
void log_failed_assertions(t_state *s); |
uint32_t log_enabled(t_state *s); |
void trigger_log(t_state *s); |
void print_opcode_fields(uint32_t opcode); |
void reserved_opcode(uint32_t pc, uint32_t opcode, t_state* s); |
int32_t read_map_file(char *filename, t_map_info* map); |
void log_call(uint32_t to, uint32_t from); |
void log_ret(uint32_t to, uint32_t from); |
int32_t function_index(uint32_t address); |
|
int32_t parse_cmd_line(uint32_t argc, char **argv, t_args *args); |
void usage(void); |
403,6 → 442,66
|
|
/*---- Local functions -------------------------------------------------------*/ |
|
/*---- Call & ret tracing (EARLY DRAFT) --------------------------------------*/ |
|
static uint32_t call_depth = 0; |
|
void log_ret(uint32_t to, uint32_t from){ |
int32_t i,j; |
|
/* If no map file has been loaded, skip trace */ |
if((!map_info.num_functions) || (!map_info.log)) return; |
|
if(call_depth>0){ |
fprintf(map_info.log, "[%08x] ", from); |
for(j=0;j<call_depth;j++){ |
fprintf(map_info.log, ". "); |
} |
fprintf(map_info.log, "}\n"); |
call_depth--; |
} |
else{ |
i = function_index(to); |
if(i>=0){ |
fprintf(map_info.log, "[%08x] %s\n", from, map_info.fn_name[i]); |
} |
else{ |
fprintf(map_info.log, "[%08x] %08x\n", from, to); |
} |
} |
} |
|
/** */ |
void log_call(uint32_t to, uint32_t from){ |
int32_t i,j; |
|
/* If no map file has been loaded, skip trace */ |
if((!map_info.num_functions) || (!map_info.log)) return; |
|
i = function_index(to); |
if(i>=0){ |
call_depth++; |
fprintf(map_info.log, "[%08x] ", from); |
for(j=0;j<call_depth;j++){ |
fprintf(map_info.log, ". "); |
} |
fprintf(map_info.log, "%s{\n", map_info.fn_name[i]); |
} |
} |
|
int32_t function_index(uint32_t address){ |
uint32_t i; |
|
for(i=0;i<map_info.num_functions;i++){ |
if(address==map_info.fn_address[i]){ |
return i; |
} |
} |
return -1; |
} |
|
/*---- Execution log ---------------------------------------------------------*/ |
|
/** Log to file a memory read operation (not including target reg change) */ |
void log_read(t_state *s, int full_address, int word_value, int size, int log){ |
461,7 → 560,8
if(!ptr){ |
/* address out of mapped blocks: log and return zero */ |
/* if bit CP0.16==1, this is a D-Cache line invalidation access and |
the HW will not read any actual data, so skip the log (@note1) */ |
the HW will not read any actual data, so skip the log (@note1) */ |
printf("MEM RD ERROR @ 0x%08x [0x%08x]\n", s->pc, full_address); |
if(log_enabled(s) && log!=0 && !(s->status & (1<<16))){ |
fprintf(s->t.log, "(%08X) [%08X] <**>=%08X RD UNMAPPED\n", |
s->pc, full_address, 0); |
565,9 → 665,11
//s->op_addr, address&0xfffffffc, mask, dvalue); |
s->op_addr, address, mask, dvalue); |
} |
|
if((address&0xffff0000)==DBG_REGS){ |
printf("[%04x]=%08x\n", address & 0xffff, value); |
|
/* Print anything that's written to a debug register, otherwise ignore it */ |
if((address&0xffff0000)==(DBG_REGS&0xffff0000)){ |
printf("DEBUG REG[%04x]=%08x\n", address & 0xffff, value); |
return; |
} |
|
switch(address){ |
607,7 → 709,8
} |
} |
if(!ptr){ |
/* address out of mapped blocks: log and return zero */ |
/* address out of mapped blocks: log and return zero */ |
printf("MEM WR ERROR @ 0x%08x [0x%08x]\n", s->pc, address); |
if(log_enabled(s) && log!=0){ |
fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR UNMAPPED\n", |
s->op_addr, address, mask, dvalue); |
718,8 → 821,57
|
s->r[reg_index] = (s->r[reg_index] & (~mask[offset])) | data; |
} |
|
/*---- Optional MIPS32 opcodes -----------------------------------------------*/ |
|
uint32_t count_leading(uint32_t lead, uint32_t src){ |
uint32_t mask, bit_val, i; |
|
mask = 0x80000000; |
bit_val = lead? mask : 0x0; |
|
for(i=0;i<32;i++){ |
if((src & mask) != bit_val){ |
return i; |
} |
mask = mask >> 1; |
} |
|
return i; |
} |
|
uint32_t mult_gpr(uint32_t m1, uint32_t m2){ |
uint32_t temp; |
|
temp = m1 * m2; |
return temp; |
} |
|
uint32_t ext_bitfield(uint32_t src, uint32_t opcode){ |
uint32_t pos, size, mask, value; |
|
pos = (opcode>>6) & 0x1f; |
size = ((opcode>>11) & 0x1f) + 1; |
mask = (1 << size)-1; |
mask = mask << pos; |
|
value = (src & mask) >> pos; |
return value; |
} |
|
uint32_t ins_bitfield(uint32_t target, uint32_t src, uint32_t opcode){ |
uint32_t pos, size, mask, value; |
|
pos = (opcode>>6) & 0x1f; |
size = ((opcode>>11) & 0x1f) + 1; |
mask = (1 << size)-1; |
mask = mask << pos; |
|
value = target & (~mask); |
value |= ((src << pos) & mask); |
return value; |
} |
|
/*---- Optional MMU and cache implementation ---------------------------------*/ |
|
/* |
789,9 → 941,9
void cycle(t_state *s, int show_mode){ |
unsigned int opcode; |
int delay_slot = 0; /* 1 of this instruction is a branch */ |
unsigned int op, rs, rt, rd, re, func, imm, target; |
int trap_cause = 0; |
int imm_shift, branch=0, lbranch=2, skip2=0; |
unsigned int op, rs, rt, rd, re, func, imm, target; |
int imm_shift, branch=0, lbranch=2, skip2=0; |
int link=0; /* !=0 if this is a 'branch-and-link' opcode */ |
int *r=s->r; |
unsigned int *u=(unsigned int*)s->r; |
unsigned int ptr, epc, rSave; |
800,8 → 952,11
uint32_t target_offset16; |
uint32_t target_long; |
|
s->trap_cause = -1; |
|
/* fetch and decode instruction */ |
opcode = mem_read(s, 4, s->pc, 0); |
opcode = mem_read(s, 4, s->pc, 0); |
|
op = (opcode >> 26) & 0x3f; |
rs = (opcode >> 21) & 0x1f; |
rt = (opcode >> 16) & 0x1f; |
845,7 → 1000,7
aux = op&0x03; |
switch(rs){ |
case 16: |
/* FIXME partial decoding */ |
/* FIXME partial decoding of some COP0 opcodes */ |
printf(" RFE "); format = ' '; break; |
case 4: |
printf(" MTC%1d ", aux); break; |
948,22 → 1103,22
case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs]; break; |
case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs]; break; |
case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs]; break; |
case 0x08:/*JR*/ delay_slot=1; |
case 0x08:/*JR*/ if(rs==31) log_ret(r[rs],epc); |
delay_slot=1; |
s->pc_next=r[rs]; break; |
case 0x09:/*JALR*/ delay_slot=1; |
r[rd]=s->pc_next; |
s->pc_next=r[rs]; break; |
s->pc_next=r[rs]; |
log_call(s->pc_next, epc); break; |
case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs]; break; /*IV*/ |
case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs]; break; /*IV*/ |
case 0x0c:/*SYSCALL*/ trap_cause = 8; |
s->exceptionId=1; |
case 0x0c:/*SYSCALL*/ s->trap_cause = 8; |
/* |
FIXME enable when running uClinux |
printf("SYSCALL (%08x)\n", s->pc); |
*/ |
break; |
case 0x0d:/*BREAK*/ trap_cause = 9; |
s->exceptionId=1; |
case 0x0d:/*BREAK*/ s->trap_cause = 9; |
/* |
FIXME enable when running uClinux |
printf("BREAK (%08x)\n", s->pc); |
994,25 → 1149,24
case 0x33:/*TLTU*/ break; |
case 0x34:/*TEQ*/ break; |
case 0x36:/*TNE*/ break; |
default: printf("ERROR0(*0x%x~0x%x)\n", s->pc, opcode); |
/* FIXME should trap unknown opcode */ |
s->wakeup=1; |
default: |
reserved_opcode(epc, opcode, s); |
} |
break; |
case 0x01:/*REGIMM*/ |
switch(rt){ |
case 0x10:/*BLTZAL*/ r[31]=s->pc_next; |
case 0x10:/*BLTZAL*/ r[31]=s->pc_next; link=1; |
case 0x00:/*BLTZ*/ branch=r[rs]<0; break; |
case 0x11:/*BGEZAL*/ r[31]=s->pc_next; |
case 0x11:/*BGEZAL*/ r[31]=s->pc_next; link=1; |
case 0x01:/*BGEZ*/ branch=r[rs]>=0; break; |
case 0x12:/*BLTZALL*/r[31]=s->pc_next; |
case 0x12:/*BLTZALL*/r[31]=s->pc_next; link=1; |
case 0x02:/*BLTZL*/ lbranch=r[rs]<0; break; |
case 0x13:/*BGEZALL*/r[31]=s->pc_next; |
case 0x13:/*BGEZALL*/r[31]=s->pc_next; link=1; |
case 0x03:/*BGEZL*/ lbranch=r[rs]>=0; break; |
default: printf("ERROR1\n"); s->wakeup=1; |
} |
break; |
case 0x03:/*JAL*/ r[31]=s->pc_next; |
case 0x03:/*JAL*/ r[31]=s->pc_next; log_call(((s->pc&0xf0000000)|target), epc); |
case 0x02:/*J*/ delay_slot=1; |
s->pc_next=(s->pc&0xf0000000)|target; break; |
case 0x04:/*BEQ*/ branch=r[rs]==r[rt]; break; |
1037,6 → 1191,7
case 14: r[rt]=s->epc; break; |
case 15: r[rt]=R3000_ID; break; |
default: |
printf("mfc0 [%02d] @ [0x%08x]\n", rt, s->pc); |
break; |
} |
} |
1052,26 → 1207,16
printf("mtc0 [%2d]=0x%08x @ [0x%08x] IGNORED\n", |
rd, r[rt], epc); |
} |
/* FIXME remove remnants of Plasma MMU simulation */ |
/* |
if(s->processId && (r[rt]&2)){ |
s->userMode|=r[rt]&2; |
//printf("CpuStatus=%d %d %d\n", r[rt], s->status, s->userMode); |
//s->wakeup = 1; |
//printf("pc=0x%x\n", epc); |
} |
*/ |
} |
} |
else{ |
/* tried to execute mtc* or mfc* in user mode: trap */ |
printf("COP0 UNAVAILABLE address=0x%08x opcode=0x%x -- ", |
epc, opcode); |
printf("COP0 UNAVAILABLE [0x%08x] = 0x%x %c -- ", |
epc, opcode, (s->delay_slot? 'D':' ')); |
print_opcode_fields(opcode); |
printf("\n"); |
|
trap_cause = 11; /* unavailable coprocessor */ |
s->exceptionId=1; |
s->trap_cause = 11; /* unavailable coprocessor */ |
} |
break; |
case 0x11:/*COP1*/ unimplemented(s,"COP1"); |
1082,7 → 1227,31
case 0x15:/*BNEL*/ lbranch=r[rs]!=r[rt]; break; |
case 0x16:/*BLEZL*/ lbranch=r[rs]<=0; break; |
case 0x17:/*BGTZL*/ lbranch=r[rs]>0; break; |
// case 0x1c:/*MAD*/ break; /*IV*/ |
case 0x1c:/*SPECIAL2*/ |
/* MIPS32 opcodes, some of which may be emulated */ |
if(cmd_line_args.emulate_some_mips32){ |
switch(func){ |
case 0x20: /* CLZ */ r[rt] = count_leading(0, r[rs]); break; |
case 0x21: /* CLO */ r[rt] = count_leading(1, r[rs]); break; |
case 0x02: /* MUL */ r[rd] = mult_gpr(r[rs], r[rt]); break; |
default: |
reserved_opcode(epc, opcode, s); |
} |
} |
else{ |
reserved_opcode(epc, opcode, s); |
} |
break; |
case 0x1f: /* SPECIAL3 */ |
if(cmd_line_args.emulate_some_mips32){ |
switch(func){ |
case 0x00: /* EXT */ r[rt] = ext_bitfield(r[rs], opcode); break; |
case 0x04: /* INS */ r[rt] = ins_bitfield(r[rt], r[rs], opcode); break; |
default: |
reserved_opcode(epc, opcode, s); |
} |
} |
break; |
case 0x20:/*LB*/ //r[rt]=(signed char)mem_read(s,1,ptr,1); break; |
start_load(s, ptr, rt,(signed char)mem_read(s,1,ptr,1)); |
break; |
1134,18 → 1303,14
// case 0x3e:/*SDC2*/ break; |
// case 0x3f:/*SDC3*/ break; |
default: /* unimplemented opcode */ |
if(cmd_line_args.trap_on_reserved){ |
trap_cause = 10; /* reserved instruction */ |
s->exceptionId=1; |
} |
else{ |
printf("RESERVED OPCODE address=0x%08x opcode=0x%x -- ", |
epc, opcode); |
print_opcode_fields(opcode); |
printf("\n"); |
} |
reserved_opcode(epc, opcode, s); |
} |
|
/* */ |
if((branch || lbranch == 1) && link){ |
log_call(s->pc_next + imm_shift, epc); |
} |
|
/* adjust next PC if this was a a jump instruction */ |
s->pc_next += (branch || lbranch == 1) ? imm_shift : 0; |
s->pc_next &= ~3; |
1161,10 → 1326,10
/* load delay slots not simulated */ |
|
/* Handle exceptions */ |
if(s->exceptionId){ |
if(s->trap_cause>=0){ |
r[rt] = rSave; |
/* set cause field ... */ |
s->cp0_cause = (s->delay_slot & 0x1) << 31 | (trap_cause & 0x1f) << 2; |
s->cp0_cause = (s->delay_slot & 0x1) << 31 | (s->trap_cause & 0x1f) << 2; |
/* ...save previous KU/IE flags in SR... */ |
s->status = (s->status & 0xffffffc3) | ((s->status & 0x0f) << 2); |
/* ...and raise KU(EXL) kernel mode flag */ |
1176,7 → 1341,6
s->epc = epc; |
s->pc_next = VECTOR_TRAP; |
s->skip = 1; |
s->exceptionId = 0; |
s->userMode = 0; |
//s->wakeup = 1; |
} |
1183,7 → 1347,7
|
/* if we're NOT showing output to console, log state of CPU to file */ |
if(!show_mode){ |
log_cycle(s); |
s->wakeup |= log_cycle(s); |
} |
|
|
1212,7 → 1376,20
printf("%02x", field); |
} |
|
/** Deal with reserved, unimplemented opcodes. Updates s->trap_cause. */ |
void reserved_opcode(uint32_t pc, uint32_t opcode, t_state* s){ |
if(cmd_line_args.trap_on_reserved){ |
s->trap_cause = 10; /* reserved instruction */ |
} |
else{ |
printf("RESERVED OPCODE [0x%08x] = 0x%08x %c -- ", |
pc, opcode, (s->delay_slot? 'D':' ')); |
print_opcode_fields(opcode); |
printf("\n"); |
} |
} |
|
|
/** Dump CPU state to console */ |
void show_state(t_state *s){ |
int i,j; |
1389,6 → 1566,18
uint8_t *target; |
uint32_t bytes=0, i, files_read=0; |
|
/* read map file if requested */ |
if(args->map_filename!=NULL){ |
if(read_map_file(args->map_filename, &map_info)<0){ |
printf("Trouble reading map file '%s', quitting!\n", |
args->map_filename); |
return 1; |
} |
printf("Read %d functions from the map file; call trace enabled.\n\n", |
map_info.num_functions); |
} |
|
/* read object code binaries */ |
for(i=0;i<NUM_MEM_BLOCKS;i++){ |
bytes = 0; |
if(args->bin_filename[i]!=NULL){ |
1418,7 → 1607,7
|
/* Now reverse the endianness of the data we just read, if it's |
necessary. */ |
/* FIXME add cmd line param, etc. */ |
/* FIXME handle little-endian stuff (?) */ |
//reverse_endianess(target, bytes); |
|
files_read++; |
1458,6 → 1647,8
|
int main(int argc,char *argv[]){ |
t_state state, *s=&state; |
|
|
|
/* Parse command line and pass any relevant arguments to CPU record */ |
if(parse_cmd_line(argc,argv, &cmd_line_args)==0){ |
1486,8 → 1677,8
reset_cpu(s); |
|
/* Simulate the work of the uClinux bootloader */ |
if(cmd_line_args.memory_map == MAP_UCLINUX){ |
/* FIXME this is a stub, flesh it out */ |
if(cmd_line_args.memory_map == MAP_UCLINUX_BRAM){ |
/* FIXME this 'bootloader' is a stub, flesh it out */ |
s->pc = 0x80002400; |
} |
|
1512,6 → 1703,7
#if FILE_LOGGING_DISABLED |
s->t.log = NULL; |
s->t.log_triggered = 0; |
map_info.log = NULL; |
return; |
#else |
/* clear trace buffer */ |
1535,6 → 1727,15
/* Setup log trigger */ |
s->t.log_triggered = 0; |
s->t.log_trigger_address = args->log_trigger_address; |
|
/* if file logging of function calls is enabled, open log file */ |
if(map_info.log_filename!=NULL){ |
map_info.log = fopen(map_info.log_filename, "w"); |
if(map_info.log==NULL){ |
printf("Error opening log file '%s', file logging disabled\n", |
map_info.log_filename); |
} |
} |
#endif |
} |
|
1551,7 → 1752,7
} |
|
/** Logs last cycle's activity (changes in state and/or loads/stores) */ |
void log_cycle(t_state *s){ |
uint32_t log_cycle(t_state *s){ |
static unsigned int last_pc = 0; |
int i; |
uint32_t log_pc; |
1561,11 → 1762,12
s->t.buf[s->t.next] = s->pc; |
s->t.next = (s->t.next + 1) % TRACE_BUFFER_SIZE; |
} |
last_pc = s->pc; |
last_pc = s->pc; |
log_pc = s->op_addr; |
|
|
/* if file logging is enabled, dump a trace log to file */ |
if(log_enabled(s)){ |
log_pc = s->op_addr; |
|
/* skip register zero which does not change */ |
for(i=1;i<32;i++){ |
1590,11 → 1792,23
} |
s->t.epc = s->epc; |
|
if(s->status != s->t. status){ |
if(s->status != s->t.status){ |
fprintf(s->t.log, "(%08X) [SR]=%08X\n", log_pc, s->status); |
} |
s->t.status = s->status; |
} |
} |
|
#if 0 |
/* FIXME Try to detect a code crash by looking at SP */ |
if(1){ |
if((s->r[29]&0xffff0000) == 0xffff00000){ |
printf("SP derailed! @ 0x%08x [0x%08x]\n", log_pc, s->r[29]); |
return 1; |
} |
} |
#endif |
|
return 0; |
} |
|
/** Frees debug buffers and closes log file */ |
1602,6 → 1816,9
if(s->t.log){ |
fclose(s->t.log); |
} |
if(map_info.log){ |
fclose(map_info.log); |
} |
} |
|
/** Logs a message for each failed assertion, each in a line */ |
1640,6 → 1857,55
s->t.epc = s->epc; |
} |
|
int32_t read_map_file(char *filename, t_map_info* map){ |
FILE *f; |
uint32_t address, i; |
uint32_t segment_text = 0; |
char line[256]; |
char name[256]; |
|
f = fopen (filename, "rt"); /* open the file for reading */ |
|
if(!f){ |
return -1; |
} |
|
while(fgets(line, sizeof(line)-1, f) != NULL){ |
if(!strncmp(line, ".text", 5)){ |
segment_text = 1; |
} |
else if(line[0]==' ' && segment_text){ |
/* may be a function address */ |
for(i=0;(i<sizeof(line)-1) && (line[i]==' '); i++); |
if(line[i]=='0'){ |
sscanf(line, "%*[ \n\t]%x%*[ \n\t]%s", &address, &(name[0])); |
|
strncpy(map->fn_name[map->num_functions], |
name, MAP_MAX_NAME_LEN-1); |
map->fn_address[map->num_functions] = address; |
map->num_functions++; |
if(map->num_functions >= MAP_MAX_FUNCTIONS){ |
printf("WARNING: too many functions in map file!\n"); |
return map->num_functions; |
} |
} |
} |
else if(line[0]=='.' && segment_text){ |
break; |
} |
} |
fclose(f); |
|
#if 0 |
for(i=0;i<map->num_functions;i++){ |
printf("--> %08x %s\n", map->fn_address[i], map->fn_name[i]); |
} |
#endif |
|
return map->num_functions; |
} |
|
|
void free_cpu(t_state *s){ |
int i; |
|
1657,9 → 1923,9
/* init trace struct to prevent spurious logs */ |
s->t.status = s->status; |
} |
|
|
/* FIXME redundant function, merge with reserved_opcode */ |
void unimplemented(t_state *s, const char *txt){ |
/* FIXME unimplemented opcode trap */ |
printf("UNIMPLEMENTED: %s\n", txt); |
} |
|
1697,9 → 1963,15
int32_t parse_cmd_line(uint32_t argc, char **argv, t_args *args){ |
uint32_t i; |
|
/* Initialize logging parameters */ |
map_info.num_functions = 0; |
map_info.log_filename = NULL; |
map_info.log = stdout; |
|
/* fill cmd line args with default values */ |
args->memory_map = MAP_DEFAULT; |
args->trap_on_reserved = 1; |
args->emulate_some_mips32 = 1; |
args->start_addr = VECTOR_RESET; |
args->do_unaligned = 0; |
args->no_prompt = 0; |
1706,6 → 1978,7
args->breakpoint = 0xffffffff; |
args->log_file_name = "sw_sim_log.txt"; |
args->log_trigger_address = VECTOR_RESET; |
args->map_filename = NULL; |
for(i=0;i<NUM_MEM_BLOCKS;i++){ |
args->bin_filename[i] = NULL; |
args->offset[i] = 0; |
1719,7 → 1992,7
return 0; |
} |
else if(strcmp(argv[i],"--uclinux")==0){ |
args->memory_map = MAP_UCLINUX; |
args->memory_map = MAP_UCLINUX_BRAM; |
/* FIXME selecting uClinux enables unaligned L/S emulation */ |
args->do_unaligned = 1; |
} |
1735,6 → 2008,9
else if(strcmp(argv[i],"--notrap10")==0){ |
args->trap_on_reserved = 0; |
} |
else if(strcmp(argv[i],"--nomips32")==0){ |
args->emulate_some_mips32 = 0; |
} |
else if(strncmp(argv[i],"--bram=", strlen("--bram="))==0){ |
args->bin_filename[0] = &(argv[i][strlen("--bram=")]); |
} |
1744,6 → 2020,12
else if(strncmp(argv[i],"--xram=", strlen("--xram="))==0){ |
args->bin_filename[1] = &(argv[i][strlen("--xram=")]); |
} |
else if(strncmp(argv[i],"--map=", strlen("--map="))==0){ |
args->map_filename = &(argv[i][strlen("--map=")]); |
} |
else if(strncmp(argv[i],"--trace_log=", strlen("--trace_log="))==0){ |
map_info.log_filename = &(argv[i][strlen("--trace_log=")]); |
} |
else if(strncmp(argv[i],"--start=", strlen("--start="))==0){ |
sscanf(&(argv[i][strlen("--start=")]), "%x", &(args->start_addr)); |
} |
1784,10 → 2066,13
printf("--kernel=<file name> : XRAM initialization file for uClinux kernel\n"); |
printf(" (loads at block offset 0x2000)\n"); |
printf("--flash=<file name> : FLASH initialization file\n"); |
printf("--map=<file name> : Map file to be used for tracing, if any\n"); |
printf("--trace_log=<file name> : Log file used for tracing, if any\n"); |
printf("--trigger=<hex number> : Log trigger address\n"); |
printf("--break=<hex number> : Breakpoint address\n"); |
printf("--start=<hex number> : Start here instead of at reset vector\n"); |
printf("--notrap10 : Reserverd opcodes are NOPs and don't trap\n"); |
printf("--nomips32 : Do not emulate any mips32 opcodes\n"); |
printf("--plasma : Simulate Plasma instead of MIPS-I\n"); |
printf("--uclinux : Use memory map tailored to uClinux\n"); |
printf("--unaligned : Implement unaligned load/store instructions\n"); |