summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2009-12-20 15:21:26 +0000
committer Aaron Giles <aaron@aarongiles.com>2009-12-20 15:21:26 +0000
commit30d57e3f481ecbc39efcef7b7d7e63503c664e26 (patch)
treec9a109f1e8ae5e04b465f76a2b780eb41076c42a
parentf0358680a7cdd037b4c6ba80d6bef4fd59808831 (diff)
Minor drc improvments:
- simplified RSP's misaligned memory accesses - removed now-unnecessary shifts from direct memory accesses in mips3/powerpc drcs - optimized AND with 0xff/0xffff/0xffffffff cases for x86/x64 - added rudimentary memory/register tracking in x86 backend to remove redundant loads
-rw-r--r--src/emu/cpu/drcbex64.c54
-rw-r--r--src/emu/cpu/drcbex86.c291
-rw-r--r--src/emu/cpu/mips/mips3drc.c34
-rw-r--r--src/emu/cpu/powerpc/ppcdrc.c34
-rw-r--r--src/emu/cpu/rsp/rspdrc.c178
-rw-r--r--src/emu/cpu/x86emit.h13
6 files changed, 417 insertions, 187 deletions
diff --git a/src/emu/cpu/drcbex64.c b/src/emu/cpu/drcbex64.c
index ca885246193..746b9848d9f 100644
--- a/src/emu/cpu/drcbex64.c
+++ b/src/emu/cpu/drcbex64.c
@@ -18,8 +18,6 @@
* Identify common pairs and optimize output
- * Convert AND 0xff/0xffff to movzx
-
* Convert SUB a,0,b to NEG
* Optimize, e.g., and [r5],i0,$FF to use rbx as temporary register
@@ -5446,6 +5444,26 @@ static x86code *op_and(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
emit_and_m32_p32(drcbe, &dst, MABS(drcbe, dstp.value), &src2p, inst); // and [dstp],src2p
+ /* AND with immediate 0xff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xff && inst->flags == 0)
+ {
+ if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_movzx_r32_r8(&dst, dstreg, src1p.value); // movzx dstreg,src1p
+ else if (src1p.type == DRCUML_PTYPE_MEMORY)
+ emit_movzx_r32_m8(&dst, dstreg, MABS(drcbe, src1p.value)); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ }
+
+ /* AND with immediate 0xffff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffff && inst->flags == 0)
+ {
+ if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_movzx_r32_r16(&dst, dstreg, src1p.value); // movzx dstreg,src1p
+ else if (src1p.type == DRCUML_PTYPE_MEMORY)
+ emit_movzx_r32_m16(&dst, dstreg, MABS(drcbe, src1p.value)); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ }
+
/* general case */
else
{
@@ -5462,6 +5480,38 @@ static x86code *op_and(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
emit_and_m64_p64(drcbe, &dst, MABS(drcbe, dstp.value), &src2p, inst); // and [dstp],src2p
+ /* AND with immediate 0xff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xff && inst->flags == 0)
+ {
+ if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_movzx_r32_r8(&dst, dstreg, src1p.value); // movzx dstreg,src1p
+ else if (src1p.type == DRCUML_PTYPE_MEMORY)
+ emit_movzx_r32_m8(&dst, dstreg, MABS(drcbe, src1p.value)); // movzx dstreg,[src1p]
+ emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ }
+
+ /* AND with immediate 0xffff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffff && inst->flags == 0)
+ {
+ if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_movzx_r32_r16(&dst, dstreg, src1p.value); // movzx dstreg,src1p
+ else if (src1p.type == DRCUML_PTYPE_MEMORY)
+ emit_movzx_r32_m16(&dst, dstreg, MABS(drcbe, src1p.value)); // movzx dstreg,[src1p]
+ emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ }
+
+ /* AND with immediate 0xffffffff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffffffff && inst->flags == 0)
+ {
+ if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_r32_r32(&dst, dstreg, dstreg); // mov dstreg,dstreg
+ else
+ {
+ emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
+ emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
/* general case */
else
{
diff --git a/src/emu/cpu/drcbex86.c b/src/emu/cpu/drcbex86.c
index d099527dace..beafe283055 100644
--- a/src/emu/cpu/drcbex86.c
+++ b/src/emu/cpu/drcbex86.c
@@ -18,8 +18,6 @@
* Identify common pairs and optimize output
- * Convert AND 0xff/0xffff to movzx
-
* Convert SUB a,0,b to NEG
* Optimize, e.g., and [r5],i0,$FF to use ebx as temporary register
@@ -174,6 +172,12 @@ struct _drcbe_state
UINT32 * reglo[REG_MAX]; /* pointer to low part of data for each register */
UINT32 * reghi[REG_MAX]; /* pointer to high part of data for each register */
+ UINT8 last_lower_reg; /* last register we stored a lower from */
+ x86code * last_lower_pc; /* PC after instruction where we last stored a lower register */
+ UINT32 * last_lower_addr; /* address where we last stored an lower register */
+ UINT8 last_upper_reg; /* last register we stored an upper from */
+ x86code * last_upper_pc; /* PC after instruction where we last stored an upper register */
+ UINT32 * last_upper_addr; /* address where we last stored an upper register */
double fptemp; /* temporary storage for floating point */
const address_space * space[ADDRESS_SPACES]; /* address spaces */
@@ -523,6 +527,85 @@ INLINE void emit_combine_z_shl_flags(x86code **dst)
}
+/*-------------------------------------------------
+ reset_last_upper_lower_reg - reset the last
+ upper/lower register state
+-------------------------------------------------*/
+
+INLINE void reset_last_upper_lower_reg(drcbe_state *drcbe)
+{
+ drcbe->last_lower_reg = REG_NONE;
+ drcbe->last_upper_reg = REG_NONE;
+}
+
+
+/*-------------------------------------------------
+ set_last_lower_reg - note that we have just
+ loaded a lower register
+-------------------------------------------------*/
+
+INLINE void set_last_lower_reg(drcbe_state *drcbe, x86code *dst, const drcuml_parameter *param, UINT8 reglo)
+{
+ if (param->type == DRCUML_PTYPE_MEMORY)
+ {
+ drcbe->last_lower_reg = reglo;
+ drcbe->last_lower_addr = (UINT32 *)((FPTR)param->value);
+ drcbe->last_lower_pc = dst;
+ }
+}
+
+
+/*-------------------------------------------------
+ set_last_upper_reg - note that we have just
+ loaded an upper register
+-------------------------------------------------*/
+
+INLINE void set_last_upper_reg(drcbe_state *drcbe, x86code *dst, const drcuml_parameter *param, UINT8 reghi)
+{
+ drcbe->last_upper_reg = reghi;
+ drcbe->last_upper_addr = (param->type == DRCUML_PTYPE_INT_REGISTER) ? drcbe->reghi[param->value] : (UINT32 *)((FPTR)param->value + 4);
+ drcbe->last_upper_pc = dst;
+}
+
+
+/*-------------------------------------------------
+ can_skip_lower_load - return TRUE if we can
+ skip re-loading a lower half of a register
+-------------------------------------------------*/
+
+INLINE int can_skip_lower_load(drcbe_state *drcbe, x86code *dst, UINT32 *memptr, UINT8 reglo)
+{
+// return FALSE;
+ return (dst == drcbe->last_lower_pc && memptr == drcbe->last_lower_addr && reglo == drcbe->last_lower_reg);
+}
+
+
+/*-------------------------------------------------
+ can_skip_upper_load - return TRUE if we can
+ skip re-loading an upper half of a register
+-------------------------------------------------*/
+
+INLINE int can_skip_upper_load(drcbe_state *drcbe, x86code *dst, UINT32 *memptr, UINT8 reghi)
+{
+// return FALSE;
+ return (dst == drcbe->last_upper_pc && memptr == drcbe->last_upper_addr && reghi == drcbe->last_upper_reg);
+}
+
+
+/*-------------------------------------------------
+ track_resolve_link - wrapper for resolve_link
+ that resets all register tracking info
+-------------------------------------------------*/
+
+INLINE void track_resolve_link(drcbe_state *drcbe, x86code **destptr, const emit_link *linkinfo)
+{
+ reset_last_upper_lower_reg(drcbe);
+ resolve_link(destptr, linkinfo);
+}
+
+#define resolve_link INVALID
+
+
/***************************************************************************
BACKEND CALLBACKS
@@ -1143,7 +1226,10 @@ static void emit_mov_r32_p32_keepflags(drcbe_state *drcbe, x86code **dst, UINT8
if (param->type == DRCUML_PTYPE_IMMEDIATE)
emit_mov_r32_imm(dst, reg, param->value); // mov reg,param
else if (param->type == DRCUML_PTYPE_MEMORY)
- emit_mov_r32_m32(dst, reg, MABS(param->value)); // mov reg,[param]
+ {
+ if (!can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), reg))
+ emit_mov_r32_m32(dst, reg, MABS(param->value)); // mov reg,[param]
+ }
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
{
if (reg != param->value)
@@ -1163,7 +1249,8 @@ static void emit_mov_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAM
emit_mov_m32_imm(dst, MEMPARAMS, param->value); // mov [mem],param
else if (param->type == DRCUML_PTYPE_MEMORY)
{
- emit_mov_r32_m32(dst, REG_EAX, MABS(param->value)); // mov eax,[param]
+ if (!can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), REG_EAX))
+ emit_mov_r32_m32(dst, REG_EAX, MABS(param->value)); // mov eax,[param]
emit_mov_m32_r32(dst, MEMPARAMS, REG_EAX); // mov [mem],eax
}
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
@@ -1180,7 +1267,10 @@ static void emit_mov_p32_r32(drcbe_state *drcbe, x86code **dst, const drcuml_par
{
assert(param->type != DRCUML_PTYPE_IMMEDIATE);
if (param->type == DRCUML_PTYPE_MEMORY)
+ {
emit_mov_m32_r32(dst, MABS(param->value), reg); // mov [param],reg
+ set_last_lower_reg(drcbe, *dst, param, reg);
+ }
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
{
if (reg != param->value)
@@ -1872,25 +1962,35 @@ static void emit_mov_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
{
if (param->type == DRCUML_PTYPE_IMMEDIATE)
{
- if ((UINT32)param->value == 0)
+ if (reglo == REG_NONE)
+ ;
+ else if ((UINT32)param->value == 0)
emit_xor_r32_r32(dst, reglo, reglo); // xor reglo,reglo
else
emit_mov_r32_imm(dst, reglo, param->value); // mov reglo,param
- if ((UINT32)(param->value >> 32) == 0)
+ if (reghi == REG_NONE)
+ ;
+ else if ((UINT32)(param->value >> 32) == 0)
emit_xor_r32_r32(dst, reghi, reghi); // xor reghi,reghi
else
emit_mov_r32_imm(dst, reghi, param->value >> 32); // mov reghi,param >> 32
}
else if (param->type == DRCUML_PTYPE_MEMORY)
{
- emit_mov_r32_m32(dst, reglo, MABS(param->value)); // mov reglo,[param]
- emit_mov_r32_m32(dst, reghi, MABS(param->value + 4)); // mov reghi,[param+4]
+ int skip_lower = can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), reglo);
+ int skip_upper = can_skip_upper_load(drcbe, *dst, (UINT32 *)((FPTR)param->value + 4), reghi);
+ if (reglo != REG_NONE && !skip_lower)
+ emit_mov_r32_m32(dst, reglo, MABS(param->value)); // mov reglo,[param]
+ if (reghi != REG_NONE && !skip_upper)
+ emit_mov_r32_m32(dst, reghi, MABS(param->value + 4)); // mov reghi,[param+4]
}
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
{
- if (reglo != param->value)
+ int skip_upper = can_skip_upper_load(drcbe, *dst, drcbe->reghi[param->value], reghi);
+ if (reglo != REG_NONE && reglo != param->value)
emit_mov_r32_r32(dst, reglo, param->value); // mov reglo,param
- emit_mov_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // mov reghi,reghi[param]
+ if (reghi != REG_NONE && !skip_upper)
+ emit_mov_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // mov reghi,reghi[param]
}
}
@@ -1905,19 +2005,27 @@ static void emit_mov_r64_p64_keepflags(drcbe_state *drcbe, x86code **dst, UINT8
{
if (param->type == DRCUML_PTYPE_IMMEDIATE)
{
- emit_mov_r32_imm(dst, reglo, param->value); // mov reglo,param
- emit_mov_r32_imm(dst, reghi, param->value >> 32); // mov reghi,param >> 32
+ if (reglo != REG_NONE)
+ emit_mov_r32_imm(dst, reglo, param->value); // mov reglo,param
+ if (reghi != REG_NONE)
+ emit_mov_r32_imm(dst, reghi, param->value >> 32); // mov reghi,param >> 32
}
else if (param->type == DRCUML_PTYPE_MEMORY)
{
- emit_mov_r32_m32(dst, reglo, MABS(param->value)); // mov reglo,[param]
- emit_mov_r32_m32(dst, reghi, MABS(param->value + 4)); // mov reghi,[param+4]
+ int skip_lower = can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), reglo);
+ int skip_upper = can_skip_upper_load(drcbe, *dst, (UINT32 *)((FPTR)param->value + 4), reghi);
+ if (reglo != REG_NONE && !skip_lower)
+ emit_mov_r32_m32(dst, reglo, MABS(param->value)); // mov reglo,[param]
+ if (reghi != REG_NONE && !skip_upper)
+ emit_mov_r32_m32(dst, reghi, MABS(param->value + 4)); // mov reghi,[param+4]
}
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
{
- if (reglo != param->value)
+ int skip_upper = can_skip_upper_load(drcbe, *dst, drcbe->reghi[param->value], reghi);
+ if (reglo != REG_NONE && reglo != param->value)
emit_mov_r32_r32(dst, reglo, param->value); // mov reglo,param
- emit_mov_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // mov reghi,reghi[param]
+ if (reghi != REG_NONE && !skip_upper)
+ emit_mov_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // mov reghi,reghi[param]
}
}
@@ -1936,7 +2044,9 @@ static void emit_mov_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAM
}
else if (param->type == DRCUML_PTYPE_MEMORY)
{
- emit_mov_r32_m32(dst, REG_EAX, MABS(param->value)); // mov eax,[param]
+ int skip_lower = can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), REG_EAX);
+ if (!skip_lower)
+ emit_mov_r32_m32(dst, REG_EAX, MABS(param->value)); // mov eax,[param]
emit_mov_m32_r32(dst, MEMPARAMS + 0, REG_EAX); // mov [mem],eax
emit_mov_r32_m32(dst, REG_EAX, MABS(param->value + 4)); // mov eax,[param+4]
emit_mov_m32_r32(dst, MEMPARAMS + 4, REG_EAX); // mov [mem+4],eax
@@ -1969,6 +2079,8 @@ static void emit_mov_p64_r64(drcbe_state *drcbe, x86code **dst, const drcuml_par
emit_mov_r32_r32(dst, param->value, reglo); // mov param,reglo
emit_mov_m32_r32(dst, MABS(drcbe->reghi[param->value]), reghi); // mov reghi[param],reghi
}
+ set_last_lower_reg(drcbe, *dst, param, reglo);
+ set_last_upper_reg(drcbe, *dst, param, reghi);
}
@@ -2583,14 +2695,14 @@ static void emit_shl_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
emit_shld_r32_r32_imm(dst, reghi, reglo, 31); // shld reghi,reglo,31
emit_shl_r32_imm(dst, reglo, 31); // shl reglo,31
- resolve_link(dst, &skip2); // skip2:
+ track_resolve_link(drcbe, dst, &skip2); // skip2:
}
else
{
emit_mov_r32_r32(dst, reghi, reglo); // mov reghi,reglo
emit_xor_r32_r32(dst, reglo, reglo); // xor reglo,reglo
}
- resolve_link(dst, &skip1); // skip1:
+ track_resolve_link(drcbe, dst, &skip1); // skip1:
emit_shld_r32_r32_cl(dst, reghi, reglo); // shld reghi,reglo,cl
if (saveflags) emit_pushf(dst); // pushf
emit_shl_r32_cl(dst, reglo); // shl reglo,cl
@@ -2654,14 +2766,14 @@ static void emit_shr_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
emit_shr_r32_imm(dst, reghi, 31); // shr reghi,31
- resolve_link(dst, &skip2); // skip2:
+ track_resolve_link(drcbe, dst, &skip2); // skip2:
}
else
{
emit_mov_r32_r32(dst, reglo, reghi); // mov reglo,reghi
emit_xor_r32_r32(dst, reghi, reghi); // xor reghi,reghi
}
- resolve_link(dst, &skip1); // skip1:
+ track_resolve_link(drcbe, dst, &skip1); // skip1:
emit_shrd_r32_r32_cl(dst, reglo, reghi); // shrd reglo,reghi,cl
if (saveflags) emit_pushf(dst); // pushf
emit_shr_r32_cl(dst, reghi); // shr reghi,cl
@@ -2725,14 +2837,14 @@ static void emit_sar_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
emit_sar_r32_imm(dst, reghi, 31); // sar reghi,31
- resolve_link(dst, &skip2); // skip2:
+ track_resolve_link(drcbe, dst, &skip2); // skip2:
}
else
{
emit_mov_r32_r32(dst, reglo, reghi); // mov reglo,reghi
emit_sar_r32_imm(dst, reghi, 31); // sar reghi,31
}
- resolve_link(dst, &skip1); // skip1:
+ track_resolve_link(drcbe, dst, &skip1); // skip1:
emit_shrd_r32_r32_cl(dst, reglo, reghi); // shrd reglo,reghi,cl
if (saveflags) emit_pushf(dst); // pushf
emit_sar_r32_cl(dst, reghi); // sar reghi,cl
@@ -2800,11 +2912,11 @@ static void emit_rol_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
emit_mov_r32_r32(dst, REG_EBX, reglo); // mov ebx,reglo
emit_shld_r32_r32_imm(dst, reglo, reghi, 31); // shld reglo,reghi,31
emit_shld_r32_r32_imm(dst, reghi, REG_EBX, 31); // shld reghi,ebx,31
- resolve_link(dst, &skip2); // skip2:
+ track_resolve_link(drcbe, dst, &skip2); // skip2:
}
else
emit_xchg_r32_r32(dst, reghi, reglo); // xchg reghi,reglo
- resolve_link(dst, &skip1); // skip1:
+ track_resolve_link(drcbe, dst, &skip1); // skip1:
emit_mov_r32_r32(dst, REG_EBX, reglo); // mov ebx,reglo
emit_shld_r32_r32_cl(dst, reglo, reghi); // shld reglo,reghi,cl
if (saveflags) emit_pushf(dst); // pushf
@@ -2874,11 +2986,11 @@ static void emit_ror_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
emit_mov_r32_r32(dst, REG_EBX, reglo); // mov ebx,reglo
emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
emit_shrd_r32_r32_imm(dst, reghi, REG_EBX, 31); // shrd reghi,ebx,31
- resolve_link(dst, &skip2); // skip2:
+ track_resolve_link(drcbe, dst, &skip2); // skip2:
}
else
emit_xchg_r32_r32(dst, reghi, reglo); // xchg reghi,reglo
- resolve_link(dst, &skip1); // skip1:
+ track_resolve_link(drcbe, dst, &skip1); // skip1:
emit_mov_r32_r32(dst, REG_EBX, reglo); // mov ebx,reglo
emit_shrd_r32_r32_cl(dst, reglo, reghi); // shrd reglo,reghi,cl
if (saveflags) emit_pushf(dst); // pushf
@@ -2910,7 +3022,7 @@ static void emit_rcl_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
emit_rcl_r32_imm(dst, reglo, 1); // rcl reglo,1
emit_rcl_r32_imm(dst, reghi, 1); // rcl reghi,1
emit_jmp(dst, loop); // jmp loop
- resolve_link(dst, &skipall); // skipall:
+ track_resolve_link(drcbe, dst, &skipall); // skipall:
}
else
{
@@ -2922,11 +3034,11 @@ static void emit_rcl_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
emit_rcl_r32_imm(dst, reglo, 1); // rcl reglo,1
emit_rcl_r32_imm(dst, reghi, 1); // rcl reghi,1
emit_jmp(dst, loop); // jmp loop
- resolve_link(dst, &skiploop); // skiploop:
+ track_resolve_link(drcbe, dst, &skiploop); // skiploop:
emit_rcl_r32_imm(dst, reglo, 1); // rcl reglo,1
emit_pushf(dst); // pushf
emit_rcl_r32_imm(dst, reghi, 1); // rcl reghi,1
- resolve_link(dst, &skipall); // skipall:
+ track_resolve_link(drcbe, dst, &skipall); // skipall:
emit_combine_z_flags(dst);
}
}
@@ -2952,7 +3064,7 @@ static void emit_rcr_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
emit_rcr_r32_imm(dst, reghi, 1); // rcr reghi,1
emit_rcr_r32_imm(dst, reglo, 1); // rcr reglo,1
emit_jmp(dst, loop); // jmp loop
- resolve_link(dst, &skipall); // skipall:
+ track_resolve_link(drcbe, dst, &skipall); // skipall:
}
else
{
@@ -2964,11 +3076,11 @@ static void emit_rcr_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UIN
emit_rcr_r32_imm(dst, reghi, 1); // rcr reghi,1
emit_rcr_r32_imm(dst, reglo, 1); // rcr reglo,1
emit_jmp(dst, loop); // jmp loop
- resolve_link(dst, &skiploop); // skiploop:
+ track_resolve_link(drcbe, dst, &skiploop); // skiploop:
emit_rcr_r32_imm(dst, reghi, 1); // rcr reghi,1
emit_pushf(dst); // pushf
emit_rcr_r32_imm(dst, reglo, 1); // rcr reglo,1
- resolve_link(dst, &skipall); // skipall:
+ track_resolve_link(drcbe, dst, &skipall); // skipall:
emit_combine_z_shl_flags(dst);
}
}
@@ -3117,6 +3229,8 @@ static x86code *op_handle(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->numparams == 1);
assert(inst->param[0].type == DRCUML_PTYPE_MEMORY);
+ reset_last_upper_lower_reg(drcbe);
+
/* emit a jump around the stack adjust in case code falls through here */
emit_jmp_short_link(&dst, &skip); // jmp skip
@@ -3125,7 +3239,7 @@ static x86code *op_handle(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/* by default, the handle points to prolog code that moves the stack pointer */
emit_lea_r32_m32(&dst, REG_ESP, MBD(REG_ESP, -28)); // lea rsp,[rsp-28]
- resolve_link(&dst, &skip); // skip:
+ track_resolve_link(drcbe, &dst, &skip); // skip:
return dst;
}
@@ -3144,6 +3258,7 @@ static x86code *op_hash(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
/* register the current pointer for the mode/PC */
drchash_set_codeptr(drcbe->hash, inst->param[0].value, inst->param[1].value, dst);
+ reset_last_upper_lower_reg(drcbe);
return dst;
}
@@ -3161,6 +3276,7 @@ static x86code *op_label(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
/* register the current pointer for the label */
drclabel_set_codeptr(drcbe->labels, inst->param[0].value, dst);
+ reset_last_upper_lower_reg(drcbe);
return dst;
}
@@ -3244,7 +3360,7 @@ static x86code *op_debug(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (FPTR)drcbe->device); // mov [esp],device
emit_call(&dst, (x86code *)debug_cpu_instruction_hook); // call debug_cpu_instruction_hook
- resolve_link(&dst, &skip); // skip:
+ track_resolve_link(drcbe, &dst, &skip); // skip:
}
return dst;
@@ -3465,7 +3581,7 @@ static x86code *op_callh(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
/* resolve the conditional link */
if (inst->condition != DRCUML_COND_ALWAYS)
- resolve_link(&dst, &skip); // skip:
+ track_resolve_link(drcbe, &dst, &skip); // skip:
return dst;
}
@@ -3494,7 +3610,7 @@ static x86code *op_ret(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
/* resolve the conditional link */
if (inst->condition != DRCUML_COND_ALWAYS)
- resolve_link(&dst, &skip); // skip:
+ track_resolve_link(drcbe, &dst, &skip); // skip:
return dst;
}
@@ -3526,7 +3642,7 @@ static x86code *op_callc(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
/* resolve the conditional link */
if (inst->condition != DRCUML_COND_ALWAYS)
- resolve_link(&dst, &skip); // skip:
+ track_resolve_link(drcbe, &dst, &skip); // skip:
return dst;
}
@@ -3928,8 +4044,10 @@ static x86code *op_load(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
+ set_last_upper_reg(drcbe, dst, &dstp, REG_EDX);
}
}
+ set_last_lower_reg(drcbe, dst, &dstp, dstreg);
return dst;
}
@@ -4001,7 +4119,9 @@ static x86code *op_loads(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
+ set_last_upper_reg(drcbe, dst, &dstp, REG_EDX);
}
+ set_last_lower_reg(drcbe, dst, &dstp, dstreg);
return dst;
}
@@ -4566,7 +4686,7 @@ static x86code *op_mov(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
/* resolve the jump */
if (skip.target != NULL)
- resolve_link(&dst, &skip);
+ track_resolve_link(drcbe, &dst, &skip);
return dst;
}
@@ -5333,7 +5453,7 @@ static x86code *op_divu(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
if (inst->flags != 0)
emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
- resolve_link(&dst, &skip); // skip:
+ track_resolve_link(drcbe, &dst, &skip); // skip:
}
/* 64-bit form */
@@ -5404,7 +5524,7 @@ static x86code *op_divs(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
if (inst->flags != 0)
emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
- resolve_link(&dst, &skip); // skip:
+ track_resolve_link(drcbe, &dst, &skip); // skip:
}
/* 64-bit form */
@@ -5464,6 +5584,26 @@ static x86code *op_and(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
emit_and_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // and [dstp],src2p
+ /* AND with immediate 0xff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xff && inst->flags == 0)
+ {
+ if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_movzx_r32_r8(&dst, dstreg, src1p.value); // movzx dstreg,src1p
+ else if (src1p.type == DRCUML_PTYPE_MEMORY)
+ emit_movzx_r32_m8(&dst, dstreg, MABS(src1p.value)); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ }
+
+ /* AND with immediate 0xffff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffff && inst->flags == 0)
+ {
+ if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_movzx_r32_r16(&dst, dstreg, src1p.value); // movzx dstreg,src1p
+ else if (src1p.type == DRCUML_PTYPE_MEMORY)
+ emit_movzx_r32_m16(&dst, dstreg, MABS(src1p.value)); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ }
+
/* general case */
else
{
@@ -5480,6 +5620,71 @@ static x86code *op_and(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
emit_and_m64_p64(drcbe, &dst, MABS(dstp.value), &src2p, inst); // and [dstp],src2p
+ /* AND with immediate 0xff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xff && inst->flags == 0)
+ {
+ if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_movzx_r32_r8(&dst, dstreg, src1p.value); // movzx dstreg,src1p
+ else if (src1p.type == DRCUML_PTYPE_MEMORY)
+ emit_movzx_r32_m8(&dst, dstreg, MABS(src1p.value)); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov dsthi,0
+ else if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov dsthi,0
+ }
+
+ /* AND with immediate 0xffff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffff && inst->flags == 0)
+ {
+ if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_movzx_r32_r16(&dst, dstreg, src1p.value); // movzx dstreg,src1p
+ else if (src1p.type == DRCUML_PTYPE_MEMORY)
+ emit_movzx_r32_m16(&dst, dstreg, MABS(src1p.value)); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov dsthi,0
+ else if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov dsthi,0
+ }
+
+ /* AND with immediate 0xffffffff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffffffff && inst->flags == 0)
+ {
+ emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov dsthi,0
+ else if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov dsthi,0
+ }
+
+ /* AND with immediate 0xffffffff00000000 */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == U64(0xffffffff00000000) && inst->flags == 0)
+ {
+ if (src1p.type != dstp.type || src1p.value != dstp.value)
+ {
+ emit_mov_r64_p64(drcbe, &dst, REG_NONE, REG_EDX, &src1p); // mov dstreg,src1p
+ emit_mov_p64_r64(drcbe, &dst, &dstp, REG_NONE, REG_EDX); // mov dstp,dstreg
+ }
+ if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_xor_r32_r32(&dst, dstp.value, dstp.value); // xor dstlo,dstlo
+ else if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value), 0); // mov dstlo,0
+ }
+
+ /* AND with immediate <= 0xffffffff */
+ else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value <= 0xffffffff && inst->flags == 0)
+ {
+ emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
+ emit_and_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // and dstreg,src2p
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov dsthi,0
+ else if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov dsthi,0
+ }
+
/* general case */
else
{
@@ -5698,7 +5903,7 @@ static x86code *op_lzcnt(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
emit_bsr_r32_r32(&dst, dstreg, REG_EDX); // bsr dstreg,edx
emit_cmovcc_r32_r32(&dst, COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
emit_add_r32_imm(&dst, REG_ECX, 32); // add ecx,32
- resolve_link(&dst, &skip); // skip:
+ track_resolve_link(drcbe, &dst, &skip); // skip:
emit_xor_r32_r32(&dst, REG_EDX, REG_EDX); // xor edx,edx
emit_xor_r32_imm(&dst, dstreg, 31); // xor dstreg,31
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
@@ -6283,7 +6488,7 @@ static x86code *op_fmov(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
/* resolve the jump */
if (skip.target != NULL)
- resolve_link(&dst, &skip); // skip:
+ track_resolve_link(drcbe, &dst, &skip); // skip:
return dst;
}
diff --git a/src/emu/cpu/mips/mips3drc.c b/src/emu/cpu/mips/mips3drc.c
index 752246acb13..3ea024143dc 100644
--- a/src/emu/cpu/mips/mips3drc.c
+++ b/src/emu/cpu/mips/mips3drc.c
@@ -1305,20 +1305,17 @@ static void static_generate_memory_accessor(mips3_state *mips3, int mode, int si
}
else if (size == 2)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
- UML_XOR(block, IREG(0), IREG(0), IMM(mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0)));
- // xor i0,i0,bytexor
- UML_LOAD(block, IREG(0), fastbase, IREG(0), WORD); // load i0,fastbase,i0,word
+ UML_XOR(block, IREG(0), IREG(0), IMM(mips3->bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0)));
+ // xor i0,i0,wordxor
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), WORD_x1); // load i0,fastbase,i0,word_x1
}
else if (size == 4)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(2)); // shr i0,i0,2
- UML_LOAD(block, IREG(0), fastbase, IREG(0), DWORD); // load i0,fastbase,i0,dword
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), DWORD_x1); // load i0,fastbase,i0,dword_x1
}
else if (size == 8)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(3)); // shr i0,i0,3
- UML_DLOAD(block, IREG(0), fastbase, IREG(0), QWORD); // dload i0,fastbase,i0,qword
+ UML_DLOAD(block, IREG(0), fastbase, IREG(0), QWORD_x1); // dload i0,fastbase,i0,qword_x1
UML_DROR(block, IREG(0), IREG(0), IMM(32 * (mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0))));
// dror i0,i0,32*bytexor
}
@@ -1334,38 +1331,35 @@ static void static_generate_memory_accessor(mips3_state *mips3, int mode, int si
}
else if (size == 2)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
- UML_XOR(block, IREG(0), IREG(0), IMM(mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0)));
- // xor i0,i0,bytexor
- UML_STORE(block, fastbase, IREG(0), IREG(1), WORD); // store fastbase,i0,i1,word
+ UML_XOR(block, IREG(0), IREG(0), IMM(mips3->bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0)));
+ // xor i0,i0,wordxor
+ UML_STORE(block, fastbase, IREG(0), IREG(1), WORD_x1); // store fastbase,i0,i1,word_x1
}
else if (size == 4)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(2)); // shr i0,i0,2
if (ismasked)
{
- UML_LOAD(block, IREG(3), fastbase, IREG(0), DWORD); // load i3,fastbase,i0,dword
+ UML_LOAD(block, IREG(3), fastbase, IREG(0), DWORD_x1); // load i3,fastbase,i0,dword_x1
UML_ROLINS(block, IREG(3), IREG(1), IMM(0), IREG(2)); // rolins i3,i1,0,i2
- UML_STORE(block, fastbase, IREG(0), IREG(3), DWORD); // store fastbase,i0,i3,dword
+ UML_STORE(block, fastbase, IREG(0), IREG(3), DWORD_x1); // store fastbase,i0,i3,dword_x1
}
else
- UML_STORE(block, fastbase, IREG(0), IREG(1), DWORD); // store fastbase,i0,i1,dword
+ UML_STORE(block, fastbase, IREG(0), IREG(1), DWORD_x1); // store fastbase,i0,i1,dword_x1
}
else if (size == 8)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(3)); // shr i0,i0,3
UML_DROR(block, IREG(1), IREG(1), IMM(32 * (mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0))));
// dror i1,i1,32*bytexor
if (ismasked)
{
UML_DROR(block, IREG(2), IREG(2), IMM(32 * (mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0))));
// dror i2,i2,32*bytexor
- UML_DLOAD(block, IREG(3), fastbase, IREG(0), QWORD); // dload i3,fastbase,i0,qword
+ UML_DLOAD(block, IREG(3), fastbase, IREG(0), QWORD_x1); // dload i3,fastbase,i0,qword_x1
UML_DROLINS(block, IREG(3), IREG(1), IMM(0), IREG(2)); // drolins i3,i1,0,i2
- UML_DSTORE(block, fastbase, IREG(0), IREG(3), QWORD); // dstore fastbase,i0,i3,qword
+ UML_DSTORE(block, fastbase, IREG(0), IREG(3), QWORD_x1); // dstore fastbase,i0,i3,qword_x1
}
else
- UML_DSTORE(block, fastbase, IREG(0), IREG(1), QWORD); // dstore fastbase,i0,i1,qword
+ UML_DSTORE(block, fastbase, IREG(0), IREG(1), QWORD_x1); // dstore fastbase,i0,i1,qword_x1
}
UML_RET(block); // ret
}
diff --git a/src/emu/cpu/powerpc/ppcdrc.c b/src/emu/cpu/powerpc/ppcdrc.c
index 88d176c8d5b..9432957639f 100644
--- a/src/emu/cpu/powerpc/ppcdrc.c
+++ b/src/emu/cpu/powerpc/ppcdrc.c
@@ -1572,25 +1572,22 @@ static void static_generate_memory_accessor(powerpc_state *ppc, int mode, int si
{
if (size == 1)
{
- UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 0)); // xor i0,i0,fastxor >> 0
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor & 7)); // xor i0,i0,fastxor & 7
UML_LOAD(block, IREG(0), fastbase, IREG(0), BYTE); // load i0,fastbase,i0,byte
}
else if (size == 2)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
- UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 1)); // xor i0,i0,fastxor >> 1
- UML_LOAD(block, IREG(0), fastbase, IREG(0), WORD); // load i0,fastbase,i0,word
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor & 6)); // xor i0,i0,fastxor & 6
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), WORD_x1); // load i0,fastbase,i0,word_x1
}
else if (size == 4)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(2)); // shr i0,i0,2
- UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 2)); // xor i0,i0,fastxor >> 2
- UML_LOAD(block, IREG(0), fastbase, IREG(0), DWORD); // load i0,fastbase,i0,dword
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor & 4)); // xor i0,i0,fastxor & 4
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), DWORD_x1); // load i0,fastbase,i0,dword_x1
}
else if (size == 8)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(3)); // shr i0,i0,3
- UML_DLOAD(block, IREG(0), fastbase, IREG(0), QWORD); // dload i0,fastbase,i0,qword
+ UML_DLOAD(block, IREG(0), fastbase, IREG(0), QWORD_x1); // dload i0,fastbase,i0,qword
}
UML_RET(block); // ret
}
@@ -1598,41 +1595,38 @@ static void static_generate_memory_accessor(powerpc_state *ppc, int mode, int si
{
if (size == 1)
{
- UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 0)); // xor i0,i0,fastxor >> 0
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor & 7)); // xor i0,i0,fastxor & 7
UML_STORE(block, fastbase, IREG(0), IREG(1), BYTE); // store fastbase,i0,i1,byte
}
else if (size == 2)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
- UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 1)); // xor i0,i0,fastxor >> 1
- UML_STORE(block, fastbase, IREG(0), IREG(1), WORD); // store fastbase,i0,i1,word
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor & 6)); // xor i0,i0,fastxor & 6
+ UML_STORE(block, fastbase, IREG(0), IREG(1), WORD_x1); // store fastbase,i0,i1,word_x1
}
else if (size == 4)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(2)); // shr i0,i0,2
- UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 2)); // xor i0,i0,fastxor >> 2
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor & 4)); // xor i0,i0,fastxor & 4
if (ismasked)
{
- UML_LOAD(block, IREG(3), fastbase, IREG(0), DWORD); // load i3,fastbase,i0,dword
+ UML_LOAD(block, IREG(3), fastbase, IREG(0), DWORD_x1); // load i3,fastbase,i0,dword_x1
UML_AND(block, IREG(1), IREG(1), IREG(2)); // and i1,i1,i2
UML_XOR(block, IREG(2), IREG(2), IMM(0xffffffff)); // xor i2,i2,0xfffffffff
UML_AND(block, IREG(3), IREG(3), IREG(2)); // and i3,i3,i2
UML_OR(block, IREG(1), IREG(1), IREG(3)); // or i1,i1,i3
}
- UML_STORE(block, fastbase, IREG(0), IREG(1), DWORD); // store fastbase,i0,i1,dword
+ UML_STORE(block, fastbase, IREG(0), IREG(1), DWORD_x1); // store fastbase,i0,i1,dword_x1
}
else if (size == 8)
{
- UML_SHR(block, IREG(0), IREG(0), IMM(3)); // shr i0,i0,3
if (ismasked)
{
- UML_DLOAD(block, IREG(3), fastbase, IREG(0), QWORD); // dload i3,fastbase,i0,qword
+ UML_DLOAD(block, IREG(3), fastbase, IREG(0), QWORD_x1); // dload i3,fastbase,i0,qword_x1
UML_DAND(block, IREG(1), IREG(1), IREG(2)); // dand i1,i1,i2
UML_DXOR(block, IREG(2), IREG(2), IMM(U64(0xffffffffffffffff))); // dxor i2,i2,0xfffffffffffffffff
UML_DAND(block, IREG(3), IREG(3), IREG(2)); // dand i3,i3,i2
UML_DOR(block, IREG(1), IREG(1), IREG(3)); // dor i1,i1,i3
}
- UML_DSTORE(block, fastbase, IREG(0), IREG(1), QWORD); // dstore fastbase,i0,i1,qword
+ UML_DSTORE(block, fastbase, IREG(0), IREG(1), QWORD_x1); // dstore fastbase,i0,i1,qword_x1
}
UML_RET(block); // ret
}
diff --git a/src/emu/cpu/rsp/rspdrc.c b/src/emu/cpu/rsp/rspdrc.c
index ffd11b1b0e7..5a65a76c2fa 100644
--- a/src/emu/cpu/rsp/rspdrc.c
+++ b/src/emu/cpu/rsp/rspdrc.c
@@ -418,12 +418,14 @@ void rspdrc_add_dmem(const device_config *device, void *base)
debugging
-------------------------------------------------*/
+#ifndef LSB_FIRST
static void cfunc_printf_debug(void *param)
{
rsp_state *rsp = (rsp_state *)param;
printf(rsp->impstate->format, rsp->impstate->arg0, rsp->impstate->arg1);
logerror(rsp->impstate->format, rsp->impstate->arg0, rsp->impstate->arg1);
}
+#endif
static void cfunc_get_cop0_reg(void *param)
@@ -3726,10 +3728,12 @@ static void cfunc_unimplemented(void *param)
cfunc_fatalerror - a generic fatalerror call
-------------------------------------------------*/
+#ifndef LSB_FIRST
static void cfunc_fatalerror(void *param)
{
//fatalerror("fatalerror");
}
+#endif
/***************************************************************************
@@ -3845,12 +3849,7 @@ static void static_generate_memory_accessor(rsp_state *rsp, int size, int iswrit
drcuml_state *drcuml = rsp->impstate->drcuml;
drcuml_block *block;
jmp_buf errorbuf;
- int label = 1;
- UINT32 unaligned_w2 = label++;
- UINT32 aligned_w2 = label++;
- UINT32 unaligned_w4 = label++;
- UINT32 unaligned_r2 = label++;
- UINT32 unaligned_r4 = label++;
+ int unaligned_case = 1;
/* if we get an error back, we're screwed */
if (setjmp(errorbuf) != 0)
@@ -3865,132 +3864,109 @@ static void static_generate_memory_accessor(rsp_state *rsp, int size, int iswrit
alloc_handle(drcuml, handleptr, name);
UML_HANDLE(block, *handleptr); // handle *handleptr
- UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff));
// write:
if (iswrite)
{
if (size == 1)
{
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor
- UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), BYTE); // store dmem,i0,i1,byte
+#ifdef LSB_FIRST
+ UML_XOR(block, IREG(0), IREG(0), IMM(3)); // xor i0,i0,3
+#endif
+ UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0xfff
+ UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), BYTE); // store dmem,i0,i1,byte
}
else if (size == 2)
{
- static const char text[] = "%08x: Unaligned word write to %08x\n";
+#ifdef LSB_FIRST
UML_TEST(block, IREG(0), IMM(1)); // test i0,1
- UML_JMPc(block, IF_NZ, unaligned_w2); // jnz <unaligned_w2>
- UML_JMP(block, aligned_w2); // jmp <aligned_w2>
-
- UML_LABEL(block, unaligned_w2); // <unaligned_w2>:
- UML_MOV(block, MEM(&rsp->impstate->format), IMM((FPTR)text)); // mov [format],text
- UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(rsp->pc)); // mov [arg0],rsp->pc
- UML_MOV(block, MEM(&rsp->impstate->arg1), IREG(0)); // mov [arg1],i0
- UML_CALLC(block, cfunc_printf_debug, rsp); // callc printf_debug
- UML_CALLC(block, cfunc_fatalerror, rsp);
-
- UML_LABEL(block, aligned_w2); // <aligned_w2>:
- UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE_XOR_BE(0))); // xor i0,i0,bytexor
- UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), WORD); // store dmem,i0,i1,word
+ UML_JMPc(block, IF_NZ, unaligned_case); // jnz <unaligned_case>
+ UML_XOR(block, IREG(0), IREG(0), IMM(2)); // xor i0,i0,2
+#endif
+ UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0xfff
+ UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), WORD_x1); // store dmem,i0,i1,word_x1
+ UML_RET(block);
+#ifdef LSB_FIRST
+ UML_LABEL(block, unaligned_case); // unaligned_case:
+ UML_ROLAND(block, IREG(2), IREG(0), IMM(3), IMM(0x18)); // roland i2,i0,3,0x18
+ UML_AND(block, IREG(0), IREG(0), IMM(0xffc)); // and i0,i0,0xffc
+ UML_DLOAD(block, IREG(3), rsp->impstate->dmem, IREG(0), QWORD_x1); // dload i3,dmem,i0,qword_x1
+ UML_DROL(block, IREG(3), IREG(3), IREG(2)); // drol i3,i3,i2
+ UML_DAND(block, IREG(1), IREG(1), IMM(0xffff)); // dand i1,i1,0xffff
+ UML_DAND(block, IREG(3), IREG(3), IMM(U64(0xffffffffffff0000))); // dand i3,i3,~0xffff
+ UML_DOR(block, IREG(1), IREG(1), IREG(3)); // dor i1,i1,i3
+ UML_DROR(block, IREG(1), IREG(1), IREG(2)); // dror i1,i1,i2
+ UML_DSTORE(block, rsp->impstate->dmem, IREG(0), IREG(1), QWORD_x1); // dstore dmem,i0,i1,qword_x1
+#endif
}
else if (size == 4)
{
+#ifdef LSB_FIRST
UML_TEST(block, IREG(0), IMM(3)); // test i0,3
- UML_JMPc(block, IF_NZ, unaligned_w4); // jnz <unaligned_w4>
-
+ UML_JMPc(block, IF_NZ, unaligned_case); // jnz <unaligned_case>
+#endif
+ UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0xfff
UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), DWORD_x1); // store dmem,i0,i1,dword_x1
UML_RET(block);
-
- UML_LABEL(block, unaligned_w4);
- UML_ADD(block, IREG(0), IREG(0), IMM(3));
-
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), BYTE);
-
- UML_SHR(block, IREG(1), IREG(1), IMM(8));
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_SUB(block, IREG(0), IREG(0), IMM(1));
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), BYTE);
-
- UML_SHR(block, IREG(1), IREG(1), IMM(8));
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_SUB(block, IREG(0), IREG(0), IMM(1));
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), BYTE);
-
- UML_SHR(block, IREG(1), IREG(1), IMM(8));
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_SUB(block, IREG(0), IREG(0), IMM(1));
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), BYTE);
+#ifdef LSB_FIRST
+ UML_LABEL(block, unaligned_case); // unaligned_case:
+ UML_ROLAND(block, IREG(2), IREG(0), IMM(3), IMM(0x18)); // roland i2,i0,3,0x18
+ UML_AND(block, IREG(0), IREG(0), IMM(0xffc)); // and i0,i0,0xffc
+ UML_DLOAD(block, IREG(3), rsp->impstate->dmem, IREG(0), QWORD_x1); // dload i3,dmem,i0,qword_x1
+ UML_DROL(block, IREG(3), IREG(3), IREG(2)); // drol i3,i3,i2
+ UML_DAND(block, IREG(1), IREG(1), IMM(0xffffffff)); // dand i1,i1,0xffffffff
+ UML_DAND(block, IREG(3), IREG(3), IMM(U64(0xffffffff00000000))); // dand i3,i3,~0xffffffff
+ UML_DOR(block, IREG(1), IREG(1), IREG(3)); // dor i1,i1,i3
+ UML_DROR(block, IREG(1), IREG(1), IREG(2)); // dror i1,i1,i2
+ UML_DSTORE(block, rsp->impstate->dmem, IREG(0), IREG(1), QWORD_x1); // dstore dmem,i0,i1,qword_x1
+#endif
}
}
else
{
if (size == 1)
{
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor
+#ifdef LSB_FIRST
+ UML_XOR(block, IREG(0), IREG(0), IMM(3)); // xor i0,i0,3
+#endif
+ UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0xfff
UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte
}
else if (size == 2)
{
- UML_TEST(block, IREG(0), IMM(1)); // test i0,3
- UML_JMPc(block, IF_NZ, unaligned_r2); // jnz <unaligned_r2>
-
- UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE_XOR_BE(0))); // xor i0,i0,bytexor
- UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), WORD); // load i0,dmem,i0,word
+#ifdef LSB_FIRST
+ UML_TEST(block, IREG(0), IMM(1)); // test i0,1
+ UML_JMPc(block, IF_NZ, unaligned_case); // jnz <unaligned_case>
+ UML_XOR(block, IREG(0), IREG(0), IMM(2)); // xor i0,i0,2
+#endif
+ UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0xfff
+ UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), WORD_x1); // load i0,dmem,i0,word_x1
UML_RET(block);
-
- UML_LABEL(block, unaligned_r2);
- UML_MOV(block, IREG(2), IMM(0));
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
-
- UML_LOAD(block, IREG(3), rsp->impstate->dmem, IREG(0), BYTE);
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_ADD(block, IREG(0), IREG(0), IMM(1));
- UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_OR(block, IREG(2), IREG(2), IREG(3));
-
- UML_LOAD(block, IREG(3), rsp->impstate->dmem, IREG(0), BYTE);
- UML_ADD(block, IREG(0), IREG(0), IMM(1));
- UML_SHL(block, IREG(2), IREG(2), IMM(8));
- UML_OR(block, IREG(2), IREG(2), IREG(3));
-
- UML_MOV(block, IREG(0), IREG(2));
+#ifdef LSB_FIRST
+ UML_LABEL(block, unaligned_case); // unaligned_case:
+ UML_ROLAND(block, IREG(1), IREG(0), IMM(3), IMM(0x18)); // roland i1,i0,3,0x18
+ UML_AND(block, IREG(0), IREG(0), IMM(0xffc)); // and i0,i0,0xffc
+ UML_DLOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), QWORD_x1); // dload i0,dmem,i0,qword_x1
+ UML_DROL(block, IREG(0), IREG(0), IREG(1)); // drol i0,i0,i1
+ UML_AND(block, IREG(0), IREG(0), IMM(0xffff)); // and i0,i0,0xffff
+#endif
}
else if (size == 4)
{
+#ifdef LSB_FIRST
UML_TEST(block, IREG(0), IMM(3)); // test i0,3
- UML_JMPc(block, IF_NZ, unaligned_r4); // jnz <unaligned_r4>
-
- UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), DWORD_x1); // load i0,dmem,i0,dword
+ UML_JMPc(block, IF_NZ, unaligned_case); // jnz <unaligned_case>
+#endif
+ UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0xfff
+ UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), DWORD_x1); // load i0,dmem,i0,dword_x1
UML_RET(block);
-
- UML_LABEL(block, unaligned_r4);
-
- UML_XOR(block, IREG(1), IREG(0), IMM(BYTE4_XOR_BE(0)));
- UML_LOAD(block, IREG(3), rsp->impstate->dmem, IREG(1), BYTE);
- UML_SHL(block, IREG(2), IREG(3), IMM(24));
-
- UML_ADD(block, IREG(1), IREG(0), IMM(1));
- UML_XOR(block, IREG(1), IREG(1), IMM(BYTE4_XOR_BE(0)));
- UML_LOAD(block, IREG(3), rsp->impstate->dmem, IREG(1), BYTE);
- UML_SHL(block, IREG(3), IREG(3), IMM(16));
- UML_OR(block, IREG(2), IREG(2), IREG(3));
-
- UML_ADD(block, IREG(1), IREG(0), IMM(2));
- UML_XOR(block, IREG(1), IREG(1), IMM(BYTE4_XOR_BE(0)));
- UML_LOAD(block, IREG(3), rsp->impstate->dmem, IREG(1), BYTE);
- UML_SHL(block, IREG(3), IREG(3), IMM(8));
- UML_OR(block, IREG(2), IREG(2), IREG(3));
-
- UML_ADD(block, IREG(1), IREG(0), IMM(3));
- UML_XOR(block, IREG(1), IREG(1), IMM(BYTE4_XOR_BE(0)));
- UML_LOAD(block, IREG(3), rsp->impstate->dmem, IREG(1), BYTE);
- UML_OR(block, IREG(0), IREG(2), IREG(3));
+#ifdef LSB_FIRST
+ UML_LABEL(block, unaligned_case); // unaligned_case:
+ UML_ROLAND(block, IREG(1), IREG(0), IMM(3), IMM(0x18)); // roland i1,i0,3,0x18
+ UML_AND(block, IREG(0), IREG(0), IMM(0xffc)); // and i0,i0,0xffc
+ UML_DLOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), QWORD_x1); // dload i0,dmem,i0,qword_x1
+ UML_DROL(block, IREG(0), IREG(0), IREG(1)); // drol i0,i0,i1
+#endif
}
}
UML_RET(block);
@@ -4314,7 +4290,7 @@ static int generate_opcode(rsp_state *rsp, drcuml_block *block, compiler_state *
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL
UML_CALLH(block, rsp->impstate->read32); // callh read32
if (RTREG != 0)
- UML_SEXT(block, R32(RTREG), IREG(0), DWORD); // dsext <rtreg>,i0
+ UML_MOV(block, R32(RTREG), IREG(0)); // mov <rtreg>,i0
if (!in_delay_slot)
generate_update_cycles(rsp, block, compiler, IMM(desc->pc + 4), TRUE);
return TRUE;
diff --git a/src/emu/cpu/x86emit.h b/src/emu/cpu/x86emit.h
index 5d1c1b522c0..10395c52d4a 100644
--- a/src/emu/cpu/x86emit.h
+++ b/src/emu/cpu/x86emit.h
@@ -1900,7 +1900,18 @@ INLINE void emit_movsx_r32_r8(x86code **emitptr, UINT8 dreg, UINT8 sreg) {
INLINE void emit_movsx_r32_m8(x86code **emitptr, UINT8 dreg, DECLARE_MEMPARAMS) { emit_op_modrm_mem(emitptr, OP_MOVSX_Gv_Eb, OP_32BIT, dreg, MEMPARAMS); }
INLINE void emit_movsx_r32_r16(x86code **emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVSX_Gv_Ew, OP_32BIT, dreg, sreg); }
INLINE void emit_movsx_r32_m16(x86code **emitptr, UINT8 dreg, DECLARE_MEMPARAMS) { emit_op_modrm_mem(emitptr, OP_MOVSX_Gv_Ew, OP_32BIT, dreg, MEMPARAMS); }
-INLINE void emit_movzx_r32_r8(x86code **emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVZX_Gv_Eb, OP_32BIT, dreg, sreg); }
+INLINE void emit_movzx_r32_r8(x86code **emitptr, UINT8 dreg, UINT8 sreg)
+{
+#ifndef PTR64
+ if (sreg >= 4)
+ {
+ emit_op_modrm_reg(emitptr, OP_MOV_Gv_Ev, OP_32BIT, dreg, sreg); // mov dreg,sreg
+ emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 4, dreg, 0xff); // and dreg,0xff
+ }
+ else
+#endif
+ emit_op_modrm_reg(emitptr, OP_MOVZX_Gv_Eb, OP_32BIT, dreg, sreg);
+}
INLINE void emit_movzx_r32_m8(x86code **emitptr, UINT8 dreg, DECLARE_MEMPARAMS) { emit_op_modrm_mem(emitptr, OP_MOVZX_Gv_Eb, OP_32BIT, dreg, MEMPARAMS); }
INLINE void emit_movzx_r32_r16(x86code **emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVZX_Gv_Ew, OP_32BIT, dreg, sreg); }
INLINE void emit_movzx_r32_m16(x86code **emitptr, UINT8 dreg, DECLARE_MEMPARAMS) { emit_op_modrm_mem(emitptr, OP_MOVZX_Gv_Ew, OP_32BIT, dreg, MEMPARAMS); }