@@ -402,14 +402,22 @@ function ZVM:Precompile_Finalize()
402
402
if not result then
403
403
print (" [ZVM ERROR]: " .. (message or " unknown error" ))
404
404
else
405
- for address = self .PrecompileStartXEIP , self .PrecompileXEIP - 1 do
405
+ -- This should guarantee the physical addresses for things.
406
+ local page = self :GetPageByIndex (math.floor (self .PrecompileStartXEIP / 128 ))
407
+ local precompileStartPEIP = self .PrecompileStartXEIP
408
+ local precompilePEIP = self .PrecompileXEIP
409
+ if page .Remapped == 1 then
410
+ precompileStartPEIP = page .MappedIndex * 128 + self .PrecompileStartXEIP % 128
411
+ precompilePEIP = precompileStartPEIP + (self .PrecompileXEIP - self .PrecompileStartXEIP )
412
+ end
413
+ for address = precompileStartPEIP , precompilePEIP - 1 do
406
414
if not self .IsAddressPrecompiled [address ] then
407
415
self .IsAddressPrecompiled [address ] = { }
408
416
end
409
- table.insert (self .IsAddressPrecompiled [address ],self . PrecompileStartXEIP )
417
+ table.insert (self .IsAddressPrecompiled [address ],precompileStartPEIP )
410
418
end
411
419
setfenv (result ,self .Env )
412
- self .PrecompiledData [self . PrecompileStartXEIP ] = result
420
+ self .PrecompiledData [precompileStartPEIP ] = result
413
421
end
414
422
415
423
return result
@@ -455,9 +463,20 @@ function ZVM:Precompile_Step()
455
463
-- Check if we crossed the page boundary, if so - repeat the check
456
464
if math.floor (self .PrecompileXEIP / 128 ) ~= self .PrecompilePreviousPage then
457
465
self :Emit (" VM:SetCurrentPage(%d)" ,math.floor (self .PrecompileXEIP / 128 ))
458
- self :Emit (" if (VM.PCAP == 1) and (VM.CurrentPage.Execute == 0) and" )
459
- self :Emit (" (VM.PreviousPage.RunLevel ~= 0) then" )
460
- self :Dyn_EmitInterrupt (" 14" ,self .PrecompileIP )
466
+ self :Emit (" if (VM.PCAP == 1) then" )
467
+ self :Emit (" if (VM.CurrentPage.Execute == 0) and (VM.PreviousPage.RunLevel ~= 0) then" )
468
+ self :Dyn_EmitInterrupt (" 14" ,self .PrecompileIP )
469
+ self :Emit (" end" )
470
+ local expectedPage = self :GetPageByIndex (math.floor (self .PrecompileXEIP / 128 ))
471
+ if expectedPage .MappedIndex ~= math.floor (expectedPage .MappedIndex ) then
472
+ -- Bad address because MappedIndex is a float, send out an invalid address interrupt if this gets executed(it probably will in a sec)
473
+ self :Dyn_EmitInterrupt (15 ,expectedPage .MappedIndex * 128 )
474
+ end
475
+ self :Emit (" end" )
476
+ self :Emit (" if (VM.CurrentPage.MappedIndex ~= %d) then" ,expectedPage .MappedIndex )
477
+ -- This page wasn't the expected continuation, we should invalidate this address. (force recompile at this point)
478
+ self :Emit (" VM:InvalidateVirtualPrecompileAddress(VM.XEIP)" )
479
+ self :Dyn_EmitBreak (true )
461
480
self :Emit (" end" )
462
481
self :Emit (" VM:SetPreviousPage(%d)" ,math.floor (self .PrecompileXEIP / 128 ))
463
482
@@ -619,8 +638,26 @@ function ZVM:Precompile_Step()
619
638
return not self .PrecompileBreak
620
639
end
621
640
641
+ -- Helper that will convert virtual => physical for you if necessary and then invalidate them.
642
+ function ZVM :InvalidateVirtualPrecompileAddress (Address )
643
+ local Page = self :GetPageByIndex (math.floor (Address / 128 ))
644
+ local newAddress = Address
645
+ if Page .Remapped == 1 then
646
+ Address = (Page .MappedIndex * 128 )+ (Address % 128 )
647
+ end
648
+ self :InvalidatePrecompileAddress (Address )
649
+ end
622
650
623
-
651
+ -- These should be physical addresses.
652
+ function ZVM :InvalidatePrecompileAddress (Address )
653
+ -- Invalidate precompiled data (Moved so the address will be changed to physical if necessary)
654
+ if self .IsAddressPrecompiled [Address ] then
655
+ for k ,v in ipairs (self .IsAddressPrecompiled [Address ]) do
656
+ self .PrecompiledData [v ] = nil
657
+ self .IsAddressPrecompiled [Address ][k ] = nil
658
+ end
659
+ end
660
+ end
624
661
625
662
---- ----------------------------------------------------------------------------
626
663
-- VM step forward
@@ -648,9 +685,14 @@ function ZVM:Step(overrideSteps,extraEmitFunction)
648
685
self .NIF = nil
649
686
end
650
687
688
+ local address = self .XEIP
689
+ if self .CurrentPage .Remapped == 1 then
690
+ address = (self .CurrentPage .MappedIndex * 128 )+ (self .XEIP % 128 )
691
+ end
692
+
651
693
-- Check if current instruction is precompiled
652
- local instructionXEIP = self . XEIP
653
- if self .PrecompiledData [instructionXEIP ] or overrideSteps then
694
+ local instructionPEIP = address
695
+ if self .PrecompiledData [instructionPEIP ] or overrideSteps then
654
696
-- Precompile next instruction
655
697
if overrideSteps then
656
698
self :Precompile_Initialize ()
@@ -670,12 +712,11 @@ function ZVM:Step(overrideSteps,extraEmitFunction)
670
712
-- Step clock forward (account for precompiling)
671
713
self .TMR = self .TMR + 24 * 8000 -- + overrideSteps*9000
672
714
end
673
-
674
715
-- Execute precompiled instruction
675
716
if CLIENT then -- FIXME: hack around crash on PCALL
676
- self .PrecompiledData [self . XEIP ]()
717
+ self .PrecompiledData [address ]()
677
718
else
678
- local status ,message = pcall (self .PrecompiledData [self . XEIP ])
719
+ local status ,message = pcall (self .PrecompiledData [address ])
679
720
if not status then
680
721
print (" [ZVM ERROR]: " .. message )
681
722
self :Interrupt (5 ,1 )
0 commit comments