void Interpreter::psq_stux(UGeckoInstruction _inst) { const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix)); const EQuantizeType stType = static_cast<EQuantizeType>(gqr.ST_TYPE); const unsigned int stScale = gqr.ST_SCALE; const u32 EA = m_GPR[_inst.RA] + m_GPR[_inst.RB]; int c = 4; if (stType == QUANTIZE_U8 || stType == QUANTIZE_S8) c = 0x1; else if (stType == QUANTIZE_U16 || stType == QUANTIZE_S16) c = 0x2; if (_inst.Wx == 0) { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); Helper_Quantize(EA + c, rPS1(_inst.RS), stType, stScale); } else { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); } if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { return; } m_GPR[_inst.RA] = EA; } // namespace=======
void Interpreter::psq_lux(UGeckoInstruction _inst) { const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix)); const EQuantizeType ldType = static_cast<EQuantizeType>(gqr.LD_TYPE); const unsigned int ldScale = gqr.LD_SCALE; const u32 EA = m_GPR[_inst.RA] + m_GPR[_inst.RB]; int c = 4; if ((ldType == 4) || (ldType == 6)) c = 0x1; if ((ldType == 5) || (ldType == 7)) c = 0x2; if (_inst.Wx == 0) { float ps0 = Helper_Dequantize( EA, ldType, ldScale ); float ps1 = Helper_Dequantize( EA+c, ldType, ldScale ); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { return; } rPS0(_inst.RS) = ps0; rPS1(_inst.RS) = ps1; } else { float ps0 = Helper_Dequantize( EA, ldType, ldScale ); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { return; } rPS0(_inst.RS) = ps0; rPS1(_inst.RS) = 1.0f; } m_GPR[_inst.RA] = EA; }
void Interpreter::psq_stu(UGeckoInstruction _inst) { const UGQR gqr(rSPR(SPR_GQR0 + _inst.I)); const EQuantizeType stType = static_cast<EQuantizeType>(gqr.ST_TYPE); const unsigned int stScale = gqr.ST_SCALE; const u32 EA = m_GPR[_inst.RA] + _inst.SIMM_12; int c = 4; if ((stType == 4) || (stType == 6)) c = 0x1; if ((stType == 5) || (stType == 7)) c = 0x2; if (_inst.W == 0) { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); Helper_Quantize(EA+c, rPS1(_inst.RS), stType, stScale); } else { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); } if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { return; } m_GPR[_inst.RA] = EA; }
// Internal inverse square root function in the crazy math lib. void FZ_rsqrt_internal() { double f = 1.0 / sqrt(rPS0(1)); rPS0(1) = f; rPS1(1) = f; NPC = LR; }
void Interpreter::psq_l(UGeckoInstruction _inst) { const UGQR gqr(rSPR(SPR_GQR0 + _inst.I)); const EQuantizeType ldType = static_cast<EQuantizeType>(gqr.LD_TYPE); const unsigned int ldScale = gqr.LD_SCALE; const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + _inst.SIMM_12) : (u32)_inst.SIMM_12; int c = 4; if ((ldType == QUANTIZE_U8) || (ldType == QUANTIZE_S8)) c = 0x1; if ((ldType == QUANTIZE_U16) || (ldType == QUANTIZE_S16)) c = 0x2; if (_inst.W == 0) { float ps0 = Helper_Dequantize(EA, ldType, ldScale); float ps1 = Helper_Dequantize(EA+c, ldType, ldScale); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { return; } rPS0(_inst.RS) = ps0; rPS1(_inst.RS) = ps1; } else { float ps0 = Helper_Dequantize(EA, ldType, ldScale); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { return; } rPS0(_inst.RS) = ps0; rPS1(_inst.RS) = 1.0f; } }
void FZ_sqrt() { u32 r3 = GPR(3); double x = rPS0(0); x = sqrt(x); FW(r3, (float)x); rPS0(0) = x; NPC = LR; }
// Internal square root function in the crazy math lib. Acts a bit odd, just read it. It's not a bug :p void FZ_sqrt_internal() { double f = sqrt(rPS0(1)); rPS0(0) = rPS0(1); rPS1(0) = rPS0(1); rPS0(1) = f; rPS1(1) = f; NPC = LR; }
void SMB_atan2() { // in: f1 = x, f2 = y // out: r3 = angle double angle = atan2(rPS0(1), rPS0(2)); int angle_fixpt = (int)(angle / 3.14159 * 32767); if (angle_fixpt < -32767) angle_fixpt = -32767; if (angle_fixpt > 32767) angle_fixpt = 32767; GPR(3) = angle_fixpt; NPC = LR; }
void FZero_evil_vec_normalize() { u32 r3 = GPR(3); float x = F(r3); float y = F(r3 + 4); float z = F(r3 + 8); float sq_len = x*x + y*y + z*z; float inv_len = 1.0f / sqrtf(sq_len); x *= inv_len; y *= inv_len; z *= inv_len; FW(r3, x); FW(r3 + 4, y); FW(r3 + 8, z); rPS0(1) = inv_len * sq_len; // len rPS1(1) = inv_len * sq_len; // len NPC = LR; /* .evil_vec_something (f6, f7, f8) <- [r3] f1 = f6 * f6 f1 += f7 * f7 f1 += f8 * f8 f2 = mystery f4 = f2 * f1 f3 = f2 + f2 f1 = 1/f0 f6 *= f1 f7 *= f1 f8 *= f1 8006d668: lis r5, 0xE000 8006d684: lfs f2, 0x01A0 (r5) 8006d69c: fmr f0,f2 8006d6a0: fmuls f4,f2,f1 8006d6a4: fadds f3,f2,f2 8006d6a8: frsqrte f1,f0,f1 8006d6ac: fadds f3,f3,f2 8006d6b0: fmuls f5,f1,f1 8006d6b4: fnmsubs f5,f5,f4,f3 8006d6b8: fmuls f1,f1,f5 8006d6bc: fmuls f5,f1,f1 8006d6c0: fnmsubs f5,f5,f4,f3 8006d6c4: fmuls f1,f1,f5 8006d6c8: fmuls f6,f6,f1 8006d6cc: stfs f6, 0 (r3) 8006d6d0: fmuls f7,f7,f1 8006d6d4: stfs f7, 0x0004 (r3) 8006d6d8: fmuls f8,f8,f1 8006d6dc: stfs f8, 0x0008 (r3) 8006d6e0: fmuls f1,f1,f0 8006d6e4: blr */ NPC = LR; }
void Interpreter::lfsx(UGeckoInstruction _inst) { u32 uTemp = Memory::Read_U32(Helper_Get_EA_X(_inst)); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { double value = *(float*)&uTemp; rPS0(_inst.FD) = value; rPS1(_inst.FD) = value; } }
wxString CRegTable::FormatFPR(int reg_index, int reg_part) { if (m_formatFRegs[reg_index][reg_part] == FormatSpecifier::Double) { double reg = (reg_part == 0) ? rPS0(reg_index) : rPS1(reg_index); return wxString::Format(GetFormatString(m_formatFRegs[reg_index][reg_part]), reg); } u64 reg = (reg_part == 0) ? riPS0(reg_index) : riPS1(reg_index); return wxString::Format(GetFormatString(m_formatFRegs[reg_index][reg_part]), reg); }
void Interpreter::psq_stx(UGeckoInstruction _inst) { const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix)); const EQuantizeType stType = static_cast<EQuantizeType>(gqr.ST_TYPE); const unsigned int stScale = gqr.ST_SCALE; const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + m_GPR[_inst.RB]) : m_GPR[_inst.RB]; int c = 4; if ((stType == 4) || (stType == 6)) c = 0x1; if ((stType == 5) || (stType == 7)) c = 0x2; if (_inst.Wx == 0) { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); Helper_Quantize(EA+c, rPS1(_inst.RS), stType, stScale); } else { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); } }
void Interpreter::lfsux(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_UX(_inst); u32 uTemp = Memory::Read_U32(uAddress); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { double value = *(float*)&uTemp; rPS0(_inst.FD) = value; rPS1(_inst.FD) = value; m_GPR[_inst.RA] = uAddress; } }
void Interpreter::psq_st(UGeckoInstruction _inst) { const UGQR gqr(rSPR(SPR_GQR0 + _inst.I)); const EQuantizeType stType = static_cast<EQuantizeType>(gqr.ST_TYPE); const unsigned int stScale = gqr.ST_SCALE; const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + _inst.SIMM_12) : (u32)_inst.SIMM_12; int c = 4; if (stType == QUANTIZE_U8 || stType == QUANTIZE_S8) c = 0x1; else if (stType == QUANTIZE_U16 || stType == QUANTIZE_S16) c = 0x2; if (_inst.W == 0) { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); Helper_Quantize(EA + c, rPS1(_inst.RS), stType, stScale); } else { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); } }
// Scales the vector pointed at by r3 to the length specified by f0. // Writes results to vector pointed at by r4. void SMB_evil_vec_setlength() { u32 r3 = GPR(3); u32 r4 = GPR(4); float x = F(r3); float y = F(r3 + 4); float z = F(r3 + 8); float inv_len = (float)(rPS0(0) / sqrt(x*x + y*y + z*z)); x *= inv_len; y *= inv_len; z *= inv_len; FW(r4, x); FW(r4 + 4, y); FW(r4 + 8, z); NPC = LR; }
// Computes the cosine of the angle between the two fvec3s pointed at by r3 and r4. void SMB_EvilVecCosine() { u32 r3 = GPR(3); u32 r4 = GPR(4); float x1 = F(r3); float y1 = F(r3 + 4); float z1 = F(r3 + 8); float x2 = F(r4); float y2 = F(r4 + 4); float z2 = F(r4 + 8); float s1 = x1*x1 + y1*y1 + z1*z1; float s2 = x2*x2 + y2*y2 + z2*z2; float dot = x1*x2 + y1*y2 + z1*z2; rPS0(1) = dot / sqrtf(s1 * s2); NPC = LR; }
void GetStringVA(std::string& _rOutBuffer, u32 strReg) { _rOutBuffer = ""; char ArgumentBuffer[256]; u32 ParameterCounter = strReg+1; u32 FloatingParameterCounter = 1; char *pString = (char*)Memory::GetPointer(GPR(strReg)); if (!pString) { ERROR_LOG(OSREPORT, "r%i invalid", strReg); return; } while (*pString) { if (*pString == '%') { char* pArgument = ArgumentBuffer; *pArgument++ = *pString++; if (*pString == '%') { _rOutBuffer += "%"; pString++; continue; } while (*pString < 'A' || *pString > 'z' || *pString == 'l' || *pString == '-') *pArgument++ = *pString++; *pArgument++ = *pString; *pArgument = 0; u64 Parameter; if (ParameterCounter > 10) { Parameter = Memory::Read_U32(GPR(1) + 0x8 + ((ParameterCounter - 11) * 4)); } else { if ((*(pString-2) == 'l') && (*(pString-1) == 'l')) // hax, just seen this on sysmenu osreport { Parameter = GPR(++ParameterCounter); Parameter = (Parameter<<32)|GPR(++ParameterCounter); } else // normal, 32bit Parameter = GPR(ParameterCounter); } ParameterCounter++; switch (*pString) { case 's': _rOutBuffer += StringFromFormat(ArgumentBuffer, (char*)Memory::GetPointer((u32)Parameter)); break; case 'd': case 'i': { //u64 Double = Memory::Read_U64(Parameter); _rOutBuffer += StringFromFormat(ArgumentBuffer, Parameter); break; } case 'f': { _rOutBuffer += StringFromFormat(ArgumentBuffer, rPS0(FloatingParameterCounter)); FloatingParameterCounter++; ParameterCounter--; break; } case 'p': // Override, so 64bit dolphin prints 32bit pointers, since the ppc is 32bit :) _rOutBuffer += StringFromFormat("%x", (u32)Parameter); break; default: _rOutBuffer += StringFromFormat(ArgumentBuffer, Parameter); break; } pString++; } else { _rOutBuffer += StringFromFormat("%c", *pString); pString++; } } if (_rOutBuffer[_rOutBuffer.length() - 1] == '\n') _rOutBuffer.resize(_rOutBuffer.length() - 1); }
void GetStringVA(std::string& _rOutBuffer, u32 strReg) { _rOutBuffer = ""; std::string ArgumentBuffer = ""; u32 ParameterCounter = strReg + 1; u32 FloatingParameterCounter = 1; std::string string = PowerPC::HostGetString(GPR(strReg)); for (u32 i = 0; i < string.size(); i++) { if (string[i] == '%') { ArgumentBuffer = "%"; i++; if (string[i] == '%') { _rOutBuffer += "%"; continue; } while (string[i] < 'A' || string[i] > 'z' || string[i] == 'l' || string[i] == '-') ArgumentBuffer += string[i++]; ArgumentBuffer += string[i]; u64 Parameter; if (ParameterCounter > 10) { Parameter = PowerPC::HostRead_U32(GPR(1) + 0x8 + ((ParameterCounter - 11) * 4)); } else { if (string[i - 1] == 'l' && string[i - 2] == 'l') // hax, just seen this on sysmenu osreport { Parameter = GPR(++ParameterCounter); Parameter = (Parameter << 32) | GPR(++ParameterCounter); } else // normal, 32bit Parameter = GPR(ParameterCounter); } ParameterCounter++; switch (string[i]) { case 's': _rOutBuffer += StringFromFormat(ArgumentBuffer.c_str(), PowerPC::HostGetString((u32)Parameter).c_str()); break; case 'd': case 'i': { _rOutBuffer += StringFromFormat(ArgumentBuffer.c_str(), Parameter); break; } case 'f': { _rOutBuffer += StringFromFormat(ArgumentBuffer.c_str(), rPS0(FloatingParameterCounter)); FloatingParameterCounter++; ParameterCounter--; break; } case 'p': // Override, so 64bit Dolphin prints 32bit pointers, since the ppc is 32bit :) _rOutBuffer += StringFromFormat("%x", (u32)Parameter); break; default: _rOutBuffer += StringFromFormat(ArgumentBuffer.c_str(), Parameter); break; } } else { _rOutBuffer += string[i]; } } if (!_rOutBuffer.empty() && _rOutBuffer[_rOutBuffer.length() - 1] == '\n') _rOutBuffer.resize(_rOutBuffer.length() - 1); }
std::string GetStringVA(u32 strReg) { std::string ArgumentBuffer; u32 ParameterCounter = strReg + 1; u32 FloatingParameterCounter = 1; std::string result; std::string string = PowerPC::HostGetString(GPR(strReg)); for (size_t i = 0; i < string.size(); i++) { if (string[i] == '%') { ArgumentBuffer = '%'; i++; if (string[i] == '%') { result += '%'; continue; } while (string[i] < 'A' || string[i] > 'z' || string[i] == 'l' || string[i] == '-') ArgumentBuffer += string[i++]; ArgumentBuffer += string[i]; u64 Parameter; if (ParameterCounter > 10) { Parameter = PowerPC::HostRead_U32(GPR(1) + 0x8 + ((ParameterCounter - 11) * 4)); } else { if (string[i - 1] == 'l' && string[i - 2] == 'l') // hax, just seen this on sysmenu osreport { Parameter = GPR(++ParameterCounter); Parameter = (Parameter << 32) | GPR(++ParameterCounter); } else // normal, 32bit Parameter = GPR(ParameterCounter); } ParameterCounter++; switch (string[i]) { case 's': result += StringFromFormat(ArgumentBuffer.c_str(), PowerPC::HostGetString((u32)Parameter).c_str()); break; case 'd': case 'i': { result += StringFromFormat(ArgumentBuffer.c_str(), Parameter); break; } case 'f': { result += StringFromFormat(ArgumentBuffer.c_str(), rPS0(FloatingParameterCounter)); FloatingParameterCounter++; ParameterCounter--; break; } case 'p': // Override, so 64bit Dolphin prints 32bit pointers, since the ppc is 32bit :) result += StringFromFormat("%x", (u32)Parameter); break; default: result += StringFromFormat(ArgumentBuffer.c_str(), Parameter); break; } } else { result += string[i]; } } if (!result.empty() && result.back() == '\n') result.pop_back(); return result; }
double HLE::SystemVABI::VAList::GetFPR(u32 fpr) const { return rPS0(fpr); }