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
This commit is contained in:
Aaron Giles 2009-12-20 15:21:26 +00:00
parent f0358680a7
commit 30d57e3f48
6 changed files with 417 additions and 187 deletions

View File

@ -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
{

View File

@ -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;
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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;

View File

@ -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); }