u32 MatchDiv32(u32 pc , Sh4RegType ®1,Sh4RegType ®2 , Sh4RegType ®3) { u32 v_pc=pc; u32 match=1; for (int i=0;i<32;i++) { u16 opcode=ReadMem16(v_pc); v_pc+=2; if ((opcode&MASK_N)==ROTCL_KEY) { if (reg1==NoReg) reg1=(Sh4RegType)GetN(opcode); else if (reg1!=(Sh4RegType)GetN(opcode)) break; match++; } else { //printf("DIV MATCH BROKEN BY: %s\n",OpDesc[opcode]->diss); break; } opcode=ReadMem16(v_pc); v_pc+=2; if ((opcode&MASK_N_M)==DIV1_KEY) { if (reg2==NoReg) reg2=(Sh4RegType)GetM(opcode); else if (reg2!=(Sh4RegType)GetM(opcode)) break; if (reg2==reg1) break; if (reg3==NoReg) reg3=(Sh4RegType)GetN(opcode); else if (reg3!=(Sh4RegType)GetN(opcode)) break; if (reg3==reg1) break; match++; } else break; } return match; }
u32 MatchDiv32(u32 pc , Sh4RegType ®1,Sh4RegType ®2 , Sh4RegType ®3) { if (settings.dynarec.Safe) return 0; u32 v_pc=pc; u32 match=1; for (int i=0;i<32;i++) { u16 opcode=ReadMem16(v_pc); v_pc+=2; if ((opcode&MASK_N)==ROTCL_KEY) { if (reg1==NoReg) reg1=(Sh4RegType)GetN(opcode); else if (reg1!=(Sh4RegType)GetN(opcode)) break; match++; } else break; opcode=ReadMem16(v_pc); v_pc+=2; if ((opcode&MASK_N_M)==DIV1_KEY) { if (reg2==NoReg) reg2=(Sh4RegType)GetM(opcode); else if (reg2!=(Sh4RegType)GetM(opcode)) break; if (reg2==reg1) break; if (reg3==NoReg) reg3=(Sh4RegType)GetN(opcode); else if (reg3!=(Sh4RegType)GetN(opcode)) break; if (reg3==reg1) break; match++; } else break; } return match; }
void setup_syscall(u32 hook_addr, u32 syscall_addr) { WriteMem32(syscall_addr, hook_addr); WriteMem16(hook_addr, REIOS_OPCODE); debugf("reios: Patching syscall vector %08X, points to %08X\n", syscall_addr, hook_addr); debugf("reios: - address %08X: data %04X [%04X]\n", hook_addr, ReadMem16(hook_addr), REIOS_OPCODE); }
void Sh4_int_Run() { sh4_int_bCpuRun=true; s32 l=SH4_TIMESLICE; #if !defined(TARGET_BOUNDED_EXECUTION) do #else for (int i=0; i<10000; i++) #endif { do { u32 op=ReadMem16(next_pc); next_pc+=2; OpPtr[op](op); l-=CPU_RATIO; } while(l>0); l+=SH4_TIMESLICE; UpdateSystem_INTC(); #if !defined(TARGET_BOUNDED_EXECUTION) } while(sh4_int_bCpuRun); sh4_int_bCpuRun=false; #else }
// Reset core, call it after OnRead/OnWrite point to the right BIOS void MinxCPU_Reset(int hardreset) { MinxCPU.Status = MINX_STATUS_NORMAL; MinxCPU.PC.W.L = ReadMem16(hardreset ? 0 : 2); MinxCPU.E = 0x1F; MinxCPU.F = 0xC0; Set_U(0); MinxCPU_OnIRQHandle(MinxCPU.F, MinxCPU.Shift_U); }
void Sh4_int_Step() { if (sh4_int_bCpuRun) { printf("Sh4 Is running , can't step\n"); } else { u32 op=ReadMem16(next_pc); next_pc+=2; ExecuteOpcode(op); } }
void Sh4_int_Run() { sh4_int_bCpuRun=true; s32 l=SH4_TIMESLICE; do { do { u32 op=ReadMem16(next_pc); next_pc+=2; OpPtr[op](op); l-=CPU_RATIO; } while(l>0); l+=SH4_TIMESLICE; UpdateSystem_INTC(); } while(sh4_int_bCpuRun); sh4_int_bCpuRun=false; }
void print_blocks() { FILE* f=0; if (print_stats) { f=fopen(GetPath("/blkmap.lst").c_str(),"w"); print_stats=0; printf("writing blocks to %p\n",f); } for (size_t i=0;i<all_blocks.size();i++) { RuntimeBlockInfo* blk=all_blocks[i]; if (f) { fprintf(f,"block: %08X\n",blk); fprintf(f,"addr: %08X\n",blk->addr); fprintf(f,"hash: %s\n",blk->hash()); fprintf(f,"hash_rloc: %s\n",blk->hash(false,true)); fprintf(f,"code: %08X\n",blk->code); fprintf(f,"runs: %d\n",blk->runs); fprintf(f,"BlockType: %d\n",blk->BlockType); fprintf(f,"NextBlock: %08X\n",blk->NextBlock); fprintf(f,"BranchBlock: %08X\n",blk->BranchBlock); fprintf(f,"pNextBlock: %08X\n",blk->pNextBlock); fprintf(f,"pBranchBlock: %08X\n",blk->pBranchBlock); fprintf(f,"guest_cycles: %d\n",blk->guest_cycles); fprintf(f,"guest_opcodes: %d\n",blk->guest_opcodes); fprintf(f,"host_opcodes: %d\n",blk->host_opcodes); fprintf(f,"il_opcodes: %d\n",blk->oplist.size()); u32 hcode=0; s32 gcode=-1; u8* pucode=(u8*)blk->code; size_t j=0; fprintf(f,"{\n"); for (;j<blk->oplist.size();j++) { shil_opcode* op=&all_blocks[i]->oplist[j]; fprint_hex(f,"//h:",pucode,hcode,op->host_offs); if (gcode!=op->guest_offs) { gcode=op->guest_offs; u32 rpc=blk->addr+gcode; u16 op=ReadMem16(rpc); char temp[128]; OpDesc[op]->Dissasemble(temp,rpc,op); fprintf(f,"//g:%s\n",temp); } string s=op->dissasm(); fprintf(f,"//il:%d:%d:%s\n",op->guest_offs,op->host_offs,s.c_str()); } fprint_hex(f,"//h:",pucode,hcode,blk->host_code_size); fprintf(f,"}\n"); } all_blocks[i]->runs=0; } if (f) fclose(f); }
void dec_DecodeBlock(RuntimeBlockInfo* rbi,u32 max_cycles) { blk=rbi; state.Setup(blk->addr,blk->fpu_cfg); ngen_GetFeatures(&state.ngen); blk->guest_opcodes=0; for(;;) { switch(state.NextOp) { case NDO_Delayslot: state.NextOp=state.DelayOp; state.cpu.is_delayslot=true; //there is no break here by design case NDO_NextOp: { if (blk->guest_cycles>=max_cycles && !state.cpu.is_delayslot) { dec_End(state.cpu.rpc,BET_StaticJump,false); } else { /* if (MatchDiv0S_0(state.cpu.rpc)) { //can also be emitted as //sar r2,31 //subcs r1,1 //in arm //r1=r1-sign bit //r2=sign mask Emit(shop_shl,mk_reg(reg_sr_T),mk_reg(reg_r2),mk_imm(31)); Emit(shop_sar,mk_reg(reg_r2),mk_reg(reg_r2),mk_imm(31)); Emit(shop_sub,mk_reg(reg_r1),mk_reg(reg_r1),mk_reg(reg_sr_T)); blk->guest_cycles+=CPU_RATIO*4; state.cpu.rpc+=2*4; continue; } */ u32 op=ReadMem16(state.cpu.rpc); if (op==0 && state.cpu.is_delayslot) { printf("Delayslot 0 hack!\n"); } else { blk->guest_opcodes++; if (op>=0xF000) blk->guest_cycles+=0; else blk->guest_cycles+=CPU_RATIO; verify(!(state.cpu.is_delayslot && OpDesc[op]->SetPC())); if (state.ngen.OnlyDynamicEnds || !OpDesc[op]->rec_oph) { if (state.ngen.InterpreterFallback || !dec_generic(op)) { dec_fallback(op); if (OpDesc[op]->SetPC()) { dec_DynamicSet(reg_nextpc); dec_End(0xFFFFFFFF,BET_DynamicJump,false); } if (OpDesc[op]->SetFPSCR() && !state.cpu.is_delayslot) { dec_End(state.cpu.rpc+2,BET_StaticJump,false); } } /* else if (state.info.has_readm || state.info.has_writem) { if (!state.cpu.is_delayslot) dec_End(state.cpu.rpc+2,BET_StaticJump,false); } */ } else { OpDesc[op]->rec_oph(op); } } state.cpu.rpc+=2; } } break; case NDO_Jump: die("Too old"); state.NextOp=state.JumpOp; state.cpu.rpc=state.JumpAddr; break; case NDO_End: goto _end; } } _end: blk->sh4_code_size=state.cpu.rpc-blk->addr; blk->NextBlock=state.NextAddr; blk->BranchBlock=state.JumpAddr; blk->BlockType=state.BlockType; #if HOST_OS == OS_WINDOWS switch(rbi->addr) { case 0x8C09ED16: case 0x8C0BA50E: case 0x8C0BA506: case 0x8C0BA526: case 0x8C224800: printf("HASH: %08X reloc %s\n",blk->addr,blk->hash(false,true)); break; } #endif //cycle tricks if (settings.dynarec.idleskip) { //Experimental hash-id based idle skip if (strstr(idle_hash,blk->hash(false,true))) { //printf("IDLESKIP: %08X reloc match %s\n",blk->addr,blk->hash(false,true)); blk->guest_cycles=max_cycles*100; } else { //Small-n-simple idle loop detector :p if (state.info.has_readm && !state.info.has_writem && !state.info.has_fpu && blk->guest_opcodes<6) { if (blk->BlockType==BET_Cond_0 || blk->BlockType==BET_Cond_1 && blk->BranchBlock<=blk->addr) { blk->guest_cycles*=3; } if (blk->BranchBlock==blk->addr) { blk->guest_cycles*=10; } } //if in syscalls area (ip.bin etc) skip fast :p if ((blk->addr&0x1FFF0000)==0x0C000000) { if (blk->addr&0x8000) { //ip.bin (boot loader/img etc) blk->guest_cycles*=15; } else { //syscalls blk->guest_cycles*=5; } } //blk->guest_cycles=5; } } else { blk->guest_cycles*=1.5; } //make sure we don't use wayy-too-many cycles blk->guest_cycles=min(blk->guest_cycles,max_cycles); //make sure we don't use wayy-too-few cycles blk->guest_cycles=max(1U,blk->guest_cycles); blk=0; }
u16 DYNACALL IReadMem16(u32 Address) { return ReadMem16(Address); }