Android project - Add vtlbDef.h

This commit is contained in:
k2154
2025-08-18 07:26:56 +09:00
parent 9da187a868
commit 71f36c6ea3
16 changed files with 274 additions and 220 deletions
+1 -3
View File
@@ -57,7 +57,6 @@ namespace a64 = vixl::aarch64;
// fastmem
#define RFASTMEMBASE a64::x25
#define PTR_MBLOCK(field) a64::MemOperand(RFASTMEMBASE, offsetof(microBlock, field))
#define RSTATE_x26 a64::x26
@@ -70,9 +69,8 @@ namespace a64 = vixl::aarch64;
#define RSTATE_MVU a64::x28
#define PTR_MVU(field) a64::MemOperand(RSTATE_MVU, offsetof(vuRegistersPack, field))
// iopMem->Main, vu1Thread
// iopMem->Main
#define RSTATE_x29 a64::x29
#define PTR_VU1(field) a64::MemOperand(RSTATE_x29, offsetof(VU_Thread, field))
static inline s64 GetPCDisplacement(const void* current, const void* target)
{
+1 -1
View File
@@ -9,7 +9,7 @@
#include <thread>
VU_Thread vu1Thread;
//VU_Thread vu1Thread;
#define MTVU_ALWAYS_KICK 0
#define MTVU_SYNC_MODE 0
+1 -1
View File
@@ -120,4 +120,4 @@ private:
u32 Get_vuCycles();
};
extern VU_Thread vu1Thread;
extern VU_Thread& vu1Thread;
+1 -1
View File
@@ -34,7 +34,7 @@ using namespace R5900; // for R5900 disasm tools
s32 EEsCycle; // used to sync the IOP to the EE
u32 EEoCycle;
alignas(32) cpuRegistersPack g_cpuRegistersPack;
alignas(64) cpuRegistersPack g_cpuRegistersPack;
alignas(16) tlbs tlb[48];
cachedTlbs_t cachedTlbs;
+4 -4
View File
@@ -8,25 +8,25 @@
#include "R5900Def.h"
#include "R3000ADef.h"
#include "VUDef.h"
#include "vtlbDef.h"
struct cpuRegistersPack
{
alignas(16) cpuRegisters cpuRegs{};
alignas(16) fpuRegisters fpuRegs{};
alignas(16) psxRegisters psxRegs{};
alignas(16) VIFregisters vifRegs[2]{};
alignas(16) VURegs vuRegs[2];
alignas(16) VIFregisters vifRegs[2];
alignas(16) mVU_SSE4 mVUss4;
alignas(32) mVU_Globals mVUglob;
alignas(64) vtlb_private::MapData vtlbdata;
};
alignas(32) extern cpuRegistersPack g_cpuRegistersPack;
alignas(64) extern cpuRegistersPack g_cpuRegistersPack;
////
static cpuRegisters& cpuRegs = g_cpuRegistersPack.cpuRegs;
static fpuRegisters& fpuRegs = g_cpuRegistersPack.fpuRegs;
static psxRegisters& psxRegs = g_cpuRegistersPack.psxRegs;
static VURegs& VU0 = g_cpuRegistersPack.vuRegs[0];
static VURegs& VU1 = g_cpuRegistersPack.vuRegs[1];
static mVU_SSE4& mVUClamp = g_cpuRegistersPack.mVUss4;
static mVU_Globals& mVUglob = g_cpuRegistersPack.mVUglob;
#endif //PCSX2_CPUREGISTERSPACK_H
+1 -1
View File
@@ -44,7 +44,7 @@ using namespace vtlb_private;
namespace vtlb_private
{
alignas(64) MapData vtlbdata;
MapData& vtlbdata = g_cpuRegistersPack.vtlbdata;
} // namespace vtlb_private
static vtlbHandler vtlbHandlerCount = 0;
+1 -137
View File
@@ -3,42 +3,11 @@
#pragma once
#include "MemoryTypes.h"
#include "vtlbDef.h"
#include "common/HostSys.h"
#include "common/SingleRegisterTypes.h"
static const uptr VTLB_AllocUpperBounds = _1gb * 2;
// Specialized function pointers for each read type
typedef mem8_t vtlbMemR8FP(u32 addr);
typedef mem16_t vtlbMemR16FP(u32 addr);
typedef mem32_t vtlbMemR32FP(u32 addr);
typedef mem64_t vtlbMemR64FP(u32 addr);
typedef RETURNS_R128 vtlbMemR128FP(u32 addr);
// Specialized function pointers for each write type
typedef void vtlbMemW8FP(u32 addr,mem8_t data);
typedef void vtlbMemW16FP(u32 addr,mem16_t data);
typedef void vtlbMemW32FP(u32 addr,mem32_t data);
typedef void vtlbMemW64FP(u32 addr,mem64_t data);
typedef void TAKES_R128 vtlbMemW128FP(u32 addr,r128 data);
template <size_t Width, bool Write> struct vtlbMemFP;
template<> struct vtlbMemFP< 8, false> { typedef vtlbMemR8FP fn; static const uptr Index = 0; };
template<> struct vtlbMemFP< 16, false> { typedef vtlbMemR16FP fn; static const uptr Index = 1; };
template<> struct vtlbMemFP< 32, false> { typedef vtlbMemR32FP fn; static const uptr Index = 2; };
template<> struct vtlbMemFP< 64, false> { typedef vtlbMemR64FP fn; static const uptr Index = 3; };
template<> struct vtlbMemFP<128, false> { typedef vtlbMemR128FP fn; static const uptr Index = 4; };
template<> struct vtlbMemFP< 8, true> { typedef vtlbMemW8FP fn; static const uptr Index = 0; };
template<> struct vtlbMemFP< 16, true> { typedef vtlbMemW16FP fn; static const uptr Index = 1; };
template<> struct vtlbMemFP< 32, true> { typedef vtlbMemW32FP fn; static const uptr Index = 2; };
template<> struct vtlbMemFP< 64, true> { typedef vtlbMemW64FP fn; static const uptr Index = 3; };
template<> struct vtlbMemFP<128, true> { typedef vtlbMemW128FP fn; static const uptr Index = 4; };
typedef u32 vtlbHandler;
extern bool vtlb_Core_Alloc();
extern void vtlb_Core_Free();
extern void vtlb_Alloc_Ppmap();
@@ -115,111 +84,6 @@ extern void vtlb_DynGenWrite_Const(u32 bits, bool xmm, u32 addr_const, int value
extern void vtlb_DynGenDispatchers();
namespace vtlb_private
{
static const uint VTLB_PAGE_BITS = 12;
static const uint VTLB_PAGE_MASK = 4095;
static const uint VTLB_PAGE_SIZE = 4096;
static const uint VTLB_PMAP_SZ = _1mb * 512;
static const uint VTLB_PMAP_ITEMS = VTLB_PMAP_SZ / VTLB_PAGE_SIZE;
static const uint VTLB_VMAP_ITEMS = _4gb / VTLB_PAGE_SIZE;
static const uint VTLB_HANDLER_ITEMS = 128;
static const uptr POINTER_SIGN_BIT = 1ULL << (sizeof(uptr) * 8 - 1);
struct VTLBPhysical
{
private:
sptr value;
explicit VTLBPhysical(sptr value): value(value) { }
public:
VTLBPhysical(): value(0) {}
/// Create from a pointer to raw memory
static VTLBPhysical fromPointer(void *ptr) { return fromPointer((sptr)ptr); }
/// Create from an integer representing a pointer to raw memory
static VTLBPhysical fromPointer(sptr ptr);
/// Create from a handler and address
static VTLBPhysical fromHandler(vtlbHandler handler);
/// Get the raw value held by the entry
uptr raw() const { return value; }
/// Returns whether or not this entry is a handler
bool isHandler() const { return value < 0; }
/// Assumes the entry is a pointer, giving back its value
uptr assumePtr() const { return value; }
/// Assumes the entry is a handler, and gets the raw handler ID
u8 assumeHandler() const { return value; }
};
struct VTLBVirtual
{
private:
uptr value;
explicit VTLBVirtual(uptr value): value(value) { }
public:
VTLBVirtual(): value(0) {}
VTLBVirtual(VTLBPhysical phys, u32 paddr, u32 vaddr);
static VTLBVirtual fromPointer(uptr ptr, u32 vaddr) {
return VTLBVirtual(VTLBPhysical::fromPointer(ptr), 0, vaddr);
}
/// Get the raw value held by the entry
uptr raw() const { return value; }
/// Returns whether or not this entry is a handler
bool isHandler(u32 vaddr) const { return (sptr)(value + vaddr) < 0; }
/// Assumes the entry is a pointer, giving back its value
uptr assumePtr(u32 vaddr) const { return value + vaddr; }
/// Assumes the entry is a handler, and gets the raw handler ID
u8 assumeHandlerGetID() const { return value; }
/// Assumes the entry is a handler, and gets the physical address
u32 assumeHandlerGetPAddr(u32 vaddr) const { return (value + vaddr - assumeHandlerGetID()) & ~POINTER_SIGN_BIT; }
/// Assumes the entry is a handler, returning it as a void*
void *assumeHandlerGetRaw(int index, bool write) const;
/// Assumes the entry is a handler, returning it
template <size_t Width, bool Write>
typename vtlbMemFP<Width, Write>::fn *assumeHandler() const;
};
struct MapData
{
// first indexer -- 8/16/32/64/128 bit tables [values 0-4]
// second indexer -- read/write [0 or 1]
// third indexer -- 128 possible handlers!
void* RWFT[5][2][VTLB_HANDLER_ITEMS];
VTLBPhysical pmap[VTLB_PMAP_ITEMS]; //512KB // PS2 physical to x86 physical
VTLBVirtual* vmap; //4MB (allocated by vtlb_init) // PS2 virtual to x86 physical
u32* ppmap; //4MB (allocated by vtlb_init) // PS2 virtual to PS2 physical
uptr fastmem_base;
MapData()
{
vmap = NULL;
ppmap = NULL;
fastmem_base = 0;
}
};
alignas(64) extern MapData vtlbdata;
inline void *VTLBVirtual::assumeHandlerGetRaw(int index, bool write) const
{
return vtlbdata.RWFT[index][write][assumeHandlerGetID()];
}
template <size_t Width, bool Write>
typename vtlbMemFP<Width, Write>::fn *VTLBVirtual::assumeHandler() const
{
using FP = vtlbMemFP<Width, Write>;
return (typename FP::fn *)assumeHandlerGetRaw(FP::Index, Write);
}
}
enum vtlb_ProtectionMode
{
ProtMode_None = 0, // page is 'unaccounted' -- neither protected nor unprotected
+145
View File
@@ -0,0 +1,145 @@
//
// Created by k2154 on 2025-08-18.
//
#ifndef PCSX2_VTLBDEF_H
#define PCSX2_VTLBDEF_H
#include "MemoryTypes.h"
#include "common/SingleRegisterTypes.h"
// Specialized function pointers for each read type
typedef mem8_t vtlbMemR8FP(u32 addr);
typedef mem16_t vtlbMemR16FP(u32 addr);
typedef mem32_t vtlbMemR32FP(u32 addr);
typedef mem64_t vtlbMemR64FP(u32 addr);
typedef RETURNS_R128 vtlbMemR128FP(u32 addr);
// Specialized function pointers for each write type
typedef void vtlbMemW8FP(u32 addr,mem8_t data);
typedef void vtlbMemW16FP(u32 addr,mem16_t data);
typedef void vtlbMemW32FP(u32 addr,mem32_t data);
typedef void vtlbMemW64FP(u32 addr,mem64_t data);
typedef void TAKES_R128 vtlbMemW128FP(u32 addr,r128 data);
template <size_t Width, bool Write> struct vtlbMemFP;
template<> struct vtlbMemFP< 8, false> { typedef vtlbMemR8FP fn; static const uptr Index = 0; };
template<> struct vtlbMemFP< 16, false> { typedef vtlbMemR16FP fn; static const uptr Index = 1; };
template<> struct vtlbMemFP< 32, false> { typedef vtlbMemR32FP fn; static const uptr Index = 2; };
template<> struct vtlbMemFP< 64, false> { typedef vtlbMemR64FP fn; static const uptr Index = 3; };
template<> struct vtlbMemFP<128, false> { typedef vtlbMemR128FP fn; static const uptr Index = 4; };
template<> struct vtlbMemFP< 8, true> { typedef vtlbMemW8FP fn; static const uptr Index = 0; };
template<> struct vtlbMemFP< 16, true> { typedef vtlbMemW16FP fn; static const uptr Index = 1; };
template<> struct vtlbMemFP< 32, true> { typedef vtlbMemW32FP fn; static const uptr Index = 2; };
template<> struct vtlbMemFP< 64, true> { typedef vtlbMemW64FP fn; static const uptr Index = 3; };
template<> struct vtlbMemFP<128, true> { typedef vtlbMemW128FP fn; static const uptr Index = 4; };
typedef u32 vtlbHandler;
namespace vtlb_private
{
static const uint VTLB_PAGE_BITS = 12;
static const uint VTLB_PAGE_MASK = 4095;
static const uint VTLB_PAGE_SIZE = 4096;
static const uint VTLB_PMAP_SZ = _1mb * 512;
static const uint VTLB_PMAP_ITEMS = VTLB_PMAP_SZ / VTLB_PAGE_SIZE;
static const uint VTLB_VMAP_ITEMS = _4gb / VTLB_PAGE_SIZE;
static const uint VTLB_HANDLER_ITEMS = 128;
static const uptr POINTER_SIGN_BIT = 1ULL << (sizeof(uptr) * 8 - 1);
struct VTLBPhysical
{
private:
sptr value;
explicit VTLBPhysical(sptr value): value(value) { }
public:
VTLBPhysical(): value(0) {}
/// Create from a pointer to raw memory
static VTLBPhysical fromPointer(void *ptr) { return fromPointer((sptr)ptr); }
/// Create from an integer representing a pointer to raw memory
static VTLBPhysical fromPointer(sptr ptr);
/// Create from a handler and address
static VTLBPhysical fromHandler(vtlbHandler handler);
/// Get the raw value held by the entry
uptr raw() const { return value; }
/// Returns whether or not this entry is a handler
bool isHandler() const { return value < 0; }
/// Assumes the entry is a pointer, giving back its value
uptr assumePtr() const { return value; }
/// Assumes the entry is a handler, and gets the raw handler ID
u8 assumeHandler() const { return value; }
};
struct VTLBVirtual
{
public:
uptr value;
explicit VTLBVirtual(uptr value): value(value) { }
public:
VTLBVirtual(): value(0) {}
VTLBVirtual(VTLBPhysical phys, u32 paddr, u32 vaddr);
static VTLBVirtual fromPointer(uptr ptr, u32 vaddr) {
return VTLBVirtual(VTLBPhysical::fromPointer(ptr), 0, vaddr);
}
/// Get the raw value held by the entry
uptr raw() const { return value; }
/// Returns whether or not this entry is a handler
bool isHandler(u32 vaddr) const { return (sptr)(value + vaddr) < 0; }
/// Assumes the entry is a pointer, giving back its value
uptr assumePtr(u32 vaddr) const { return value + vaddr; }
/// Assumes the entry is a handler, and gets the raw handler ID
u8 assumeHandlerGetID() const { return value; }
/// Assumes the entry is a handler, and gets the physical address
u32 assumeHandlerGetPAddr(u32 vaddr) const { return (value + vaddr - assumeHandlerGetID()) & ~POINTER_SIGN_BIT; }
/// Assumes the entry is a handler, returning it as a void*
void *assumeHandlerGetRaw(int index, bool write) const;
/// Assumes the entry is a handler, returning it
template <size_t Width, bool Write>
typename vtlbMemFP<Width, Write>::fn *assumeHandler() const;
};
struct MapData
{
// first indexer -- 8/16/32/64/128 bit tables [values 0-4]
// second indexer -- read/write [0 or 1]
// third indexer -- 128 possible handlers!
void* RWFT[5][2][VTLB_HANDLER_ITEMS];
VTLBPhysical pmap[VTLB_PMAP_ITEMS]; //512KB // PS2 physical to x86 physical
VTLBVirtual* vmap; //4MB (allocated by vtlb_init) // PS2 virtual to x86 physical
u32* ppmap; //4MB (allocated by vtlb_init) // PS2 virtual to PS2 physical
uptr fastmem_base;
MapData()
{
vmap = NULL;
ppmap = NULL;
fastmem_base = 0;
}
};
extern MapData& vtlbdata;
inline void *VTLBVirtual::assumeHandlerGetRaw(int index, bool write) const
{
return vtlbdata.RWFT[index][write][assumeHandlerGetID()];
}
template <size_t Width, bool Write>
typename vtlbMemFP<Width, Write>::fn *VTLBVirtual::assumeHandler() const
{
using FP = vtlbMemFP<Width, Write>;
return (typename FP::fn *)assumeHandlerGetRaw(FP::Index, Write);
}
}
#endif //PCSX2_VTLBDEF_H
@@ -493,7 +493,7 @@ static const void* _DynGen_EnterRecompiledCode()
if (CHECK_FASTMEM) {
// xMOV(RFASTMEMBASE, ptrNative[&vtlb_private::vtlbdata.fastmem_base]);
armAsm->Ldr(RFASTMEMBASE, armMemOperandPtr(&vtlb_private::vtlbdata.fastmem_base));
armAsm->Ldr(RFASTMEMBASE, PTR_CPU(vtlbdata.fastmem_base));
}
// xJMP(DispatcherReg);
+90 -49
View File
@@ -166,7 +166,8 @@ namespace vtlb_private
// xSHR(eax, VTLB_PAGE_BITS);
armAsm->Lsr(EAX, EAX, VTLB_PAGE_BITS);
// xMOV(rax, ptrNative[xComplexAddress(arg3reg, vtlbdata.vmap, rax * wordsize)]);
armMoveAddressToReg(RXVIXLSCRATCH, vtlbdata.vmap);
// armMoveAddressToReg(RXVIXLSCRATCH, vtlbdata.vmap);
armAsm->Ldr(RXVIXLSCRATCH, PTR_CPU(vtlbdata.vmap));
armAsm->Ldr(RAX, a64::MemOperand(RXVIXLSCRATCH, RAX, a64::LSL, 3));
// xADD(arg1reg, rax);
armAsm->Adds(RCX, RCX, RAX);
@@ -177,49 +178,50 @@ namespace vtlb_private
{
pxAssert(bits == 8 || bits == 16 || bits == 32 || bits == 64 || bits == 128);
auto mop = a64::MemOperand(RCX);
switch (bits)
{
case 8:
if (sign) {
// xMOVSX(rax, ptr8[arg1reg]);
armAsm->Ldrsb(RAX, a64::MemOperand(RCX));
armAsm->Ldrsb(RAX, mop);
}
else {
// xMOVZX(rax, ptr8[arg1reg]);
armAsm->Ldrb(RAX, a64::MemOperand(RCX));
armAsm->Ldrb(RAX, mop);
}
break;
case 16:
if (sign) {
// xMOVSX(rax, ptr16[arg1reg]);
armAsm->Ldrsh(RAX, a64::MemOperand(RCX));
armAsm->Ldrsh(RAX, mop);
}
else {
// xMOVZX(rax, ptr16[arg1reg]);
armAsm->Ldrh(RAX, a64::MemOperand(RCX));
armAsm->Ldrh(RAX, mop);
}
break;
case 32:
if (sign) {
// xMOVSX(rax, ptr32[arg1reg]);
armAsm->Ldrsw(RAX, a64::MemOperand(RCX));
armAsm->Ldrsw(RAX, mop);
}
else {
// xMOV(eax, ptr32[arg1reg]);
armAsm->Ldr(EAX, a64::MemOperand(RCX));
armAsm->Ldr(EAX, mop);
}
break;
case 64:
// xMOV(rax, ptr64[arg1reg]);
armAsm->Ldr(RAX, a64::MemOperand(RCX));
armAsm->Ldr(RAX, mop);
break;
case 128:
// xMOVAPS(xmm0, ptr128[arg1reg]);
armAsm->Ldr(xmm0.Q(), a64::MemOperand(RCX));
armAsm->Ldr(xmm0.Q(), mop);
break;
jNO_DEFAULT
@@ -229,31 +231,32 @@ namespace vtlb_private
// ------------------------------------------------------------------------
static void DynGen_DirectWrite(u32 bits)
{
auto mop = a64::MemOperand(RCX);
switch (bits)
{
case 8:
// xMOV(ptr[arg1reg], xRegister8(arg2regd));
armAsm->Strb(EDX, a64::MemOperand(RCX));
armAsm->Strb(EDX, mop);
break;
case 16:
// xMOV(ptr[arg1reg], xRegister16(arg2regd));
armAsm->Strh(EDX, a64::MemOperand(RCX));
armAsm->Strh(EDX, mop);
break;
case 32:
// xMOV(ptr[arg1reg], arg2regd);
armAsm->Str(EDX, a64::MemOperand(RCX));
armAsm->Str(EDX, mop);
break;
case 64:
// xMOV(ptr[arg1reg], arg2reg);
armAsm->Str(RDX, a64::MemOperand(RCX));
armAsm->Str(RDX, mop);
break;
case 128:
// xMOVAPS(ptr[arg1reg], xRegisterSSE::GetArgRegister(1, 0));
armAsm->Str(armQRegister(1).Q(), a64::MemOperand(RCX));
armAsm->Str(armQRegister(1).Q(), mop);
break;
}
}
@@ -425,7 +428,7 @@ void vtlb_DynGenDispatchers()
//// copy code
memcpy(code_start, m_IndirectDispatchers, INDIRECT_DISPATCHERS_SIZE);
////
armSetAsmPtr(code_start, INDIRECT_DISPATCHERS_SIZE, nullptr);
armSetAsmPtr(code_start + INDIRECT_DISPATCHERS_SIZE, INDIRECT_DISPATCHERS_SIZE, nullptr);
armStartBlock();
}
@@ -469,7 +472,7 @@ int vtlb_DynGenReadNonQuad(u32 bits, bool sign, bool xmm, int addr_reg, vtlb_Rea
const u8* codeStart;
// const xAddressReg x86addr(addr_reg);
a64::MemOperand baseAddr = a64::MemOperand(RFASTMEMBASE, a64::XRegister(addr_reg));
a64::MemOperand x86addr = a64::MemOperand(RFASTMEMBASE, a64::XRegister(addr_reg));
if (!xmm)
{
@@ -479,23 +482,24 @@ int vtlb_DynGenReadNonQuad(u32 bits, bool sign, bool xmm, int addr_reg, vtlb_Rea
codeStart = armGetCurrentCodePointer();
// const xRegister64 x86reg(x86_dest_reg);
auto x86reg = a64::XRegister(x86_dest_reg);
switch (bits)
{
case 8:
// sign ? xMOVSX(x86reg, ptr8[RFASTMEMBASE + x86addr]) : xMOVZX(xRegister32(x86reg), ptr8[RFASTMEMBASE + x86addr]);
sign ? armAsm->Ldrsb(a64::XRegister(x86_dest_reg), baseAddr) : armAsm->Ldrb(a64::WRegister(x86_dest_reg), baseAddr);
sign ? armAsm->Ldrsb(x86reg, x86addr) : armAsm->Ldrb(x86reg.W(), x86addr);
break;
case 16:
// sign ? xMOVSX(x86reg, ptr16[RFASTMEMBASE + x86addr]) : xMOVZX(xRegister32(x86reg), ptr16[RFASTMEMBASE + x86addr]);
sign ? armAsm->Ldrsh(a64::XRegister(x86_dest_reg), baseAddr) : armAsm->Ldrh(a64::WRegister(x86_dest_reg), baseAddr);
sign ? armAsm->Ldrsh(x86reg, x86addr) : armAsm->Ldrh(x86reg.W(), x86addr);
break;
case 32:
// sign ? xMOVSX(x86reg, ptr32[RFASTMEMBASE + x86addr]) : xMOV(xRegister32(x86reg), ptr32[RFASTMEMBASE + x86addr]);
sign ? armAsm->Ldrsw(a64::XRegister(x86_dest_reg), baseAddr) : armAsm->Ldr(a64::WRegister(x86_dest_reg), baseAddr);
sign ? armAsm->Ldrsw(x86reg, x86addr) : armAsm->Ldr(x86reg.W(), x86addr);
break;
case 64:
// xMOV(x86reg, ptr64[RFASTMEMBASE + x86addr]);
armAsm->Ldr(a64::XRegister(x86_dest_reg), baseAddr);
armAsm->Ldr(x86reg, x86addr);
break;
jNO_DEFAULT
@@ -510,7 +514,7 @@ int vtlb_DynGenReadNonQuad(u32 bits, bool sign, bool xmm, int addr_reg, vtlb_Rea
// const xRegisterSSE xmmreg(x86_dest_reg);
const a64::QRegister xmmreg(x86_dest_reg);
// xMOVSSZX(xmmreg, ptr32[RFASTMEMBASE + x86addr]);
armAsm->Ldr(xmmreg.S(), baseAddr);
armAsm->Ldr(xmmreg.S(), x86addr);
}
// vtlb_AddLoadStoreInfo((uptr)codeStart, static_cast<u32>(x86Ptr - codeStart),
@@ -536,31 +540,43 @@ int vtlb_DynGenReadNonQuad_Const(u32 bits, bool sign, bool xmm, u32 addr_const,
auto vmv = vtlbdata.vmap[addr_const >> VTLB_PAGE_BITS];
if (!vmv.isHandler(addr_const))
{
auto ppf = vmv.assumePtr(addr_const);
// uptr ppf = vmv.assumePtr(addr_const);
// auto mop = armMemOperandPtr((u8*)ppf);
armAsm->Mov(ECX, addr_const);
armAsm->Mov(EAX, ECX);
armAsm->Lsr(EAX, EAX, VTLB_PAGE_BITS);
armAsm->Ldr(RXVIXLSCRATCH, PTR_CPU(vtlbdata.vmap));
armAsm->Ldr(RAX, a64::MemOperand(RXVIXLSCRATCH, RAX, a64::LSL, 3));
armAsm->Add(RCX, RCX, RAX);
auto mop = a64::MemOperand(RCX);
if (!xmm)
{
// x86_dest_reg = dest_reg_alloc ? dest_reg_alloc() : (_freeX86reg(eax), eax.GetId());
x86_dest_reg = dest_reg_alloc ? dest_reg_alloc() : (_freeX86reg(EAX), EAX.GetCode());
auto regX = a64::XRegister(x86_dest_reg);
switch (bits)
{
case 8:
// sign ? xMOVSX(xRegister64(x86_dest_reg), ptr8[(u8*)ppf]) : xMOVZX(xRegister32(x86_dest_reg), ptr8[(u8*)ppf]);
sign ? armAsm->Ldrsb(a64::XRegister(x86_dest_reg), armMemOperandPtr((u8*)ppf)) : armAsm->Ldrb(a64::WRegister(x86_dest_reg), armMemOperandPtr((u8*)ppf));
sign ? armAsm->Ldrsb(regX, mop) : armAsm->Ldrb(regX.W(), mop);
break;
case 16:
// sign ? xMOVSX(xRegister64(x86_dest_reg), ptr16[(u16*)ppf]) : xMOVZX(xRegister32(x86_dest_reg), ptr16[(u16*)ppf]);
sign ? armAsm->Ldrsh(a64::XRegister(x86_dest_reg), armMemOperandPtr((u16*)ppf)) : armAsm->Ldrh(a64::WRegister(x86_dest_reg), armMemOperandPtr((u16*)ppf));
sign ? armAsm->Ldrsh(regX, mop) : armAsm->Ldrh(regX.W(), mop);
break;
case 32:
// sign ? xMOVSX(xRegister64(x86_dest_reg), ptr32[(u32*)ppf]) : xMOV(xRegister32(x86_dest_reg), ptr32[(u32*)ppf]);
sign ? armAsm->Ldrsw(a64::XRegister(x86_dest_reg), armMemOperandPtr((u32*)ppf)) : armAsm->Ldr(a64::WRegister(x86_dest_reg), armMemOperandPtr((u32*)ppf));
sign ? armAsm->Ldrsw(regX, mop) : armAsm->Ldr(regX.W(), mop);
break;
case 64:
// xMOV(xRegister64(x86_dest_reg), ptr64[(u64*)ppf]);
armAsm->Ldr(a64::XRegister(x86_dest_reg), armMemOperandPtr((u64*)ppf));
armAsm->Ldr(regX, mop);
break;
}
}
@@ -568,7 +584,7 @@ int vtlb_DynGenReadNonQuad_Const(u32 bits, bool sign, bool xmm, u32 addr_const,
{
x86_dest_reg = dest_reg_alloc ? dest_reg_alloc() : (_freeXMMreg(0), 0);
// xMOVSSZX(xRegisterSSE(x86_dest_reg), ptr32[(float*)ppf]);
armAsm->Ldr(a64::QRegister(x86_dest_reg).S(), armMemOperandPtr((float*)ppf));
armAsm->Ldr(a64::QRegister(x86_dest_reg).S(), mop);
}
}
else
@@ -619,27 +635,29 @@ int vtlb_DynGenReadNonQuad_Const(u32 bits, bool sign, bool xmm, u32 addr_const,
{
// x86_dest_reg = dest_reg_alloc ? dest_reg_alloc() : (_freeX86reg(eax), eax.GetId());
x86_dest_reg = dest_reg_alloc ? dest_reg_alloc() : (_freeX86reg(EAX), EAX.GetCode());
auto regX = a64::XRegister(x86_dest_reg);
switch (bits)
{
// save REX prefix by using 32bit dest for zext
case 8:
// sign ? xMOVSX(xRegister64(x86_dest_reg), al) : xMOVZX(xRegister32(x86_dest_reg), al);
sign ? armAsm->Sxtb(a64::XRegister(x86_dest_reg), EAX) : armAsm->Uxtb(a64::WRegister(x86_dest_reg), EAX);
sign ? armAsm->Sxtb(regX, EAX) : armAsm->Uxtb(regX.W(), EAX);
break;
case 16:
// sign ? xMOVSX(xRegister64(x86_dest_reg), ax) : xMOVZX(xRegister32(x86_dest_reg), ax);
sign ? armAsm->Sxth(a64::XRegister(x86_dest_reg), EAX) : armAsm->Uxth(a64::WRegister(x86_dest_reg), EAX);
sign ? armAsm->Sxth(regX, EAX) : armAsm->Uxth(regX.W(), EAX);
break;
case 32:
// sign ? xMOVSX(xRegister64(x86_dest_reg), eax) : xMOV(xRegister32(x86_dest_reg), eax);
sign ? armAsm->Sxtw(a64::XRegister(x86_dest_reg), EAX) : armAsm->Mov(a64::WRegister(x86_dest_reg), EAX);
sign ? armAsm->Sxtw(regX, EAX) : armAsm->Mov(regX.W(), EAX);
break;
case 64:
// xMOV(xRegister64(x86_dest_reg), rax);
armAsm->Mov(a64::XRegister(x86_dest_reg) , RAX);
armAsm->Mov(regX , RAX);
break;
}
}
@@ -704,11 +722,19 @@ int vtlb_DynGenReadQuad_Const(u32 bits, u32 addr_const, vtlb_ReadRegAllocCallbac
auto vmv = vtlbdata.vmap[addr_const >> VTLB_PAGE_BITS];
if (!vmv.isHandler(addr_const))
{
void* ppf = reinterpret_cast<void*>(vmv.assumePtr(addr_const));
// void* ppf = reinterpret_cast<void*>(vmv.assumePtr(addr_const));
reg = dest_reg_alloc ? dest_reg_alloc() : (_freeXMMreg(0), 0);
if (reg >= 0) {
// xMOVAPS(xRegisterSSE(reg), ptr128[ppf]);
armAsm->Ldr(a64::QRegister(reg).Q(), armMemOperandPtr(ppf));
// armAsm->Ldr(a64::QRegister(reg).Q(), armMemOperandPtr(ppf));
armAsm->Mov(ECX, addr_const);
armAsm->Mov(EAX, ECX);
armAsm->Lsr(EAX, EAX, VTLB_PAGE_BITS);
armAsm->Ldr(RXVIXLSCRATCH, PTR_CPU(vtlbdata.vmap));
armAsm->Ldr(RAX, a64::MemOperand(RXVIXLSCRATCH, RAX, a64::LSL, 3));
armAsm->Add(RCX, RCX, RAX);
armAsm->Ldr(a64::QRegister(reg).Q(), a64::MemOperand(RCX));
}
}
else
@@ -806,23 +832,24 @@ void vtlb_DynGenWrite(u32 sz, bool xmm, int addr_reg, int value_reg)
if (!xmm)
{
auto regX = a64::XRegister(value_reg);
switch (sz)
{
case 8:
// xMOV(ptr8[RFASTMEMBASE + vaddr_reg], xRegister8(xRegister32(value_reg)));
armAsm->Strb(a64::WRegister(value_reg), mop);
armAsm->Strb(regX.W(), mop);
break;
case 16:
// xMOV(ptr16[RFASTMEMBASE + vaddr_reg], xRegister16(value_reg));
armAsm->Strh(a64::WRegister(value_reg), mop);
armAsm->Strh(regX.W(), mop);
break;
case 32:
// xMOV(ptr32[RFASTMEMBASE + vaddr_reg], xRegister32(value_reg));
armAsm->Str(a64::WRegister(value_reg), mop);
armAsm->Str(regX.W(), mop);
break;
case 64:
// xMOV(ptr64[RFASTMEMBASE + vaddr_reg], xRegister64(value_reg));
armAsm->Str(a64::XRegister(value_reg), mop);
armAsm->Str(regX, mop);
break;
jNO_DEFAULT
@@ -831,15 +858,17 @@ void vtlb_DynGenWrite(u32 sz, bool xmm, int addr_reg, int value_reg)
else
{
pxAssert(sz == 32 || sz == 128);
auto regQ = a64::QRegister(value_reg);
switch (sz)
{
case 32:
// xMOVSS(ptr32[RFASTMEMBASE + vaddr_reg], xRegisterSSE(value_reg));
armAsm->Str(a64::QRegister(value_reg).S(), mop);
armAsm->Str(regQ.S(), mop);
break;
case 128:
// xMOVAPS(ptr128[RFASTMEMBASE + vaddr_reg], xRegisterSSE(value_reg));
armAsm->Str(a64::QRegister(value_reg).Q(), mop);
armAsm->Str(regQ.Q(), mop);
break;
jNO_DEFAULT
@@ -918,30 +947,40 @@ void vtlb_DynGenWrite_Const(u32 bits, bool xmm, u32 addr_const, int value_reg)
auto vmv = vtlbdata.vmap[addr_const >> VTLB_PAGE_BITS];
if (!vmv.isHandler(addr_const))
{
auto ppf = vmv.assumePtr(addr_const);
const a64::MemOperand mop = armMemOperandPtr((void*)ppf);
// auto ppf = vmv.assumePtr(addr_const);
// a64::MemOperand mop = armMemOperandPtr((u8*)ppf);
armAsm->Mov(ECX, addr_const);
armAsm->Mov(EAX, ECX);
armAsm->Lsr(EAX, EAX, VTLB_PAGE_BITS);
armAsm->Ldr(RXVIXLSCRATCH, PTR_CPU(vtlbdata.vmap));
armAsm->Ldr(RAX, a64::MemOperand(RXVIXLSCRATCH, RAX, a64::LSL, 3));
armAsm->Add(RCX, RCX, RAX);
auto mop = a64::MemOperand(RCX);
if (!xmm)
{
auto regX = a64::XRegister(value_reg);
switch (bits)
{
case 8:
// xMOV(ptr[(void*)ppf], xRegister8(xRegister32(value_reg)));
armAsm->Strb(a64::WRegister(value_reg), mop);
armAsm->Strb(regX.W(), mop);
break;
case 16:
// xMOV(ptr[(void*)ppf], xRegister16(value_reg));
armAsm->Strh(a64::WRegister(value_reg), mop);
armAsm->Strh(regX.W(), mop);
break;
case 32:
// xMOV(ptr[(void*)ppf], xRegister32(value_reg));
armAsm->Str(a64::WRegister(value_reg), mop);
armAsm->Str(regX.W(), mop);
break;
case 64:
// xMOV(ptr64[(void*)ppf], xRegister64(value_reg));
armAsm->Str(a64::XRegister(value_reg), mop);
armAsm->Str(regX, mop);
break;
jNO_DEFAULT
@@ -949,16 +988,17 @@ void vtlb_DynGenWrite_Const(u32 bits, bool xmm, u32 addr_const, int value_reg)
}
else
{
auto regQ = a64::QRegister(value_reg);
switch (bits)
{
case 32:
// xMOVSS(ptr[(void*)ppf], xRegisterSSE(value_reg));
armAsm->Str(a64::QRegister(value_reg).S(), mop);
armAsm->Str(regQ.S(), mop);
break;
case 128:
// xMOVAPS(ptr128[(void*)ppf], xRegisterSSE(value_reg));
armAsm->Str(a64::QRegister(value_reg).Q(), mop);
armAsm->Str(regQ.Q(), mop);
break;
jNO_DEFAULT
@@ -1047,8 +1087,9 @@ void vtlb_DynV2P()
// xSHR(eax, VTLB_PAGE_BITS);
armAsm->Lsr(EAX, EAX, VTLB_PAGE_BITS);
// xMOV(eax, ptr[xComplexAddress(rdx, vtlbdata.ppmap, rax * 4)]);
armMoveAddressToReg(RDX, vtlbdata.ppmap);
armAsm->Ldr(EAX, a64::MemOperand(RDX, RAX, a64::LSL, 2));
// armMoveAddressToReg(RDX, vtlbdata.ppmap);
armAsm->Ldr(RXVIXLSCRATCH, PTR_CPU(vtlbdata.ppmap));
armAsm->Ldr(EAX, a64::MemOperand(RXVIXLSCRATCH, RAX, a64::LSL, 2));
// xOR(eax, ecx);
armAsm->Orr(EAX, EAX, ECX);
+2 -1
View File
@@ -7,7 +7,8 @@
#include "common/Perf.h"
#include "common/StringUtil.h"
alignas(16) vuRegistersPack g_vuRegistersPack;
alignas(64) vuRegistersPack g_vuRegistersPack;
VU_Thread& vu1Thread = g_vuRegistersPack.vu1Thread;
//------------------------------------------------------------------
// Micro VU - Main Functions
+2 -1
View File
@@ -278,8 +278,9 @@ public:
struct vuRegistersPack
{
alignas(16) microVU microVU[2];
alignas(64) VU_Thread vu1Thread;
};
alignas(16) extern vuRegistersPack g_vuRegistersPack;
alignas(64) extern vuRegistersPack g_vuRegistersPack;
////
static microVU& microVU0 = g_vuRegistersPack.microVU[0];
static microVU& microVU1 = g_vuRegistersPack.microVU[1];
+16 -10
View File
@@ -413,7 +413,9 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump)
else
{
// xLoadFarAddr(arg2reg, &mVUpBlock->pStateEnd);
armAsm->Ldr(RCX, PTR_MBLOCK(pStateEnd));
armMoveAddressToReg(RCX, &mVUpBlock->pStateEnd);
// armAsm->Ldr(RXVIXLSCRATCH, PTR_MVU(microVU[mVU.index].prog.IRinfo.pBlock));
// armAsm->Add(RCX, RXVIXLSCRATCH, offsetof(microBlock, pStateEnd));
}
if (mVUup.eBit && isEvilJump) // E-bit EvilJump
@@ -442,7 +444,7 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump)
mVUrestoreRegs(mVU);
// xJMP(gprT1q); // Jump to rec-code address
armAsm->Br(RAX);
armAsm->Br(gprT1q);
}
void normBranch(mV, microFlagCycles& mFC)
@@ -456,7 +458,7 @@ void normBranch(mV, microFlagCycles& mFC)
u32 tempPC = iPC;
if (mVU.index && THREAD_VU1) {
// xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(PTR_VU1(vuFBRST)), (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(PTR_MVU(vu1Thread.vuFBRST)), (isVU1 ? 0x400 : 0x4));
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
@@ -486,7 +488,7 @@ void normBranch(mV, microFlagCycles& mFC)
u32 tempPC = iPC;
if (mVU.index && THREAD_VU1) {
// xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(PTR_VU1(vuFBRST)), (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(PTR_MVU(vu1Thread.vuFBRST)), (isVU1 ? 0x800 : 0x8));
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
@@ -515,7 +517,9 @@ void normBranch(mV, microFlagCycles& mFC)
memcpy(&mVUpBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
// xLoadFarAddr(rax, &mVUpBlock->pStateEnd);
armAsm->Ldr(RAX, PTR_MBLOCK(pStateEnd));
armMoveAddressToReg(RAX, &mVUpBlock->pStateEnd);
// armAsm->Ldr(RXVIXLSCRATCH, PTR_MVU(microVU[mVU.index].prog.IRinfo.pBlock));
// armAsm->Add(RAX, RXVIXLSCRATCH, offsetof(microBlock, pStateEnd));
// xCALL((void*)mVU.copyPLState);
armEmitCall(mVU.copyPLState);
@@ -557,7 +561,7 @@ void condBranch(mV, microFlagCycles& mFC, a64::Condition JMPcc)
u32 tempPC = iPC;
if (mVU.index && THREAD_VU1) {
// xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(PTR_VU1(vuFBRST)), (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(PTR_MVU(vu1Thread.vuFBRST)), (isVU1 ? 0x800 : 0x8));
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
@@ -609,7 +613,7 @@ void condBranch(mV, microFlagCycles& mFC, a64::Condition JMPcc)
u32 tempPC = iPC;
if (mVU.index && THREAD_VU1) {
// xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(PTR_VU1(vuFBRST)), (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(PTR_MVU(vu1Thread.vuFBRST)), (isVU1 ? 0x400 : 0x4));
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
@@ -654,7 +658,9 @@ void condBranch(mV, microFlagCycles& mFC, a64::Condition JMPcc)
memcpy(&mVUpBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
// xLoadFarAddr(rax, &mVUpBlock->pStateEnd);
armAsm->Ldr(RAX, PTR_MBLOCK(pStateEnd));
armMoveAddressToReg(RAX, &mVUpBlock->pStateEnd);
// armAsm->Ldr(RXVIXLSCRATCH, PTR_MVU(microVU[mVU.index].prog.IRinfo.pBlock));
// armAsm->Add(RAX, RXVIXLSCRATCH, offsetof(microBlock, pStateEnd));
// xCALL((void*)mVU.copyPLState);
armEmitCall(mVU.copyPLState);
@@ -800,7 +806,7 @@ void normJump(mV, microFlagCycles& mFC)
if (THREAD_VU1) {
// xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(PTR_VU1(vuFBRST)), (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(PTR_MVU(vu1Thread.vuFBRST)), (isVU1 ? 0x400 : 0x4));
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
@@ -833,7 +839,7 @@ void normJump(mV, microFlagCycles& mFC)
if (mVU.index && THREAD_VU1) {
// xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(PTR_VU1(vuFBRST)), (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(PTR_MVU(vu1Thread.vuFBRST)), (isVU1 ? 0x800 : 0x8));
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
@@ -515,7 +515,7 @@ void mVUtestCycles(microVU& mVU, microFlagCycles& mFC)
armAsm->B(&skip, a64::Condition::pl);
// xLoadFarAddr(rax, &mVUpBlock->pState);
armAsm->Ldr(RAX, PTR_MBLOCK(pState));
armMoveAddressToReg(RAX, &mVUpBlock->pState);
// xCALL((void*)mVU.copyPLState);
armEmitCall(mVU.copyPLState);
@@ -597,7 +597,7 @@ void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
{
if (mVU.index && THREAD_VU1) {
// xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(PTR_VU1(vuFBRST)), (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(PTR_MVU(vu1Thread.vuFBRST)), (isVU1 ? 0x400 : 0x4));
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
@@ -624,7 +624,7 @@ void mVUDoTBit(microVU& mVU, microFlagCycles* mFC)
{
if (mVU.index && THREAD_VU1) {
// xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(PTR_VU1(vuFBRST)), (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(PTR_MVU(vu1Thread.vuFBRST)), (isVU1 ? 0x800 : 0x8));
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
@@ -28,10 +28,8 @@ void mVUdispatcherAB(mV)
armBeginStackFrame();
// From memory to registry
armMoveAddressToReg(RSTATE_x29, &vu1Thread);
armMoveAddressToReg(RSTATE_MVU, &g_vuRegistersPack);
armMoveAddressToReg(RSTATE_CPU, &g_cpuRegistersPack);
armMoveAddressToReg(RFASTMEMBASE, &mVUpBlock);
// = The caller has already put the needed parameters in ecx/edx:
if (!isVU1) {
+5 -5
View File
@@ -388,9 +388,9 @@ mVUop(mVU_EEXP)
// xMUL.SS(t1, ptr32[mVUglob.E2]);
armAsm->Fmul(t1.S(), t1.S(), armLoadPtrV(PTR_CPU(mVUglob.E2)).S());
SSE_ADDSS(mVU, xmmPQ, t1);
eexpHelper(&mVUglob.E3);
eexpHelper(&mVUglob.E4);
eexpHelper(&mVUglob.E5);
eexpHelper(PTR_CPU(mVUglob.E3));
eexpHelper(PTR_CPU(mVUglob.E4));
eexpHelper(PTR_CPU(mVUglob.E5));
SSE_MULSS(mVU, t2, Fs);
// xMUL.SS(t2, ptr32[mVUglob.E6]);
armAsm->Fmul(t2.S(), t2.S(), armLoadPtrV(PTR_CPU(mVUglob.E6)).S());
@@ -2069,7 +2069,7 @@ mVUop(mVU_XTOP)
const a64::Register& regT = mVU.regAlloc->allocGPR(-1, _It_, mVUlow.backupVI);
// xMOVZX(regT, ptr16[&mVU.getVifRegs().top]);
if (mVU.index && THREAD_VU1) {
armAsm->Ldrh(regT, PTR_VU1(vifRegs.top));
armAsm->Ldrh(regT, PTR_MVU(vu1Thread.vifRegs.top));
} else {
armAsm->Ldrh(regT, PTR_CPU(vifRegs[mVU.index].top));
}
@@ -2093,7 +2093,7 @@ mVUop(mVU_XITOP)
const a64::Register& regT = mVU.regAlloc->allocGPR(-1, _It_, mVUlow.backupVI);
// xMOVZX(regT, ptr16[&mVU.getVifRegs().itop]);
if (mVU.index && THREAD_VU1) {
armAsm->Ldrh(regT, PTR_VU1(vifRegs.itop));
armAsm->Ldrh(regT, PTR_MVU(vu1Thread.vifRegs.itop));
} else {
armAsm->Ldrh(regT, PTR_CPU(vifRegs[mVU.index].itop));
}