1 |
/* |
/* |
2 |
* Cisco 7200 (Predator) simulation platform. |
* Cisco router simulation platform. |
3 |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
4 |
* |
* |
5 |
* XXX TODO: proper context save/restore for CPUs. |
* XXX TODO: proper context save/restore for CPUs. |
16 |
#include <assert.h> |
#include <assert.h> |
17 |
|
|
18 |
#include "rbtree.h" |
#include "rbtree.h" |
19 |
#include "mips64.h" |
#include "cpu.h" |
20 |
#include "dynamips.h" |
#include "mips64_mem.h" |
|
#include "cp0.h" |
|
21 |
#include "mips64_exec.h" |
#include "mips64_exec.h" |
22 |
|
#include "mips64_jit.h" |
23 |
|
#include "dynamips.h" |
24 |
#include "memory.h" |
#include "memory.h" |
25 |
#include "device.h" |
#include "device.h" |
26 |
|
|
68 |
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)); |
69 |
|
|
70 |
/* Restart the MTS subsystem */ |
/* Restart the MTS subsystem */ |
71 |
mts_set_addr_mode(cpu,64); |
mips64_set_addr_mode(cpu,64); |
72 |
cpu->mts_rebuild(cpu); |
cpu->gen->mts_rebuild(cpu->gen); |
73 |
|
|
74 |
/* Flush JIT structures */ |
/* Flush JIT structures */ |
75 |
mips64_jit_flush(cpu,0); |
mips64_jit_flush(cpu,0); |
79 |
/* Initialize a MIPS64 processor */ |
/* Initialize a MIPS64 processor */ |
80 |
int mips64_init(cpu_mips_t *cpu) |
int mips64_init(cpu_mips_t *cpu) |
81 |
{ |
{ |
|
cpu->state = MIPS_CPU_SUSPENDED; |
|
82 |
cpu->addr_bus_mask = 0xFFFFFFFFFFFFFFFFULL; |
cpu->addr_bus_mask = 0xFFFFFFFFFFFFFFFFULL; |
83 |
cpu->cp0.reg[MIPS_CP0_PRID] = MIPS_PRID_R4600; |
cpu->cp0.reg[MIPS_CP0_PRID] = MIPS_PRID_R4600; |
84 |
cpu->cp0.tlb_entries = MIPS64_TLB_STD_ENTRIES; |
cpu->cp0.tlb_entries = MIPS64_TLB_STD_ENTRIES; |
85 |
|
|
86 |
/* Initialize idle timer */ |
/* Initialize idle timer */ |
87 |
cpu->idle_max = 1500; |
cpu->gen->idle_max = 1500; |
88 |
cpu->idle_sleep_time = 30000; |
cpu->gen->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; |
98 |
pthread_mutex_init(&cpu->irq_lock,NULL); |
pthread_mutex_init(&cpu->irq_lock,NULL); |
99 |
|
|
100 |
/* Idle loop mutex and condition */ |
/* Idle loop mutex and condition */ |
101 |
pthread_mutex_init(&cpu->idle_mutex,NULL); |
pthread_mutex_init(&cpu->gen->idle_mutex,NULL); |
102 |
pthread_cond_init(&cpu->idle_cond,NULL); |
pthread_cond_init(&cpu->gen->idle_cond,NULL); |
103 |
|
|
104 |
|
/* Set the CPU methods */ |
105 |
|
cpu->gen->reg_set = (void *)mips64_reg_set; |
106 |
|
cpu->gen->reg_dump = (void *)mips64_dump_regs; |
107 |
|
cpu->gen->mmu_dump = (void *)mips64_tlb_dump; |
108 |
|
cpu->gen->mmu_raw_dump = (void *)mips64_tlb_raw_dump; |
109 |
|
cpu->gen->add_breakpoint = (void *)mips64_add_breakpoint; |
110 |
|
cpu->gen->remove_breakpoint = (void *)mips64_remove_breakpoint; |
111 |
|
cpu->gen->set_idle_pc = (void *)mips64_set_idle_pc; |
112 |
|
cpu->gen->get_idling_pc = (void *)mips64_get_idling_pc; |
113 |
|
|
114 |
/* Set the startup parameters */ |
/* Set the startup parameters */ |
115 |
mips64_reset(cpu); |
mips64_reset(cpu); |
120 |
void mips64_delete(cpu_mips_t *cpu) |
void mips64_delete(cpu_mips_t *cpu) |
121 |
{ |
{ |
122 |
if (cpu) { |
if (cpu) { |
123 |
mts_shutdown(cpu); |
mips64_mem_shutdown(cpu); |
124 |
mips64_jit_shutdown(cpu); |
mips64_jit_shutdown(cpu); |
|
free(cpu); |
|
125 |
} |
} |
126 |
} |
} |
127 |
|
|
134 |
cpu->cp0.tlb_entries = MIPS64_TLB_MAX_ENTRIES; |
cpu->cp0.tlb_entries = MIPS64_TLB_MAX_ENTRIES; |
135 |
} |
} |
136 |
|
|
137 |
/* Virtual idle loop */ |
/* Set idle PC value */ |
138 |
void mips64_idle_loop(cpu_mips_t *cpu) |
void mips64_set_idle_pc(cpu_gen_t *cpu,m_uint64_t addr) |
|
{ |
|
|
struct timespec t_spc; |
|
|
m_tmcnt_t expire; |
|
|
|
|
|
expire = m_gettime_usec() + cpu->idle_sleep_time; |
|
|
|
|
|
pthread_mutex_lock(&cpu->idle_mutex); |
|
|
t_spc.tv_sec = expire / 1000000; |
|
|
t_spc.tv_nsec = (expire % 1000000) * 1000; |
|
|
pthread_cond_timedwait(&cpu->idle_cond,&cpu->idle_mutex,&t_spc); |
|
|
pthread_mutex_unlock(&cpu->idle_mutex); |
|
|
} |
|
|
|
|
|
/* Break idle wait state */ |
|
|
void mips64_idle_break_wait(cpu_mips_t *cpu) |
|
139 |
{ |
{ |
140 |
pthread_cond_signal(&cpu->idle_cond); |
CPU_MIPS64(cpu)->idle_pc = addr; |
|
cpu->idle_count = 0; |
|
141 |
} |
} |
142 |
|
|
143 |
/* Timer IRQ */ |
/* Timer IRQ */ |
154 |
threshold = cpu->timer_irq_freq * 10; |
threshold = cpu->timer_irq_freq * 10; |
155 |
expire = m_gettime_usec() + interval; |
expire = m_gettime_usec() + interval; |
156 |
|
|
157 |
while(cpu->state != MIPS_CPU_HALTED) { |
while(cpu->gen->state != CPU_STATE_HALTED) { |
158 |
pthread_mutex_lock(&umutex); |
pthread_mutex_lock(&umutex); |
159 |
t_spc.tv_sec = expire / 1000000; |
t_spc.tv_sec = expire / 1000000; |
160 |
t_spc.tv_nsec = (expire % 1000000) * 1000; |
t_spc.tv_nsec = (expire % 1000000) * 1000; |
162 |
pthread_mutex_unlock(&umutex); |
pthread_mutex_unlock(&umutex); |
163 |
|
|
164 |
if (likely(!cpu->irq_disable) && |
if (likely(!cpu->irq_disable) && |
165 |
likely(cpu->state == MIPS_CPU_RUNNING)) |
likely(cpu->gen->state == CPU_STATE_RUNNING)) |
166 |
{ |
{ |
167 |
cpu->timer_irq_pending++; |
cpu->timer_irq_pending++; |
168 |
|
|
194 |
}; |
}; |
195 |
|
|
196 |
/* Determine an "idling" PC */ |
/* Determine an "idling" PC */ |
197 |
int mips64_get_idling_pc(cpu_mips_t *cpu) |
int mips64_get_idling_pc(cpu_gen_t *cpu) |
198 |
{ |
{ |
199 |
|
cpu_mips_t *mcpu = CPU_MIPS64(cpu); |
200 |
struct mips64_idle_pc_hash **pc_hash,*p; |
struct mips64_idle_pc_hash **pc_hash,*p; |
201 |
struct mips64_idle_pc *res; |
struct cpu_idle_pc *res; |
202 |
u_int h_index,res_count; |
u_int h_index,res_count; |
203 |
m_uint64_t cur_pc; |
m_uint64_t cur_pc; |
204 |
int i; |
int i; |
205 |
|
|
206 |
cpu->idle_pc_prop_count = 0; |
cpu->idle_pc_prop_count = 0; |
207 |
|
|
208 |
if (cpu->idle_pc != 0) { |
if (mcpu->idle_pc != 0) { |
209 |
printf("\nYou already use an idle PC, using the calibration would give " |
printf("\nYou already use an idle PC, using the calibration would give " |
210 |
"incorrect results.\n"); |
"incorrect results.\n"); |
211 |
return(-1); |
return(-1); |
213 |
|
|
214 |
printf("\nPlease wait while gathering statistics...\n"); |
printf("\nPlease wait while gathering statistics...\n"); |
215 |
|
|
216 |
pc_hash = calloc(IDLE_HASH_SIZE,sizeof(struct mips64_idle_pc *)); |
pc_hash = calloc(IDLE_HASH_SIZE,sizeof(struct mips64_idle_pc_hash *)); |
217 |
|
|
218 |
/* Disable IRQ */ |
/* Disable IRQ */ |
219 |
cpu->irq_disable = TRUE; |
mcpu->irq_disable = TRUE; |
220 |
|
|
221 |
/* Take 1000 measures, each mesure every 10ms */ |
/* Take 1000 measures, each mesure every 10ms */ |
222 |
for(i=0;i<1000;i++) { |
for(i=0;i<1000;i++) { |
223 |
cur_pc = cpu->pc; |
cur_pc = mcpu->pc; |
224 |
h_index = (cur_pc >> 2) & (IDLE_HASH_SIZE-1); |
h_index = (cur_pc >> 2) & (IDLE_HASH_SIZE-1); |
225 |
|
|
226 |
for(p=pc_hash[h_index];p;p=p->next) |
for(p=pc_hash[h_index];p;p=p->next) |
250 |
res->pc = p->pc; |
res->pc = p->pc; |
251 |
res->count = p->count; |
res->count = p->count; |
252 |
|
|
253 |
if (cpu->idle_pc_prop_count >= MIPS64_IDLE_PC_MAX_RES) |
if (cpu->idle_pc_prop_count >= CPU_IDLE_PC_MAX_RES) |
254 |
goto done; |
goto done; |
255 |
} |
} |
256 |
} |
} |
273 |
} |
} |
274 |
|
|
275 |
/* Re-enable IRQ */ |
/* Re-enable IRQ */ |
276 |
cpu->irq_disable = FALSE; |
mcpu->irq_disable = FALSE; |
277 |
return(0); |
return(0); |
278 |
} |
} |
279 |
|
|
280 |
|
/* Set an IRQ (VM IRQ standard routing) */ |
281 |
|
void mips64_vm_set_irq(vm_instance_t *vm,u_int irq) |
282 |
|
{ |
283 |
|
cpu_mips_t *boot_cpu; |
284 |
|
|
285 |
|
boot_cpu = CPU_MIPS64(vm->boot_cpu); |
286 |
|
|
287 |
|
if (boot_cpu->irq_disable) { |
288 |
|
boot_cpu->irq_pending = 0; |
289 |
|
return; |
290 |
|
} |
291 |
|
|
292 |
|
mips64_set_irq(boot_cpu,irq); |
293 |
|
|
294 |
|
if (boot_cpu->irq_idle_preempt[irq]) |
295 |
|
cpu_idle_break_wait(vm->boot_cpu); |
296 |
|
} |
297 |
|
|
298 |
|
/* Clear an IRQ (VM IRQ standard routing) */ |
299 |
|
void mips64_vm_clear_irq(vm_instance_t *vm,u_int irq) |
300 |
|
{ |
301 |
|
cpu_mips_t *boot_cpu; |
302 |
|
|
303 |
|
boot_cpu = CPU_MIPS64(vm->boot_cpu); |
304 |
|
mips64_clear_irq(boot_cpu,irq); |
305 |
|
} |
306 |
|
|
307 |
/* Update the IRQ flag (inline) */ |
/* Update the IRQ flag (inline) */ |
308 |
static forced_inline int mips64_update_irq_flag_fast(cpu_mips_t *cpu) |
static forced_inline int mips64_update_irq_flag_fast(cpu_mips_t *cpu) |
309 |
{ |
{ |
454 |
fastcall void mips64_exec_break(cpu_mips_t *cpu,u_int code) |
fastcall void mips64_exec_break(cpu_mips_t *cpu,u_int code) |
455 |
{ |
{ |
456 |
printf("MIPS64: BREAK instruction (code=%u)\n",code); |
printf("MIPS64: BREAK instruction (code=%u)\n",code); |
457 |
mips64_dump_regs(cpu); |
mips64_dump_regs(cpu->gen); |
458 |
|
|
459 |
/* XXX TODO: Branch Delay slot */ |
/* XXX TODO: Branch Delay slot */ |
460 |
mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_BP,0); |
mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_BP,0); |
513 |
/* Virtual breakpoint */ |
/* Virtual breakpoint */ |
514 |
fastcall void mips64_run_breakpoint(cpu_mips_t *cpu) |
fastcall void mips64_run_breakpoint(cpu_mips_t *cpu) |
515 |
{ |
{ |
516 |
cpu_log(cpu,"BREAKPOINT", |
cpu_log(cpu->gen,"BREAKPOINT", |
517 |
"Virtual breakpoint reached at PC=0x%llx\n",cpu->pc); |
"Virtual breakpoint reached at PC=0x%llx\n",cpu->pc); |
518 |
|
|
519 |
printf("[[[ Virtual Breakpoint reached at PC=0x%llx RA=0x%llx]]]\n", |
printf("[[[ Virtual Breakpoint reached at PC=0x%llx RA=0x%llx]]]\n", |
520 |
cpu->pc,cpu->gpr[MIPS_GPR_RA]); |
cpu->pc,cpu->gpr[MIPS_GPR_RA]); |
521 |
|
|
522 |
mips64_dump_regs(cpu); |
mips64_dump_regs(cpu->gen); |
523 |
memlog_dump(cpu); |
memlog_dump(cpu->gen); |
524 |
} |
} |
525 |
|
|
526 |
/* Add a virtual breakpoint */ |
/* Add a virtual breakpoint */ |
527 |
int mips64_add_breakpoint(cpu_mips_t *cpu,m_uint64_t pc) |
int mips64_add_breakpoint(cpu_gen_t *cpu,m_uint64_t pc) |
528 |
{ |
{ |
529 |
|
cpu_mips_t *mcpu = CPU_MIPS64(cpu); |
530 |
int i; |
int i; |
531 |
|
|
532 |
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
533 |
if (!cpu->breakpoints[i]) |
if (!mcpu->breakpoints[i]) |
534 |
break; |
break; |
535 |
|
|
536 |
if (i == MIPS64_MAX_BREAKPOINTS) |
if (i == MIPS64_MAX_BREAKPOINTS) |
537 |
return(-1); |
return(-1); |
538 |
|
|
539 |
cpu->breakpoints[i] = pc; |
mcpu->breakpoints[i] = pc; |
540 |
cpu->breakpoints_enabled = TRUE; |
mcpu->breakpoints_enabled = TRUE; |
541 |
return(0); |
return(0); |
542 |
} |
} |
543 |
|
|
544 |
/* Remove a virtual breakpoint */ |
/* Remove a virtual breakpoint */ |
545 |
void mips64_remove_breakpoint(cpu_mips_t *cpu,m_uint64_t pc) |
void mips64_remove_breakpoint(cpu_gen_t *cpu,m_uint64_t pc) |
546 |
{ |
{ |
547 |
|
cpu_mips_t *mcpu = CPU_MIPS64(cpu); |
548 |
int i,j; |
int i,j; |
549 |
|
|
550 |
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
551 |
if (cpu->breakpoints[i] == pc) |
if (mcpu->breakpoints[i] == pc) |
552 |
{ |
{ |
553 |
for(j=i;j<MIPS64_MAX_BREAKPOINTS-1;j++) |
for(j=i;j<MIPS64_MAX_BREAKPOINTS-1;j++) |
554 |
cpu->breakpoints[j] = cpu->breakpoints[j+1]; |
mcpu->breakpoints[j] = mcpu->breakpoints[j+1]; |
555 |
|
|
556 |
cpu->breakpoints[MIPS64_MAX_BREAKPOINTS-1] = 0; |
mcpu->breakpoints[MIPS64_MAX_BREAKPOINTS-1] = 0; |
557 |
} |
} |
558 |
|
|
559 |
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) |
560 |
if (cpu->breakpoints[i] != 0) |
if (mcpu->breakpoints[i] != 0) |
561 |
return; |
return; |
562 |
|
|
563 |
cpu->breakpoints_enabled = TRUE; |
mcpu->breakpoints_enabled = FALSE; |
564 |
} |
} |
565 |
|
|
566 |
/* Debugging for register-jump to address 0 */ |
/* Debugging for register-jump to address 0 */ |
567 |
fastcall void mips64_debug_jr0(cpu_mips_t *cpu) |
fastcall void mips64_debug_jr0(cpu_mips_t *cpu) |
568 |
{ |
{ |
569 |
printf("MIPS64: cpu %p jumping to address 0...\n",cpu); |
printf("MIPS64: cpu %p jumping to address 0...\n",cpu); |
570 |
mips64_dump_regs(cpu); |
mips64_dump_regs(cpu->gen); |
571 |
|
} |
572 |
|
|
573 |
|
/* Set a register */ |
574 |
|
void mips64_reg_set(cpu_gen_t *cpu,u_int reg,m_uint64_t val) |
575 |
|
{ |
576 |
|
if (reg < MIPS64_GPR_NR) |
577 |
|
CPU_MIPS64(cpu)->gpr[reg] = val; |
578 |
} |
} |
579 |
|
|
580 |
/* Dump registers of a MIPS64 processor */ |
/* Dump registers of a MIPS64 processor */ |
581 |
void mips64_dump_regs(cpu_mips_t *cpu) |
void mips64_dump_regs(cpu_gen_t *cpu) |
582 |
{ |
{ |
583 |
|
cpu_mips_t *mcpu = CPU_MIPS64(cpu); |
584 |
mips_insn_t *ptr,insn; |
mips_insn_t *ptr,insn; |
585 |
char buffer[80]; |
char buffer[80]; |
586 |
int i; |
int i; |
589 |
|
|
590 |
for(i=0;i<MIPS64_GPR_NR/2;i++) { |
for(i=0;i<MIPS64_GPR_NR/2;i++) { |
591 |
printf(" %s ($%2d) = 0x%16.16llx %s ($%2d) = 0x%16.16llx\n", |
printf(" %s ($%2d) = 0x%16.16llx %s ($%2d) = 0x%16.16llx\n", |
592 |
mips64_gpr_reg_names[i*2], i*2, cpu->gpr[i*2], |
mips64_gpr_reg_names[i*2], i*2, mcpu->gpr[i*2], |
593 |
mips64_gpr_reg_names[(i*2)+1], (i*2)+1, cpu->gpr[(i*2)+1]); |
mips64_gpr_reg_names[(i*2)+1], (i*2)+1, mcpu->gpr[(i*2)+1]); |
594 |
} |
} |
595 |
|
|
596 |
printf(" lo = 0x%16.16llx, hi = 0x%16.16llx\n", cpu->lo, cpu->hi); |
printf(" lo = 0x%16.16llx, hi = 0x%16.16llx\n", mcpu->lo, mcpu->hi); |
597 |
printf(" pc = 0x%16.16llx, ll_bit = %u\n", cpu->pc, cpu->ll_bit); |
printf(" pc = 0x%16.16llx, ll_bit = %u\n", mcpu->pc, mcpu->ll_bit); |
598 |
|
|
599 |
/* Fetch the current instruction */ |
/* Fetch the current instruction */ |
600 |
ptr = cpu->mem_op_lookup(cpu,cpu->pc); |
ptr = mcpu->mem_op_lookup(mcpu,mcpu->pc); |
601 |
if (ptr) { |
if (ptr) { |
602 |
insn = vmtoh32(*ptr); |
insn = vmtoh32(*ptr); |
603 |
|
|
604 |
if (mips64_dump_insn(buffer,sizeof(buffer),1,cpu->pc,insn) != -1) |
if (mips64_dump_insn(buffer,sizeof(buffer),1,mcpu->pc,insn) != -1) |
605 |
printf(" Instruction: %s\n",buffer); |
printf(" Instruction: %s\n",buffer); |
606 |
} |
} |
607 |
|
|
609 |
|
|
610 |
for(i=0;i<MIPS64_CP0_REG_NR/2;i++) { |
for(i=0;i<MIPS64_CP0_REG_NR/2;i++) { |
611 |
printf(" %-10s ($%2d) = 0x%16.16llx %-10s ($%2d) = 0x%16.16llx\n", |
printf(" %-10s ($%2d) = 0x%16.16llx %-10s ($%2d) = 0x%16.16llx\n", |
612 |
mips64_cp0_reg_names[i*2], i*2, cp0_get_reg(cpu,i*2), |
mips64_cp0_reg_names[i*2], i*2, |
613 |
mips64_cp0_reg_names[(i*2)+1], (i*2)+1, cp0_get_reg(cpu,(i*2)+1)); |
mips64_cp0_get_reg(mcpu,i*2), |
614 |
|
mips64_cp0_reg_names[(i*2)+1], (i*2)+1, |
615 |
|
mips64_cp0_get_reg(mcpu,(i*2)+1)); |
616 |
} |
} |
617 |
|
|
618 |
printf("\n IRQ count: %llu, IRQ false positives: %llu, " |
printf("\n IRQ count: %llu, IRQ false positives: %llu, " |
619 |
"IRQ Pending: %u\n", |
"IRQ Pending: %u\n", |
620 |
cpu->irq_count,cpu->irq_fp_count,cpu->irq_pending); |
mcpu->irq_count,mcpu->irq_fp_count,mcpu->irq_pending); |
621 |
|
|
622 |
printf(" Timer IRQ count: %llu, pending: %u, timer drift: %u\n\n", |
printf(" Timer IRQ count: %llu, pending: %u, timer drift: %u\n\n", |
623 |
cpu->timer_irq_count,cpu->timer_irq_pending,cpu->timer_drift); |
mcpu->timer_irq_count,mcpu->timer_irq_pending,mcpu->timer_drift); |
624 |
|
|
625 |
printf("\n"); |
printf("\n"); |
626 |
} |
} |
765 |
} |
} |
766 |
|
|
767 |
/* cp0 register ? */ |
/* cp0 register ? */ |
768 |
if ((index = cp0_get_reg_index(buffer)) != -1) { |
if ((index = mips64_cp0_get_reg_index(buffer)) != -1) { |
769 |
cpu->cp0.reg[index] = mips64_hex_u64(value,NULL); |
cpu->cp0.reg[index] = mips64_hex_u64(value,NULL); |
770 |
continue; |
continue; |
771 |
} |
} |
823 |
} |
} |
824 |
} |
} |
825 |
|
|
826 |
cp0_map_all_tlb_to_mts(cpu); |
mips64_cp0_map_all_tlb_to_mts(cpu); |
827 |
|
|
828 |
mips64_dump_regs(cpu); |
mips64_dump_regs(cpu->gen); |
829 |
tlb_dump(cpu); |
mips64_tlb_dump(cpu->gen); |
830 |
|
|
831 |
fclose(fd); |
fclose(fd); |
832 |
return(0); |
return(0); |
837 |
{ |
{ |
838 |
struct stat file_info; |
struct stat file_info; |
839 |
size_t len,clen; |
size_t len,clen; |
840 |
|
m_uint32_t remain; |
841 |
void *haddr; |
void *haddr; |
842 |
FILE *bfd; |
FILE *bfd; |
843 |
|
|
871 |
else |
else |
872 |
clen = len; |
clen = len; |
873 |
|
|
874 |
|
remain = MIPS_MIN_PAGE_SIZE; |
875 |
|
remain -= (vaddr - (vaddr & MIPS_MIN_PAGE_MASK)); |
876 |
|
|
877 |
|
clen = m_min(clen,remain); |
878 |
|
|
879 |
if (fread((u_char *)haddr,clen,1,bfd) != 1) |
if (fread((u_char *)haddr,clen,1,bfd) != 1) |
880 |
break; |
break; |
881 |
|
|
882 |
vaddr += MIPS_MIN_PAGE_SIZE; |
vaddr += clen; |
883 |
len -= clen; |
len -= clen; |
884 |
} |
} |
885 |
|
|
892 |
m_uint32_t *entry_point) |
m_uint32_t *entry_point) |
893 |
{ |
{ |
894 |
m_uint64_t vaddr; |
m_uint64_t vaddr; |
895 |
|
m_uint32_t remain; |
896 |
void *haddr; |
void *haddr; |
897 |
Elf32_Ehdr *ehdr; |
Elf32_Ehdr *ehdr; |
898 |
Elf32_Shdr *shdr; |
Elf32_Shdr *shdr; |
975 |
else |
else |
976 |
clen = len; |
clen = len; |
977 |
|
|
978 |
clen = fread((u_char *)haddr,clen,1,bfd); |
remain = PPC32_MIN_PAGE_SIZE; |
979 |
|
remain -= (vaddr - (vaddr & PPC32_MIN_PAGE_MASK)); |
980 |
|
|
981 |
|
clen = m_min(clen,remain); |
982 |
|
|
983 |
if (clen != 1) |
if (fread((u_char *)haddr,clen,1,bfd) < 1) |
984 |
break; |
break; |
985 |
|
|
986 |
vaddr += MIPS_MIN_PAGE_SIZE; |
vaddr += clen; |
987 |
len -= clen; |
len -= clen; |
988 |
} |
} |
989 |
} |
} |
1060 |
FILE *fd; |
FILE *fd; |
1061 |
|
|
1062 |
if (!cpu->sym_tree && (mips64_sym_create_tree(cpu) == -1)) { |
if (!cpu->sym_tree && (mips64_sym_create_tree(cpu) == -1)) { |
1063 |
fprintf(stderr,"CPU%u: Unable to create symbol tree.\n",cpu->id); |
fprintf(stderr,"CPU%u: Unable to create symbol tree.\n",cpu->gen->id); |
1064 |
return(-1); |
return(-1); |
1065 |
} |
} |
1066 |
|
|