diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp index 2a13f960..1e72fe49 100644 --- a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp +++ b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp @@ -200,6 +200,16 @@ LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) } LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) +LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) +{ +#if defined(__x86_64__) + POPQm(d, X86_NOREG, X86_NOREG, 1); +#else + POPLm(d, X86_NOREG, X86_NOREG, 1); +#endif +} +LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) + LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) { BTLir(i, r); @@ -925,6 +935,12 @@ LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) } LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) +LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) +{ + XORLir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) + LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) { ANDLir(i, d); @@ -1208,6 +1224,14 @@ LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) } LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) +LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) +{ + emit_byte(0x8f); + emit_byte(0x05); + emit_long(d); +} +LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) + LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) { emit_byte(0x0f); @@ -2500,6 +2524,14 @@ LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) } LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) +LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) +{ + emit_byte(0x81); + emit_byte(0xf0+d); + emit_long(i); +} +LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) + LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) { if (optimize_imm8 && isbyte(i)) { @@ -3214,6 +3246,18 @@ static __inline__ void raw_reg_to_flags(int r) raw_sahf(0); } +#define FLAG_NREG3 0 /* Set to -1 if any register will do */ +static __inline__ void raw_flags_set_zero(int s, int tmp) +{ + raw_mov_l_rr(tmp,s); + raw_lahf(s); /* flags into ah */ + raw_and_l_ri(s,0xffffbfff); + raw_and_l_ri(tmp,0x00004000); + raw_xor_l_ri(tmp,0x00004000); + raw_or_l(s,tmp); + raw_sahf(s); +} + #else #define FLAG_NREG1 -1 /* Set to -1 if any register will do */ @@ -3240,6 +3284,19 @@ static __inline__ void raw_reg_to_flags(int r) raw_popfl(); } +#define FLAG_NREG3 -1 /* Set to -1 if any register will do */ +static __inline__ void raw_flags_set_zero(int s, int tmp) +{ + raw_mov_l_rr(tmp,s); + raw_pushfl(); + raw_pop_l_r(s); + raw_and_l_ri(s,0xffffffbf); + raw_and_l_ri(tmp,0x00000040); + raw_xor_l_ri(tmp,0x00000040); + raw_or_l(s,tmp); + raw_push_l_r(s); + raw_popfl(); +} #endif /* Apparently, there are enough instructions between flag store and @@ -3265,22 +3322,6 @@ static __inline__ void raw_load_flagx(uae_u32 target, uae_u32 r) raw_mov_l_rm(target,(uintptr)live.state[r].mem); } -#define NATIVE_FLAG_Z 0x40 -static __inline__ void raw_flags_set_zero(int f, int r, int t) -{ - // FIXME: this is really suboptimal - raw_pushfl(); - raw_pop_l_r(f); - raw_and_l_ri(f,~NATIVE_FLAG_Z); - raw_test_l_rr(r,r); - raw_mov_l_ri(r,0); - raw_mov_l_ri(t,NATIVE_FLAG_Z); - raw_cmov_l_rr(r,t,NATIVE_CC_EQ); - raw_or_l(f,r); - raw_push_l_r(f); - raw_popfl(); -} - static __inline__ void raw_inc_sp(int off) { raw_add_l_ri(ESP_INDEX,off); diff --git a/BasiliskII/src/uae_cpu/compiler/compemu.h b/BasiliskII/src/uae_cpu/compiler/compemu.h index b478da59..855c39ee 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu.h +++ b/BasiliskII/src/uae_cpu/compiler/compemu.h @@ -348,8 +348,7 @@ DECLARE_MIDFUNC(setcc(W1 d, IMM cc)); DECLARE_MIDFUNC(setcc_m(IMM d, IMM cc)); DECLARE_MIDFUNC(cmov_l_rr(RW4 d, R4 s, IMM cc)); DECLARE_MIDFUNC(cmov_l_rm(RW4 d, IMM s, IMM cc)); -/* Set native Z flag only if register is zero */ -DECLARE_MIDFUNC(setzflg_l(RW4 r)); +DECLARE_MIDFUNC(bsf_l_rr(W4 d, R4 s)); DECLARE_MIDFUNC(pop_m(IMM d)); DECLARE_MIDFUNC(push_m(IMM d)); DECLARE_MIDFUNC(pop_l(W4 d)); @@ -516,6 +515,8 @@ extern void writelong_clobber(int address, int source, int tmp); extern void get_n_addr(int address, int dest, int tmp); extern void get_n_addr_jmp(int address, int dest, int tmp); extern void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp); +/* Set native Z flag only if register is zero */ +extern void set_zero(int r, int tmp); extern int kill_rodent(int r); extern void sync_m68k_pc(void); extern uae_u32 get_const(int r); diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp index e58a557a..b31c3592 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp @@ -121,6 +121,9 @@ static compop_func *nfcompfunctbl[65536]; static cpuop_func *nfcpufunctbl[65536]; uae_u8* comp_pc_p; +// From main_unix.cpp +extern bool ThirtyThreeBitAddressing; + // From newcpu.cpp extern bool quit_program; @@ -2934,30 +2937,30 @@ MIDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc)) } MENDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc)) -MIDFUNC(1,setzflg_l,(RW4 r)) +MIDFUNC(2,bsf_l_rr,(W4 d, W4 s)) { - if (setzflg_uses_bsf) { - CLOBBER_BSF; - r=rmw(r,4,4); - raw_bsf_l_rr(r,r); - unlock2(r); - } - else { - Dif (live.flags_in_flags!=VALID) { - write_log("setzflg() wanted flags in native flags, they are %d\n", - live.flags_in_flags); - abort(); - } - r=readreg(r,4); - int f=writereg(S11,4); - int t=writereg(S12,4); - raw_flags_set_zero(f,r,t); - unlock2(f); - unlock2(r); - unlock2(t); - } + CLOBBER_BSF; + s = readreg(s, 4); + d = writereg(d, 4); + raw_bsf_l_rr(d, s); + unlock2(s); + unlock2(d); } -MENDFUNC(1,setzflg_l,(RW4 r)) +MENDFUNC(2,bsf_l_rr,(W4 d, W4 s)) + +/* Set the Z flag depending on the value in s. Note that the + value has to be 0 or -1 (or, more precisely, for non-zero + values, bit 14 must be set)! */ +MIDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) +{ + CLOBBER_BSF; + s=rmw_specific(s,4,4,FLAG_NREG3); + tmp=writereg(tmp,4); + raw_flags_set_zero(s, tmp); + unlock2(tmp); + unlock2(s); +} +MENDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) MIDFUNC(2,imul_32_32,(RW4 d, R4 s)) { @@ -4879,6 +4882,14 @@ MENDFUNC(2,fmul_rr,(FRW d, FR s)) * Support functions exposed to gencomp. CREATE time * ********************************************************************/ +void set_zero(int r, int tmp) +{ + if (setzflg_uses_bsf) + bsf_l_rr(r,r); + else + simulate_bsf(tmp,r); +} + int kill_rodent(int r) { return KILLTHERAT && @@ -5366,8 +5377,8 @@ static void writemem_real(int address, int source, int size, int tmp, int clobbe f=source; #if SIZEOF_VOID_P == 8 - /* HACK: address calculation is suboptimal and possibly broken */ - sign_extend_32_rr(address, address); + if (!ThirtyThreeBitAddressing) + sign_extend_32_rr(address, address); #endif switch(size) { @@ -5430,8 +5441,8 @@ static void readmem_real(int address, int dest, int size, int tmp) f=dest; #if SIZEOF_VOID_P == 8 - /* HACK: address calculation is suboptimal and possibly broken */ - sign_extend_32_rr(address, address); + if (!ThirtyThreeBitAddressing) + sign_extend_32_rr(address, address); #endif switch(size) { diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp.c b/BasiliskII/src/uae_cpu/compiler/gencomp.c index b9cc631b..a061014d 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp.c @@ -1100,7 +1100,7 @@ genflags (flagtypes type, wordsizes size, char *value, char *src, char *dst) "\tint one=scratchie++;\n" "\tif (needed_flags&FLAG_Z) {\n" "\tmov_l_ri(zero,0);\n" - "\tmov_l_ri(one,1);\n" + "\tmov_l_ri(one,-1);\n" "\tmake_flags_live();\n" "\tcmov_l_rr(zero,one,5);\n" "\t}\n"); @@ -1123,7 +1123,7 @@ genflags (flagtypes type, wordsizes size, char *value, char *src, char *dst) comprintf("\tlive_flags();\n"); comprintf("\tif (needed_flags&FLAG_Z) {\n" "\tcmov_l_rr(zero,one,5);\n" - "\tsetzflg_l(zero);\n" + "\tset_zero(zero, one);\n" /* No longer need one */ "\tlive_flags();\n" "\t}\n"); comprintf("\tend_needflags();\n"); @@ -1365,6 +1365,7 @@ gen_opcode (unsigned long int opcode) genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace(); comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" "\tmov_l_rr(s,src);\n"); if (curi->size == sz_byte) comprintf("\tand_l_ri(s,7);\n"); @@ -1380,6 +1381,7 @@ gen_opcode (unsigned long int opcode) case i_BCLR: op="btr"; break; case i_BSET: op="bts"; break; case i_BTST: op="bt"; need_write=0; break; + default: abort(); } comprintf("\t%s_l_rr(dst,s);\n" /* Answer now in C */ "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ @@ -1387,7 +1389,7 @@ gen_opcode (unsigned long int opcode) "\tdont_care_flags();\n",op); if (!noflags) { comprintf("\tstart_needflags();\n" - "\tsetzflg_l(s);\n" + "\tset_zero(s,tmp);\n" "\tlive_flags();\n" "\tend_needflags();\n"); }