mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Interpreter: Add correct alignment checks to loads/stores, cleanup
This commit is contained in:
1 parent
5dfeaed63b
commit
d8edeb7649
6 files changed
+184
-103
No files matched your search
@@ -124,7 +124,7 @@ void WebSocketMemoryReadU8(DebuggerRequest &req) {
|
|||||||
Core_RunOnCPUThread([&] {
|
Core_RunOnCPUThread([&] {
|
||||||
AutoDisabledReplacements memLock = LockMemory(true);
|
AutoDisabledReplacements memLock = LockMemory(true);
|
||||||
JsonWriter &json = req.Respond();
|
JsonWriter &json = req.Respond();
|
||||||
json.writeUint("value", Memory::Read_U8(addr));
|
json.writeUint("value", Memory::ReadUnchecked_U8(addr));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ void WebSocketMemoryReadU16(DebuggerRequest &req) {
|
|||||||
return req.Fail("CPU not started");
|
return req.Fail("CPU not started");
|
||||||
// This only depends on addr, not on anything CPU-thread-owned, so fail fast here rather than
|
// This only depends on addr, not on anything CPU-thread-owned, so fail fast here rather than
|
||||||
// making a round trip through the queue for a request we already know is invalid.
|
// making a round trip through the queue for a request we already know is invalid.
|
||||||
if (!Memory::IsValidAddress(addr))
|
if (!Memory::IsValidRange(addr, 2))
|
||||||
return req.Fail("Invalid address");
|
return req.Fail("Invalid address");
|
||||||
|
|
||||||
// Route the actual memory read to the CPU thread instead of poking at it directly
|
// Route the actual memory read to the CPU thread instead of poking at it directly
|
||||||
@@ -153,7 +153,7 @@ void WebSocketMemoryReadU16(DebuggerRequest &req) {
|
|||||||
Core_RunOnCPUThread([&] {
|
Core_RunOnCPUThread([&] {
|
||||||
AutoDisabledReplacements memLock = LockMemory(true);
|
AutoDisabledReplacements memLock = LockMemory(true);
|
||||||
JsonWriter &json = req.Respond();
|
JsonWriter &json = req.Respond();
|
||||||
json.writeUint("value", Memory::Read_U16(addr));
|
json.writeUint("value", Memory::ReadUnchecked_U16(addr));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ void WebSocketMemoryReadU32(DebuggerRequest &req) {
|
|||||||
return req.Fail("CPU not started");
|
return req.Fail("CPU not started");
|
||||||
// This only depends on addr, not on anything CPU-thread-owned, so fail fast here rather than
|
// This only depends on addr, not on anything CPU-thread-owned, so fail fast here rather than
|
||||||
// making a round trip through the queue for a request we already know is invalid.
|
// making a round trip through the queue for a request we already know is invalid.
|
||||||
if (!Memory::IsValidAddress(addr))
|
if (!Memory::IsValidRange(addr, 4))
|
||||||
return req.Fail("Invalid address");
|
return req.Fail("Invalid address");
|
||||||
|
|
||||||
// Route the actual memory read to the CPU thread instead of poking at it directly
|
// Route the actual memory read to the CPU thread instead of poking at it directly
|
||||||
|
|||||||
+117
-39
@@ -293,8 +293,7 @@ namespace MIPSInt
|
|||||||
|
|
||||||
void Int_JumpRegType(MIPSOpcode op)
|
void Int_JumpRegType(MIPSOpcode op)
|
||||||
{
|
{
|
||||||
if (mipsr4k.inDelaySlot)
|
if (mipsr4k.inDelaySlot) {
|
||||||
{
|
|
||||||
// There's one of these in Star Soldier at 0881808c, which seems benign.
|
// There's one of these in Star Soldier at 0881808c, which seems benign.
|
||||||
ERROR_LOG(Log::CPU, "Jump in delay slot :(");
|
ERROR_LOG(Log::CPU, "Jump in delay slot :(");
|
||||||
}
|
}
|
||||||
@@ -318,8 +317,7 @@ namespace MIPSInt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Int_IType(MIPSOpcode op)
|
void Int_IType(MIPSOpcode op) {
|
||||||
{
|
|
||||||
u32 uimm = op & 0xFFFF;
|
u32 uimm = op & 0xFFFF;
|
||||||
u32 suimm = SignExtend16ToU32(op);
|
u32 suimm = SignExtend16ToU32(op);
|
||||||
s32 simm = SignExtend16ToS32(op);
|
s32 simm = SignExtend16ToS32(op);
|
||||||
@@ -349,9 +347,8 @@ namespace MIPSInt
|
|||||||
PC += 4;
|
PC += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Int_StoreSync(MIPSOpcode op)
|
void Int_StoreSync(MIPSOpcode op) {
|
||||||
{
|
int imm = (signed short)(op & 0xFFFF);
|
||||||
int imm = (signed short)(op&0xFFFF);
|
|
||||||
int rt = _RT;
|
int rt = _RT;
|
||||||
int rs = _RS;
|
int rs = _RS;
|
||||||
u32 addr = R(rs) + imm;
|
u32 addr = R(rs) + imm;
|
||||||
@@ -360,12 +357,20 @@ namespace MIPSInt
|
|||||||
{
|
{
|
||||||
case 48: // ll
|
case 48: // ll
|
||||||
if (rt != 0) {
|
if (rt != 0) {
|
||||||
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::READ_WORD, "ll");
|
||||||
|
return;
|
||||||
|
}
|
||||||
R(rt) = Memory::Read_U32(addr);
|
R(rt) = Memory::Read_U32(addr);
|
||||||
}
|
}
|
||||||
currentMIPS->llBit = 1;
|
currentMIPS->llBit = 1;
|
||||||
break;
|
break;
|
||||||
case 56: // sc
|
case 56: // sc
|
||||||
if (currentMIPS->llBit) {
|
if (currentMIPS->llBit) {
|
||||||
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::WRITE_WORD, "sc");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Memory::Write_U32(R(rt), addr);
|
Memory::Write_U32(R(rt), addr);
|
||||||
if (rt != 0) {
|
if (rt != 0) {
|
||||||
R(rt) = 1;
|
R(rt) = 1;
|
||||||
@@ -382,21 +387,18 @@ namespace MIPSInt
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Int_RType3(MIPSOpcode op)
|
void Int_RType3(MIPSOpcode op) {
|
||||||
{
|
|
||||||
int rt = _RT;
|
int rt = _RT;
|
||||||
int rs = _RS;
|
int rs = _RS;
|
||||||
int rd = _RD;
|
int rd = _RD;
|
||||||
|
|
||||||
// Don't change $zr.
|
// Don't change $zr.
|
||||||
if (rd == 0)
|
if (rd == 0) {
|
||||||
{
|
|
||||||
PC += 4;
|
PC += 4;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (op & 63)
|
switch (op & 63) {
|
||||||
{
|
|
||||||
case 10: if (R(rt) == 0) R(rd) = R(rs); break; //movz
|
case 10: if (R(rt) == 0) R(rd) = R(rs); break; //movz
|
||||||
case 11: if (R(rt) != 0) R(rd) = R(rs); break; //movn
|
case 11: if (R(rt) != 0) R(rd) = R(rs); break; //movn
|
||||||
case 32: R(rd) = R(rs) + R(rt); break; //add (exception on overflow)
|
case 32: R(rd) = R(rs) + R(rt); break; //add (exception on overflow)
|
||||||
@@ -419,12 +421,11 @@ namespace MIPSInt
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Int_ITypeMem(MIPSOpcode op)
|
void Int_ITypeMem(MIPSOpcode op) {
|
||||||
{
|
|
||||||
int imm = (signed short)(op&0xFFFF);
|
int imm = (signed short)(op&0xFFFF);
|
||||||
int rt = _RT;
|
int rt = _RT;
|
||||||
int rs = _RS;
|
int rs = _RS;
|
||||||
u32 addr = R(rs) + imm;
|
const u32 addr = R(rs) + imm;
|
||||||
|
|
||||||
if (((op >> 29) & 1) == 0 && rt == 0) {
|
if (((op >> 29) & 1) == 0 && rt == 0) {
|
||||||
// Don't load anything into $zr
|
// Don't load anything into $zr
|
||||||
@@ -432,23 +433,75 @@ namespace MIPSInt
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (op >> 26)
|
switch (op >> 26) {
|
||||||
{
|
case 32:
|
||||||
case 32: R(rt) = SignExtend8ToU32(Memory::Read_U8(addr)); break; //lb
|
if (!Memory::IsValidAddress(addr)) {
|
||||||
case 33: R(rt) = SignExtend16ToU32(Memory::Read_U16(addr)); break; //lh
|
Core_MemoryException(addr, 1, PC, MemoryExceptionType::READ_WORD, "lb");
|
||||||
case 35: R(rt) = Memory::Read_U32(addr); break; //lw
|
return;
|
||||||
case 36: R(rt) = Memory::Read_U8 (addr); break; //lbu
|
}
|
||||||
case 37: R(rt) = Memory::Read_U16(addr); break; //lhu
|
R(rt) = SignExtend8ToU32(Memory::ReadUnchecked_U8(addr));
|
||||||
case 40: Memory::Write_U8(R(rt), addr); break; //sb
|
break; //lb
|
||||||
case 41: Memory::Write_U16(R(rt), addr); break; //sh
|
case 33:
|
||||||
case 43: Memory::Write_U32(R(rt), addr); break; //sw
|
if (!Memory::IsValid2AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 2, PC, MemoryExceptionType::READ_WORD, "lh");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
R(rt) = SignExtend16ToU32(Memory::ReadUnchecked_U16(addr));
|
||||||
|
break; //lh
|
||||||
|
case 35:
|
||||||
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::READ_WORD, "lw");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
R(rt) = Memory::ReadUnchecked_U32(addr);
|
||||||
|
break; //lw
|
||||||
|
case 36:
|
||||||
|
if (!Memory::IsValidAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 1, PC, MemoryExceptionType::READ_WORD, "lbu");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
R(rt) = Memory::Read_U8 (addr);
|
||||||
|
break; //lbu
|
||||||
|
case 37:
|
||||||
|
if (!Memory::IsValid2AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 2, PC, MemoryExceptionType::READ_WORD, "lhu");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
R(rt) = Memory::Read_U16(addr);
|
||||||
|
break; //lhu
|
||||||
|
case 40:
|
||||||
|
if (!Memory::IsValidAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 1, PC, MemoryExceptionType::WRITE_WORD, "sb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Memory::Write_U8(R(rt), addr);
|
||||||
|
break; //sb
|
||||||
|
case 41:
|
||||||
|
if (!Memory::IsValid2AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 2, PC, MemoryExceptionType::WRITE_WORD, "sh");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Memory::Write_U16(R(rt), addr);
|
||||||
|
break; //sh
|
||||||
|
case 43:
|
||||||
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::WRITE_WORD, "sw");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Memory::Write_U32(R(rt), addr);
|
||||||
|
break; //sw
|
||||||
|
|
||||||
// When there's an LWL and an LWR together, we should be able to peephole optimize that
|
// When there's an LWL and an LWR together, we should be able to peephole optimize that
|
||||||
// into a single non-alignment-checking LW.
|
// into a single non-alignment-checking LW.
|
||||||
case 34: //lwl
|
case 34: //lwl
|
||||||
{
|
{
|
||||||
|
// Not checking for alignment here - the actual read will be aligned.
|
||||||
|
if (!Memory::IsValidAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::READ_WORD, "lwl");
|
||||||
|
return;
|
||||||
|
}
|
||||||
u32 shift = (addr & 3) * 8;
|
u32 shift = (addr & 3) * 8;
|
||||||
u32 mem = Memory::Read_U32(addr & 0xfffffffc);
|
u32 mem = Memory::ReadUnchecked_U32(addr & 0xfffffffc);
|
||||||
u32 result = ( u32(R(rt)) & (0x00ffffff >> shift) ) | ( mem << (24 - shift) );
|
u32 result = ( u32(R(rt)) & (0x00ffffff >> shift) ) | ( mem << (24 - shift) );
|
||||||
R(rt) = result;
|
R(rt) = result;
|
||||||
}
|
}
|
||||||
@@ -456,8 +509,13 @@ namespace MIPSInt
|
|||||||
|
|
||||||
case 38: //lwr
|
case 38: //lwr
|
||||||
{
|
{
|
||||||
|
// Not checking for alignment here - the actual read will be aligned.
|
||||||
|
if (!Memory::IsValidAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::READ_WORD, "lwr");
|
||||||
|
return;
|
||||||
|
}
|
||||||
u32 shift = (addr & 3) * 8;
|
u32 shift = (addr & 3) * 8;
|
||||||
u32 mem = Memory::Read_U32(addr & 0xfffffffc);
|
u32 mem = Memory::ReadUnchecked_U32(addr & 0xfffffffc);
|
||||||
u32 regval = R(rt);
|
u32 regval = R(rt);
|
||||||
u32 result = ( regval & (0xffffff00 << (24 - shift)) ) | ( mem >> shift );
|
u32 result = ( regval & (0xffffff00 << (24 - shift)) ) | ( mem >> shift );
|
||||||
R(rt) = result;
|
R(rt) = result;
|
||||||
@@ -466,19 +524,29 @@ namespace MIPSInt
|
|||||||
|
|
||||||
case 42: //swl
|
case 42: //swl
|
||||||
{
|
{
|
||||||
|
// Not checking for alignment here - the actual read/write will be aligned.
|
||||||
|
if (!Memory::IsValidAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::WRITE_WORD, "swl");
|
||||||
|
return;
|
||||||
|
}
|
||||||
u32 shift = (addr & 3) * 8;
|
u32 shift = (addr & 3) * 8;
|
||||||
u32 mem = Memory::Read_U32(addr & 0xfffffffc);
|
u32 mem = Memory::ReadUnchecked_U32(addr & 0xfffffffc);
|
||||||
u32 result = ( ( u32(R(rt)) >> (24 - shift) ) ) | ( mem & (0xffffff00 << shift) );
|
u32 result = ( ( u32(R(rt)) >> (24 - shift) ) ) | ( mem & (0xffffff00 << shift) );
|
||||||
Memory::Write_U32(result, (addr & 0xfffffffc));
|
Memory::WriteUnchecked_U32(result, (addr & 0xfffffffc));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 46: //swr
|
case 46: //swr
|
||||||
{
|
{
|
||||||
|
// Not checking for alignment here - the actual read/write will be aligned.
|
||||||
|
if (!Memory::IsValidAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::WRITE_WORD, "swr");
|
||||||
|
return;
|
||||||
|
}
|
||||||
u32 shift = (addr & 3) << 3;
|
u32 shift = (addr & 3) << 3;
|
||||||
u32 mem = Memory::Read_U32(addr & 0xfffffffc);
|
u32 mem = Memory::ReadUnchecked_U32(addr & 0xfffffffc);
|
||||||
u32 result = ( ( u32(R(rt)) << shift ) | (mem & (0x00ffffff >> (24 - shift)) ) );
|
u32 result = ( ( u32(R(rt)) << shift ) | (mem & (0x00ffffff >> (24 - shift)) ) );
|
||||||
Memory::Write_U32(result, (addr & 0xfffffffc));
|
Memory::WriteUnchecked_U32(result, (addr & 0xfffffffc));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -489,17 +557,27 @@ namespace MIPSInt
|
|||||||
PC += 4;
|
PC += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Int_FPULS(MIPSOpcode op)
|
void Int_FPULS(MIPSOpcode op) {
|
||||||
{
|
s32 offset = (s16)(op & 0xFFFF);
|
||||||
s32 offset = (s16)(op&0xFFFF);
|
|
||||||
int ft = _FT;
|
int ft = _FT;
|
||||||
int rs = _RS;
|
int rs = _RS;
|
||||||
u32 addr = R(rs) + offset;
|
u32 addr = R(rs) + offset;
|
||||||
|
|
||||||
switch(op >> 26)
|
switch (op >> 26) {
|
||||||
{
|
case 49:
|
||||||
case 49: FI(ft) = Memory::Read_U32(addr); break; //lwc1
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
case 57: Memory::Write_U32(FI(ft), addr); break; //swc1
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::READ_WORD, "lwc1");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FI(ft) = Memory::Read_U32(addr);
|
||||||
|
break; //lwc1
|
||||||
|
case 57:
|
||||||
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 4, PC, MemoryExceptionType::WRITE_WORD, "swc1");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Memory::Write_U32(FI(ft), addr);
|
||||||
|
break; //swc1
|
||||||
default:
|
default:
|
||||||
_dbg_assert_msg_(false,"Trying to interpret FPULS instruction that can't be interpreted");
|
_dbg_assert_msg_(false,"Trying to interpret FPULS instruction that can't be interpreted");
|
||||||
break;
|
break;
|
||||||
|
|||||||
+47
-50
@@ -200,8 +200,7 @@ namespace MIPSInt
|
|||||||
PC += 4;
|
PC += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Int_SVQ(MIPSOpcode op)
|
void Int_SVQ(MIPSOpcode op) {
|
||||||
{
|
|
||||||
int imm = SignExtend16ToS32(op & 0xFFFC);
|
int imm = SignExtend16ToS32(op & 0xFFFC);
|
||||||
int rs = _RS;
|
int rs = _RS;
|
||||||
int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5);
|
int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5);
|
||||||
@@ -210,31 +209,29 @@ namespace MIPSInt
|
|||||||
float *f;
|
float *f;
|
||||||
const float *cf;
|
const float *cf;
|
||||||
|
|
||||||
switch (op >> 26)
|
switch (op >> 26) {
|
||||||
{
|
|
||||||
case 53: //lvl.q/lvr.q
|
case 53: //lvl.q/lvr.q
|
||||||
{
|
{
|
||||||
if (addr & 0x3)
|
|
||||||
{
|
|
||||||
_dbg_assert_msg_( 0, "Misaligned lvX.q at %08x (pc = %08x)", addr, PC);
|
|
||||||
}
|
|
||||||
float d[4];
|
float d[4];
|
||||||
ReadVector(d, V_Quad, vt);
|
ReadVector(d, V_Quad, vt);
|
||||||
int offset = (addr >> 2) & 3;
|
int offset = (addr >> 2) & 3;
|
||||||
if ((op & 2) == 0)
|
if ((op & 2) == 0) {
|
||||||
{
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
// It's an LVL
|
Core_MemoryException(addr, 16, PC, MemoryExceptionType::READ_WORD, "lvl.q");
|
||||||
for (int i = 0; i < offset + 1; i++)
|
return;
|
||||||
{
|
}
|
||||||
d[3 - i] = Memory::Read_Float(addr - 4 * i);
|
// It's an LVL
|
||||||
|
for (int i = 0; i < offset + 1; i++) {
|
||||||
|
d[3 - i] = Memory::ReadUnchecked_Float(addr - 4 * i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 16, PC, MemoryExceptionType::READ_WORD, "lvr.q");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// It's an LVR
|
// It's an LVR
|
||||||
for (int i = 0; i < (3 - offset) + 1; i++)
|
for (int i = 0; i < (3 - offset) + 1; i++) {
|
||||||
{
|
d[i] = Memory::ReadUnchecked_Float(addr + 4 * i);
|
||||||
d[i] = Memory::Read_Float(addr + 4 * i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WriteVector(d, V_Quad, vt);
|
WriteVector(d, V_Quad, vt);
|
||||||
@@ -242,21 +239,21 @@ namespace MIPSInt
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 54: //lv.q
|
case 54: //lv.q
|
||||||
if (addr & 0xF)
|
if ((addr & 0xF) || !Memory::IsValid4AlignedAddress(addr)) {
|
||||||
{
|
Core_MemoryException(addr, 16, PC, MemoryExceptionType::READ_WORD, "lv.q");
|
||||||
_dbg_assert_msg_( 0, "Misaligned lv.q at %08x (pc = %08x)", addr, PC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef COMMON_BIG_ENDIAN
|
#ifndef COMMON_BIG_ENDIAN
|
||||||
cf = reinterpret_cast<const float *>(Memory::GetPointerRange(addr, 16));
|
cf = reinterpret_cast<const float *>(Memory::GetPointerUnchecked(addr));
|
||||||
if (cf)
|
if (cf)
|
||||||
WriteVector(cf, V_Quad, vt);
|
WriteVector(cf, V_Quad, vt);
|
||||||
#else
|
#else
|
||||||
float lvqd[4];
|
float lvqd[4];
|
||||||
|
|
||||||
lvqd[0] = Memory::Read_Float(addr);
|
lvqd[0] = Memory::ReadUnchecked_Float(addr);
|
||||||
lvqd[1] = Memory::Read_Float(addr + 4);
|
lvqd[1] = Memory::ReadUnchecked_Float(addr + 4);
|
||||||
lvqd[2] = Memory::Read_Float(addr + 8);
|
lvqd[2] = Memory::ReadUnchecked_Float(addr + 8);
|
||||||
lvqd[3] = Memory::Read_Float(addr + 12);
|
lvqd[3] = Memory::ReadUnchecked_Float(addr + 12);
|
||||||
|
|
||||||
WriteVector(lvqd, V_Quad, vt);
|
WriteVector(lvqd, V_Quad, vt);
|
||||||
#endif
|
#endif
|
||||||
@@ -264,49 +261,49 @@ namespace MIPSInt
|
|||||||
|
|
||||||
case 61: // svl.q/svr.q
|
case 61: // svl.q/svr.q
|
||||||
{
|
{
|
||||||
if (addr & 0x3)
|
|
||||||
{
|
|
||||||
_dbg_assert_msg_( 0, "Misaligned svX.q at %08x (pc = %08x)", addr, PC);
|
|
||||||
}
|
|
||||||
float d[4];
|
float d[4];
|
||||||
ReadVector(d, V_Quad, vt);
|
ReadVector(d, V_Quad, vt);
|
||||||
int offset = (addr >> 2) & 3;
|
int offset = (addr >> 2) & 3;
|
||||||
if ((op&2) == 0)
|
if ((op & 2) == 0) {
|
||||||
{
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 16, PC, MemoryExceptionType::WRITE_WORD, "svl.q");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// It's an SVL
|
// It's an SVL
|
||||||
for (int i = 0; i < offset + 1; i++)
|
for (int i = 0; i < offset + 1; i++)
|
||||||
{
|
{
|
||||||
Memory::Write_Float(d[3 - i], addr - i * 4);
|
Memory::WriteUnchecked_Float(d[3 - i], addr - i * 4);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!Memory::IsValid4AlignedAddress(addr)) {
|
||||||
|
Core_MemoryException(addr, 16, PC, MemoryExceptionType::WRITE_WORD, "svr.q");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// It's an SVR
|
// It's an SVR
|
||||||
for (int i = 0; i < (3 - offset) + 1; i++)
|
for (int i = 0; i < (3 - offset) + 1; i++) {
|
||||||
{
|
Memory::WriteUnchecked_Float(d[i], addr + 4 * i);
|
||||||
Memory::Write_Float(d[i], addr + 4 * i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 62: //sv.q
|
case 62: //sv.q
|
||||||
if (addr & 0xF)
|
if ((addr & 0xF) || !Memory::IsValid4AlignedAddress(addr)) {
|
||||||
{
|
Core_MemoryException(addr, 16, PC, MemoryExceptionType::WRITE_WORD, "sv.q");
|
||||||
_dbg_assert_msg_( 0, "Misaligned sv.q at %08x (pc = %08x)", addr, PC);
|
|
||||||
}
|
}
|
||||||
#ifndef COMMON_BIG_ENDIAN
|
#ifndef COMMON_BIG_ENDIAN
|
||||||
f = reinterpret_cast<float *>(Memory::GetPointerWriteRange(addr, 16));
|
f = reinterpret_cast<float *>(Memory::GetPointerWriteUnchecked(addr));
|
||||||
if (f)
|
if (f) {
|
||||||
ReadVector(f, V_Quad, vt);
|
ReadVector(f, V_Quad, vt);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
float svqd[4];
|
float svqd[4];
|
||||||
ReadVector(svqd, V_Quad, vt);
|
ReadVector(svqd, V_Quad, vt);
|
||||||
|
|
||||||
Memory::Write_Float(svqd[0], addr);
|
Memory::WriteUnchecked_Float(svqd[0], addr);
|
||||||
Memory::Write_Float(svqd[1], addr + 4);
|
Memory::WriteUnchecked_Float(svqd[1], addr + 4);
|
||||||
Memory::Write_Float(svqd[2], addr + 8);
|
Memory::WriteUnchecked_Float(svqd[2], addr + 8);
|
||||||
Memory::Write_Float(svqd[3], addr + 12);
|
Memory::WriteUnchecked_Float(svqd[3], addr + 12);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
+14
-8
@@ -238,14 +238,6 @@ inline void WriteUnchecked_U8(u8 data, u32 address) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float Read_Float(u32 address)
|
|
||||||
{
|
|
||||||
u32 ifloat = Read_U32(address);
|
|
||||||
float f;
|
|
||||||
memcpy(&f, &ifloat, sizeof(float));
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// used by JIT. Return zero-extended 32bit values
|
// used by JIT. Return zero-extended 32bit values
|
||||||
u32 Read_U8_ZX(const u32 address);
|
u32 Read_U8_ZX(const u32 address);
|
||||||
u32 Read_U16_ZX(const u32 address);
|
u32 Read_U16_ZX(const u32 address);
|
||||||
@@ -325,6 +317,20 @@ inline bool IsValidAddress(const u32 address) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool IsValid2AlignedAddress(const u32 address) {
|
||||||
|
if ((address & 0x3E000001) == 0x08000000) {
|
||||||
|
return true;
|
||||||
|
} else if ((address & 0x3F800001) == 0x04000000) {
|
||||||
|
return address < 0x80000000; // Let's disallow kernel-flagged VRAM. We don't have it mapped and I am not sure if it's accessible.
|
||||||
|
} else if ((address & 0xBFFFC001) == 0x00010000) {
|
||||||
|
return true;
|
||||||
|
} else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
|
||||||
|
return (address & 1) == 0;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline bool IsValid4AlignedAddress(const u32 address) {
|
inline bool IsValid4AlignedAddress(const u32 address) {
|
||||||
if ((address & 0x3E000003) == 0x08000000) {
|
if ((address & 0x3E000003) == 0x08000000) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ void ImMemView::PopupMenu() {
|
|||||||
|
|
||||||
if (ImGui::MenuItem("Copy value (float32)")) {
|
if (ImGui::MenuItem("Copy value (float32)")) {
|
||||||
char temp[64];
|
char temp[64];
|
||||||
snprintf(temp, sizeof(temp), "%f", Memory::IsValidAddress(curAddress_) ? Memory::Read_Float(curAddress_) : NAN);
|
snprintf(temp, sizeof(temp), "%f", Memory::IsValid4AlignedAddress(curAddress_) ? Memory::ReadUnchecked_Float(curAddress_) : NAN);
|
||||||
System_CopyStringToClipboard(temp);
|
System_CopyStringToClipboard(temp);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -597,7 +597,7 @@ void CtrlMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) {
|
|||||||
{
|
{
|
||||||
auto memLock = Memory::Lock();
|
auto memLock = Memory::Lock();
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << (Memory::IsValidAddress(curAddress_) ? Memory::Read_Float(curAddress_) : NAN);
|
stream << (Memory::IsValid4AlignedAddress(curAddress_) ? Memory::ReadUnchecked_Float(curAddress_) : NAN);
|
||||||
auto temp_string = stream.str();
|
auto temp_string = stream.str();
|
||||||
W32Util::CopyTextToClipboard(wnd, temp_string);
|
W32Util::CopyTextToClipboard(wnd, temp_string);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user