67 |
memset(&cpu->cp0.tlb,0,MIPS64_TLB_MAX_ENTRIES*sizeof(tlb_entry_t)); |
memset(&cpu->cp0.tlb,0,MIPS64_TLB_MAX_ENTRIES*sizeof(tlb_entry_t)); |
68 |
|
|
69 |
/* Restart the MTS subsystem */ |
/* Restart the MTS subsystem */ |
70 |
mts_shutdown(cpu); |
mts_set_addr_mode(cpu,64); |
|
mts64_init(cpu); |
|
|
mts_init_memop_vectors(cpu); |
|
71 |
cpu->mts_rebuild(cpu); |
cpu->mts_rebuild(cpu); |
72 |
|
|
73 |
/* Flush JIT structures */ |
/* Flush JIT structures */ |
85 |
|
|
86 |
/* Initialize idle timer */ |
/* Initialize idle timer */ |
87 |
cpu->idle_max = 1500; |
cpu->idle_max = 1500; |
88 |
cpu->idle_sleep_time = 50000; |
cpu->idle_sleep_time = 30000; |
89 |
|
|
90 |
/* Timer IRQ parameters (default frequency: 250 Hz <=> 4ms period) */ |
/* Timer IRQ parameters (default frequency: 250 Hz <=> 4ms period) */ |
91 |
cpu->timer_irq_check_itv = 1000; |
cpu->timer_irq_check_itv = 1000; |
144 |
void mips64_idle_break_wait(cpu_mips_t *cpu) |
void mips64_idle_break_wait(cpu_mips_t *cpu) |
145 |
{ |
{ |
146 |
pthread_cond_signal(&cpu->idle_cond); |
pthread_cond_signal(&cpu->idle_cond); |
147 |
|
cpu->idle_count = 0; |
148 |
} |
} |
149 |
|
|
150 |
/* Timer IRQ */ |
/* Timer IRQ */ |
191 |
return NULL; |
return NULL; |
192 |
} |
} |
193 |
|
|
194 |
|
#define IDLE_HASH_SIZE 8192 |
195 |
|
|
196 |
/* Idle PC hash item */ |
/* Idle PC hash item */ |
197 |
struct mips64_idle_pc { |
struct mips64_idle_pc_hash { |
198 |
m_uint64_t pc; |
m_uint64_t pc; |
199 |
u_int count; |
u_int count; |
200 |
struct mips64_idle_pc *next; |
struct mips64_idle_pc_hash *next; |
201 |
}; |
}; |
202 |
|
|
|
#define IDLE_HASH_SIZE 8192 |
|
|
#define IDLE_MAX_RES 10 |
|
|
|
|
203 |
/* Determine an "idling" PC */ |
/* Determine an "idling" PC */ |
204 |
int mips64_get_idling_pc(cpu_mips_t *cpu) |
int mips64_get_idling_pc(cpu_mips_t *cpu) |
205 |
{ |
{ |
206 |
struct mips64_idle_pc *res[IDLE_MAX_RES]; |
struct mips64_idle_pc_hash **pc_hash,*p; |
207 |
struct mips64_idle_pc **pc_hash,*p; |
struct mips64_idle_pc *res; |
208 |
u_int h_index,res_count; |
u_int h_index,res_count; |
209 |
m_uint64_t cur_pc; |
m_uint64_t cur_pc; |
210 |
int i; |
int i; |
211 |
|
|
212 |
|
cpu->idle_pc_prop_count = 0; |
213 |
|
|
214 |
if (cpu->idle_pc != 0) { |
if (cpu->idle_pc != 0) { |
215 |
printf("\nYou already use an idle PC, using the calibration would give " |
printf("\nYou already use an idle PC, using the calibration would give " |
216 |
"incorrect results.\n"); |
"incorrect results.\n"); |
248 |
} |
} |
249 |
|
|
250 |
/* Select PCs */ |
/* Select PCs */ |
|
memset(res,0,sizeof(res)); |
|
|
|
|
251 |
for(i=0,res_count=0;i<IDLE_HASH_SIZE;i++) { |
for(i=0,res_count=0;i<IDLE_HASH_SIZE;i++) { |
252 |
for(p=pc_hash[i];p;p=p->next) |
for(p=pc_hash[i];p;p=p->next) |
253 |
if ((p->count >= 20) && (p->count <= 80)) { |
if ((p->count >= 20) && (p->count <= 80)) { |
254 |
res[res_count++] = p; |
res = &cpu->idle_pc_prop[cpu->idle_pc_prop_count++]; |
255 |
|
|
256 |
if (res_count >= IDLE_MAX_RES) |
res->pc = p->pc; |
257 |
|
res->count = p->count; |
258 |
|
|
259 |
|
if (cpu->idle_pc_prop_count >= MIPS64_IDLE_PC_MAX_RES) |
260 |
goto done; |
goto done; |
261 |
} |
} |
262 |
} |
} |
263 |
|
|
264 |
done: |
done: |
265 |
/* Set idle PC */ |
/* Set idle PC */ |
266 |
if (res_count) { |
if (cpu->idle_pc_prop_count) { |
267 |
printf("Done. Suggested idling PC:\n"); |
printf("Done. Suggested idling PC:\n"); |
268 |
|
|
269 |
for(i=0;i<res_count;i++) |
for(i=0;i<cpu->idle_pc_prop_count;i++) { |
270 |
printf(" 0x%llx (count=%u)\n",res[i]->pc,res[i]->count); |
printf(" 0x%llx (count=%u)\n", |
271 |
|
cpu->idle_pc_prop[i].pc, |
272 |
|
cpu->idle_pc_prop[i].count); |
273 |
|
} |
274 |
|
|
275 |
printf("Restart the emulator with \"--idle-pc=0x%llx\" (for example)\n", |
printf("Restart the emulator with \"--idle-pc=0x%llx\" (for example)\n", |
276 |
res[0]->pc); |
cpu->idle_pc_prop[0].pc); |
277 |
} else { |
} else { |
278 |
printf("Done. No suggestion for idling PC\n"); |
printf("Done. No suggestion for idling PC\n"); |
279 |
} |
} |
495 |
cpu_log(cpu,"BREAKPOINT", |
cpu_log(cpu,"BREAKPOINT", |
496 |
"Virtual breakpoint reached at PC=0x%llx\n",cpu->pc); |
"Virtual breakpoint reached at PC=0x%llx\n",cpu->pc); |
497 |
|
|
498 |
printf("[[[ Virtual Breakpoint reached at PC=0x%llx ]]]\n",cpu->pc); |
printf("[[[ Virtual Breakpoint reached at PC=0x%llx RA=0x%llx]]]\n", |
499 |
|
cpu->pc,cpu->gpr[MIPS_GPR_RA]); |
500 |
|
|
501 |
mips64_dump_regs(cpu); |
mips64_dump_regs(cpu); |
502 |
memlog_dump(cpu); |
memlog_dump(cpu); |
503 |
} |
} |
504 |
|
|
505 |
|
/* Add a virtual breakpoint */ |
506 |
|
int mips64_add_breakpoint(cpu_mips_t *cpu,m_uint64_t pc) |
507 |
|
{ |
508 |
|
int i; |
509 |
|
|
510 |
|
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
511 |
|
if (!cpu->breakpoints[i]) |
512 |
|
break; |
513 |
|
|
514 |
|
if (i == MIPS64_MAX_BREAKPOINTS) |
515 |
|
return(-1); |
516 |
|
|
517 |
|
cpu->breakpoints[i] = pc; |
518 |
|
cpu->breakpoints_enabled = TRUE; |
519 |
|
return(0); |
520 |
|
} |
521 |
|
|
522 |
|
/* Remove a virtual breakpoint */ |
523 |
|
void mips64_remove_breakpoint(cpu_mips_t *cpu,m_uint64_t pc) |
524 |
|
{ |
525 |
|
int i,j; |
526 |
|
|
527 |
|
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
528 |
|
if (cpu->breakpoints[i] == pc) |
529 |
|
{ |
530 |
|
for(j=i;j<MIPS64_MAX_BREAKPOINTS-1;j++) |
531 |
|
cpu->breakpoints[j] = cpu->breakpoints[j+1]; |
532 |
|
|
533 |
|
cpu->breakpoints[MIPS64_MAX_BREAKPOINTS-1] = 0; |
534 |
|
} |
535 |
|
|
536 |
|
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
537 |
|
if (cpu->breakpoints[i] != 0) |
538 |
|
return; |
539 |
|
|
540 |
|
cpu->breakpoints_enabled = TRUE; |
541 |
|
} |
542 |
|
|
543 |
/* Debugging for register-jump to address 0 */ |
/* Debugging for register-jump to address 0 */ |
544 |
fastcall void mips64_debug_jr0(cpu_mips_t *cpu) |
fastcall void mips64_debug_jr0(cpu_mips_t *cpu) |
545 |
{ |
{ |
849 |
} |
} |
850 |
|
|
851 |
/* Load an ELF image into the simulated memory */ |
/* Load an ELF image into the simulated memory */ |
852 |
int mips64_load_elf_image(cpu_mips_t *cpu,char *filename, |
int mips64_load_elf_image(cpu_mips_t *cpu,char *filename,int skip_load, |
853 |
m_uint32_t *entry_point) |
m_uint32_t *entry_point) |
854 |
{ |
{ |
855 |
m_uint64_t vaddr; |
m_uint64_t vaddr; |
901 |
return(-1); |
return(-1); |
902 |
} |
} |
903 |
|
|
904 |
for(i=0;i<ehdr->e_shnum;i++) { |
if (!skip_load) { |
905 |
scn = elf_getscn(img_elf,i); |
for(i=0;i<ehdr->e_shnum;i++) { |
906 |
|
scn = elf_getscn(img_elf,i); |
907 |
shdr = elf32_getshdr(scn); |
|
908 |
name = elf_strptr(img_elf, ehdr->e_shstrndx, (size_t)shdr->sh_name); |
shdr = elf32_getshdr(scn); |
909 |
len = shdr->sh_size; |
name = elf_strptr(img_elf, ehdr->e_shstrndx, (size_t)shdr->sh_name); |
910 |
|
len = shdr->sh_size; |
911 |
if (!(shdr->sh_flags & SHF_ALLOC) || !len) |
|
912 |
continue; |
if (!(shdr->sh_flags & SHF_ALLOC) || !len) |
913 |
|
continue; |
914 |
fseek(bfd,shdr->sh_offset,SEEK_SET); |
|
915 |
vaddr = sign_extend(shdr->sh_addr,32); |
fseek(bfd,shdr->sh_offset,SEEK_SET); |
916 |
|
vaddr = sign_extend(shdr->sh_addr,32); |
917 |
if (cpu->vm->debug_level > 0) { |
|
918 |
printf(" * Adding section at virtual address 0x%8.8llx " |
if (cpu->vm->debug_level > 0) { |
919 |
"(len=0x%8.8lx)\n",vaddr & 0xFFFFFFFF,(u_long)len); |
printf(" * Adding section at virtual address 0x%8.8llx " |
920 |
} |
"(len=0x%8.8lx)\n",vaddr & 0xFFFFFFFF,(u_long)len); |
|
|
|
|
while(len > 0) |
|
|
{ |
|
|
haddr = cpu->mem_op_lookup(cpu,vaddr); |
|
|
|
|
|
if (!haddr) { |
|
|
fprintf(stderr,"load_elf_image: invalid load address 0x%llx\n", |
|
|
vaddr); |
|
|
return(-1); |
|
921 |
} |
} |
922 |
|
|
923 |
|
while(len > 0) |
924 |
|
{ |
925 |
|
haddr = cpu->mem_op_lookup(cpu,vaddr); |
926 |
|
|
927 |
|
if (!haddr) { |
928 |
|
fprintf(stderr,"load_elf_image: invalid load address 0x%llx\n", |
929 |
|
vaddr); |
930 |
|
return(-1); |
931 |
|
} |
932 |
|
|
933 |
if (len > MIPS_MIN_PAGE_SIZE) |
if (len > MIPS_MIN_PAGE_SIZE) |
934 |
clen = MIPS_MIN_PAGE_SIZE; |
clen = MIPS_MIN_PAGE_SIZE; |
935 |
else |
else |
936 |
clen = len; |
clen = len; |
937 |
|
|
938 |
clen = fread((u_char *)haddr,clen,1,bfd); |
clen = fread((u_char *)haddr,clen,1,bfd); |
939 |
|
|
940 |
if (clen != 1) |
if (clen != 1) |
941 |
break; |
break; |
942 |
|
|
943 |
vaddr += MIPS_MIN_PAGE_SIZE; |
vaddr += MIPS_MIN_PAGE_SIZE; |
944 |
len -= clen; |
len -= clen; |
945 |
|
} |
946 |
} |
} |
947 |
|
} else { |
948 |
|
printf("ELF loading skipped, using a ghost RAM file.\n"); |
949 |
} |
} |
950 |
|
|
951 |
printf("ELF entry point: 0x%x\n",ehdr->e_entry); |
printf("ELF entry point: 0x%x\n",ehdr->e_entry); |