Skip to content

Commit

Permalink
Precompile now checks using physical addresses rather than XEIP (#60)
Browse files Browse the repository at this point in the history
* start of work

* Addresses are now invalidated if next page unexpected

* Tweaks, seems to be running now

* Page remap checks are now accurate
  • Loading branch information
DerelictDrone authored Aug 15, 2024
1 parent 8fea6c3 commit e041c35
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 27 deletions.
65 changes: 53 additions & 12 deletions lua/wire/zvm/zvm_core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -402,14 +402,22 @@ function ZVM:Precompile_Finalize()
if not result then
print("[ZVM ERROR]: "..(message or "unknown error"))
else
for address = self.PrecompileStartXEIP, self.PrecompileXEIP-1 do
-- This should guarantee the physical addresses for things.
local page = self:GetPageByIndex(math.floor(self.PrecompileStartXEIP/128))
local precompileStartPEIP = self.PrecompileStartXEIP
local precompilePEIP = self.PrecompileXEIP
if page.Remapped == 1 then
precompileStartPEIP = page.MappedIndex*128+self.PrecompileStartXEIP%128
precompilePEIP = precompileStartPEIP+(self.PrecompileXEIP-self.PrecompileStartXEIP)
end
for address = precompileStartPEIP, precompilePEIP-1 do
if not self.IsAddressPrecompiled[address] then
self.IsAddressPrecompiled[address] = { }
end
table.insert(self.IsAddressPrecompiled[address],self.PrecompileStartXEIP)
table.insert(self.IsAddressPrecompiled[address],precompileStartPEIP)
end
setfenv(result,self.Env)
self.PrecompiledData[self.PrecompileStartXEIP] = result
self.PrecompiledData[precompileStartPEIP] = result
end

return result
Expand Down Expand Up @@ -455,9 +463,20 @@ function ZVM:Precompile_Step()
-- Check if we crossed the page boundary, if so - repeat the check
if math.floor(self.PrecompileXEIP / 128) ~= self.PrecompilePreviousPage then
self:Emit("VM:SetCurrentPage(%d)",math.floor(self.PrecompileXEIP/128))
self:Emit("if (VM.PCAP == 1) and (VM.CurrentPage.Execute == 0) and")
self:Emit(" (VM.PreviousPage.RunLevel ~= 0) then")
self:Dyn_EmitInterrupt("14",self.PrecompileIP)
self:Emit("if (VM.PCAP == 1) then")
self:Emit("if (VM.CurrentPage.Execute == 0) and (VM.PreviousPage.RunLevel ~= 0) then")
self:Dyn_EmitInterrupt("14",self.PrecompileIP)
self:Emit("end")
local expectedPage = self:GetPageByIndex(math.floor(self.PrecompileXEIP/128))
if expectedPage.MappedIndex ~= math.floor(expectedPage.MappedIndex) then
-- Bad address because MappedIndex is a float, send out an invalid address interrupt if this gets executed(it probably will in a sec)
self:Dyn_EmitInterrupt(15,expectedPage.MappedIndex*128)
end
self:Emit("end")
self:Emit("if (VM.CurrentPage.MappedIndex ~= %d) then",expectedPage.MappedIndex)
-- This page wasn't the expected continuation, we should invalidate this address. (force recompile at this point)
self:Emit("VM:InvalidateVirtualPrecompileAddress(VM.XEIP)")
self:Dyn_EmitBreak(true)
self:Emit("end")
self:Emit("VM:SetPreviousPage(%d)",math.floor(self.PrecompileXEIP/128))

Expand Down Expand Up @@ -619,8 +638,26 @@ function ZVM:Precompile_Step()
return not self.PrecompileBreak
end

-- Helper that will convert virtual => physical for you if necessary and then invalidate them.
function ZVM:InvalidateVirtualPrecompileAddress(Address)
local Page = self:GetPageByIndex(math.floor(Address/128))
local newAddress = Address
if Page.Remapped == 1 then
Address = (Page.MappedIndex*128)+(Address%128)
end
self:InvalidatePrecompileAddress(Address)
end


-- These should be physical addresses.
function ZVM:InvalidatePrecompileAddress(Address)
-- Invalidate precompiled data (Moved so the address will be changed to physical if necessary)
if self.IsAddressPrecompiled[Address] then
for k,v in ipairs(self.IsAddressPrecompiled[Address]) do
self.PrecompiledData[v] = nil
self.IsAddressPrecompiled[Address][k] = nil
end
end
end

--------------------------------------------------------------------------------
-- VM step forward
Expand Down Expand Up @@ -648,9 +685,14 @@ function ZVM:Step(overrideSteps,extraEmitFunction)
self.NIF = nil
end

local address = self.XEIP
if self.CurrentPage.Remapped == 1 then
address = (self.CurrentPage.MappedIndex*128)+(self.XEIP%128)
end

-- Check if current instruction is precompiled
local instructionXEIP = self.XEIP
if self.PrecompiledData[instructionXEIP] or overrideSteps then
local instructionPEIP = address
if self.PrecompiledData[instructionPEIP] or overrideSteps then
-- Precompile next instruction
if overrideSteps then
self:Precompile_Initialize()
Expand All @@ -670,12 +712,11 @@ function ZVM:Step(overrideSteps,extraEmitFunction)
-- Step clock forward (account for precompiling)
self.TMR = self.TMR + 24*8000 -- + overrideSteps*9000
end

-- Execute precompiled instruction
if CLIENT then -- FIXME: hack around crash on PCALL
self.PrecompiledData[self.XEIP]()
self.PrecompiledData[address]()
else
local status,message = pcall(self.PrecompiledData[self.XEIP])
local status,message = pcall(self.PrecompiledData[address])
if not status then
print("[ZVM ERROR]: "..message)
self:Interrupt(5,1)
Expand Down
12 changes: 3 additions & 9 deletions lua/wire/zvm/zvm_features.lua
Original file line number Diff line number Diff line change
Expand Up @@ -291,14 +291,6 @@ function ZVM:WriteCell(Address,Value)
return false
end

-- Invalidate precompiled data
if self.IsAddressPrecompiled[Address] then
for k,v in ipairs(self.IsAddressPrecompiled[Address]) do
self.PrecompiledData[v] = nil
self.IsAddressPrecompiled[Address][k] = nil
end
end

-- Do we need to perform page checking
if self.PCAP == 1 and self.MF == 1 then
-- Fetch page
Expand Down Expand Up @@ -351,7 +343,9 @@ function ZVM:WriteCell(Address,Value)
end
end

-- Perform I/O operation
-- Invalidate precompiled data (Moved so the address will be changed to physical if necessary)
self:InvalidatePrecompileAddress(Address)
-- Perform I/O operation
if (Address >= 0) and (Address < self.RAMSize) then
self.Memory[Address] = Value
else
Expand Down
7 changes: 1 addition & 6 deletions lua/wire/zvm/zvm_opcodes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1206,12 +1206,7 @@ ZVM.OpcodeTable[131] = function(self) --SMAP
self:Dyn_EmitInterruptCheck()

self:Dyn_Emit("for address=IDX*128,IDX*128+127 do")
self:Dyn_Emit("if VM.IsAddressPrecompiled[address] then")
self:Dyn_Emit("for k,v in ipairs(VM.IsAddressPrecompiled[address]) do")
self:Dyn_Emit("VM.PrecompiledData[v] = nil")
self:Dyn_Emit("VM.IsAddressPrecompiled[address][k] = nil")
self:Dyn_Emit("end")
self:Dyn_Emit("end")
self:Dyn_Emit("VM:InvalidateVirtualPrecompileAddress(address)")
self:Dyn_Emit("end")
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("11","IDX")
Expand Down

0 comments on commit e041c35

Please sign in to comment.