146 |
void mips64_idle_break_wait(cpu_mips_t *cpu) |
void mips64_idle_break_wait(cpu_mips_t *cpu) |
147 |
{ |
{ |
148 |
pthread_cond_signal(&cpu->idle_cond); |
pthread_cond_signal(&cpu->idle_cond); |
149 |
|
cpu->idle_count = 0; |
150 |
} |
} |
151 |
|
|
152 |
/* Timer IRQ */ |
/* Timer IRQ */ |
193 |
return NULL; |
return NULL; |
194 |
} |
} |
195 |
|
|
196 |
|
#define IDLE_HASH_SIZE 8192 |
197 |
|
|
198 |
/* Idle PC hash item */ |
/* Idle PC hash item */ |
199 |
struct mips64_idle_pc { |
struct mips64_idle_pc_hash { |
200 |
m_uint64_t pc; |
m_uint64_t pc; |
201 |
u_int count; |
u_int count; |
202 |
struct mips64_idle_pc *next; |
struct mips64_idle_pc_hash *next; |
203 |
}; |
}; |
204 |
|
|
|
#define IDLE_HASH_SIZE 8192 |
|
|
#define IDLE_MAX_RES 10 |
|
|
|
|
205 |
/* Determine an "idling" PC */ |
/* Determine an "idling" PC */ |
206 |
int mips64_get_idling_pc(cpu_mips_t *cpu) |
int mips64_get_idling_pc(cpu_mips_t *cpu) |
207 |
{ |
{ |
208 |
struct mips64_idle_pc *res[IDLE_MAX_RES]; |
struct mips64_idle_pc_hash **pc_hash,*p; |
209 |
struct mips64_idle_pc **pc_hash,*p; |
struct mips64_idle_pc *res; |
210 |
u_int h_index,res_count; |
u_int h_index,res_count; |
211 |
m_uint64_t cur_pc; |
m_uint64_t cur_pc; |
212 |
int i; |
int i; |
213 |
|
|
214 |
|
cpu->idle_pc_prop_count = 0; |
215 |
|
|
216 |
if (cpu->idle_pc != 0) { |
if (cpu->idle_pc != 0) { |
217 |
printf("\nYou already use an idle PC, using the calibration would give " |
printf("\nYou already use an idle PC, using the calibration would give " |
218 |
"incorrect results.\n"); |
"incorrect results.\n"); |
250 |
} |
} |
251 |
|
|
252 |
/* Select PCs */ |
/* Select PCs */ |
|
memset(res,0,sizeof(res)); |
|
|
|
|
253 |
for(i=0,res_count=0;i<IDLE_HASH_SIZE;i++) { |
for(i=0,res_count=0;i<IDLE_HASH_SIZE;i++) { |
254 |
for(p=pc_hash[i];p;p=p->next) |
for(p=pc_hash[i];p;p=p->next) |
255 |
if ((p->count >= 20) && (p->count <= 80)) { |
if ((p->count >= 20) && (p->count <= 80)) { |
256 |
res[res_count++] = p; |
res = &cpu->idle_pc_prop[cpu->idle_pc_prop_count++]; |
257 |
|
|
258 |
|
res->pc = p->pc; |
259 |
|
res->count = p->count; |
260 |
|
|
261 |
if (res_count >= IDLE_MAX_RES) |
if (cpu->idle_pc_prop_count >= MIPS64_IDLE_PC_MAX_RES) |
262 |
goto done; |
goto done; |
263 |
} |
} |
264 |
} |
} |
265 |
|
|
266 |
done: |
done: |
267 |
/* Set idle PC */ |
/* Set idle PC */ |
268 |
if (res_count) { |
if (cpu->idle_pc_prop_count) { |
269 |
printf("Done. Suggested idling PC:\n"); |
printf("Done. Suggested idling PC:\n"); |
270 |
|
|
271 |
for(i=0;i<res_count;i++) |
for(i=0;i<cpu->idle_pc_prop_count;i++) { |
272 |
printf(" 0x%llx (count=%u)\n",res[i]->pc,res[i]->count); |
printf(" 0x%llx (count=%u)\n", |
273 |
|
cpu->idle_pc_prop[i].pc, |
274 |
|
cpu->idle_pc_prop[i].count); |
275 |
|
} |
276 |
|
|
277 |
printf("Restart the emulator with \"--idle-pc=0x%llx\" (for example)\n", |
printf("Restart the emulator with \"--idle-pc=0x%llx\" (for example)\n", |
278 |
res[0]->pc); |
cpu->idle_pc_prop[0].pc); |
279 |
} else { |
} else { |
280 |
printf("Done. No suggestion for idling PC\n"); |
printf("Done. No suggestion for idling PC\n"); |
281 |
} |
} |
497 |
cpu_log(cpu,"BREAKPOINT", |
cpu_log(cpu,"BREAKPOINT", |
498 |
"Virtual breakpoint reached at PC=0x%llx\n",cpu->pc); |
"Virtual breakpoint reached at PC=0x%llx\n",cpu->pc); |
499 |
|
|
500 |
printf("[[[ Virtual Breakpoint reached at PC=0x%llx ]]]\n",cpu->pc); |
printf("[[[ Virtual Breakpoint reached at PC=0x%llx RA=0x%llx]]]\n", |
501 |
|
cpu->pc,cpu->gpr[MIPS_GPR_RA]); |
502 |
|
|
503 |
mips64_dump_regs(cpu); |
mips64_dump_regs(cpu); |
504 |
memlog_dump(cpu); |
memlog_dump(cpu); |
505 |
} |
} |
506 |
|
|
507 |
|
/* Add a virtual breakpoint */ |
508 |
|
int mips64_add_breakpoint(cpu_mips_t *cpu,m_uint64_t pc) |
509 |
|
{ |
510 |
|
int i; |
511 |
|
|
512 |
|
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
513 |
|
if (!cpu->breakpoints[i]) |
514 |
|
break; |
515 |
|
|
516 |
|
if (i == MIPS64_MAX_BREAKPOINTS) |
517 |
|
return(-1); |
518 |
|
|
519 |
|
cpu->breakpoints[i] = pc; |
520 |
|
cpu->breakpoints_enabled = TRUE; |
521 |
|
return(0); |
522 |
|
} |
523 |
|
|
524 |
|
/* Remove a virtual breakpoint */ |
525 |
|
void mips64_remove_breakpoint(cpu_mips_t *cpu,m_uint64_t pc) |
526 |
|
{ |
527 |
|
int i,j; |
528 |
|
|
529 |
|
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
530 |
|
if (cpu->breakpoints[i] == pc) |
531 |
|
{ |
532 |
|
for(j=i;j<MIPS64_MAX_BREAKPOINTS-1;j++) |
533 |
|
cpu->breakpoints[j] = cpu->breakpoints[j+1]; |
534 |
|
|
535 |
|
cpu->breakpoints[MIPS64_MAX_BREAKPOINTS-1] = 0; |
536 |
|
} |
537 |
|
|
538 |
|
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
539 |
|
if (cpu->breakpoints[i] != 0) |
540 |
|
return; |
541 |
|
|
542 |
|
cpu->breakpoints_enabled = TRUE; |
543 |
|
} |
544 |
|
|
545 |
/* Debugging for register-jump to address 0 */ |
/* Debugging for register-jump to address 0 */ |
546 |
fastcall void mips64_debug_jr0(cpu_mips_t *cpu) |
fastcall void mips64_debug_jr0(cpu_mips_t *cpu) |
547 |
{ |
{ |