Adding basic constant checks and updates to memory instructions.

Only those instructions likely to have immediate values have been updated.
It'd be nice to go further than this and a) centralize the ea calculations
b) move this all to the analysis pass c) generate mov's in Read/WriteMemory
using the immediates as bases instead of all the register work.

Also fixing a broken stwcx that was causing crashes.
This commit is contained in:
Ben Vanik 2013-05-30 23:20:05 -07:00
parent 78086684c6
commit e7665c11eb
1 changed files with 238 additions and 78 deletions

View File

@ -35,8 +35,14 @@ XEEMITTER(lbz, 0x88000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -54,14 +60,21 @@ XEEMITTER(lbzu, 0x8C000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
GpVar v = e.ReadMemory(i.address, ea, 1, false); GpVar v = e.ReadMemory(i.address, ea, 1, false);
e.update_gpr_value(i.D.RT, v); e.update_gpr_value(i.D.RT, v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RT); e.clear_constant_gpr_value(i.D.RT);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }
@ -115,8 +128,14 @@ XEEMITTER(ld, 0xE8000000, DS )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.DS.RA) { if (i.DS.RA) {
c.mov(ea, e.gpr_value(i.DS.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.DS.DS << 2))); if (e.get_constant_gpr_value(i.DS.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.DS.DS << 2);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
} else {
c.mov(ea, e.gpr_value(i.DS.RA));
c.add(ea, imm(XEEXTS16(i.DS.DS << 2)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.DS.DS << 2))); c.mov(ea, imm(XEEXTS16(i.DS.DS << 2)));
} }
@ -134,14 +153,21 @@ XEEMITTER(ldu, 0xE8000001, DS )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.DS.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.DS.DS << 2))); if (e.get_constant_gpr_value(i.DS.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.DS.DS << 2);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
e.set_constant_gpr_value(i.DS.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.DS.RA));
c.add(ea, imm(XEEXTS16(i.DS.DS << 2)));
e.clear_constant_gpr_value(i.DS.RA);
}
GpVar v = e.ReadMemory(i.address, ea, 8, false); GpVar v = e.ReadMemory(i.address, ea, 8, false);
e.update_gpr_value(i.DS.RT, v); e.update_gpr_value(i.DS.RT, v);
e.update_gpr_value(i.DS.RA, ea); e.update_gpr_value(i.DS.RA, ea);
e.clear_constant_gpr_value(i.DS.RT); e.clear_constant_gpr_value(i.DS.RT);
e.clear_constant_gpr_value(i.DS.RA);
return 0; return 0;
} }
@ -195,8 +221,14 @@ XEEMITTER(lha, 0xA8000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -251,8 +283,14 @@ XEEMITTER(lhz, 0xA0000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -271,15 +309,22 @@ XEEMITTER(lhzu, 0xA4000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
GpVar v = e.ReadMemory(i.address, ea, 2, false); GpVar v = e.ReadMemory(i.address, ea, 2, false);
// Zero extend done by ReadMemory. // Zero extend done by ReadMemory.
e.update_gpr_value(i.D.RT, v); e.update_gpr_value(i.D.RT, v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RT); e.clear_constant_gpr_value(i.D.RT);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }
@ -335,8 +380,14 @@ XEEMITTER(lwa, 0xE8000002, DS )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.DS.RA) { if (i.DS.RA) {
c.mov(ea, e.gpr_value(i.DS.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.DS.DS << 2))); if (e.get_constant_gpr_value(i.DS.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.DS.DS << 2);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
} else {
c.mov(ea, e.gpr_value(i.DS.RA));
c.add(ea, imm(XEEXTS16(i.DS.DS << 2)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.DS.DS << 2))); c.mov(ea, imm(XEEXTS16(i.DS.DS << 2)));
} }
@ -400,8 +451,14 @@ XEEMITTER(lwz, 0x80000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -420,15 +477,22 @@ XEEMITTER(lwzu, 0x84000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
GpVar v = e.ReadMemory(i.address, ea, 4, false); GpVar v = e.ReadMemory(i.address, ea, 4, false);
// Zero extend done by ReadMemory. // Zero extend done by ReadMemory.
e.update_gpr_value(i.D.RT, v); e.update_gpr_value(i.D.RT, v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RT); e.clear_constant_gpr_value(i.D.RT);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }
@ -487,8 +551,14 @@ XEEMITTER(stb, 0x98000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -504,14 +574,20 @@ XEEMITTER(stbu, 0x9C000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
GpVar v = e.gpr_value(i.D.RT); GpVar v = e.gpr_value(i.D.RT);
e.WriteMemory(i.address, ea, 1, v); e.WriteMemory(i.address, ea, 1, v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }
@ -561,8 +637,14 @@ XEEMITTER(std, 0xF8000000, DS )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.DS.RA) { if (i.DS.RA) {
c.mov(ea, e.gpr_value(i.DS.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.DS.DS << 2))); if (e.get_constant_gpr_value(i.DS.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.DS.DS << 2);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
} else {
c.mov(ea, e.gpr_value(i.DS.RA));
c.add(ea, imm(XEEXTS16(i.DS.DS << 2)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.DS.DS << 2))); c.mov(ea, imm(XEEXTS16(i.DS.DS << 2)));
} }
@ -578,14 +660,20 @@ XEEMITTER(stdu, 0xF8000001, DS )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.DS.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.DS.DS << 2))); if (e.get_constant_gpr_value(i.DS.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.DS.DS << 2);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
e.set_constant_gpr_value(i.DS.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.DS.RA));
c.add(ea, imm(XEEXTS16(i.DS.DS << 2)));
e.clear_constant_gpr_value(i.DS.RA);
}
GpVar v = e.gpr_value(i.DS.RT); GpVar v = e.gpr_value(i.DS.RT);
e.WriteMemory(i.address, ea, 8, v); e.WriteMemory(i.address, ea, 8, v);
e.update_gpr_value(i.DS.RA, ea); e.update_gpr_value(i.DS.RA, ea);
e.clear_constant_gpr_value(i.DS.RA);
return 0; return 0;
} }
@ -635,8 +723,15 @@ XEEMITTER(sth, 0xB0000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -652,14 +747,20 @@ XEEMITTER(sthu, 0xB4000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
GpVar v = e.gpr_value(i.D.RT); GpVar v = e.gpr_value(i.D.RT);
e.WriteMemory(i.address, ea, 2, v); e.WriteMemory(i.address, ea, 2, v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }
@ -709,8 +810,14 @@ XEEMITTER(stw, 0x90000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -726,14 +833,20 @@ XEEMITTER(stwu, 0x94000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea & 0xFFFFFFFF));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
GpVar v = e.gpr_value(i.D.RT); GpVar v = e.gpr_value(i.D.RT);
e.WriteMemory(i.address, ea, 4, v); e.WriteMemory(i.address, ea, 4, v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }
@ -905,13 +1018,11 @@ XEEMITTER(stwcx, 0x7C00012D, X )(X64Emitter& e, X86Compiler& c, InstrDat
// TODO(benvanik): make this right // TODO(benvanik): make this right
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { c.mov(ea, e.gpr_value(i.X.RB));
c.mov(ea, e.gpr_value(i.D.RA)); if (i.X.RA) {
c.add(ea, imm(XEEXTS16(i.D.DS))); c.add(ea, e.gpr_value(i.X.RA));
} else {
c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
GpVar v = e.gpr_value(i.D.RT); GpVar v = e.gpr_value(i.X.RT);
e.WriteMemory(i.address, ea, 4, v, /* release */ true); e.WriteMemory(i.address, ea, 4, v, /* release */ true);
// We always succeed. // We always succeed.
@ -938,8 +1049,14 @@ XEEMITTER(lfd, 0xC8000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea));
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -958,8 +1075,16 @@ XEEMITTER(lfdu, 0xCC000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
GpVar v = e.ReadMemory(i.address, ea, 8, false); GpVar v = e.ReadMemory(i.address, ea, 8, false);
XmmVar xmm_v(c.newXmmVar()); XmmVar xmm_v(c.newXmmVar());
c.save(v); // Force to memory. c.save(v); // Force to memory.
@ -967,8 +1092,6 @@ XEEMITTER(lfdu, 0xCC000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
e.update_fpr_value(i.D.RT, xmm_v); e.update_fpr_value(i.D.RT, xmm_v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }
@ -1024,8 +1147,14 @@ XEEMITTER(lfs, 0xC0000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea));
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -1044,8 +1173,16 @@ XEEMITTER(lfsu, 0xC4000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
GpVar v = e.ReadMemory(i.address, ea, 4, false); GpVar v = e.ReadMemory(i.address, ea, 4, false);
XmmVar xmm_v(c.newXmmVar()); XmmVar xmm_v(c.newXmmVar());
c.movd(xmm_v, v.r32()); c.movd(xmm_v, v.r32());
@ -1053,8 +1190,6 @@ XEEMITTER(lfsu, 0xC4000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
e.update_fpr_value(i.D.RT, xmm_v); e.update_fpr_value(i.D.RT, xmm_v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }
@ -1113,8 +1248,14 @@ XEEMITTER(stfd, 0xD8000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea));
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -1133,8 +1274,16 @@ XEEMITTER(stfdu, 0xDC000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
XmmVar v = e.fpr_value(i.D.RT); XmmVar v = e.fpr_value(i.D.RT);
GpVar gpr_v(c.newGpVar()); GpVar gpr_v(c.newGpVar());
c.save(gpr_v); // Force to memory. c.save(gpr_v); // Force to memory.
@ -1142,8 +1291,6 @@ XEEMITTER(stfdu, 0xDC000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
e.WriteMemory(i.address, ea, 8, gpr_v); e.WriteMemory(i.address, ea, 8, gpr_v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }
@ -1220,8 +1367,15 @@ XEEMITTER(stfs, 0xD0000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
if (i.D.RA) { if (i.D.RA) {
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
}
} else { } else {
c.mov(ea, imm(XEEXTS16(i.D.DS))); c.mov(ea, imm(XEEXTS16(i.D.DS)));
} }
@ -1240,8 +1394,16 @@ XEEMITTER(stfsu, 0xD4000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
// RA <- EA // RA <- EA
GpVar ea(c.newGpVar()); GpVar ea(c.newGpVar());
c.mov(ea, e.gpr_value(i.D.RA)); uint64_t constant_ea;
c.add(ea, imm(XEEXTS16(i.D.DS))); if (e.get_constant_gpr_value(i.D.RA, &constant_ea)) {
constant_ea += XEEXTS16(i.D.DS);
c.mov(ea, imm(constant_ea));
e.set_constant_gpr_value(i.D.RA, constant_ea);
} else {
c.mov(ea, e.gpr_value(i.D.RA));
c.add(ea, imm(XEEXTS16(i.D.DS)));
e.clear_constant_gpr_value(i.D.RA);
}
XmmVar v = e.fpr_value(i.D.RT); XmmVar v = e.fpr_value(i.D.RT);
c.cvtsd2ss(v, v); c.cvtsd2ss(v, v);
GpVar gpr_v(c.newGpVar()); GpVar gpr_v(c.newGpVar());
@ -1249,8 +1411,6 @@ XEEMITTER(stfsu, 0xD4000000, D )(X64Emitter& e, X86Compiler& c, InstrDat
e.WriteMemory(i.address, ea, 4, gpr_v); e.WriteMemory(i.address, ea, 4, gpr_v);
e.update_gpr_value(i.D.RA, ea); e.update_gpr_value(i.D.RA, ea);
e.clear_constant_gpr_value(i.D.RA);
return 0; return 0;
} }