mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
sh2 drc, fix reading from constant memory address
This commit is contained in:
parent
d35a929551
commit
2d2387b293
2 changed files with 28 additions and 17 deletions
|
@ -1033,8 +1033,7 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common
|
||||||
#define host_instructions_updated(base, end, force) (void)(base),(void)(end)
|
#define host_instructions_updated(base, end, force) (void)(base),(void)(end)
|
||||||
#define emith_update_cache() /**/
|
#define emith_update_cache() /**/
|
||||||
|
|
||||||
// NB this MUST be <0x40000000 to avoid overflow in address calculations
|
#define emith_rw_offs_max() 0xffffffffU
|
||||||
#define emith_rw_offs_max() 0xfffffff // for better perfomance: <0x10000000
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
|
|
|
@ -2590,8 +2590,21 @@ static void emit_le_ptr8(int cond, int r)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// split address by mask, in base part (upper) and offset (lower, signed!)
|
||||||
|
static uptr split_address(uptr la, uptr mask, s32 *offs)
|
||||||
|
{
|
||||||
|
uptr sign = (mask>>1) + 1; // sign bit in offset
|
||||||
|
*offs = (la & mask) | (la & sign ? ~mask : 0); // offset part, sign extended
|
||||||
|
la = (la & ~mask) + ((la & sign) << 1); // base part, corrected for offs sign
|
||||||
|
if (~mask && la == ~mask && !(*offs & sign)) { // special case la=-1 & offs>0
|
||||||
|
*offs = -*offs;
|
||||||
|
la = 0;
|
||||||
|
}
|
||||||
|
return la;
|
||||||
|
}
|
||||||
|
|
||||||
// NB may return either REG or TEMP
|
// NB may return either REG or TEMP
|
||||||
static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, u32 *offs)
|
static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, s32 *offs)
|
||||||
{
|
{
|
||||||
uptr omask = emith_rw_offs_max(); // offset mask
|
uptr omask = emith_rw_offs_max(); // offset mask
|
||||||
u32 mask = 0;
|
u32 mask = 0;
|
||||||
|
@ -2614,14 +2627,14 @@ static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, u32 *offs)
|
||||||
a = (a + *offs) & mask;
|
a = (a + *offs) & mask;
|
||||||
if (poffs == offsetof(SH2, p_da)) {
|
if (poffs == offsetof(SH2, p_da)) {
|
||||||
// access sh2->data_array directly
|
// access sh2->data_array directly
|
||||||
a += offsetof(SH2, data_array);
|
a = split_address(a + offsetof(SH2, data_array), omask, offs);
|
||||||
emith_add_r_r_ptr_imm(hr, CONTEXT_REG, a & ~omask);
|
emith_add_r_r_ptr_imm(hr, CONTEXT_REG, a);
|
||||||
} else {
|
} else {
|
||||||
|
a = split_address(a, omask, offs);
|
||||||
emith_ctx_read_ptr(hr, poffs);
|
emith_ctx_read_ptr(hr, poffs);
|
||||||
if (a & ~omask)
|
if (a)
|
||||||
emith_add_r_r_ptr_imm(hr, hr, a & ~omask);
|
emith_add_r_r_ptr_imm(hr, hr, a);
|
||||||
}
|
}
|
||||||
*offs = a & omask;
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2637,24 +2650,23 @@ static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, u32 *offs)
|
||||||
la -= (s32)((a & ~mask) - *offs); // diff between reg and memory
|
la -= (s32)((a & ~mask) - *offs); // diff between reg and memory
|
||||||
hr = hr2 = rcache_get_reg(r, rmode, NULL);
|
hr = hr2 = rcache_get_reg(r, rmode, NULL);
|
||||||
if ((s32)a < 0) emith_uext_ptr(hr2);
|
if ((s32)a < 0) emith_uext_ptr(hr2);
|
||||||
if (la & ~omask) {
|
la = split_address(la, omask, offs);
|
||||||
|
if (la) {
|
||||||
hr = rcache_get_tmp();
|
hr = rcache_get_tmp();
|
||||||
emith_add_r_r_ptr_imm(hr, hr2, la & ~omask);
|
emith_add_r_r_ptr_imm(hr, hr2, la);
|
||||||
rcache_free(hr2);
|
rcache_free(hr2);
|
||||||
}
|
}
|
||||||
*offs = (la & omask);
|
|
||||||
} else {
|
} else {
|
||||||
// known fixed host address
|
// known fixed host address
|
||||||
la += (a + *offs) & mask;
|
la = split_address(la + ((a + *offs) & mask), omask, offs);
|
||||||
hr = rcache_get_tmp();
|
hr = rcache_get_tmp();
|
||||||
emith_move_r_ptr_imm(hr, la & ~omask);
|
emith_move_r_ptr_imm(hr, la);
|
||||||
*offs = la & omask;
|
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read const data from const ROM address
|
// read const data from const ROM address
|
||||||
static int emit_get_rom_data(SH2 *sh2, sh2_reg_e r, u32 offs, int size, u32 *val)
|
static int emit_get_rom_data(SH2 *sh2, sh2_reg_e r, s32 offs, int size, u32 *val)
|
||||||
{
|
{
|
||||||
u32 a, mask;
|
u32 a, mask;
|
||||||
|
|
||||||
|
@ -2788,7 +2800,7 @@ static void emit_memhandler_write(int size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// rd = @(Rs,#offs); rd < 0 -> return a temp
|
// rd = @(Rs,#offs); rd < 0 -> return a temp
|
||||||
static int emit_memhandler_read_rr(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rs, u32 offs, int size)
|
static int emit_memhandler_read_rr(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rs, s32 offs, int size)
|
||||||
{
|
{
|
||||||
int hr, hr2;
|
int hr, hr2;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
@ -2859,7 +2871,7 @@ static int emit_memhandler_read_rr(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rs, u32 off
|
||||||
}
|
}
|
||||||
|
|
||||||
// @(Rs,#offs) = rd; rd < 0 -> write arg1
|
// @(Rs,#offs) = rd; rd < 0 -> write arg1
|
||||||
static void emit_memhandler_write_rr(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rs, u32 offs, int size)
|
static void emit_memhandler_write_rr(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rs, s32 offs, int size)
|
||||||
{
|
{
|
||||||
int hr, hr2;
|
int hr, hr2;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue