mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
sh2 drc, optimisation for SH2 16x16 multiplication
This commit is contained in:
parent
7a7265eea0
commit
dd67441606
1 changed files with 82 additions and 35 deletions
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* SH2 recompiler
|
* SH2 recompiler
|
||||||
* (C) notaz, 2009,2010,2013
|
* (C) notaz, 2009,2010,2013
|
||||||
* (C) kub, 2018,2019
|
* (C) kub, 2018,2019,2020
|
||||||
*
|
*
|
||||||
* This work is licensed under the terms of MAME license.
|
* This work is licensed under the terms of MAME license.
|
||||||
* See COPYING file in the top-level directory.
|
* See COPYING file in the top-level directory.
|
||||||
|
@ -398,12 +398,13 @@ int rchit, rcmiss;
|
||||||
enum cache_reg_htype {
|
enum cache_reg_htype {
|
||||||
HRT_TEMP = 1, // is for temps and args
|
HRT_TEMP = 1, // is for temps and args
|
||||||
HRT_REG = 2, // is for sh2 regs
|
HRT_REG = 2, // is for sh2 regs
|
||||||
HRT_STATIC = 2, // is for static mappings (same as HRT_REG)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cache_reg_flags {
|
enum cache_reg_flags {
|
||||||
HRF_DIRTY = 1 << 0, // has "dirty" value to be written to ctx
|
HRF_DIRTY = 1 << 0, // has "dirty" value to be written to ctx
|
||||||
HRF_PINNED = 1 << 1, // has a pinned mapping
|
HRF_PINNED = 1 << 1, // has a pinned mapping
|
||||||
|
HRF_S16 = 1 << 2, // has a sign extended 16 bit value
|
||||||
|
HRF_U16 = 1 << 3, // has a zero extended 16 bit value
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cache_reg_type {
|
enum cache_reg_type {
|
||||||
|
@ -413,9 +414,9 @@ enum cache_reg_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 hreg; // "host" reg
|
u8 hreg:6; // "host" reg
|
||||||
u8 htype:2; // TEMP or REG?
|
u8 htype:2; // TEMP or REG?
|
||||||
u8 flags:2; // DIRTY, PINNED?
|
u8 flags:4; // DIRTY, PINNED?
|
||||||
u8 type:2; // CACHED or TEMP?
|
u8 type:2; // CACHED or TEMP?
|
||||||
u8 locked:2; // LOCKED reference counter
|
u8 locked:2; // LOCKED reference counter
|
||||||
u16 stamp; // kind of a timestamp
|
u16 stamp; // kind of a timestamp
|
||||||
|
@ -1334,6 +1335,37 @@ static void rcache_remove_vreg_alias(int x, sh2_reg_e r);
|
||||||
static void rcache_evict_vreg(int x);
|
static void rcache_evict_vreg(int x);
|
||||||
static void rcache_remap_vreg(int x);
|
static void rcache_remap_vreg(int x);
|
||||||
|
|
||||||
|
static void rcache_set_x16(int hr, int s16_, int u16_)
|
||||||
|
{
|
||||||
|
int x = reg_map_host[hr];
|
||||||
|
if (x >= 0) {
|
||||||
|
cache_regs[x].flags &= ~(HRF_S16|HRF_U16);
|
||||||
|
if (s16_) cache_regs[x].flags |= HRF_S16;
|
||||||
|
if (u16_) cache_regs[x].flags |= HRF_U16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rcache_copy_x16(int hr, int hr2)
|
||||||
|
{
|
||||||
|
int x = reg_map_host[hr], y = reg_map_host[hr2];
|
||||||
|
if (x >= 0 && y >= 0) {
|
||||||
|
cache_regs[x].flags = (cache_regs[x].flags & ~(HRF_S16|HRF_U16)) |
|
||||||
|
(cache_regs[y].flags & (HRF_S16|HRF_U16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rcache_is_s16(int hr)
|
||||||
|
{
|
||||||
|
int x = reg_map_host[hr];
|
||||||
|
return (x >= 0 ? cache_regs[x].flags & HRF_S16 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rcache_is_u16(int hr)
|
||||||
|
{
|
||||||
|
int x = reg_map_host[hr];
|
||||||
|
return (x >= 0 ? cache_regs[x].flags & HRF_U16 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
#define RCACHE_DUMP(msg) { \
|
#define RCACHE_DUMP(msg) { \
|
||||||
cache_reg_t *cp; \
|
cache_reg_t *cp; \
|
||||||
guest_reg_t *gp; \
|
guest_reg_t *gp; \
|
||||||
|
@ -1467,10 +1499,13 @@ static int gconst_check(sh2_reg_e r)
|
||||||
static int gconst_try_read(int vreg, sh2_reg_e r)
|
static int gconst_try_read(int vreg, sh2_reg_e r)
|
||||||
{
|
{
|
||||||
int i, x;
|
int i, x;
|
||||||
|
u32 v;
|
||||||
|
|
||||||
if (guest_regs[r].flags & GRF_CDIRTY) {
|
if (guest_regs[r].flags & GRF_CDIRTY) {
|
||||||
x = guest_regs[r].cnst;
|
x = guest_regs[r].cnst;
|
||||||
emith_move_r_imm(cache_regs[vreg].hreg, gconsts[x].val);
|
v = gconsts[x].val;
|
||||||
|
emith_move_r_imm(cache_regs[vreg].hreg, v);
|
||||||
|
rcache_set_x16(cache_regs[vreg].hreg, v == (s16)v, v == (u16)v);
|
||||||
FOR_ALL_BITS_SET_DO(gconsts[x].gregs, i,
|
FOR_ALL_BITS_SET_DO(gconsts[x].gregs, i,
|
||||||
{
|
{
|
||||||
if (guest_regs[i].vreg >= 0 && guest_regs[i].vreg != vreg)
|
if (guest_regs[i].vreg >= 0 && guest_regs[i].vreg != vreg)
|
||||||
|
@ -1641,6 +1676,8 @@ static void rcache_clean_vreg(int x)
|
||||||
rcache_evict_vreg(guest_regs[r].sreg);
|
rcache_evict_vreg(guest_regs[r].sreg);
|
||||||
emith_move_r_r(cache_regs[guest_regs[r].sreg].hreg,
|
emith_move_r_r(cache_regs[guest_regs[r].sreg].hreg,
|
||||||
cache_regs[guest_regs[r].vreg].hreg);
|
cache_regs[guest_regs[r].vreg].hreg);
|
||||||
|
rcache_copy_x16(cache_regs[guest_regs[r].sreg].hreg,
|
||||||
|
cache_regs[guest_regs[r].vreg].hreg);
|
||||||
rcache_remove_vreg_alias(x, r);
|
rcache_remove_vreg_alias(x, r);
|
||||||
rcache_add_vreg_alias(guest_regs[r].sreg, r);
|
rcache_add_vreg_alias(guest_regs[r].sreg, r);
|
||||||
cache_regs[guest_regs[r].sreg].flags |= HRF_DIRTY;
|
cache_regs[guest_regs[r].sreg].flags |= HRF_DIRTY;
|
||||||
|
@ -1783,9 +1820,9 @@ static int rcache_allocate_temp(void)
|
||||||
|
|
||||||
#if REMAP_REGISTER
|
#if REMAP_REGISTER
|
||||||
// maps a host register to a REG
|
// maps a host register to a REG
|
||||||
static int rcache_map_reg(sh2_reg_e r, int hr, int mode)
|
static int rcache_map_reg(sh2_reg_e r, int hr)
|
||||||
{
|
{
|
||||||
int x, i;
|
int i;
|
||||||
|
|
||||||
gconst_kill(r);
|
gconst_kill(r);
|
||||||
|
|
||||||
|
@ -1797,19 +1834,6 @@ static int rcache_map_reg(sh2_reg_e r, int hr, int mode)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deal with statically mapped regs
|
|
||||||
if (mode == RC_GR_RMW && (guest_regs[r].flags & (GRF_STATIC|GRF_PINNED))) {
|
|
||||||
x = guest_regs[r].sreg;
|
|
||||||
if (guest_regs[r].vreg == x) {
|
|
||||||
// STATIC in its sreg with no aliases, and some processing pending
|
|
||||||
if (cache_regs[x].gregs == 1 << r)
|
|
||||||
return cache_regs[x].hreg;
|
|
||||||
} else if (cache_regs[x].type == HR_FREE ||
|
|
||||||
(cache_regs[x].type == HR_TEMP && !cache_regs[x].locked))
|
|
||||||
// STATIC not in its sreg, with sreg available -> move it
|
|
||||||
i = guest_regs[r].sreg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove old mappings of r and i if one exists
|
// remove old mappings of r and i if one exists
|
||||||
if (guest_regs[r].vreg >= 0)
|
if (guest_regs[r].vreg >= 0)
|
||||||
rcache_remove_vreg_alias(guest_regs[r].vreg, r);
|
rcache_remove_vreg_alias(guest_regs[r].vreg, r);
|
||||||
|
@ -1818,7 +1842,6 @@ static int rcache_map_reg(sh2_reg_e r, int hr, int mode)
|
||||||
// set new mappping
|
// set new mappping
|
||||||
cache_regs[i].type = HR_CACHED;
|
cache_regs[i].type = HR_CACHED;
|
||||||
cache_regs[i].gregs = 1 << r;
|
cache_regs[i].gregs = 1 << r;
|
||||||
cache_regs[i].flags &= HRF_PINNED;
|
|
||||||
cache_regs[i].locked = 0;
|
cache_regs[i].locked = 0;
|
||||||
cache_regs[i].stamp = ++rcache_counter;
|
cache_regs[i].stamp = ++rcache_counter;
|
||||||
cache_regs[i].flags |= HRF_DIRTY;
|
cache_regs[i].flags |= HRF_DIRTY;
|
||||||
|
@ -2010,7 +2033,9 @@ static int rcache_get_reg_(sh2_reg_e r, rc_gr_mode mode, int do_locking, int *hr
|
||||||
tr->flags |= HRF_DIRTY;
|
tr->flags |= HRF_DIRTY;
|
||||||
guest_regs[r].flags |= GRF_DIRTY;
|
guest_regs[r].flags |= GRF_DIRTY;
|
||||||
gconst_kill(r);
|
gconst_kill(r);
|
||||||
}
|
rcache_set_x16(tr->hreg, 0, 0);
|
||||||
|
} else if (src >= 0 && cache_regs[src].hreg != tr->hreg)
|
||||||
|
rcache_copy_x16(tr->hreg, cache_regs[src].hreg);
|
||||||
#if DRC_DEBUG & 64
|
#if DRC_DEBUG & 64
|
||||||
RCACHE_CHECK("after getreg");
|
RCACHE_CHECK("after getreg");
|
||||||
#endif
|
#endif
|
||||||
|
@ -2410,6 +2435,8 @@ static void rcache_clean(void)
|
||||||
else {
|
else {
|
||||||
emith_move_r_r(cache_regs[guest_regs[i].sreg].hreg,
|
emith_move_r_r(cache_regs[guest_regs[i].sreg].hreg,
|
||||||
cache_regs[guest_regs[i].vreg].hreg);
|
cache_regs[guest_regs[i].vreg].hreg);
|
||||||
|
rcache_copy_x16(cache_regs[guest_regs[i].sreg].hreg,
|
||||||
|
cache_regs[guest_regs[i].vreg].hreg);
|
||||||
rcache_remove_vreg_alias(guest_regs[i].vreg, i);
|
rcache_remove_vreg_alias(guest_regs[i].vreg, i);
|
||||||
}
|
}
|
||||||
cache_regs[guest_regs[i].sreg].gregs = 1 << i;
|
cache_regs[guest_regs[i].sreg].gregs = 1 << i;
|
||||||
|
@ -2689,6 +2716,8 @@ static void emit_sync_t_to_sr(void)
|
||||||
// rd = @(arg0)
|
// rd = @(arg0)
|
||||||
static int emit_memhandler_read(int size)
|
static int emit_memhandler_read(int size)
|
||||||
{
|
{
|
||||||
|
int hr;
|
||||||
|
|
||||||
emit_sync_t_to_sr();
|
emit_sync_t_to_sr();
|
||||||
rcache_clean_tmp();
|
rcache_clean_tmp();
|
||||||
#ifndef DRC_SR_REG
|
#ifndef DRC_SR_REG
|
||||||
|
@ -2711,7 +2740,9 @@ static int emit_memhandler_read(int size)
|
||||||
case 2: emith_call(sh2_drc_read32); break; // 32
|
case 2: emith_call(sh2_drc_read32); break; // 32
|
||||||
}
|
}
|
||||||
|
|
||||||
return rcache_get_tmp_ret();
|
hr = rcache_get_tmp_ret();
|
||||||
|
rcache_set_x16(hr, (size & MF_SIZEMASK) < 2, 0);
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @(arg0) = arg1
|
// @(arg0) = arg1
|
||||||
|
@ -2747,6 +2778,7 @@ static int emit_memhandler_read_rr(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rs, u32 off
|
||||||
emit_move_r_imm32(rd, val);
|
emit_move_r_imm32(rd, val);
|
||||||
hr2 = rcache_get_reg(rd, RC_GR_RMW, NULL);
|
hr2 = rcache_get_reg(rd, RC_GR_RMW, NULL);
|
||||||
}
|
}
|
||||||
|
rcache_set_x16(hr2, val == (s16)val, val == (u16)val);
|
||||||
if (size & MF_POSTINCR)
|
if (size & MF_POSTINCR)
|
||||||
emit_add_r_imm(rs, 1 << (size & MF_SIZEMASK));
|
emit_add_r_imm(rs, 1 << (size & MF_SIZEMASK));
|
||||||
return hr2;
|
return hr2;
|
||||||
|
@ -2790,12 +2822,11 @@ static int emit_memhandler_read_rr(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rs, u32 off
|
||||||
}
|
}
|
||||||
hr = emit_memhandler_read(size);
|
hr = emit_memhandler_read(size);
|
||||||
|
|
||||||
size &= MF_SIZEMASK;
|
|
||||||
if (rd == SHR_TMP)
|
if (rd == SHR_TMP)
|
||||||
hr2 = hr;
|
hr2 = hr;
|
||||||
else
|
else
|
||||||
#if REMAP_REGISTER
|
#if REMAP_REGISTER
|
||||||
hr2 = rcache_map_reg(rd, hr, RC_GR_WRITE);
|
hr2 = rcache_map_reg(rd, hr);
|
||||||
#else
|
#else
|
||||||
hr2 = rcache_get_reg(rd, RC_GR_WRITE, NULL);
|
hr2 = rcache_get_reg(rd, RC_GR_WRITE, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2865,12 +2896,11 @@ static int emit_indirect_indexed_read(SH2 *sh2, sh2_reg_e rd, sh2_reg_e rx, sh2_
|
||||||
emith_add_r_r_r(hr, tx, ty);
|
emith_add_r_r_r(hr, tx, ty);
|
||||||
hr = emit_memhandler_read(size);
|
hr = emit_memhandler_read(size);
|
||||||
|
|
||||||
size &= MF_SIZEMASK;
|
|
||||||
if (rd == SHR_TMP)
|
if (rd == SHR_TMP)
|
||||||
hr2 = hr;
|
hr2 = hr;
|
||||||
else
|
else
|
||||||
#if REMAP_REGISTER
|
#if REMAP_REGISTER
|
||||||
hr2 = rcache_map_reg(rd, hr, RC_GR_WRITE);
|
hr2 = rcache_map_reg(rd, hr);
|
||||||
#else
|
#else
|
||||||
hr2 = rcache_get_reg(rd, RC_GR_WRITE, NULL);
|
hr2 = rcache_get_reg(rd, RC_GR_WRITE, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
@ -3644,7 +3674,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
}
|
}
|
||||||
tmp2 = emit_memhandler_read(opd->size);
|
tmp2 = emit_memhandler_read(opd->size);
|
||||||
#if REMAP_REGISTER
|
#if REMAP_REGISTER
|
||||||
tmp3 = rcache_map_reg(GET_Rn(), tmp2, RC_GR_WRITE);
|
tmp3 = rcache_map_reg(GET_Rn(), tmp2);
|
||||||
#else
|
#else
|
||||||
tmp3 = rcache_get_reg(GET_Rn(), RC_GR_WRITE, NULL);
|
tmp3 = rcache_get_reg(GET_Rn(), RC_GR_WRITE, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
@ -3886,16 +3916,29 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
|
tmp2 = rcache_get_reg(GET_Rn(), RC_GR_READ, NULL);
|
||||||
tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
|
tmp3 = rcache_get_reg(GET_Rm(), RC_GR_READ, NULL);
|
||||||
tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE, NULL);
|
tmp = rcache_get_reg(SHR_MACL, RC_GR_WRITE, NULL);
|
||||||
tmp4 = rcache_get_tmp();
|
tmp4 = tmp3;
|
||||||
if (op & 1) {
|
if (op & 1) {
|
||||||
emith_sext(tmp, tmp2, 16);
|
if (! rcache_is_s16(tmp2)) {
|
||||||
emith_sext(tmp4, tmp3, 16);
|
emith_sext(tmp, tmp2, 16);
|
||||||
|
tmp2 = tmp;
|
||||||
|
}
|
||||||
|
if (! rcache_is_s16(tmp3)) {
|
||||||
|
tmp4 = rcache_get_tmp();
|
||||||
|
emith_sext(tmp4, tmp3, 16);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
emith_clear_msb(tmp, tmp2, 16);
|
if (! rcache_is_u16(tmp2)) {
|
||||||
emith_clear_msb(tmp4, tmp3, 16);
|
emith_clear_msb(tmp, tmp2, 16);
|
||||||
|
tmp2 = tmp;
|
||||||
|
}
|
||||||
|
if (! rcache_is_u16(tmp3)) {
|
||||||
|
tmp4 = rcache_get_tmp();
|
||||||
|
emith_clear_msb(tmp4, tmp3, 16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emith_mul(tmp, tmp, tmp4);
|
emith_mul(tmp, tmp2, tmp4);
|
||||||
rcache_free_tmp(tmp4);
|
if (tmp4 != tmp3)
|
||||||
|
rcache_free_tmp(tmp4);
|
||||||
goto end_op;
|
goto end_op;
|
||||||
}
|
}
|
||||||
goto default_;
|
goto default_;
|
||||||
|
@ -4415,15 +4458,19 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
break;
|
break;
|
||||||
case 0x0c: // EXTU.B Rm,Rn 0110nnnnmmmm1100
|
case 0x0c: // EXTU.B Rm,Rn 0110nnnnmmmm1100
|
||||||
emith_clear_msb(tmp2, tmp, 24);
|
emith_clear_msb(tmp2, tmp, 24);
|
||||||
|
rcache_set_x16(tmp2, 1, 1);
|
||||||
break;
|
break;
|
||||||
case 0x0d: // EXTU.W Rm,Rn 0110nnnnmmmm1101
|
case 0x0d: // EXTU.W Rm,Rn 0110nnnnmmmm1101
|
||||||
emith_clear_msb(tmp2, tmp, 16);
|
emith_clear_msb(tmp2, tmp, 16);
|
||||||
|
rcache_set_x16(tmp2, 0, 1);
|
||||||
break;
|
break;
|
||||||
case 0x0e: // EXTS.B Rm,Rn 0110nnnnmmmm1110
|
case 0x0e: // EXTS.B Rm,Rn 0110nnnnmmmm1110
|
||||||
emith_sext(tmp2, tmp, 8);
|
emith_sext(tmp2, tmp, 8);
|
||||||
|
rcache_set_x16(tmp2, 1, 0);
|
||||||
break;
|
break;
|
||||||
case 0x0f: // EXTS.W Rm,Rn 0110nnnnmmmm1111
|
case 0x0f: // EXTS.W Rm,Rn 0110nnnnmmmm1111
|
||||||
emith_sext(tmp2, tmp, 16);
|
emith_sext(tmp2, tmp, 16);
|
||||||
|
rcache_set_x16(tmp2, 1, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
goto end_op;
|
goto end_op;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue