diff options
author | 2009-12-20 15:21:26 +0000 | |
---|---|---|
committer | 2009-12-20 15:21:26 +0000 | |
commit | 30d57e3f481ecbc39efcef7b7d7e63503c664e26 (patch) | |
tree | c9a109f1e8ae5e04b465f76a2b780eb41076c42a | |
parent | f0358680a7cdd037b4c6ba80d6bef4fd59808831 (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.c | 54 | ||||
-rw-r--r-- | src/emu/cpu/drcbex86.c | 291 | ||||
-rw-r--r-- | src/emu/cpu/mips/mips3drc.c | 34 | ||||
-rw-r--r-- | src/emu/cpu/powerpc/ppcdrc.c | 34 | ||||
-rw-r--r-- | src/emu/cpu/rsp/rspdrc.c | 178 | ||||
-rw-r--r-- | src/emu/cpu/x86emit.h | 13 |
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); } |