From f79d6b8028aa0fd6b76dca88ecd9fb40de7e40c3 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Sun, 26 Nov 2023 07:46:38 -0600 Subject: [PATCH 1/5] Emit & Dyn_emit now wrap string.format + Vector instruction segment fix --- lua/entities/gmod_wire_cpu.lua | 8 +- lua/wire/zvm/zvm_core.lua | 48 ++--- lua/wire/zvm/zvm_opcodes.lua | 324 +++++++++++++++++++++++---------- 3 files changed, 259 insertions(+), 121 deletions(-) diff --git a/lua/entities/gmod_wire_cpu.lua b/lua/entities/gmod_wire_cpu.lua index 92c0150..b4233a1 100644 --- a/lua/entities/gmod_wire_cpu.lua +++ b/lua/entities/gmod_wire_cpu.lua @@ -160,8 +160,8 @@ function ENT:Run() self:Dyn_EmitState() self:Emit("VM.CPUIF.OnBreakpointInstruction(VM.IP)") self:Emit("VM.CPUIF.VMStopped = true") - self:Emit("VM.TMR = VM.TMR + "..self.PrecompileInstruction) - self:Emit("VM.CODEBYTES = VM.CODEBYTES + "..self.PrecompileBytes) + self:Emit("VM.TMR = VM.TMR + %d",self.PrecompileInstruction) + self:Emit("VM.CODEBYTES = VM.CODEBYTES + %d",self.PrecompileBytes) self:Emit("if true then return end") self:Emit("end") self:Emit("if VM.CPUIF.LastInstruction and ((VM.IP > VM.CPUIF.LastInstruction) or VM.CPUIF.ForceLastInstruction) then") @@ -169,8 +169,8 @@ function ENT:Run() self:Emit("VM.CPUIF.ForceLastInstruction = nil") self:Emit("VM.CPUIF.OnLastInstruction()") self:Emit("VM.CPUIF.VMStopped = true") - self:Emit("VM.TMR = VM.TMR + "..self.PrecompileInstruction) - self:Emit("VM.CODEBYTES = VM.CODEBYTES + "..self.PrecompileBytes) + self:Emit("VM.TMR = VM.TMR + %d",self.PrecompileInstruction) + self:Emit("VM.CODEBYTES = VM.CODEBYTES + %d",self.PrecompileBytes) self:Emit("if true then return end") self:Emit("end") end) diff --git a/lua/wire/zvm/zvm_core.lua b/lua/wire/zvm/zvm_core.lua index fc7a575..c5b94df 100644 --- a/lua/wire/zvm/zvm_core.lua +++ b/lua/wire/zvm/zvm_core.lua @@ -40,8 +40,8 @@ if ZVM.MicrocodeDebug then -- Debug microcode generator then pad = pad + 1 end end else - function ZVM:Emit(text) - self.EmitBlock = self.EmitBlock..text.."\n" + function ZVM:Emit(...) + self.EmitBlock = self.EmitBlock..string.format(...).."\n" end end @@ -155,8 +155,8 @@ end -------------------------------------------------------------------------------- -- Emit preprocessed text -function ZVM:Dyn_Emit(text) - self:Emit(self:Dyn_PreprocessEmit(text)) +function ZVM:Dyn_Emit(...) + self:Emit(self:Dyn_PreprocessEmit(string.format(...))) end @@ -196,11 +196,11 @@ end -------------------------------------------------------------------------------- -- Emit forced block return function ZVM:Dyn_EmitBreak(emitIP) - self:Emit("VM.TMR = VM.TMR + "..self.PrecompileInstruction) - self:Emit("VM.CODEBYTES = VM.CODEBYTES + "..self.PrecompileBytes) + self:Emit("VM.TMR = VM.TMR + %d",self.PrecompileInstruction) + self:Emit("VM.CODEBYTES = VM.CODEBYTES + %d",self.PrecompileBytes) if emitIP then - self:Emit("VM.IP = "..(self.PrecompileIP or 0)) - self:Emit("VM.XEIP = "..(self.PrecompileTrueXEIP or 0)) + self:Emit("VM.IP = %d",(self.PrecompileIP or 0)) + self:Emit("VM.XEIP = %d",(self.PrecompileTrueXEIP or 0)) end if self.ExtraEmitFunction then self.ExtraEmitFunction(self) end self:Emit("if true then return end") @@ -265,9 +265,9 @@ end -- Emit interrupt call function ZVM:Dyn_EmitInterrupt(intNo,intParam) self:Dyn_EmitState() - self:Emit("VM.IP = "..(self.PrecompileIP or 0)) - self:Emit("VM.XEIP = "..(self.PrecompileTrueXEIP or 0)) - self:Dyn_Emit("VM:Interrupt("..intNo..","..intParam..")") + self:Emit("VM.IP = %d",(self.PrecompileIP or 0)) + self:Emit("VM.XEIP = %d",(self.PrecompileTrueXEIP or 0)) + self:Dyn_Emit("VM:Interrupt(%d,%d)",intNo,intParam) self:Dyn_EmitBreak() end @@ -280,23 +280,23 @@ function ZVM:Dyn_EmitInterruptCheck() if self.RQCAP == 1 then self:Emit("if VM.MEMRQ > 0 then") -- Extended memory request self:Emit("if VM.MEMRQ == 1 then") -- Delayed request - self:Emit("VM.IP = "..self.PrecompileStartIP) - self:Emit("VM.XEIP = "..(self.PrecompileTrueXEIP or 0)) + self:Emit("VM.IP = %d",self.PrecompileStartIP) + self:Emit("VM.XEIP = %d",(self.PrecompileTrueXEIP or 0)) self:Emit("VM.IDLE = 1") self:Dyn_EmitState(true) self:Dyn_EmitBreak() self:Emit("elseif VM.MEMRQ == 2 then") -- Reading self:Dyn_EmitState(true) self:Emit("VM.MEMRQ = 4") - self:Emit("VM.IP = "..self.PrecompileStartIP) - self:Emit("VM.XEIP = "..(self.PrecompileTrueXEIP or 0)) + self:Emit("VM.IP = %d",self.PrecompileStartIP) + self:Emit("VM.XEIP = %d",(self.PrecompileTrueXEIP or 0)) self:Emit("VM:Interrupt(28,VM.LADD)") self:Dyn_EmitBreak() self:Emit("elseif VM.MEMRQ == 3 then") -- Writing self:Dyn_EmitState(true) self:Emit("VM.MEMRQ = 5") - self:Emit("VM.IP = "..self.PrecompileStartIP) - self:Emit("VM.XEIP = "..(self.PrecompileTrueXEIP or 0)) + self:Emit("VM.IP = %d",self.PrecompileStartIP) + self:Emit("VM.XEIP = %d",(self.PrecompileTrueXEIP or 0)) self:Emit("VM:Interrupt(29,VM.LADD)") self:Dyn_EmitBreak() self:Emit("end") @@ -406,12 +406,12 @@ 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("..math.floor(self.PrecompileXEIP/128)..")") + 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("end") - self:Emit("VM:SetPreviousPage("..math.floor(self.PrecompileXEIP/128)..")") + self:Emit("VM:SetPreviousPage(%d)",math.floor(self.PrecompileXEIP/128)) self.PrecompilePreviousPage = math.floor(self.PrecompileXEIP / 128) end @@ -442,7 +442,7 @@ function ZVM:Precompile_Step() -- Check opcode runlevel if self.OpcodeRunLevel[Opcode] then - self:Emit("if (VM.PCAP == 1) and (VM.CurrentPage.RunLevel > "..self.OpcodeRunLevel[Opcode]..") then") + self:Emit("if (VM.PCAP == 1) and (VM.CurrentPage.RunLevel > %d) then",self.OpcodeRunLevel[Opcode]) self:Dyn_EmitInterrupt("13",Opcode) self:Emit("end") end @@ -536,8 +536,8 @@ function ZVM:Precompile_Step() -- Emit interrupt check prefix if self.EmitNeedInterruptCheck then - self:Emit("VM.IP = "..(self.PrecompileIP or 0)) - self:Emit("VM.XEIP = "..(self.PrecompileTrueXEIP or 0)) + self:Emit("VM.IP = %d",(self.PrecompileIP or 0)) + self:Emit("VM.XEIP = %d",(self.PrecompileTrueXEIP or 0)) end -- Emit opcode @@ -600,8 +600,8 @@ function ZVM:Step(overrideSteps,extraEmitFunction) local instruction = 1 while (instruction <= overrideSteps) and self:Precompile_Step() do if self.ExtraEmitFunction then - self:Emit("VM.IP = "..(self.PrecompileIP or 0)) - self:Emit("VM.XEIP = "..(self.PrecompileTrueXEIP or 0)) + self:Emit("VM.IP = %d",(self.PrecompileIP or 0)) + self:Emit("VM.XEIP = %d",(self.PrecompileTrueXEIP or 0)) self.ExtraEmitFunction(self) end instruction = instruction + 1 diff --git a/lua/wire/zvm/zvm_opcodes.lua b/lua/wire/zvm/zvm_opcodes.lua index 069aea8..d7f9937 100644 --- a/lua/wire/zvm/zvm_opcodes.lua +++ b/lua/wire/zvm/zvm_opcodes.lua @@ -255,7 +255,7 @@ ZVM.OpcodeTable[30] = function(self) --POP end ZVM.OpcodeTable[31] = function(self) --CALL self:Dyn_EmitForceRegisterGlobal("ESP") - self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then") + self:Dyn_Emit("if VM:Push(%d) then",self.PrecompileIP) self:Dyn_Emit("VM:Jump($1)") self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -457,8 +457,8 @@ end -------------------------------------------------------------------------------- ZVM.OpcodeTable[70] = function(self) --EXTINT self:Dyn_EmitState() - self:Emit("VM.IP = "..(self.PrecompileIP or 0)) - self:Emit("VM.XEIP = "..(self.PrecompileTrueXEIP or 0)) + self:Emit("VM.IP = %d",(self.PrecompileIP or 0)) + self:Emit("VM.XEIP = %d",(self.PrecompileTrueXEIP or 0)) self:Dyn_Emit("VM:ExternalInterrupt(math.floor($1))") self:Dyn_EmitBreak() self.PrecompileBreak = true @@ -466,7 +466,7 @@ end ZVM.OpcodeTable[71] = function(self) --CNE self:Dyn_EmitForceRegisterGlobal("ESP") self:Dyn_Emit("if VM.CMPR ~= 0 then") - self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then") + self:Dyn_Emit("if VM:Push(%d) then",self.PrecompileIP) self:Dyn_Emit("VM:Jump($1)") self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -476,7 +476,7 @@ ZVM.OpcodeTable[71] = function(self) --CNE end ZVM.OpcodeTable[72] = function(self) --CJMP self:Dyn_EmitForceRegisterGlobal("ESP") - self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then") + self:Dyn_Emit("if VM:Push(%d) then",self.PrecompileIP) self:Dyn_Emit("VM:Jump($1)") self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -486,7 +486,7 @@ end ZVM.OpcodeTable[73] = function(self) --CG self:Dyn_EmitForceRegisterGlobal("ESP") self:Dyn_Emit("if VM.CMPR > 0 then") - self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then") + self:Dyn_Emit("if VM:Push(%d) then",self.PrecompileIP) self:Dyn_Emit("VM:Jump($1)") self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -497,7 +497,7 @@ end ZVM.OpcodeTable[74] = function(self) --CGE self:Dyn_EmitForceRegisterGlobal("ESP") self:Dyn_Emit("if VM.CMPR >= 0 then") - self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then") + self:Dyn_Emit("if VM:Push(%d) then",self.PrecompileIP) self:Dyn_Emit("VM:Jump($1)") self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -508,7 +508,7 @@ end ZVM.OpcodeTable[75] = function(self) --CL self:Dyn_EmitForceRegisterGlobal("ESP") self:Dyn_Emit("if VM.CMPR < 0 then") - self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then") + self:Dyn_Emit("if VM:Push(%d) then",self.PrecompileIP) self:Dyn_Emit("VM:Jump($1)") self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -519,7 +519,7 @@ end ZVM.OpcodeTable[76] = function(self) --CLE self:Dyn_EmitForceRegisterGlobal("ESP") self:Dyn_Emit("if VM.CMPR <= 0 then") - self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then") + self:Dyn_Emit("if VM:Push(%d) then",self.PrecompileIP) self:Dyn_Emit("VM:Jump($1)") self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -530,7 +530,7 @@ end ZVM.OpcodeTable[77] = function(self) --CE self:Dyn_EmitForceRegisterGlobal("ESP") self:Dyn_Emit("if VM.CMPR == 0 then") - self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then") + self:Dyn_Emit("if VM:Push(%d) then",self.PrecompileIP) self:Dyn_Emit("VM:Jump($1)") self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -610,7 +610,7 @@ end ZVM.OpcodeTable[89] = function(self) --CALLF self:Dyn_EmitForceRegisterGlobal("CS") self:Dyn_EmitForceRegisterGlobal("ESP") - self:Dyn_Emit("if VM:Push(VM.CS) and VM:Push("..self.PrecompileIP..") then") + self:Dyn_Emit("if VM:Push(VM.CS) and VM:Push(%d) then",self.PrecompileIP) self:Dyn_Emit("VM:Jump($1,$2)") self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -686,7 +686,7 @@ ZVM.OpcodeTable[97] = function(self) --RDPG self:Dyn_Emit("end") end ZVM.OpcodeTable[98] = function(self) --TIMER - self:Dyn_EmitOperand("(VM.TIMER+"..(self.PrecompileInstruction or 0).."*VM.TimerDT)") + self:Dyn_EmitOperand("(VM.TIMER+%d*VM.TimerDT)",(self.PrecompileInstruction or 0)) end ZVM.OpcodeTable[99] = function(self) --LIDTR self:Dyn_Emit("VM.IDTR = $1") @@ -694,7 +694,7 @@ end -------------------------------------------------------------------------------- ZVM.OpcodeTable[100] = function(self) --STATESTORE self:Dyn_EmitState() - self:Dyn_Emit("VM:WriteCell($1 + 00,"..self.PrecompileIP..")") + self:Dyn_Emit("VM:WriteCell($1 + 00,%d)",self.PrecompileIP) self:Dyn_Emit("VM:WriteCell($1 + 01,VM.EAX)") self:Dyn_Emit("VM:WriteCell($1 + 02,VM.EBX)") @@ -717,13 +717,13 @@ ZVM.OpcodeTable[100] = function(self) --STATESTORE end ZVM.OpcodeTable[101] = function(self) --JNER self:Dyn_Emit("if VM.CMPR ~= 0 then") - self:Dyn_Emit("VM:Jump("..self.PrecompileIP.." + $1)") + self:Dyn_Emit("VM:Jump(%d + $1)",self.PrecompileIP) self:Dyn_EmitState() self:Dyn_EmitBreak() self:Dyn_Emit("end") end ZVM.OpcodeTable[102] = function(self) --JMPR - self:Dyn_Emit("VM:Jump("..self.PrecompileIP.." + $1)") + self:Dyn_Emit("VM:Jump(%d + $1)",self.PrecompileIP) self:Dyn_EmitState() self:Dyn_EmitBreak() @@ -731,35 +731,35 @@ ZVM.OpcodeTable[102] = function(self) --JMPR end ZVM.OpcodeTable[103] = function(self) --JGR self:Dyn_Emit("if VM.CMPR > 0 then") - self:Dyn_Emit("VM:Jump("..self.PrecompileIP.." + $1)") + self:Dyn_Emit("VM:Jump(%d + $1)",self.PrecompileIP) self:Dyn_EmitState() self:Dyn_EmitBreak() self:Dyn_Emit("end") end ZVM.OpcodeTable[104] = function(self) --JGER self:Dyn_Emit("if VM.CMPR >= 0 then") - self:Dyn_Emit("VM:Jump("..self.PrecompileIP.." + $1)") + self:Dyn_Emit("VM:Jump(%d + $1)",self.PrecompileIP) self:Dyn_EmitState() self:Dyn_EmitBreak() self:Dyn_Emit("end") end ZVM.OpcodeTable[105] = function(self) --JLR self:Dyn_Emit("if VM.CMPR < 0 then") - self:Dyn_Emit("VM:Jump("..self.PrecompileIP.." + $1)") + self:Dyn_Emit("VM:Jump(%d + $1)",self.PrecompileIP) self:Dyn_EmitState() self:Dyn_EmitBreak() self:Dyn_Emit("end") end ZVM.OpcodeTable[106] = function(self) --JLER self:Dyn_Emit("if VM.CMPR <= 0 then") - self:Dyn_Emit("VM:Jump("..self.PrecompileIP.." + $1)") + self:Dyn_Emit("VM:Jump(%d + $1)",self.PrecompileIP) self:Dyn_EmitState() self:Dyn_EmitBreak() self:Dyn_Emit("end") end ZVM.OpcodeTable[107] = function(self) --JER self:Dyn_Emit("if VM.CMPR == 0 then") - self:Dyn_Emit("VM:Jump("..self.PrecompileIP.." + $1)") + self:Dyn_Emit("VM:Jump(%d + $1)",self.PrecompileIP) self:Dyn_EmitState() self:Dyn_EmitBreak() self:Dyn_Emit("end") @@ -927,7 +927,7 @@ ZVM.OpcodeTable[121] = function(self) --CPUSET self:Dyn_Emit("$L limit = VM.InternalLimits[REG]") self:Dyn_Emit("VM[VM.InternalRegister[REG]] = limit and math.Clamp(OP, limit[1], limit[2]) or OP") self:Dyn_Emit("if (REG == 0) or (REG == 16) then") - self:Dyn_Emit("VM:Jump("..self.PrecompileIP..",VM.CS)") + self:Dyn_Emit("VM:Jump(%d,VM.CS)",self.PrecompileIP) self:Dyn_EmitState() self:Dyn_EmitBreak() self:Dyn_Emit("else") @@ -1045,7 +1045,7 @@ end ZVM.OpcodeTable[126] = function(self) --LEA local emitText = self.OperandEffectiveAddress[self.EmitOperandRM[2]] or "0" emitText = string.gsub(emitText,"$BYTE",self.EmitOperandByte[2] or "0") - emitText = string.gsub(emitText,"$SEG","VM."..(self.EmitOperandSegment[2] or "DS")) + emitText = string.format(string.gsub(emitText,"$SEG","VM[%q]",(self.EmitOperandSegment[2] or "DS"))) self:Dyn_EmitOperand(emitText) end ZVM.OpcodeTable[127] = function(self) --BLOCK @@ -1187,7 +1187,7 @@ ZVM.OpcodeTable[140] = function(self) --EXTRETA self:Dyn_EmitInterruptCheck() for i=0,31 do - self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.R"..i.." = V") + self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.R%d = V") end self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L IP = V") @@ -1231,128 +1231,181 @@ end -------------------------------------------------------------------------------- ZVM.OpcodeTable[250] = function(self) --VADD + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end self:Dyn_Emit("if VM.VMODE == 2 then") - self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) + self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteVector2f($1 + %s,",seg1code) self:Dyn_Emit("{x = V1.x+V2.x, y=V1.y+V2.y, z=0})") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("elseif VM.VMODE == 3 then") - self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L V2 = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + %s)",seg1code) + self:Dyn_Emit("$L V2 = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteVector3f($1 + %s,",seg1code) self:Dyn_Emit("{x = V1.x+V2.x, y=V1.y+V2.y, z=V1.z+V2.z})") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("end") end ZVM.OpcodeTable[251] = function(self) --VSUB + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end self:Dyn_Emit("if VM.VMODE == 2 then") - self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) + self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteVector2f($1 + %s,",seg1code) self:Dyn_Emit("{x = V1.x-V2.x, y=V1.y-V2.y, z=0})") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("elseif VM.VMODE == 3 then") - self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L V2 = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + %s)",seg1code) + self:Dyn_Emit("$L V2 = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteVector3f($1 + %s,",seg1code) self:Dyn_Emit("{x = V1.x-V2.x, y=V1.y-V2.y, z=V1.z-V2.z})") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("end") end ZVM.OpcodeTable[252] = function(self) --VMUL + local seg1code = "0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end self:Dyn_Emit("if VM.VMODE == 2 then") - self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) self:Dyn_Emit("$L V2 = $2") self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteVector2f($1 + %s,",seg1code) self:Dyn_Emit("{x = V1.x*V2, y=V1.y*V2, z=0})") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("elseif VM.VMODE == 3 then") - self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + %s)",seg1code) self:Dyn_Emit("$L V2 = $2") self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteVector3f($1 + %s,",seg1code) self:Dyn_Emit("{x = V1.x*V2, y=V1.y*V2, z=V1.z*V2})") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("end") end ZVM.OpcodeTable[253] = function(self) --VDOT + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end self:Dyn_Emit("if VM.VMODE == 2 then") - self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) + self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteCell($1 + VM."..self.EmitOperandSegment[1]..",") + self:Dyn_Emit("VM:WriteCell($1 + %s,",seg1code) self:Dyn_Emit("V1.x*V2.x+V1.y*V2.y)") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("elseif VM.VMODE == 3 then") - self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L V2 = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + %s)",seg1code) + self:Dyn_Emit("$L V2 = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteCell($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteCell($1 + %s,",seg1code) self:Dyn_Emit("V1.x*V2.x+V1.y*V2.y+V1.z*V2.z)") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("end") end ZVM.OpcodeTable[254] = function(self) --VCROSS + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end self:Dyn_Emit("if VM.VMODE == 2 then") - self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) + self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteCell($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteCell($1 + %s,",seg1code) self:Dyn_Emit("V1.x*V2.y-V1.y*V2.x)") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("elseif VM.VMODE == 3 then") - self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L V2 = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V1 = VM:ReadVector3f($1 + %s)",seg1code) + self:Dyn_Emit("$L V2 = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteVector3f($1 + %s,",seg1code) self:Dyn_Emit("{x = V1.y*V2.z-V1.z*V2.y, y=V1.z*V2.x-V1.x*V2.z, z=V1.x*V2.y-V1.y*V2.x})") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("end") end ZVM.OpcodeTable[255] = function(self) --VMOV + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end self:Dyn_Emit("if VM.VMODE == 2 then") - self:Dyn_Emit("$L V = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",V)") + self:Dyn_Emit("VM:WriteVector2f($1 + %s,V)",seg1code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("elseif VM.VMODE == 3 then") - self:Dyn_Emit("$L V = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",V)") + self:Dyn_Emit("VM:WriteVector3f($1 + %s,V)",seg1code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("end") end ZVM.OpcodeTable[256] = function(self) --VNORM + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end self:Dyn_Emit("if VM.VMODE == 2 then") - self:Dyn_Emit("$L V = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L D = (V.x^2+V.y^2)^(1/2)+1e-8") - self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteVector2f($1 + %s,",seg1code) self:Dyn_Emit("{x = V.x/D, y = V.y/D, z = 0})") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("elseif VM.VMODE == 3 then") - self:Dyn_Emit("$L V = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L D = (V.x^2+V.y^2+V.z^2)^(1/2)+1e-8") - self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",") + self:Dyn_Emit("VM:WriteVector3f($1 + %s,",seg1code) self:Dyn_Emit("{x = V.x/D, y = V.y/D, z = V.z/D})") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("end") end ZVM.OpcodeTable[257] = function(self) --VCOLORNORM - self:Dyn_Emit("$L V = VM:ReadVector4f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L V = VM:ReadVector4f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("V.x = math.min(255,math.max(0,V.x))") self:Dyn_Emit("V.y = math.min(255,math.max(0,V.y))") self:Dyn_Emit("V.z = math.min(255,math.max(0,V.z))") self:Dyn_Emit("V.w = math.min(255,math.max(0,V.w))") - self:Dyn_Emit("VM:WriteVector4f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",V)") + self:Dyn_Emit("VM:WriteVector4f($1 + %s,V)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[259] = function(self) --LOOPXY @@ -1363,30 +1416,51 @@ ZVM.OpcodeTable[259] = function(self) --LOOPXY end -------------------------------------------------------------------------------- ZVM.OpcodeTable[260] = function(self) --MADD - self:Dyn_Emit("$L M1 = VM:ReadMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L M2 = VM:ReadMatrix($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L M1 = VM:ReadMatrix($1 + %s)",seg1code) + self:Dyn_Emit("$L M2 = VM:ReadMatrix($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L RM = {}") self:Dyn_Emit("for i=0,15 do RM[i] = M1[i]+M2[i] end") - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",RM)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,RM)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[261] = function(self) --MSUB - self:Dyn_Emit("$L M1 = VM:ReadMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L M2 = VM:ReadMatrix($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L M1 = VM:ReadMatrix($1 + %s)",seg1code) + self:Dyn_Emit("$L M2 = VM:ReadMatrix($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L RM = {}") self:Dyn_Emit("for i=0,15 do RM[i] = M1[i]-M2[i] end") - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",RM)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,RM)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[262] = function(self) --MMUL - self:Dyn_Emit("$L M1 = VM:ReadMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") - self:Dyn_Emit("$L M2 = VM:ReadMatrix($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L M1 = VM:ReadMatrix($1 + %s)",seg1code) + self:Dyn_Emit("$L M2 = VM:ReadMatrix($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L RM = {}") @@ -1399,11 +1473,18 @@ ZVM.OpcodeTable[262] = function(self) --MMUL self:Dyn_Emit("end") self:Dyn_Emit("end") - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",RM)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,RM)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[263] = function(self) --MROTATE - self:Dyn_Emit("$L VEC = VM:ReadVector4f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L VEC = VM:ReadVector4f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L MAG = math.sqrt(VEC.x^2+VEC.y^2+VEC.z^2)+1e-7") @@ -1439,11 +1520,18 @@ ZVM.OpcodeTable[263] = function(self) --MROTATE self:Dyn_Emit("RM[14] = 0") self:Dyn_Emit("RM[15] = 1") - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",RM)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,RM)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[264] = function(self) --MSCALE - self:Dyn_Emit("$L VEC = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L VEC = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L RM = {}") @@ -1467,11 +1555,18 @@ ZVM.OpcodeTable[264] = function(self) --MSCALE self:Dyn_Emit("RM[14] = 0") self:Dyn_Emit("RM[15] = 1") - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",RM)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,RM)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[265] = function(self) --MPERSPECTIVE - self:Dyn_Emit("$L VEC = VM:ReadVector4f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L VEC = VM:ReadVector4f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L DZ = VEC.w - VEC.z") @@ -1500,11 +1595,18 @@ ZVM.OpcodeTable[265] = function(self) --MPERSPECTIVE self:Dyn_Emit("RM[11] = -1") self:Dyn_Emit("RM[15] = 0") - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",RM)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,RM)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[266] = function(self) --MTRANSLATE - self:Dyn_Emit("$L VEC = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L VEC = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L RM = {}") @@ -1528,13 +1630,20 @@ ZVM.OpcodeTable[266] = function(self) --MTRANSLATE self:Dyn_Emit("RM[14] = 0") self:Dyn_Emit("RM[15] = 1") - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",RM)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,RM)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[267] = function(self) --MLOOKAT - self:Dyn_Emit("$L EYE = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS").."+0)") - self:Dyn_Emit("$L CENTER = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS").."+3)") - self:Dyn_Emit("$L UP = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS").."+6)") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L EYE = VM:ReadVector3f($2 + %s+0",seg2code) + self:Dyn_Emit("$L CENTER = VM:ReadVector3f($2 + %s+3",seg2code) + self:Dyn_Emit("$L UP = VM:ReadVector3f($2 + %s+6",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L X = { 0, 0, 0 }") @@ -1585,34 +1694,52 @@ ZVM.OpcodeTable[267] = function(self) --MLOOKAT self:Dyn_Emit("RM[14] = 0") self:Dyn_Emit("RM[15] = 1") - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",RM)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,RM)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[268] = function(self) --MMOV - self:Dyn_Emit("$L M = VM:ReadMatrix($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("$L M = VM:ReadMatrix($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",M)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,M)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[269] = function(self) --VLEN + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end self:Dyn_Emit("if VM.VMODE == 2 then") - self:Dyn_Emit("$L V = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_EmitOperand(1,"(V.x^2+V.y^2)^0.5",true) self:Dyn_Emit("elseif VM.VMODE == 3 then") - self:Dyn_Emit("$L V = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")") + self:Dyn_Emit("$L V = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_EmitOperand(1,"(V.x^2+V.y^2+V.z^2)^0.5",true) self:Dyn_Emit("end") end -------------------------------------------------------------------------------- ZVM.OpcodeTable[270] = function(self) --MIDENT + local seg1code + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end self:Dyn_Emit("$L M = {}") self:Dyn_Emit("M[ 0]=1 M[ 1]=0 M[ 2]=0 M[ 3]=0") self:Dyn_Emit("M[ 4]=0 M[ 5]=1 M[ 6]=0 M[ 7]=0") self:Dyn_Emit("M[ 8]=0 M[ 9]=0 M[10]=1 M[11]=0") self:Dyn_Emit("M[12]=0 M[13]=0 M[14]=0 M[15]=1") - self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",M)") + self:Dyn_Emit("VM:WriteMatrix($1 + %s,M)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[273] = function(self) --VMODE @@ -1620,27 +1747,38 @@ ZVM.OpcodeTable[273] = function(self) --VMODE end -------------------------------------------------------------------------------- ZVM.OpcodeTable[295] = function(self) --VDIV + local seg1code = "0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end self:Dyn_Emit("$L SCALAR = $2") self:Dyn_Emit("if VM.VMODE == 2 then") - self:Dyn_Emit("$L V = VM:ReadVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") + self:Dyn_Emit("$L V = VM:ReadVector2f($1 + %s)",seg1code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("V.x = V.x / SCALAR") self:Dyn_Emit("V.y = V.y / SCALAR") - self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",V)") + self:Dyn_Emit("VM:WriteVector2f($1 + %s,V)",seg1code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("elseif VM.VMODE == 3 then") - self:Dyn_Emit("$L V = VM:ReadVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..")") + self:Dyn_Emit("$L V = VM:ReadVector3f($1 + %s)",seg1code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("V.x = V.x / SCALAR") self:Dyn_Emit("V.y = V.y / SCALAR") self:Dyn_Emit("V.z = V.z / SCALAR") - self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",V)") + self:Dyn_Emit("VM:WriteVector3f($1 + %s,V)",seg1code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("end") end ZVM.OpcodeTable[296] = function(self) --VTRANSFORM - self:Dyn_Emit("local address_1 = $1 + VM."..(self.EmitOperandSegment[1] or "DS")) - self:Dyn_Emit("local address_2 = $2 + VM."..(self.EmitOperandSegment[2] or "DS")) + local seg1code,seg2code = "0","0" + if not self.EmitOperandSegment[1] then + seg1code = "VM.DS" + end + if not self.EmitOperandSegment[2] then + seg2code = "VM.DS" + end + self:Dyn_Emit("local address_1 = $1 + $s",seg1code) + self:Dyn_Emit("local address_2 = $2 + %s",seg2code) self:Dyn_Emit [[ local V = {0, 0, 0, 1} if address_1~=0 then From 39b3a4b7e4af5a61e3a9b43662e0bb54fd602329 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Mon, 27 Nov 2023 17:36:46 -0600 Subject: [PATCH 2/5] Shorter segcode for vector instructions --- lua/wire/zvm/zvm_opcodes.lua | 172 ++++++++--------------------------- 1 file changed, 38 insertions(+), 134 deletions(-) diff --git a/lua/wire/zvm/zvm_opcodes.lua b/lua/wire/zvm/zvm_opcodes.lua index d7f9937..2ce5509 100644 --- a/lua/wire/zvm/zvm_opcodes.lua +++ b/lua/wire/zvm/zvm_opcodes.lua @@ -1231,13 +1231,8 @@ end -------------------------------------------------------------------------------- ZVM.OpcodeTable[250] = function(self) --VADD - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("if VM.VMODE == 2 then") self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + %s)",seg2code) @@ -1255,13 +1250,8 @@ ZVM.OpcodeTable[250] = function(self) --VADD self:Dyn_Emit("end") end ZVM.OpcodeTable[251] = function(self) --VSUB - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("if VM.VMODE == 2 then") self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + %s)",seg2code) @@ -1279,10 +1269,7 @@ ZVM.OpcodeTable[251] = function(self) --VSUB self:Dyn_Emit("end") end ZVM.OpcodeTable[252] = function(self) --VMUL - local seg1code = "0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" self:Dyn_Emit("if VM.VMODE == 2 then") self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) self:Dyn_Emit("$L V2 = $2") @@ -1300,13 +1287,8 @@ ZVM.OpcodeTable[252] = function(self) --VMUL self:Dyn_Emit("end") end ZVM.OpcodeTable[253] = function(self) --VDOT - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("if VM.VMODE == 2 then") self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + %s)",seg2code) @@ -1324,13 +1306,8 @@ ZVM.OpcodeTable[253] = function(self) --VDOT self:Dyn_Emit("end") end ZVM.OpcodeTable[254] = function(self) --VCROSS - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("if VM.VMODE == 2 then") self:Dyn_Emit("$L V1 = VM:ReadVector2f($1 + %s)",seg1code) self:Dyn_Emit("$L V2 = VM:ReadVector2f($2 + %s)",seg2code) @@ -1348,13 +1325,8 @@ ZVM.OpcodeTable[254] = function(self) --VCROSS self:Dyn_Emit("end") end ZVM.OpcodeTable[255] = function(self) --VMOV - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("if VM.VMODE == 2 then") self:Dyn_Emit("$L V = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1368,13 +1340,8 @@ ZVM.OpcodeTable[255] = function(self) --VMOV self:Dyn_Emit("end") end ZVM.OpcodeTable[256] = function(self) --VNORM - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("if VM.VMODE == 2 then") self:Dyn_Emit("$L V = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1392,13 +1359,8 @@ ZVM.OpcodeTable[256] = function(self) --VNORM self:Dyn_Emit("end") end ZVM.OpcodeTable[257] = function(self) --VCOLORNORM - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L V = VM:ReadVector4f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("V.x = math.min(255,math.max(0,V.x))") @@ -1416,13 +1378,8 @@ ZVM.OpcodeTable[259] = function(self) --LOOPXY end -------------------------------------------------------------------------------- ZVM.OpcodeTable[260] = function(self) --MADD - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L M1 = VM:ReadMatrix($1 + %s)",seg1code) self:Dyn_Emit("$L M2 = VM:ReadMatrix($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1434,13 +1391,8 @@ ZVM.OpcodeTable[260] = function(self) --MADD self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[261] = function(self) --MSUB - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L M1 = VM:ReadMatrix($1 + %s)",seg1code) self:Dyn_Emit("$L M2 = VM:ReadMatrix($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1452,13 +1404,8 @@ ZVM.OpcodeTable[261] = function(self) --MSUB self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[262] = function(self) --MMUL - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L M1 = VM:ReadMatrix($1 + %s)",seg1code) self:Dyn_Emit("$L M2 = VM:ReadMatrix($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1477,13 +1424,8 @@ ZVM.OpcodeTable[262] = function(self) --MMUL self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[263] = function(self) --MROTATE - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L VEC = VM:ReadVector4f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1524,13 +1466,8 @@ ZVM.OpcodeTable[263] = function(self) --MROTATE self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[264] = function(self) --MSCALE - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L VEC = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1559,13 +1496,8 @@ ZVM.OpcodeTable[264] = function(self) --MSCALE self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[265] = function(self) --MPERSPECTIVE - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L VEC = VM:ReadVector4f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1599,13 +1531,8 @@ ZVM.OpcodeTable[265] = function(self) --MPERSPECTIVE self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[266] = function(self) --MTRANSLATE - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L VEC = VM:ReadVector3f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1634,13 +1561,8 @@ ZVM.OpcodeTable[266] = function(self) --MTRANSLATE self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[267] = function(self) --MLOOKAT - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L EYE = VM:ReadVector3f($2 + %s+0",seg2code) self:Dyn_Emit("$L CENTER = VM:ReadVector3f($2 + %s+3",seg2code) self:Dyn_Emit("$L UP = VM:ReadVector3f($2 + %s+6",seg2code) @@ -1698,26 +1620,16 @@ ZVM.OpcodeTable[267] = function(self) --MLOOKAT self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[268] = function(self) --MMOV - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("$L M = VM:ReadMatrix($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM:WriteMatrix($1 + %s,M)",seg1code) self:Dyn_EmitInterruptCheck() end ZVM.OpcodeTable[269] = function(self) --VLEN - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("if VM.VMODE == 2 then") self:Dyn_Emit("$L V = VM:ReadVector2f($2 + %s)",seg2code) self:Dyn_EmitInterruptCheck() @@ -1747,10 +1659,7 @@ ZVM.OpcodeTable[273] = function(self) --VMODE end -------------------------------------------------------------------------------- ZVM.OpcodeTable[295] = function(self) --VDIV - local seg1code = "0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" self:Dyn_Emit("$L SCALAR = $2") self:Dyn_Emit("if VM.VMODE == 2 then") self:Dyn_Emit("$L V = VM:ReadVector2f($1 + %s)",seg1code) @@ -1770,13 +1679,8 @@ ZVM.OpcodeTable[295] = function(self) --VDIV self:Dyn_Emit("end") end ZVM.OpcodeTable[296] = function(self) --VTRANSFORM - local seg1code,seg2code = "0","0" - if not self.EmitOperandSegment[1] then - seg1code = "VM.DS" - end - if not self.EmitOperandSegment[2] then - seg2code = "VM.DS" - end + local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS" + local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS" self:Dyn_Emit("local address_1 = $1 + $s",seg1code) self:Dyn_Emit("local address_2 = $2 + %s",seg2code) self:Dyn_Emit [[ From f4bcd4e245cc4fe5cfa82e93e445d07378861b79 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Mon, 27 Nov 2023 18:53:29 -0600 Subject: [PATCH 3/5] Mark the microcode var for later removal --- lua/wire/zvm/zvm_core.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/wire/zvm/zvm_core.lua b/lua/wire/zvm/zvm_core.lua index c5b94df..2c2e690 100644 --- a/lua/wire/zvm/zvm_core.lua +++ b/lua/wire/zvm/zvm_core.lua @@ -4,6 +4,7 @@ -- Virtual machine implementation core -------------------------------------------------------------------------------- ZVM = {} +-- TODO: Remove microcode debugging, it's not possible to access normally. if not SERVER and not CLIENT then ZVM.MicrocodeDebug = true end From 3090ebfe8375165c1fdd09aae711519a0cd99df5 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Tue, 28 Nov 2023 15:21:13 -0600 Subject: [PATCH 4/5] mark the rest of the microcode debug checks/cases --- lua/wire/zvm/zvm_core.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lua/wire/zvm/zvm_core.lua b/lua/wire/zvm/zvm_core.lua index 2c2e690..2119637 100644 --- a/lua/wire/zvm/zvm_core.lua +++ b/lua/wire/zvm/zvm_core.lua @@ -27,6 +27,7 @@ include("wire/zvm/zvm_data.lua") if ZVM.MicrocodeDebug then -- Debug microcode generator local pad = 0 function ZVM:Emit(text) + -- TODO: Remove microcode debugging, it's not possible to access normally. if string.find(text,"end") and (not string.find(text,"if")) then pad = pad - 1 end @@ -318,7 +319,7 @@ function ZVM:Dyn_EndBlock() self:Dyn_EmitState() self:Dyn_EmitBreak(true) end - + -- TODO: Remove microcode debugging, it's not possible to access normally. if self.MicrocodeDebug then if Msg then local str = self.EmitBlock From 19c3e2772e5e0dbf1dbd58b357cc1987f0200e82 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Tue, 28 Nov 2023 15:25:33 -0600 Subject: [PATCH 5/5] Mark the opcodes that check for microcode debugging --- lua/wire/zvm/zvm_opcodes.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/wire/zvm/zvm_opcodes.lua b/lua/wire/zvm/zvm_opcodes.lua index 2ce5509..64100b7 100644 --- a/lua/wire/zvm/zvm_opcodes.lua +++ b/lua/wire/zvm/zvm_opcodes.lua @@ -337,6 +337,7 @@ ZVM.OpcodeTable[45] = function(self) --CLP self:Dyn_Emit("VM.PF = 0") end ZVM.OpcodeTable[46] = function(self) --STD + -- TODO: Remove microcode debugging, it's not possible to access normally. if self.MicrocodeDebug then self:Dyn_Emit("VM.Debug = true") end @@ -1170,6 +1171,7 @@ ZVM.OpcodeTable[137] = function(self) --EXTRETP self.OpcodeTable[110](self) -- as EXTRET end ZVM.OpcodeTable[139] = function(self) --CLD + -- TODO: Remove microcode debugging, it's not possible to access normally. if self.MicrocodeDebug then self:Dyn_Emit("VM.Debug = false") end