mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
arm64/EE: rehome w4-w7 scratch out of EE-block emitters (rung-3 prep)
x4-x7 become EE-SRA pins in rung 3; every EE-block-inline emission that used them as scratch moves to the non-allocatable scratches instead: - recSkipTimeoutLoop: w4/x5/w6 -> w9/x10/w8 - iCOP2 MAC-flag denorm update + CTC2 STATUS denorm: w4 -> w9 - iCOP2 native VCLIP body: w4 clipflag accumulator -> w9 - recMADD/MADDU/MADD1/MADDU1: HI scratch w4 -> w8 (RWSCRATCH) IOP-rec and VIF-dynarec uses of x4-x7 stay: they only execute behind C boundaries whose EE call sites reload caller-saved pins. Pure re-scratching, no semantic change. 1110/1110 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
fe17838bc1
commit
4473a4b7e5
+15
-13
@@ -495,9 +495,10 @@ static void cop2EmitFlagUpdate(int xyzw)
|
||||
armMoveAddressToReg(RSCRATCHADDR, &s_cop2DenormStatusFlag);
|
||||
armAsm->Ldr(RWSCRATCH, a64::MemOperand(RSCRATCHADDR));
|
||||
|
||||
// Clear current (non-sticky) bits 8-15
|
||||
armAsm->Mov(a64::w4, 0xFF00);
|
||||
armAsm->Bic(RWSCRATCH, RWSCRATCH, a64::w4);
|
||||
// Clear current (non-sticky) bits 8-15. w9 scratch: w4 is an EE-SRA pin
|
||||
// (rung 3) and this body emits inline into EE blocks.
|
||||
armAsm->Mov(a64::w9, 0xFF00);
|
||||
armAsm->Bic(RWSCRATCH, RWSCRATCH, a64::w9);
|
||||
|
||||
// OR macFlag into sticky bits (0-7) — accumulates over time
|
||||
armAsm->Orr(RWSCRATCH, RWSCRATCH, macFlag);
|
||||
@@ -841,8 +842,8 @@ void recCOP2_CTC2()
|
||||
armAsm->And(a64::w2, a64::w2, 0x1800);
|
||||
armAsm->Orr(RWSCRATCH, RWSCRATCH, a64::w2);
|
||||
armAsm->Lsl(a64::w3, RWARG2, 14);
|
||||
armAsm->Mov(a64::w4, 0x3cf0000); // not a valid logical-imm; materialize
|
||||
armAsm->And(a64::w3, a64::w3, a64::w4);
|
||||
armAsm->Mov(a64::w9, 0x3cf0000); // not a valid logical-imm; materialize (w9: w4 is a rung-3 pin)
|
||||
armAsm->And(a64::w3, a64::w3, a64::w9);
|
||||
armAsm->Orr(RWSCRATCH, RWSCRATCH, a64::w3);
|
||||
|
||||
// Broadcast the denormalized value into all 4 lanes of micro_statusflags.
|
||||
@@ -1950,9 +1951,10 @@ void recCOP2_VCLIP()
|
||||
armAsm->Cmp(a64::w2, 0);
|
||||
armAsm->Csel(a64::w1, a64::w1, a64::w3, a64::ne); // w1 = clip value
|
||||
|
||||
// Shift clipflag left by 6
|
||||
armAsm->Ldr(a64::w4, armVU0Mem(&VU0.clipflag));
|
||||
armAsm->Lsl(a64::w4, a64::w4, 6);
|
||||
// Shift clipflag left by 6. Accumulates in w9 across the NEON stretch
|
||||
// below (w4 is a rung-3 EE-SRA pin; this body emits inline into EE blocks).
|
||||
armAsm->Ldr(a64::w9, armVU0Mem(&VU0.clipflag));
|
||||
armAsm->Lsl(a64::w9, a64::w9, 6);
|
||||
|
||||
// Load fs = [x,y,z,w] as integers for the lane comparisons.
|
||||
armAsm->Ldr(RQSCRATCH, armVU0Mem(&VU0.VF[_Fs_cop2])); // q30 = [x,y,z,w]
|
||||
@@ -1985,19 +1987,19 @@ void recCOP2_VCLIP()
|
||||
armAsm->Umov(a64::w2, posMask.V4S(), 0); // 6-bit clip field
|
||||
|
||||
// Merge into clipflag and mask to 24 bits
|
||||
armAsm->Orr(a64::w4, a64::w4, a64::w2);
|
||||
armAsm->And(a64::w4, a64::w4, 0xFFFFFF);
|
||||
armAsm->Orr(a64::w9, a64::w9, a64::w2);
|
||||
armAsm->And(a64::w9, a64::w9, 0xFFFFFF);
|
||||
|
||||
// Store clipflag and sync to VI[REG_CLIP_FLAG]
|
||||
armAsm->Str(a64::w4, armVU0Mem(&VU0.clipflag));
|
||||
armAsm->Str(a64::w4, armVU0Mem(&VU0.VI[REG_CLIP_FLAG]));
|
||||
armAsm->Str(a64::w9, armVU0Mem(&VU0.clipflag));
|
||||
armAsm->Str(a64::w9, armVU0Mem(&VU0.VI[REG_CLIP_FLAG]));
|
||||
|
||||
// Broadcast the new clipflag into all 4 lanes of micro_clipflags. A
|
||||
// subsequent VU0 microprogram loads its clip-flag instances directly from
|
||||
// the VURegs::micro_clipflags field in the mVU Execute prologue — without
|
||||
// this they would be stale (pre-VCLIP). RQSCRATCH is free here (its earlier
|
||||
// fs load is consumed).
|
||||
armAsm->Dup(RQSCRATCH.V4S(), a64::w4);
|
||||
armAsm->Dup(RQSCRATCH.V4S(), a64::w9);
|
||||
armAsm->Str(RQSCRATCH, armVU0Mem(&VU0.micro_clipflags));
|
||||
}
|
||||
|
||||
|
||||
@@ -2063,35 +2063,36 @@ static bool recSkipTimeoutLoop(s32 reg, bool is_timeout_loop)
|
||||
armAsm->Cmp(RECCYCLE, 0);
|
||||
armEmitCondBranch(a64::ge, DispatcherEvent);
|
||||
|
||||
// w4 = reg value (the decrementing counter)
|
||||
armAsm->Ldr(a64::w4, armCpuRegMem(&cpuRegs.GPR.r[reg].UL[0]));
|
||||
// w9 = reg value (the decrementing counter). Scratches are w9/x10/w8:
|
||||
// w4-w7 are rung-3 EE-SRA pins and this emits inline into EE blocks.
|
||||
armAsm->Ldr(a64::w9, armCpuRegMem(&cpuRegs.GPR.r[reg].UL[0]));
|
||||
|
||||
// x5 = reg * 8 + delta (estimated end delta, s64)
|
||||
armAsm->Add(a64::x5, RECCYCLE, a64::Operand(a64::x4, a64::LSL, 3));
|
||||
// x10 = reg * 8 + delta (estimated end delta, s64)
|
||||
armAsm->Add(a64::x10, RECCYCLE, a64::Operand(a64::x9, a64::LSL, 3));
|
||||
|
||||
// x5 = min(x5, 0) — can't run past the next event
|
||||
armAsm->Cmp(a64::x5, 0);
|
||||
armAsm->Csel(a64::x5, a64::xzr, a64::x5, a64::gt); // if x5 > 0, clamp to 0
|
||||
// x10 = min(x10, 0) — can't run past the next event
|
||||
armAsm->Cmp(a64::x10, 0);
|
||||
armAsm->Csel(a64::x10, a64::xzr, a64::x10, a64::gt); // if x10 > 0, clamp to 0
|
||||
|
||||
// w6 = (new_delta - old_delta) >> 3 = iterations consumed (deltas share
|
||||
// w8 = (new_delta - old_delta) >> 3 = iterations consumed (deltas share
|
||||
// the same nextEventCycle base, so their difference equals the absolute
|
||||
// cycle difference).
|
||||
armAsm->Sub(a64::w6, a64::w5, RECCYCLE.W());
|
||||
armAsm->Lsr(a64::w6, a64::w6, 3);
|
||||
armAsm->Sub(RWSCRATCH, a64::w10, RECCYCLE.W());
|
||||
armAsm->Lsr(RWSCRATCH, RWSCRATCH, 3);
|
||||
|
||||
// Commit the new delta into RECCYCLE (no memory store — DispatcherEvent
|
||||
// converts and flushes it if we exit there; otherwise the next block-tail
|
||||
// event check uses RECCYCLE directly).
|
||||
armAsm->Mov(RECCYCLE, a64::x5);
|
||||
armAsm->Mov(RECCYCLE, a64::x10);
|
||||
|
||||
// reg -= iterations consumed; sign-extend into the 64-bit guest reg
|
||||
// (the full UD[0] store covers the UL[0] half).
|
||||
armAsm->Sub(a64::w4, a64::w4, a64::w6);
|
||||
armAsm->Sxtw(a64::x4, a64::w4);
|
||||
armStoreEERegPtr(a64::x4, &cpuRegs.GPR.r[reg].UD[0]);
|
||||
armAsm->Sub(a64::w9, a64::w9, RWSCRATCH);
|
||||
armAsm->Sxtw(a64::x9, a64::w9);
|
||||
armStoreEERegPtr(a64::x9, &cpuRegs.GPR.r[reg].UD[0]);
|
||||
|
||||
// if reg != 0, event interrupted the loop — go to dispatcher
|
||||
armEmitCbnz(a64::w4, DispatcherEvent);
|
||||
armEmitCbnz(a64::w9, DispatcherEvent);
|
||||
|
||||
// Loop finished — set PC to end of block and dispatch
|
||||
armAsm->Mov(RWSCRATCH, s_nEndBlock);
|
||||
|
||||
@@ -476,8 +476,8 @@ void recMADD()
|
||||
|
||||
// Load existing HI:LO into x1
|
||||
armLoadEERegPtr(a64::w3, &cpuRegs.LO.UL[0]);
|
||||
armLoadEERegPtr(a64::w4, &cpuRegs.HI.UL[0]);
|
||||
armAsm->Orr(a64::x3, a64::x3, a64::Operand(a64::x4, a64::LSL, 32));
|
||||
armLoadEERegPtr(RWSCRATCH, &cpuRegs.HI.UL[0]); // w8: w4 is a rung-3 EE-SRA pin
|
||||
armAsm->Orr(a64::x3, a64::x3, a64::Operand(RXSCRATCH, a64::LSL, 32));
|
||||
|
||||
// Add
|
||||
armAsm->Add(a64::x0, a64::x0, a64::x3);
|
||||
@@ -512,8 +512,8 @@ void recMADDU()
|
||||
armAsm->Umull(a64::x0, a64::w1, a64::w2);
|
||||
|
||||
armLoadEERegPtr(a64::w3, &cpuRegs.LO.UL[0]);
|
||||
armLoadEERegPtr(a64::w4, &cpuRegs.HI.UL[0]);
|
||||
armAsm->Orr(a64::x3, a64::x3, a64::Operand(a64::x4, a64::LSL, 32));
|
||||
armLoadEERegPtr(RWSCRATCH, &cpuRegs.HI.UL[0]); // w8: w4 is a rung-3 EE-SRA pin
|
||||
armAsm->Orr(a64::x3, a64::x3, a64::Operand(RXSCRATCH, a64::LSL, 32));
|
||||
|
||||
armAsm->Add(a64::x0, a64::x0, a64::x3);
|
||||
|
||||
@@ -547,8 +547,8 @@ void recMADD1()
|
||||
armAsm->Smull(a64::x0, a64::w1, a64::w2);
|
||||
|
||||
armLoadEERegPtr(a64::w3, &cpuRegs.LO.UL[2]); // LO1 = LO.UL[2] (upper 64 bits)
|
||||
armLoadEERegPtr(a64::w4, &cpuRegs.HI.UL[2]); // HI1 = HI.UL[2]
|
||||
armAsm->Orr(a64::x3, a64::x3, a64::Operand(a64::x4, a64::LSL, 32));
|
||||
armLoadEERegPtr(RWSCRATCH, &cpuRegs.HI.UL[2]); // HI1 = HI.UL[2] (w8: w4 is a rung-3 pin)
|
||||
armAsm->Orr(a64::x3, a64::x3, a64::Operand(RXSCRATCH, a64::LSL, 32));
|
||||
|
||||
armAsm->Add(a64::x0, a64::x0, a64::x3);
|
||||
|
||||
@@ -582,8 +582,8 @@ void recMADDU1()
|
||||
armAsm->Umull(a64::x0, a64::w1, a64::w2);
|
||||
|
||||
armLoadEERegPtr(a64::w3, &cpuRegs.LO.UL[2]);
|
||||
armLoadEERegPtr(a64::w4, &cpuRegs.HI.UL[2]);
|
||||
armAsm->Orr(a64::x3, a64::x3, a64::Operand(a64::x4, a64::LSL, 32));
|
||||
armLoadEERegPtr(RWSCRATCH, &cpuRegs.HI.UL[2]); // w8: w4 is a rung-3 pin
|
||||
armAsm->Orr(a64::x3, a64::x3, a64::Operand(RXSCRATCH, a64::LSL, 32));
|
||||
|
||||
armAsm->Add(a64::x0, a64::x0, a64::x3);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user