#include <stdlib.h>
#include <stdint.h> //include for uint64_t
#include <assert.h>
+#include <sys/mman.h>
#include "emu_if.h" //emulator interface
-#include <sys/mman.h>
+//#define DISASM
+//#define assem_debug printf
+//#define inv_debug printf
+#define assem_debug(...)
+#define inv_debug(...)
#ifdef __i386__
#include "assem_x86.h"
static uint64_t gte_rt[MAXBLOCK];
static uint64_t gte_unneeded[MAXBLOCK];
static int gte_reads_flags; // gte flag read encountered
+ static u_int smrv[32]; // speculated MIPS register values
+ static u_int smrv_strong; // mask or regs that are likely to have correct values
+ static u_int smrv_weak; // same, but somewhat less likely
+ static u_int smrv_strong_next; // same, but after current insn executes
+ static u_int smrv_weak_next;
int imm[MAXBLOCK];
u_int ba[MAXBLOCK];
char likely[MAXBLOCK];
#else
static const u_int using_tlb=0;
#endif
- static u_int sp_in_mirror;
+ int new_dynarec_did_compile;
u_int stop_after_jal;
extern u_char restore_candidate[512];
extern int cycle_count;
//#define DEBUG_CYCLE_COUNT 1
-void nullf() {}
-//#define assem_debug printf
-//#define inv_debug printf
-#define assem_debug nullf
-#define inv_debug nullf
-
static void tlb_hacks()
{
#ifndef DISABLE_TLB
}
}
-
+#ifndef FORCE32
void div64(int64_t dividend,int64_t divisor)
{
lo=dividend/divisor;
else original=loaded;
return original;
}
+#endif
#ifdef __i386__
#include "assem_x86.c"
void shiftimm_alloc(struct regstat *current,int i)
{
- clear_const(current,rs1[i]);
- clear_const(current,rt1[i]);
if(opcode2[i]<=0x3) // SLL/SRL/SRA
{
if(rt1[i]) {
alloc_reg(current,i,rt1[i]);
current->is32|=1LL<<rt1[i];
dirty_reg(current,rt1[i]);
+ if(is_const(current,rs1[i])) {
+ int v=get_const(current,rs1[i]);
+ if(opcode2[i]==0x00) set_const(current,rt1[i],v<<imm[i]);
+ if(opcode2[i]==0x02) set_const(current,rt1[i],(u_int)v>>imm[i]);
+ if(opcode2[i]==0x03) set_const(current,rt1[i],v>>imm[i]);
+ }
+ else clear_const(current,rt1[i]);
}
}
+ else
+ {
+ clear_const(current,rs1[i]);
+ clear_const(current,rt1[i]);
+ }
+
if(opcode2[i]>=0x38&&opcode2[i]<=0x3b) // DSLL/DSRL/DSRA
{
if(rt1[i]) {
t=get_reg(i_regs->regmap,rt1[i]);
s=get_reg(i_regs->regmap,rs1[i]);
//assert(t>=0);
- if(t>=0){
+ if(t>=0&&!((i_regs->isconst>>t)&1)){
if(rs1[i]==0)
{
emit_zeroreg(t);
if(rs1[i]!=29||start<0x80001000||start>=0x80000000+RAM_SIZE)
#endif
{
- #ifdef PCSX
- if(sp_in_mirror&&rs1[i]==29) {
- emit_andimm(addr,~0x00e00000,HOST_TEMPREG);
- emit_cmpimm(HOST_TEMPREG,RAM_SIZE);
- fastload_reg_override=HOST_TEMPREG;
- }
- else
- #endif
- emit_cmpimm(addr,RAM_SIZE);
- jaddr=(int)out;
- #ifdef CORTEX_A8_BRANCH_PREDICTION_HACK
- // Hint to branch predictor that the branch is unlikely to be taken
- if(rs1[i]>=28)
- emit_jno_unlikely(0);
- else
- #endif
- emit_jno(0);
+ jaddr=emit_fastpath_cmp_jump(i,addr,&fastload_reg_override);
}
}
}else{ // using tlb
else addr=s;
if(!using_tlb) {
if(!c) {
- #ifdef PCSX
- if(sp_in_mirror&&rs1[i]==29) {
- emit_andimm(addr,~0x00e00000,HOST_TEMPREG);
- emit_cmpimm(HOST_TEMPREG,RAM_SIZE);
- faststore_reg_override=HOST_TEMPREG;
- }
- else
- #endif
+ #ifndef PCSX
#ifdef R29_HACK
// Strmnnrmn's speed hack
if(rs1[i]!=29||start<0x80001000||start>=0x80000000+RAM_SIZE)
#endif
emit_jno(0);
}
+ #else
+ jaddr=emit_fastpath_cmp_jump(i,addr,&faststore_reg_override);
+ #endif
}
}else{ // using tlb
int x=0;
}
type=STORED_STUB;
}
+#ifdef PCSX
+ if(jaddr) {
+ // PCSX store handlers don't check invcode again
+ reglist|=1<<addr;
+ add_stub(type,jaddr,(int)out,i,addr,(int)i_regs,ccadj[i],reglist);
+ jaddr=0;
+ }
+#endif
if(!using_tlb) {
if(!c||memtarget) {
#ifdef DESTRUCTIVE_SHIFT
int memtarget=0,c=0;
int jaddr2=0,jaddr3,type;
int agr=AGEN1+(i&1);
+ int fastio_reg_override=0;
u_int hr,reglist=0;
u_int copr=(source[i]>>16)&0x1f;
s=get_reg(i_regs->regmap,rs1[i]);
}
else {
if(!c) {
- emit_cmpimm(offset||c||s<0?ar:s,RAM_SIZE);
- jaddr2=(int)out;
- emit_jno(0);
+ jaddr2=emit_fastpath_cmp_jump(i,ar,&fastio_reg_override);
}
if (opcode[i]==0x32) { // LWC2
#ifdef HOST_IMM_ADDR32
if(c) emit_readword_tlb(constmap[i][s]+offset,-1,tl);
else
#endif
- emit_readword_indexed(0,ar,tl);
+ int a=ar;
+ if(fastio_reg_override) a=fastio_reg_override;
+ emit_readword_indexed(0,a,tl);
}
if (opcode[i]==0x3a) { // SWC2
#ifdef DESTRUCTIVE_SHIFT
if(!offset&&!c&&s>=0) emit_mov(s,ar);
#endif
- emit_writeword_indexed(tl,0,ar);
+ int a=ar;
+ if(fastio_reg_override) a=fastio_reg_override;
+ emit_writeword_indexed(tl,0,a);
}
}
if(jaddr2)
void ds_assemble(int i,struct regstat *i_regs)
{
+ speculate_register_values(i);
is_delayslot=1;
switch(itype[i]) {
case ALU:
}
}
+#ifdef DISASM
/* disassembly */
void disassemble_inst(int i)
{
printf (" %x: %s\n",start+i*4,insn[i]);
}
}
+#else
+static void disassemble_inst(int i) {}
+#endif // DISASM
// clear the state completely, instead of just marking
// things invalid like invalidate_all_pages() does
#ifndef DISABLE_TLB
using_tlb=0;
#endif
- sp_in_mirror=0;
for(n=0;n<524288;n++) // 0 .. 0x7FFFFFFF
memory_map[n]=-1;
for(n=524288;n<526336;n++) // 0x80000000 .. 0x807FFFFF
//rlist();
start = (u_int)addr&~3;
//assert(((u_int)addr&1)==0);
+ new_dynarec_did_compile=1;
#ifdef PCSX
- if(!sp_in_mirror&&(signed int)(psxRegs.GPR.n.sp&0xffe00000)>0x80200000&&
- 0x10000<=psxRegs.GPR.n.sp&&(psxRegs.GPR.n.sp&~0xe0e00000)<RAM_SIZE) {
- printf("SP hack enabled (%08x), @%08x\n", psxRegs.GPR.n.sp, psxRegs.pc);
- sp_in_mirror=1;
- }
if (Config.HLE && start == 0x80001000) // hlecall
{
// XXX: is this enough? Maybe check hleSoftCall?
if(itype[slen-1]==SPAN) {
bt[slen-1]=1; // Mark as a branch target so instruction can restart after exception
}
-
+
+#ifdef DISASM
/* Debug/disassembly */
- if((void*)assem_debug==(void*)printf)
for(i=0;i<slen;i++)
{
printf("U:");
#endif
}
}
+#endif // DISASM
/* Pass 8 - Assembly */
linkcount=0;stubcount=0;
for(i=0;i<slen;i++)
{
//if(ds) printf("ds: ");
- if((void*)assem_debug==(void*)printf) disassemble_inst(i);
+ disassemble_inst(i);
if(ds) {
ds=0; // Skip delay slot
if(bt[i]) assem_debug("OOPS - branch into delay slot\n");
instr_addr[i]=0;
} else {
+ speculate_register_values(i);
#ifndef DESTRUCTIVE_WRITEBACK
if(i<2||(itype[i-2]!=UJUMP&&itype[i-2]!=RJUMP&&(source[i-2]>>16)!=0x1000))
{
}
inv_code_start=inv_code_end=~0;
#ifdef PCSX
- // PCSX maps all RAM mirror invalid_code tests to 0x80000000..0x80000000+RAM_SIZE
+ // for PCSX we need to mark all mirrors too
if(get_page(start)<(RAM_SIZE>>12))
for(i=start>>12;i<=(start+slen*4)>>12;i++)
- invalid_code[((u_int)0x80000000>>12)|i]=0;
+ invalid_code[((u_int)0x00000000>>12)|(i&0x1ff)]=
+ invalid_code[((u_int)0x80000000>>12)|(i&0x1ff)]=
+ invalid_code[((u_int)0xa0000000>>12)|(i&0x1ff)]=0;
#endif
/* Pass 10 - Free memory by expiring oldest blocks */