diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 2a542f4709..af55254741 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -539,8 +539,14 @@ void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type, bool reverse = case R_MIPS_LO16: { // Sign extend the existing low value (e.g. from addiu.) - const u32 exportOffsetLo = exportAddress + (s16)(u16)(relocData & 0xFFFF); - u32 full = exportOffsetLo; + const u32 offsetLo = (s32)(s16)(u16)(relocData & 0xFFFF); + u32 full = exportAddress; + // This is only used in the error case (no hi/wrong hi.) + if (!reverse) { + full = offsetLo + exportAddress; + } else { + full = offsetLo - exportAddress; + } // The ABI requires that these come in pairs, at least. if (lastHI16Relocs.empty()) { @@ -553,9 +559,9 @@ void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type, bool reverse = for (auto it = lastHI16Relocs.begin(), end = lastHI16Relocs.end(); it != end; ++it) { if (!reverse) { - full = (it->data << 16) + exportOffsetLo; + full = (it->data << 16) + offsetLo + exportAddress; } else { - full = (it->data << 16) - exportOffsetLo; + full = (it->data << 16) + offsetLo - exportAddress; } // The low instruction will be a signed add, which means (full & 0x8000) will subtract. // We add 1 in that case so that it ends up the right value.