--- upstream/dynamips-0.2.5/mips64.c 2007/10/06 16:01:44 1 +++ upstream/dynamips-0.2.6-RC4/mips64.c 2007/10/06 16:08:03 5 @@ -67,9 +67,7 @@ memset(&cpu->cp0.tlb,0,MIPS64_TLB_MAX_ENTRIES*sizeof(tlb_entry_t)); /* Restart the MTS subsystem */ - mts_shutdown(cpu); - mts64_init(cpu); - mts_init_memop_vectors(cpu); + mts_set_addr_mode(cpu,64); cpu->mts_rebuild(cpu); /* Flush JIT structures */ @@ -87,7 +85,7 @@ /* Initialize idle timer */ cpu->idle_max = 1500; - cpu->idle_sleep_time = 50000; + cpu->idle_sleep_time = 30000; /* Timer IRQ parameters (default frequency: 250 Hz <=> 4ms period) */ cpu->timer_irq_check_itv = 1000; @@ -146,6 +144,7 @@ void mips64_idle_break_wait(cpu_mips_t *cpu) { pthread_cond_signal(&cpu->idle_cond); + cpu->idle_count = 0; } /* Timer IRQ */ @@ -192,25 +191,26 @@ return NULL; } +#define IDLE_HASH_SIZE 8192 + /* Idle PC hash item */ -struct mips64_idle_pc { +struct mips64_idle_pc_hash { m_uint64_t pc; u_int count; - struct mips64_idle_pc *next; + struct mips64_idle_pc_hash *next; }; -#define IDLE_HASH_SIZE 8192 -#define IDLE_MAX_RES 10 - /* Determine an "idling" PC */ int mips64_get_idling_pc(cpu_mips_t *cpu) { - struct mips64_idle_pc *res[IDLE_MAX_RES]; - struct mips64_idle_pc **pc_hash,*p; + struct mips64_idle_pc_hash **pc_hash,*p; + struct mips64_idle_pc *res; u_int h_index,res_count; m_uint64_t cur_pc; int i; + cpu->idle_pc_prop_count = 0; + if (cpu->idle_pc != 0) { printf("\nYou already use an idle PC, using the calibration would give " "incorrect results.\n"); @@ -248,28 +248,32 @@ } /* Select PCs */ - memset(res,0,sizeof(res)); - for(i=0,res_count=0;inext) if ((p->count >= 20) && (p->count <= 80)) { - res[res_count++] = p; + res = &cpu->idle_pc_prop[cpu->idle_pc_prop_count++]; - if (res_count >= IDLE_MAX_RES) + res->pc = p->pc; + res->count = p->count; + + if (cpu->idle_pc_prop_count >= MIPS64_IDLE_PC_MAX_RES) goto done; } } done: /* Set idle PC */ - if (res_count) { + if (cpu->idle_pc_prop_count) { printf("Done. Suggested idling PC:\n"); - for(i=0;ipc,res[i]->count); - + for(i=0;iidle_pc_prop_count;i++) { + printf(" 0x%llx (count=%u)\n", + cpu->idle_pc_prop[i].pc, + cpu->idle_pc_prop[i].count); + } + printf("Restart the emulator with \"--idle-pc=0x%llx\" (for example)\n", - res[0]->pc); + cpu->idle_pc_prop[0].pc); } else { printf("Done. No suggestion for idling PC\n"); } @@ -491,11 +495,51 @@ cpu_log(cpu,"BREAKPOINT", "Virtual breakpoint reached at PC=0x%llx\n",cpu->pc); - printf("[[[ Virtual Breakpoint reached at PC=0x%llx ]]]\n",cpu->pc); + printf("[[[ Virtual Breakpoint reached at PC=0x%llx RA=0x%llx]]]\n", + cpu->pc,cpu->gpr[MIPS_GPR_RA]); + mips64_dump_regs(cpu); memlog_dump(cpu); } +/* Add a virtual breakpoint */ +int mips64_add_breakpoint(cpu_mips_t *cpu,m_uint64_t pc) +{ + int i; + + for(i=0;ibreakpoints[i]) + break; + + if (i == MIPS64_MAX_BREAKPOINTS) + return(-1); + + cpu->breakpoints[i] = pc; + cpu->breakpoints_enabled = TRUE; + return(0); +} + +/* Remove a virtual breakpoint */ +void mips64_remove_breakpoint(cpu_mips_t *cpu,m_uint64_t pc) +{ + int i,j; + + for(i=0;ibreakpoints[i] == pc) + { + for(j=i;jbreakpoints[j] = cpu->breakpoints[j+1]; + + cpu->breakpoints[MIPS64_MAX_BREAKPOINTS-1] = 0; + } + + for(i=0;ibreakpoints[i] != 0) + return; + + cpu->breakpoints_enabled = TRUE; +} + /* Debugging for register-jump to address 0 */ fastcall void mips64_debug_jr0(cpu_mips_t *cpu) { @@ -805,7 +849,7 @@ } /* Load an ELF image into the simulated memory */ -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, m_uint32_t *entry_point) { m_uint64_t vaddr; @@ -857,47 +901,51 @@ return(-1); } - for(i=0;ie_shnum;i++) { - scn = elf_getscn(img_elf,i); - - shdr = elf32_getshdr(scn); - name = elf_strptr(img_elf, ehdr->e_shstrndx, (size_t)shdr->sh_name); - len = shdr->sh_size; - - if (!(shdr->sh_flags & SHF_ALLOC) || !len) - continue; - - fseek(bfd,shdr->sh_offset,SEEK_SET); - vaddr = sign_extend(shdr->sh_addr,32); - - if (cpu->vm->debug_level > 0) { - printf(" * Adding section at virtual address 0x%8.8llx " - "(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); + if (!skip_load) { + for(i=0;ie_shnum;i++) { + scn = elf_getscn(img_elf,i); + + shdr = elf32_getshdr(scn); + name = elf_strptr(img_elf, ehdr->e_shstrndx, (size_t)shdr->sh_name); + len = shdr->sh_size; + + if (!(shdr->sh_flags & SHF_ALLOC) || !len) + continue; + + fseek(bfd,shdr->sh_offset,SEEK_SET); + vaddr = sign_extend(shdr->sh_addr,32); + + if (cpu->vm->debug_level > 0) { + printf(" * Adding section at virtual address 0x%8.8llx " + "(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); + } - if (len > MIPS_MIN_PAGE_SIZE) - clen = MIPS_MIN_PAGE_SIZE; - else - clen = len; + if (len > MIPS_MIN_PAGE_SIZE) + clen = MIPS_MIN_PAGE_SIZE; + else + clen = len; - clen = fread((u_char *)haddr,clen,1,bfd); + clen = fread((u_char *)haddr,clen,1,bfd); - if (clen != 1) - break; + if (clen != 1) + break; - vaddr += MIPS_MIN_PAGE_SIZE; - len -= clen; + vaddr += MIPS_MIN_PAGE_SIZE; + len -= clen; + } } + } else { + printf("ELF loading skipped, using a ghost RAM file.\n"); } printf("ELF entry point: 0x%x\n",ehdr->e_entry);