diff --git a/src/xenia/cpu/x64/x64_emit_altivec.cc b/src/xenia/cpu/x64/x64_emit_altivec.cc index e16d1105b..a02db5c2f 100644 --- a/src/xenia/cpu/x64/x64_emit_altivec.cc +++ b/src/xenia/cpu/x64/x64_emit_altivec.cc @@ -1554,9 +1554,63 @@ XEEMITTER(vsl, 0x100001C4, VX )(X64Emitter& e, X86Compiler& c, Instr XEEMITTER(vslb, 0x10000104, VX )(X64Emitter& e, X86Compiler& c, InstrData& i) { XEINSTRNOTIMPLEMENTED(); + // o = {0} + // for each byte: + // t = shift input by VB[b] *bits* + // o = o | (t & mask) + // write o return 1; } +XEEMITTER(vslh, 0x10000144, VX )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +int InstrEmit_vslw_(X64Emitter& e, X86Compiler& c, uint32_t vd, uint32_t va, uint32_t vb) { + // VA = |xxxxx|yyyyy|zzzzz|wwwww| + // VB = |...sh|...sh|...sh|...sh| + // VD = |x< 8 and load. + int32_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xF0) : i.VX.VA; + GpVar simm_v(c.newGpVar()); + c.mov(simm_v, imm(simm)); + c.movd(v, simm_v.r32()); + XmmVar z(c.newXmmVar()); + c.xorps(z, z); + c.pshufb(v, z); + } else { + // Zero out the register. + c.xorps(v, v); + } + e.update_vr_value(i.VX.VD, v); + e.TraceVR(i.VX.VD); + return 0; } XEEMITTER(vspltish, 0x1000034C, VX )(X64Emitter& e, X86Compiler& c, InstrData& i) { diff --git a/src/xenia/cpu/x64/x64_emit_memory.cc b/src/xenia/cpu/x64/x64_emit_memory.cc index e4528c132..1db4a5a23 100644 --- a/src/xenia/cpu/x64/x64_emit_memory.cc +++ b/src/xenia/cpu/x64/x64_emit_memory.cc @@ -990,8 +990,29 @@ XEEMITTER(isync, 0x4C00012C, XL )(X64Emitter& e, X86Compiler& c, InstrDat } XEEMITTER(ldarx, 0x7C0000A8, X )(X64Emitter& e, X86Compiler& c, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // RESERVE <- 1 + // RESERVE_LENGTH <- 8 + // RESERVE_ADDR <- real_addr(EA) + // RT <- MEM(EA, 8) + + // TODO(benvanik): make this right + + GpVar ea(c.newGpVar()); + c.mov(ea, e.gpr_value(i.X.RB)); + if (i.X.RA) { + c.add(ea, e.gpr_value(i.X.RA)); + } + GpVar v = e.ReadMemory(i.address, ea, 8, /* acquire */ true); + e.update_gpr_value(i.X.RT, v); + + e.clear_constant_gpr_value(i.X.RT); + + return 0; } XEEMITTER(lwarx, 0x7C000028, X )(X64Emitter& e, X86Compiler& c, InstrData& i) { @@ -1021,8 +1042,30 @@ XEEMITTER(lwarx, 0x7C000028, X )(X64Emitter& e, X86Compiler& c, InstrDat } XEEMITTER(stdcx, 0x7C0001AD, X )(X64Emitter& e, X86Compiler& c, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // RESERVE stuff... + // MEM(EA, 8) <- (RS) + // n <- 1 if store performed + // CR0[LT GT EQ SO] = 0b00 || n || XER[SO] + + // TODO(benvanik): make this right + + GpVar ea(c.newGpVar()); + c.mov(ea, e.gpr_value(i.X.RB)); + if (i.X.RA) { + c.add(ea, e.gpr_value(i.X.RA)); + } + GpVar v = e.gpr_value(i.X.RT); + e.WriteMemory(i.address, ea, 8, v, /* release */ true); + + // We always succeed. + e.update_cr_value(0, e.get_uint64(1 << 2)); + + return 0; } XEEMITTER(stwcx, 0x7C00012D, X )(X64Emitter& e, X86Compiler& c, InstrData& i) { diff --git a/src/xenia/cpu/x64/x64_emitter.cc b/src/xenia/cpu/x64/x64_emitter.cc index 8cacdd480..cbbe940bf 100644 --- a/src/xenia/cpu/x64/x64_emitter.cc +++ b/src/xenia/cpu/x64/x64_emitter.cc @@ -650,6 +650,7 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) { // TODO(benvanik): assert this doesn't occur - means a bad sdb run! XELOGCPU("SDB function scan error in %.8X: bb %.8X has unknown exit", symbol_->start_address, block->start_address); + XEASSERTALWAYS(); c.ret(); }