dobrograd-13-06-2022/garrysmod/addons/feature-wire/lua/wire/zvm/zvm_opcodes.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

1657 lines
61 KiB
Lua

--------------------------------------------------------------------------------
-- Zyelios VM (Zyelios CPU/GPU virtual machine)
--
-- Primary opcode set
--------------------------------------------------------------------------------
-- Initialize opcode count lookup table
ZVM.OperandCount = {}
for _,instruction in pairs(CPULib.InstructionTable) do
ZVM.OperandCount[instruction.Opcode] = instruction.OperandCount
end
-- Initialize runlevel lookup table
ZVM.OpcodeRunLevel = {}
for _,instruction in pairs(CPULib.InstructionTable) do
if instruction.Privileged then
ZVM.OpcodeRunLevel[instruction.Opcode] = 0
end
end
--------------------------------------------------------------------------------
-- Hand-leg guide to writing ZCPU microcode
-- self:Dyn_Emit(code)
-- Emits microcode to output stream
--
-- self:Dyn_EmitOperand(OP,code,emitNow)
-- self:Dyn_EmitOperand(code)
-- Emits write to specific operand (if no operant specified - then operand #1)
-- Passing emitNow as true will emit operand at the current spot in microcode,
-- and set it later (must be done if operand is set inside block).
--
-- self:Dyn_EmitState()
-- Pushes state update - all global registers are set to their local values
--
-- self:Dyn_EmitBreak(emitIP)
-- Emits a return (does not push state). Emits new IP if required
--
-- self:Dyn_EmitForceRegisterGlobal(register)
-- Forces a specific register to be global (so VM.EAX has valid value)
--
-- self:Dyn_EmitForceRegisterLocal(register)
-- Forces a specific register to be local (so EAX has valid value)
-- Marks register as changed
--
-- self:Dyn_EmitRegisterValueChanged(register)
-- Marks that there now exists local state for the register
--
-- self:Dyn_EmitInterrupt(intNo,intParam)
-- Emits interrupt call
--
-- self:Dyn_EmitInterruptCheck()
-- Emits interrupt check
--------------------------------------------------------------------------------
-- Load all opcodes
ZVM.OpcodeTable = {}
ZVM.OpcodeTable[0] = function(self) --END (STOP)
self:Dyn_EmitInterrupt("2","0")
self.PrecompileBreak = true -- Stop precompiler from following further
end
ZVM.OpcodeTable[1] = function(self) --JNE
self:Dyn_Emit("if VM.CMPR ~= 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[2] = function(self) --JMP
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self.PrecompileBreak = true -- Stop precompiler from following further
end
ZVM.OpcodeTable[3] = function(self) --JG
self:Dyn_Emit("if VM.CMPR > 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[4] = function(self) --JGE
self:Dyn_Emit("if VM.CMPR >= 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[5] = function(self) --JL
self:Dyn_Emit("if VM.CMPR < 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
-- self.PrecompileBreak = true
end
ZVM.OpcodeTable[6] = function(self) --JLE
self:Dyn_Emit("if VM.CMPR <= 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[7] = function(self) --JE
self:Dyn_Emit("if VM.CMPR == 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[8] = function(self) --CPUID
self:Dyn_Emit("EAX = VM:CPUID($1)")
self:Dyn_EmitRegisterValueChanged("EAX")
end
ZVM.OpcodeTable[9] = function(self) --PUSH
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("VM:Push($1)")
self:Dyn_EmitInterruptCheck()
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[10] = function(self) --ADD
self:Dyn_EmitOperand("$1 + $2")
end
ZVM.OpcodeTable[11] = function(self) --SUB
self:Dyn_EmitOperand("$1 - $2")
end
ZVM.OpcodeTable[12] = function(self) --MUL
self:Dyn_EmitOperand("$1 * $2")
end
ZVM.OpcodeTable[13] = function(self) --DIV
self:Dyn_Emit("$L OP = $2")
self:Dyn_EmitOperand("$1 / OP")
self:Dyn_Emit("if math.abs(OP) < 1e-12 then")
self:Dyn_EmitInterrupt("3","0")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[14] = function(self) --MOV
self:Dyn_EmitOperand("$2")
end
ZVM.OpcodeTable[15] = function(self) --CMP
self:Dyn_Emit("VM.CMPR = $1 - $2")
end
ZVM.OpcodeTable[16] = function(self) --RD
self:Dyn_Emit("$L OP,ANS = $2,0")
self:Dyn_EmitOperand("ANS")
self:Dyn_Emit("if VM.Memory[OP] then")
self:Dyn_Emit("ANS = VM.Memory[OP]")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[17] = function(self) --WD
self:Dyn_Emit("$L ADDR = math.floor($1)")
self:Dyn_Emit("if (ADDR >= 0) and (ADDR <= 65535) then")
self:Dyn_Emit("VM.Memory[ADDR] = $2")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[18] = function(self) --MIN
self:Dyn_EmitOperand("math.min($1,$2)")
end
ZVM.OpcodeTable[19] = function(self) --MAX
self:Dyn_EmitOperand("math.max($1,$2)")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[20] = function(self) --INC
self:Dyn_EmitOperand("$1 + 1")
end
ZVM.OpcodeTable[21] = function(self) --DEC
self:Dyn_EmitOperand("$1 - 1")
end
ZVM.OpcodeTable[22] = function(self) --NEG
self:Dyn_EmitOperand("-$1")
end
ZVM.OpcodeTable[23] = function(self) --RAND
self:Dyn_EmitOperand("math.random()")
end
ZVM.OpcodeTable[24] = function(self) --LOOP
self:Dyn_EmitForceRegisterLocal("ECX")
self:Dyn_Emit("ECX = ECX - 1")
self:Dyn_Emit("if ECX ~= 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[25] = function(self) --LOOPA
self:Dyn_EmitForceRegisterLocal("EAX")
self:Dyn_Emit("EAX = EAX - 1")
self:Dyn_Emit("if EAX ~= 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[26] = function(self) --LOOPB
self:Dyn_EmitForceRegisterLocal("EBX")
self:Dyn_Emit("EBX = EBX - 1")
self:Dyn_Emit("if VM.EBX ~= 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[27] = function(self) --LOOPD
self:Dyn_EmitForceRegisterLocal("EDX")
self:Dyn_Emit("EDX = EDX - 1")
self:Dyn_Emit("if EDX ~= 0 then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[28] = function(self) --SPG
self:Dyn_Emit("$L IDX = math.floor($1 / 128)")
self:Dyn_Emit("$L PAGE = VM:GetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("if VM.CurrentPage.RunLevel <= PAGE.RunLevel then")
self:Dyn_Emit("PAGE.Read = 1")
self:Dyn_Emit("PAGE.Write = 0")
self:Dyn_Emit("VM:SetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("11","IDX")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[29] = function(self) --CPG
self:Dyn_Emit("$L idx = math.floor($1 / 128)")
self:Dyn_Emit("$L PAGE = VM:GetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("if VM.CurrentPage.RunLevel <= VM.Page[idx].RunLevel then")
self:Dyn_Emit("PAGE.Read = 1")
self:Dyn_Emit("PAGE.Write = 1")
self:Dyn_Emit("VM:SetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("11","IDX")
self:Dyn_Emit("end")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[30] = function(self) --POP
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_EmitOperand(1,"VM:Pop()",true)
self:Dyn_EmitInterruptCheck()
end
ZVM.OpcodeTable[31] = function(self) --CALL
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self.PrecompileBreak = true
end
ZVM.OpcodeTable[32] = function(self) --BNOT
self:Dyn_EmitOperand("VM:BinaryNot($1)")
end
ZVM.OpcodeTable[33] = function(self) --FINT
self:Dyn_EmitOperand("math.floor($1)")
end
ZVM.OpcodeTable[34] = function(self) --RND
self:Dyn_EmitOperand("math.Round($1)")
end
ZVM.OpcodeTable[35] = function(self) --FFRAC
self:Dyn_Emit("$L OP = $1")
self:Dyn_EmitOperand("OP - math.floor(OP)")
end
ZVM.OpcodeTable[36] = function(self) --FINV
self:Dyn_Emit("$L OP = $1")
self:Dyn_EmitOperand("1 / OP")
self:Dyn_Emit("if math.abs(OP) < 1e-12 then")
self:Dyn_EmitInterrupt("3","1")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[37] = function(self) --HALT
self:Dyn_Emit("VM.HaltPort = math.floor($1)")
end
ZVM.OpcodeTable[38] = function(self) --FSHL
self:Dyn_EmitOperand("$1 * 2")
end
ZVM.OpcodeTable[39] = function(self) --FSHR
self:Dyn_EmitOperand("$1 / 2")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[40] = function(self) --RET
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("$L IP = VM:Pop()")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Jump(IP)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self.PrecompileBreak = true
end
ZVM.OpcodeTable[41] = function(self) --IRET
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("if VM.EF == 1 then")
self:Dyn_Emit("$L CS = VM:Pop()")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("$L IP = VM:Pop()")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Jump(IP,CS)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("else")
self:Dyn_Emit("$L IP = VM:Pop()")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Jump(IP,CS)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self.PrecompileBreak = true
end
ZVM.OpcodeTable[42] = function(self) --STI
self:Dyn_Emit("VM.NIF = 1")
end
ZVM.OpcodeTable[43] = function(self) --CLI
self:Dyn_Emit("VM.IF = 0")
end
ZVM.OpcodeTable[44] = function(self) --STP
self:Dyn_Emit("VM.PF = 1")
end
ZVM.OpcodeTable[45] = function(self) --CLP
self:Dyn_Emit("VM.PF = 0")
end
ZVM.OpcodeTable[46] = function(self) --STD
if self.MicrocodeDebug then
self:Dyn_Emit("VM.Debug = true")
end
end
ZVM.OpcodeTable[47] = function(self) --RETF
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("$L IP = VM:Pop()")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("$L CS = VM:Pop()")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Jump(IP,CS)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self.PrecompileBreak = true
end
ZVM.OpcodeTable[48] = function(self) --STEF
self:Dyn_Emit("VM.EF = 1")
end
ZVM.OpcodeTable[49] = function(self) --CLEF
self:Dyn_Emit("VM.EF = 0")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[50] = function(self) --AND
self:Dyn_Emit("$L OP = 0")
self:Dyn_EmitOperand("OP")
self:Dyn_Emit("if ($1 > 0) and ($2 > 0) then")
self:Dyn_Emit("OP = 1")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[51] = function(self) --OR
self:Dyn_Emit("$L OP = 0")
self:Dyn_EmitOperand("OP")
self:Dyn_Emit("if ($1 > 0) or ($2 > 0) then")
self:Dyn_Emit("OP = 1")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[52] = function(self) --XOR
self:Dyn_Emit("$L OP1,OP2 = $1,$2")
self:Dyn_Emit("$L OP = 0")
self:Dyn_EmitOperand("OP")
self:Dyn_Emit("if ((OP1 > 0) and (OP2 <= 0)) or")
self:Dyn_Emit(" ((OP1 <= 0) and (OP2 > 0)) then")
self:Dyn_Emit("OP = 1")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[53] = function(self) --FSIN
self:Dyn_EmitOperand("math.sin($2)")
end
ZVM.OpcodeTable[54] = function(self) --FCOS
self:Dyn_EmitOperand("math.cos($2)")
end
ZVM.OpcodeTable[55] = function(self) --FTAN
self:Dyn_EmitOperand("math.tan($2)")
end
ZVM.OpcodeTable[56] = function(self) --FASIN
self:Dyn_EmitOperand("math.asin($2)")
end
ZVM.OpcodeTable[57] = function(self) --FACOS
self:Dyn_EmitOperand("math.acos($2)")
end
ZVM.OpcodeTable[58] = function(self) --FATAN
self:Dyn_EmitOperand("math.atan($2)")
end
ZVM.OpcodeTable[59] = function(self) --MOD
self:Dyn_EmitOperand("math.fmod($1,$2)")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[60] = function(self) --BIT
self:Dyn_Emit("$L BITS = VM:IntegerToBinary($1)")
self:Dyn_Emit("VM.CMPR = BITS[math.floor($2)] or 0")
self:Dyn_Emit("VM.TMR = VM.TMR + 30")
end
ZVM.OpcodeTable[61] = function(self) --SBIT
self:Dyn_Emit("$L BITS = VM:IntegerToBinary($1)")
self:Dyn_Emit("BITS[math.floor($2)] = 1")
self:Dyn_EmitOperand("VM:BinaryToInteger(BITS)")
self:Dyn_Emit("VM.TMR = VM.TMR + 20")
end
ZVM.OpcodeTable[62] = function(self) --CBIT
self:Dyn_Emit("$L BITS = VM:IntegerToBinary($1)")
self:Dyn_Emit("BITS[math.floor($2)] = 0")
self:Dyn_EmitOperand("VM:BinaryToInteger(BITS)")
self:Dyn_Emit("VM.TMR = VM.TMR + 20")
end
ZVM.OpcodeTable[63] = function(self) --TBIT
self:Dyn_Emit("$L BITS = VM:IntegerToBinary($1)")
self:Dyn_Emit("BITS[math.floor($2)] = 1 - (BITS[math.floor($2)] or 0)")
self:Dyn_EmitOperand("VM:BinaryToInteger(BITS)")
self:Dyn_Emit("VM.TMR = VM.TMR + 30")
end
ZVM.OpcodeTable[64] = function(self) --BAND
self:Dyn_EmitOperand("VM:BinaryAnd($1,$2)")
self:Dyn_Emit("VM.TMR = VM.TMR + 30")
end
ZVM.OpcodeTable[65] = function(self) --BOR
self:Dyn_EmitOperand("VM:BinaryOr($1,$2)")
self:Dyn_Emit("VM.TMR = VM.TMR + 30")
end
ZVM.OpcodeTable[66] = function(self) --BXOR
self:Dyn_EmitOperand("VM:BinaryXor($1,$2)")
self:Dyn_Emit("VM.TMR = VM.TMR + 30")
end
ZVM.OpcodeTable[67] = function(self) --BSHL
self:Dyn_EmitOperand("VM:BinarySHL($1,$2)")
self:Dyn_Emit("VM.TMR = VM.TMR + 30")
end
ZVM.OpcodeTable[68] = function(self) --BSHR
self:Dyn_EmitOperand("VM:BinarySHR($1,$2)")
self:Dyn_Emit("VM.TMR = VM.TMR + 30")
end
ZVM.OpcodeTable[69] = function(self) --JMPF
self:Dyn_Emit("VM:Jump($1,$2)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self.PrecompileBreak = true
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:Dyn_Emit("VM:ExternalInterrupt(math.floor($1))")
self:Dyn_EmitBreak()
self.PrecompileBreak = true
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("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[72] = function(self) --CJMP
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("if VM:Push("..self.PrecompileIP..") then")
self:Dyn_Emit("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
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("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("end")
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("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("end")
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("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("end")
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("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("end")
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("VM:Jump($1)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[78] = function(self) --MCOPY
self:Dyn_EmitForceRegisterLocal("ESI")
self:Dyn_EmitForceRegisterLocal("EDI")
self:Dyn_Emit("for i = 1,math.Clamp($1,0,8192) do")
self:Dyn_Emit("$L VAL")
self:Dyn_Emit("VAL = VM:ReadCell(ESI)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteCell(EDI,VAL)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("EDI = EDI + 1")
self:Dyn_Emit("ESI = ESI + 1")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[79] = function(self) --MXCHG
self:Dyn_EmitForceRegisterLocal("ESI")
self:Dyn_EmitForceRegisterLocal("EDI")
self:Dyn_Emit("for i = 1,math.Clamp($1,0,8192) do")
self:Dyn_Emit("$L VAL1,VAL2")
self:Dyn_Emit("VAL1 = VM:ReadCell(ESI)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VAL2 = VM:ReadCell(EDI)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteCell(EDI,VAL1)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteCell(ESI,VAL2)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("EDI = EDI + 1")
self:Dyn_Emit("ESI = ESI + 1")
self:Dyn_Emit("end")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[80] = function(self) --FPWR
self:Dyn_EmitOperand("$1^$2")
end
ZVM.OpcodeTable[81] = function(self) --XCHG
self:Dyn_Emit("$L L0,L1 = $1,$2")
self:Dyn_EmitOperand(1,"L1")
self:Dyn_EmitOperand(2,"L0")
end
ZVM.OpcodeTable[82] = function(self) --FLOG
self:Dyn_EmitOperand("math.log($2)")
end
ZVM.OpcodeTable[83] = function(self) --FLOG10
self:Dyn_EmitOperand("math.log10($2)")
end
ZVM.OpcodeTable[84] = function(self) --IN
self:Dyn_EmitOperand("VM:ReadPort($2)")
self:Dyn_EmitInterruptCheck()
end
ZVM.OpcodeTable[85] = function(self) --OUT
self:Dyn_Emit("VM:WritePort($1,$2)")
self:Dyn_EmitInterruptCheck()
end
ZVM.OpcodeTable[86] = function(self) --FABS
self:Dyn_EmitOperand("math.abs($2)")
end
ZVM.OpcodeTable[87] = function(self) --FSGN
self:Dyn_Emit("$L OP = $2")
self:Dyn_Emit("if OP > 0 then")
self:Dyn_EmitOperand(1,"1",true)
self:Dyn_Emit("elseif OP < 0 then")
self:Dyn_EmitOperand(1,"-1",true)
self:Dyn_Emit("else")
self:Dyn_EmitOperand(1,"0",true)
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[88] = function(self) --FEXP
self:Dyn_EmitOperand("math.exp($2)")
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("VM:Jump($1,$2)")
self:Dyn_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self.PrecompileBreak = true
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[90] = function(self) --FPI
self:Dyn_EmitOperand("3.141592653589793")
end
ZVM.OpcodeTable[91] = function(self) --FE
self:Dyn_EmitOperand("2.718281828459045")
end
ZVM.OpcodeTable[92] = function(self) --INT
self:Dyn_EmitInterrupt("$1","0")
end
ZVM.OpcodeTable[93] = function(self) --TPG
self:Dyn_Emit("$L TADD = math.floor($1*128)")
self:Dyn_Emit("$L OLDIF = VM.IF")
self:Dyn_Emit("$L OP = $1")
self:Dyn_Emit("VM.IF = 0")
self:Dyn_Emit("VM.CMPR = 0")
self:Dyn_Emit("while TADD < OP*128+128 do")
self:Dyn_Emit("$L VAL = VM:ReadCell(TADD)")
self:Dyn_Emit("if VM.INTR == 1 then")
self:Dyn_Emit("VM.CMPR = TADD")
self:Dyn_Emit("TADD = OP*128+128")
self:Dyn_Emit("end")
self:Dyn_Emit("TADD = TADD+1")
self:Dyn_Emit("end")
self:Dyn_Emit("VM.INTR = 0")
self:Dyn_Emit("VM.IF = OLDIF")
end
ZVM.OpcodeTable[94] = function(self) --FCEIL
self:Dyn_EmitOperand("math.ceil($1)")
end
ZVM.OpcodeTable[95] = function(self) --ERPG
self:Dyn_Emit("$L OP = $1")
self:Dyn_Emit("if (OP >= 0) and (OP < VM.ROMSize/128) then")
self:Dyn_Emit("$L TADD = OP*128")
self:Dyn_Emit("while TADD < OP*128+128 do")
self:Dyn_Emit("VM.ROM[TADD] = nil")
self:Dyn_Emit("TADD = TADD+1")
self:Dyn_Emit("end")
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("12","0")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[96] = function(self) --WRPG
self:Dyn_Emit("$L OP = $1")
self:Dyn_Emit("if (OP >= 0) and (OP < VM.ROMSize/128) then")
self:Dyn_Emit("$L TADD = OP*128")
self:Dyn_Emit("while TADD < OP*128+128 do")
self:Dyn_Emit("VM.ROM[TADD] = VM.Memory[TADD]")
self:Dyn_Emit("TADD = TADD+1")
self:Dyn_Emit("end")
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("12","0")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[97] = function(self) --RDPG
self:Dyn_Emit("$L OP = $1")
self:Dyn_Emit("if (OP >= 0) and (OP < VM.ROMSize/128) then")
self:Dyn_Emit("$L TADD = OP*128")
self:Dyn_Emit("while TADD < OP*128+128 do")
self:Dyn_Emit("VM.Memory[TADD] = VM.ROM[TADD]")
self:Dyn_Emit("TADD = TADD+1")
self:Dyn_Emit("end")
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("12","0")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[98] = function(self) --TIMER
self:Dyn_EmitOperand("(VM.TIMER+"..(self.PrecompileInstruction or 0).."*VM.TimerDT)")
end
ZVM.OpcodeTable[99] = function(self) --LIDTR
self:Dyn_Emit("VM.IDTR = $1")
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 + 01,VM.EAX)")
self:Dyn_Emit("VM:WriteCell($1 + 02,VM.EBX)")
self:Dyn_Emit("VM:WriteCell($1 + 03,VM.ECX)")
self:Dyn_Emit("VM:WriteCell($1 + 04,VM.EDX)")
self:Dyn_Emit("VM:WriteCell($1 + 05,VM.ESI)")
self:Dyn_Emit("VM:WriteCell($1 + 06,VM.EDI)")
self:Dyn_Emit("VM:WriteCell($1 + 07,VM.ESP)")
self:Dyn_Emit("VM:WriteCell($1 + 08,VM.EBP)")
self:Dyn_Emit("VM:WriteCell($1 + 09,VM.CS)")
self:Dyn_Emit("VM:WriteCell($1 + 10,VM.SS)")
self:Dyn_Emit("VM:WriteCell($1 + 11,VM.DS)")
self:Dyn_Emit("VM:WriteCell($1 + 12,VM.ES)")
self:Dyn_Emit("VM:WriteCell($1 + 13,VM.GS)")
self:Dyn_Emit("VM:WriteCell($1 + 14,VM.FS)")
self:Dyn_Emit("VM:WriteCell($1 + 15,VM.CMPR)")
self:Dyn_EmitInterruptCheck()
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_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_EmitState()
self:Dyn_EmitBreak()
self.PrecompileBreak = true
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_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_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_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_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_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[108] = function(self) --LNEG
self:Dyn_EmitOperand("1-math.Clamp($1,0,1)")
end
ZVM.OpcodeTable[109] = function(self) --STATERESTORE
self:Dyn_Emit(" VM:ReadCell($1 + 00)")
self:Dyn_Emit("EAX = VM:ReadCell($1 + 01) or 0")
self:Dyn_Emit("EBX = VM:ReadCell($1 + 02) or 0")
self:Dyn_Emit("ECX = VM:ReadCell($1 + 03) or 0")
self:Dyn_Emit("EDX = VM:ReadCell($1 + 04) or 0")
self:Dyn_Emit("ESI = VM:ReadCell($1 + 05) or 0")
self:Dyn_Emit("EDI = VM:ReadCell($1 + 06) or 0")
self:Dyn_Emit("ESP = VM:ReadCell($1 + 07) or 0")
self:Dyn_Emit("EBP = VM:ReadCell($1 + 08) or 0")
self:Dyn_Emit("CS = VM:ReadCell($1 + 09) or 0")
self:Dyn_Emit("SS = VM:ReadCell($1 + 10) or 0")
self:Dyn_Emit("DS = VM:ReadCell($1 + 11) or 0")
self:Dyn_Emit("ES = VM:ReadCell($1 + 12) or 0")
self:Dyn_Emit("GS = VM:ReadCell($1 + 13) or 0")
self:Dyn_Emit("FS = VM:ReadCell($1 + 14) or 0")
self:Dyn_Emit("VM.CMPR = VM:ReadCell($1 + 15) or 0")
self:Dyn_EmitInterruptCheck()
self:Dyn_EmitRegisterValueChanged("EAX")
self:Dyn_EmitRegisterValueChanged("EBX")
self:Dyn_EmitRegisterValueChanged("ECX")
self:Dyn_EmitRegisterValueChanged("EDX")
self:Dyn_EmitRegisterValueChanged("ESI")
self:Dyn_EmitRegisterValueChanged("EDI")
self:Dyn_EmitRegisterValueChanged("ESP")
self:Dyn_EmitRegisterValueChanged("EBP")
self:Dyn_EmitRegisterValueChanged("CS")
self:Dyn_EmitRegisterValueChanged("SS")
self:Dyn_EmitRegisterValueChanged("DS")
self:Dyn_EmitRegisterValueChanged("ES")
self:Dyn_EmitRegisterValueChanged("GS")
self:Dyn_EmitRegisterValueChanged("FS")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[110] = function(self) --EXTRET
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("$L V = 0")
self:Dyn_EmitState()
self:Dyn_Emit("V = VM:Pop()") -- IRET CS
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("V = VM:Pop()") -- IRET EIP
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L IP = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.CMPR = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EAX = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EBX = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.ECX = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EDX = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EBP = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() -- Do not set ESP right now
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.ESI = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EDI = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L CS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() -- Do not set SS right now
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.DS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.FS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.GS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.ES = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.KS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.LS = V")
self:Dyn_Emit("VM:Jump(IP,CS)")
self:Dyn_EmitBreak()
self.PrecompileBreak = true
end
ZVM.OpcodeTable[111] = function(self) --IDLE
self:Dyn_Emit("VM.Idle = 1")
end
ZVM.OpcodeTable[112] = function(self) --NOP
end
ZVM.OpcodeTable[113] = function(self) --RLADD
self:Dyn_Emit("EAX = VM.LADD")
self:Dyn_EmitRegisterValueChanged("EAX")
end
ZVM.OpcodeTable[114] = function(self) --PUSHA
self:Dyn_EmitForceRegisterLocal("EAX")
self:Dyn_EmitForceRegisterLocal("EBX")
self:Dyn_EmitForceRegisterLocal("ECX")
self:Dyn_EmitForceRegisterLocal("EDX")
self:Dyn_EmitForceRegisterLocal("ESI")
self:Dyn_EmitForceRegisterLocal("EDI")
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_EmitForceRegisterLocal("EBP")
self:Dyn_Emit("VM:Push(EDI)") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Push(ESI)") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Push(EBP)") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Push(VM.ESP)") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Push(EDX)") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Push(ECX)") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Push(EBX)") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:Push(EAX)") self:Dyn_EmitInterruptCheck()
end
ZVM.OpcodeTable[115] = function(self) --POPA
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("EAX = VM:Pop()") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("EBX = VM:Pop()") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("ECX = VM:Pop()") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("EDX = VM:Pop()") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("$L SP = VM:Pop()") self:Dyn_EmitInterruptCheck() -- Do not write stack pointer
self:Dyn_Emit("EBP = VM:Pop()") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("ESI = VM:Pop()") self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("EDI = VM:Pop()") self:Dyn_EmitInterruptCheck()
self:Dyn_EmitRegisterValueChanged("EAX")
self:Dyn_EmitRegisterValueChanged("EBX")
self:Dyn_EmitRegisterValueChanged("ECX")
self:Dyn_EmitRegisterValueChanged("EDX")
self:Dyn_EmitRegisterValueChanged("ESI")
self:Dyn_EmitRegisterValueChanged("EDI")
self:Dyn_EmitRegisterValueChanged("EBP")
end
ZVM.OpcodeTable[116] = function(self) --STD2
self:Dyn_Emit("VM.HWDEBUG = 1")
self:Dyn_Emit("VM.DBGSTATE = 0")
end
ZVM.OpcodeTable[117] = function(self) --LEAVE
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_EmitForceRegisterGlobal("EBP")
self:Dyn_Emit("VM.ESP = VM.EBP-1")
self:Dyn_Emit("EBP = VM:Pop()")
self:Dyn_EmitInterruptCheck()
self:Dyn_EmitRegisterValueChanged("EBP")
end
ZVM.OpcodeTable[118] = function(self) --STM
self:Dyn_Emit("VM.MF = 1")
end
ZVM.OpcodeTable[119] = function(self) --CLM
self:Dyn_Emit("VM.MF = 0")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[120] = function(self) --CPUGET
self:Dyn_Emit("$L REG = $2")
self:Dyn_Emit("$L OP = 0")
self:Dyn_EmitState()
self:Dyn_EmitOperand("OP")
self:Dyn_Emit("if VM.InternalRegister[REG] then")
self:Dyn_Emit("OP = VM[VM.InternalRegister[REG]]")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[121] = function(self) --CPUSET
self:Dyn_Emit("$L REG = $1")
self:Dyn_Emit("if VM.InternalRegister[REG] and (not VM.ReadOnlyRegister[REG]) then")
self:Dyn_Emit("$L OP = $2")
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_EmitState()
self:Dyn_EmitBreak()
self:Dyn_Emit("else")
self:Dyn_Emit("if REG == 1 then EAX = OP end")
self:Dyn_Emit("if REG == 2 then EBX = OP end")
self:Dyn_Emit("if REG == 3 then ECX = OP end")
self:Dyn_Emit("if REG == 4 then EDX = OP end")
self:Dyn_Emit("if REG == 5 then ESI = OP end")
self:Dyn_Emit("if REG == 6 then EDI = OP end")
self:Dyn_Emit("if REG == 7 then ESP = OP end")
self:Dyn_Emit("if REG == 8 then EBP = OP end")
self:Dyn_Emit("end")
self:Dyn_Emit("end")
-- FIXME: registers must be properly synced
end
ZVM.OpcodeTable[122] = function(self) --SPP
self:Dyn_Emit("$L FirstAddr")
self:Dyn_Emit("$L LastAddr")
self:Dyn_Emit("if VM.BlockSize > 0 then")
self:Dyn_Emit("FirstAddr = VM.BlockStart")
self:Dyn_Emit("LastAddr = FirstAddr + math.Clamp(VM.BlockSize,0,8192)")
self:Dyn_Emit("VM.BlockSize = 0")
self:Dyn_Emit("else")
self:Dyn_Emit("FirstAddr = $1 * 128")
self:Dyn_Emit("LastAddr = $1 * 128 + 127")
self:Dyn_Emit("end")
self:Dyn_Emit("$L ADDR = FirstAddr")
self:Dyn_Emit("$L FLAG = $2")
self:Dyn_Emit("while ADDR < LastAddr do")
self:Dyn_Emit("$L IDX = math.floor(ADDR / 128)")
self:Dyn_Emit("$L PAGE = VM:GetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("if VM.CurrentPage.RunLevel <= PAGE.RunLevel then")
self:Dyn_Emit(" if FLAG == 0 then PAGE.Read = 1")
self:Dyn_Emit("elseif FLAG == 1 then PAGE.Write = 1")
self:Dyn_Emit("elseif FLAG == 2 then PAGE.Execute = 1")
self:Dyn_Emit("elseif FLAG == 3 then PAGE.RunLevel = 1 end")
self:Dyn_Emit("VM:SetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("11","IDX")
self:Dyn_Emit("end")
self:Dyn_Emit("ADDR = ADDR + 128")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[123] = function(self) --CPP
self:Dyn_Emit("$L FirstAddr")
self:Dyn_Emit("$L LastAddr")
self:Dyn_Emit("if VM.BlockSize > 0 then")
self:Dyn_Emit("FirstAddr = VM.BlockStart")
self:Dyn_Emit("LastAddr = FirstAddr + math.Clamp(VM.BlockSize,0,8192)")
self:Dyn_Emit("VM.BlockSize = 0")
self:Dyn_Emit("else")
self:Dyn_Emit("FirstAddr = $1 * 128")
self:Dyn_Emit("LastAddr = $1 * 128 + 127")
self:Dyn_Emit("end")
self:Dyn_Emit("$L ADDR = FirstAddr")
self:Dyn_Emit("$L FLAG = $2")
self:Dyn_Emit("while ADDR < LastAddr do")
self:Dyn_Emit("$L IDX = math.floor(ADDR / 128)")
self:Dyn_Emit("$L PAGE = VM:GetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("if VM.CurrentPage.RunLevel <= PAGE.RunLevel then")
self:Dyn_Emit(" if FLAG == 0 then PAGE.Read = 0")
self:Dyn_Emit("elseif FLAG == 1 then PAGE.Write = 0")
self:Dyn_Emit("elseif FLAG == 2 then PAGE.Execute = 0")
self:Dyn_Emit("elseif FLAG == 3 then PAGE.RunLevel = 0 end")
self:Dyn_Emit("VM:SetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("11","IDX")
self:Dyn_Emit("end")
self:Dyn_Emit("ADDR = ADDR + 128")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[124] = function(self) --SRL
self:Dyn_Emit("$L FirstAddr")
self:Dyn_Emit("$L LastAddr")
self:Dyn_Emit("if VM.BlockSize > 0 then")
self:Dyn_Emit("FirstAddr = VM.BlockStart")
self:Dyn_Emit("LastAddr = FirstAddr + math.Clamp(VM.BlockSize,0,8192)")
self:Dyn_Emit("VM.BlockSize = 0")
self:Dyn_Emit("else")
self:Dyn_Emit("FirstAddr = $1 * 128")
self:Dyn_Emit("LastAddr = $1 * 128 + 127")
self:Dyn_Emit("end")
self:Dyn_Emit("$L ADDR = FirstAddr")
self:Dyn_Emit("while ADDR < LastAddr do")
self:Dyn_Emit("$L IDX = math.floor(ADDR / 128)")
self:Dyn_Emit("$L PAGE = VM:GetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("if VM.CurrentPage.RunLevel <= PAGE.RunLevel then")
self:Dyn_Emit("PAGE.RunLevel = $2")
self:Dyn_Emit("VM:SetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("11","IDX")
self:Dyn_Emit("end")
self:Dyn_Emit("ADDR = ADDR + 128")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[125] = function(self) --GRL
self:Dyn_Emit("$L IDX = math.floor($2 / 128)")
self:Dyn_Emit("$L PAGE = VM:GetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_EmitOperand("PAGE.RunLevel")
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"))
self:Dyn_EmitOperand(emitText)
end
ZVM.OpcodeTable[127] = function(self) --BLOCK
self:Dyn_Emit("VM.BlockStart = $1")
self:Dyn_Emit("VM.BlockSize = $2")
end
ZVM.OpcodeTable[128] = function(self) --CMPAND
self:Dyn_Emit("if VM.CMPR ~= 0 then")
self:Dyn_Emit("VM.CMPR = $1 - $2")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[129] = function(self) --CMPOR
self:Dyn_Emit("if VM.CMPR == 0 then")
self:Dyn_Emit("VM.CMPR = $1 - $2")
self:Dyn_Emit("end")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[130] = function(self) --MSHIFT FIXME: Inoperative
self:Dyn_EmitForceRegisterLocal("ESI")
self:Dyn_Emit("$L Count = math.Clamp($1,0,8192)")
self:Dyn_Emit("if Count ~= 0 then")
self:Dyn_Emit("$L Offset = $2")
self:Dyn_Emit("$L Buffer = {}")
self:Dyn_Emit("if Offset > 0 then")
self:Dyn_Emit("for i = 0,math.Clamp(Count-1-Offset,0,8191) do") --Shifted part
self:Dyn_Emit("Buffer[i] = VM:ReadCell(ESI+i+Offset)")
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("for i = math.Clamp(Count-1-Offset+1,0,8191),math.Clamp(Count,0,8191) do") --Remaining part
self:Dyn_Emit("Buffer[i] = VM:ReadCell(ESI+i-(Count-1-Offset+1))")
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("else")
self:Dyn_Emit("for i = math.Clamp(-Offset,0,8191),math.Clamp(Count,0,8191) do") --Shifted part
self:Dyn_Emit("Buffer[i] = VM:ReadCell(ESI+i+Offset)")
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("for i = 0,math.Clamp(-Offset-1,0,8191) do") --Remaining part
self:Dyn_Emit("Buffer[i] = VM:ReadCell(ESI+i+(Count-1+Offset+1))")
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("end")
self:Dyn_Emit("for i = 0,Count-1 do")
self:Dyn_Emit("VM:WriteCell(ESI+i,Buffer[i] or 32)")
self:Dyn_Emit("end")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("ESI = ESI + Count")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[131] = function(self) --SMAP
self:Dyn_Emit("$L FirstAddr")
self:Dyn_Emit("$L LastAddr")
self:Dyn_Emit("if VM.BlockSize > 0 then")
self:Dyn_Emit("FirstAddr = VM.BlockStart")
self:Dyn_Emit("LastAddr = FirstAddr + math.Clamp(VM.BlockSize,0,8192)")
self:Dyn_Emit("VM.BlockSize = 0")
self:Dyn_Emit("else")
self:Dyn_Emit("FirstAddr = $1 * 128")
self:Dyn_Emit("LastAddr = $1 * 128 + 127")
self:Dyn_Emit("end")
self:Dyn_Emit("$L ADDR = FirstAddr")
self:Dyn_Emit("while ADDR < LastAddr do")
self:Dyn_Emit("$L IDX = math.floor(ADDR / 128)")
self:Dyn_Emit("$L PAGE = VM:GetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("if VM.CurrentPage.RunLevel <= PAGE.RunLevel then")
self:Dyn_Emit("PAGE.MappedIndex = $2")
self:Dyn_Emit("PAGE.Remapped = 1")
self:Dyn_Emit("VM:SetPageByIndex(IDX)")
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("end")
self:Dyn_Emit("else")
self:Dyn_EmitInterrupt("11","IDX")
self:Dyn_Emit("end")
self:Dyn_Emit("ADDR = ADDR + 128")
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[132] = function(self) --GMAP
self:Dyn_Emit("$L IDX = math.floor(ADDR / 128)")
self:Dyn_Emit("$L PAGE = VM:GetPageByIndex(IDX)")
self:Dyn_EmitInterruptCheck()
self:Dyn_EmitOperand("PAGE.MappedIndex")
end
ZVM.OpcodeTable[133] = function(self) --RSTACK
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_EmitOperand("VM:ReadFromStack($2)")
self:Dyn_EmitInterruptCheck()
end
ZVM.OpcodeTable[134] = function(self) --SSTACK
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("VM:WriteToStack($1,$2)")
self:Dyn_EmitInterruptCheck()
end
ZVM.OpcodeTable[135] = function(self) --ENTER
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_EmitForceRegisterLocal("EBP")
self:Dyn_Emit("VM:Push(EBP)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("EBP = VM.ESP+1")
self:Dyn_Emit("VM.ESP = VM.ESP-$1")
end
ZVM.OpcodeTable[136] = function(self) --IRETP
self:Dyn_Emit("VM.PTBL = $1")
self.OpcodeTable[41](self) -- as IRET
end
ZVM.OpcodeTable[137] = function(self) --EXTRETP
self:Dyn_Emit("VM.PTBL = $1")
self.OpcodeTable[110](self) -- as EXTRET
end
ZVM.OpcodeTable[139] = function(self) --CLD
if self.MicrocodeDebug then
self:Dyn_Emit("VM.Debug = false")
end
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[140] = function(self) --EXTRETA
self:Dyn_EmitForceRegisterGlobal("ESP")
self:Dyn_Emit("$L V = 0")
self:Dyn_EmitState()
self:Dyn_Emit("V = VM:Pop()") -- IRET CS
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("V = VM:Pop()") -- IRET EIP
self:Dyn_EmitInterruptCheck()
for i=0,31 do
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.R"..i.." = V")
end
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L IP = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.CMPR = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EAX = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EBX = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.ECX = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EDX = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EBP = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() -- Do not set ESP right now
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.ESI = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.EDI = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("$L CS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() -- Do not set SS right now
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.DS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.FS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.GS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.ES = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.KS = V")
self:Dyn_Emit("V = VM:Pop()") self:Dyn_EmitInterruptCheck() self:Dyn_Emit("VM.LS = V")
self:Dyn_Emit("VM:Jump(IP,CS)")
self:Dyn_EmitBreak()
self.PrecompileBreak = true
end
ZVM.OpcodeTable[141] = function(self) --EXTRETPA
self:Dyn_Emit("VM.PTBL = $1")
self.OpcodeTable[140](self) -- as EXTRETP
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[250] = function(self) --VADD
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_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",")
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_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",")
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
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_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",")
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_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",")
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
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 = $2")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",")
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 V2 = $2")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",")
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
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_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteCell($1 + VM."..self.EmitOperandSegment[1]..",")
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_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteCell($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",")
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
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_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteCell($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",")
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_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",")
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
self:Dyn_Emit("if VM.VMODE == 2 then")
self:Dyn_Emit("$L V = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteVector2f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",V)")
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_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteVector3f($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",V)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("end")
end
ZVM.OpcodeTable[256] = function(self) --VNORM
self:Dyn_Emit("if VM.VMODE == 2 then")
self:Dyn_Emit("$L V = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")")
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("{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_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("{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")..")")
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_EmitInterruptCheck()
end
ZVM.OpcodeTable[259] = function(self) --LOOPXY
self:Dyn_EmitForceRegisterLocal("ECX")
self:Dyn_EmitForceRegisterLocal("EDX")
-- self:Dyn_Emit("
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")..")")
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_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")..")")
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_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")..")")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("$L RM = {}")
self:Dyn_Emit("for i=0,3 do")
self:Dyn_Emit("for j=0,3 do")
self:Dyn_Emit("RM[i*4+j] = M1[i*4+0]*M2[0*4+j] +")
self:Dyn_Emit(" M1[i*4+1]*M2[1*4+j] +")
self:Dyn_Emit(" M1[i*4+2]*M2[2*4+j] +")
self:Dyn_Emit(" M1[i*4+3]*M2[3*4+j]")
self:Dyn_Emit("end")
self:Dyn_Emit("end")
self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",RM)")
self:Dyn_EmitInterruptCheck()
end
ZVM.OpcodeTable[263] = function(self) --MROTATE
self:Dyn_Emit("$L VEC = VM:ReadVector4f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("$L MAG = math.sqrt(VEC.x^2+VEC.y^2+VEC.z^2)+1e-7")
self:Dyn_Emit("VEC.x = VEC.x / MAG")
self:Dyn_Emit("VEC.y = VEC.y / MAG")
self:Dyn_Emit("VEC.z = VEC.z / MAG")
self:Dyn_Emit("$L SIN = math.sin(VEC.w)")
self:Dyn_Emit("$L COS = math.cos(VEC.w)")
self:Dyn_Emit("$L ab = VEC.x * VEC.y * (1 - COS)")
self:Dyn_Emit("$L bc = VEC.y * VEC.z * (1 - COS)")
self:Dyn_Emit("$L ca = VEC.z * VEC.x * (1 - COS)")
self:Dyn_Emit("$L tx = VEC.x * VEC.x")
self:Dyn_Emit("$L ty = VEC.y * VEC.y")
self:Dyn_Emit("$L tz = VEC.z * VEC.z")
self:Dyn_Emit("$L RM = {}")
self:Dyn_Emit("RM[0] = tx + COS * (1 - tx)")
self:Dyn_Emit("RM[1] = ab + VEC.z * SIN")
self:Dyn_Emit("RM[2] = ca - VEC.y * SIN")
self:Dyn_Emit("RM[3] = 0")
self:Dyn_Emit("RM[4] = ab - VEC.z * SIN")
self:Dyn_Emit("RM[5] = ty + COS * (1 - ty)")
self:Dyn_Emit("RM[6] = bc + VEC.x * SIN")
self:Dyn_Emit("RM[7] = 0")
self:Dyn_Emit("RM[8] = ca + VEC.y * SIN")
self:Dyn_Emit("RM[9] = bc - VEC.x * SIN")
self:Dyn_Emit("RM[10] = tz + COS * (1 - tz)")
self:Dyn_Emit("RM[11] = 0")
self:Dyn_Emit("RM[12] = 0")
self:Dyn_Emit("RM[13] = 0")
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_EmitInterruptCheck()
end
ZVM.OpcodeTable[264] = function(self) --MSCALE
self:Dyn_Emit("$L VEC = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("$L RM = {}")
self:Dyn_Emit("RM[0] = VEC.x")
self:Dyn_Emit("RM[1] = 0")
self:Dyn_Emit("RM[2] = 0")
self:Dyn_Emit("RM[3] = 0")
self:Dyn_Emit("RM[4] = 0")
self:Dyn_Emit("RM[5] = VEC.y")
self:Dyn_Emit("RM[6] = 0")
self:Dyn_Emit("RM[7] = 0")
self:Dyn_Emit("RM[8] = 0")
self:Dyn_Emit("RM[9] = 0")
self:Dyn_Emit("RM[10] = VEC.z")
self:Dyn_Emit("RM[11] = 0")
self:Dyn_Emit("RM[12] = 0")
self:Dyn_Emit("RM[13] = 0")
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_EmitInterruptCheck()
end
ZVM.OpcodeTable[265] = function(self) --MPERSPECTIVE
self:Dyn_Emit("$L VEC = VM:ReadVector4f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("$L DZ = VEC.w - VEC.z")
self:Dyn_Emit("$L RADS = (VEC.x / 2.0) * math.pi / 180")
self:Dyn_Emit("$L SIN = math.sin(RADS)")
self:Dyn_Emit("$L CTG = math.cos(RADS)/SIN")
self:Dyn_Emit("$L RM = {}")
self:Dyn_Emit("RM[0] = CTG / VEC.y")
self:Dyn_Emit("RM[4] = 0")
self:Dyn_Emit("RM[8] = 0")
self:Dyn_Emit("RM[12] = 0")
self:Dyn_Emit("RM[1] = 0")
self:Dyn_Emit("RM[5] = CTG")
self:Dyn_Emit("RM[9] = 0")
self:Dyn_Emit("RM[13] = 0")
self:Dyn_Emit("RM[2] = 0")
self:Dyn_Emit("RM[6] = 0")
self:Dyn_Emit("RM[10] = -(VEC.z + VEC.w) / DZ")
self:Dyn_Emit("RM[14] = -2*VEC.z*VEC.w / DZ")
self:Dyn_Emit("RM[3] = 0")
self:Dyn_Emit("RM[7] = 0")
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_EmitInterruptCheck()
end
ZVM.OpcodeTable[266] = function(self) --MTRANSLATE
self:Dyn_Emit("$L VEC = VM:ReadVector3f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("$L RM = {}")
self:Dyn_Emit("RM[0] = 1")
self:Dyn_Emit("RM[1] = 0")
self:Dyn_Emit("RM[2] = 0")
self:Dyn_Emit("RM[3] = VEC.x")
self:Dyn_Emit("RM[4] = 0")
self:Dyn_Emit("RM[5] = 1")
self:Dyn_Emit("RM[6] = 0")
self:Dyn_Emit("RM[7] = VEC.y")
self:Dyn_Emit("RM[8] = 0")
self:Dyn_Emit("RM[9] = 0")
self:Dyn_Emit("RM[10] = 1")
self:Dyn_Emit("RM[11] = VEC.z")
self:Dyn_Emit("RM[12] = 0")
self:Dyn_Emit("RM[13] = 0")
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_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)")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("$L X = { 0, 0, 0 }")
self:Dyn_Emit("$L Y = { UP.x, UP.y, UP.z }")
self:Dyn_Emit("$L Z = { EYE.x - CENTER.x, EYE.y - CENTER.y, EYE.z - CENTER.z }")
self:Dyn_Emit("$L ZMAG = math.sqrt(Z[1]^2+Z[2]^2+Z[3]^2)+1e-7")
self:Dyn_Emit("Z[1] = Z[1] / ZMAG")
self:Dyn_Emit("Z[2] = Z[2] / ZMAG")
self:Dyn_Emit("Z[3] = Z[3] / ZMAG")
self:Dyn_Emit("X[1] = Y[2]*Z[3] - Y[3]*Z[2]")
self:Dyn_Emit("X[2] = -Y[1]*Z[3] + Y[3]*Z[1]")
self:Dyn_Emit("X[3] = Y[1]*Z[2] - Y[2]*Z[1]")
self:Dyn_Emit("Y[1] = Z[2]*X[3] - Z[3]*X[2]")
self:Dyn_Emit("Y[2] = -Z[1]*X[3] + Z[3]*X[1]")
self:Dyn_Emit("Y[3] = Z[1]*X[2] - Z[2]*X[1]")
self:Dyn_Emit("$L XMAG = math.sqrt(X[1]^2+X[2]^2+X[3]^2)+1e-7")
self:Dyn_Emit("X[1] = X[1] / XMAG")
self:Dyn_Emit("X[2] = X[2] / XMAG")
self:Dyn_Emit("X[3] = X[3] / XMAG")
self:Dyn_Emit("$L YMAG = math.sqrt(Y[1]^2+Y[2]^2+Y[3]^2)+1e-7")
self:Dyn_Emit("Y[1] = Y[1] / YMAG")
self:Dyn_Emit("Y[2] = Y[2] / YMAG")
self:Dyn_Emit("Y[3] = Y[3] / YMAG")
self:Dyn_Emit("$L RM = {}")
self:Dyn_Emit("RM[0] = X[1]")
self:Dyn_Emit("RM[1] = X[2]")
self:Dyn_Emit("RM[2] = X[3]")
self:Dyn_Emit("RM[3] = -X[1]*EYE.x + -X[2]*EYE.y + -X[3]*EYE.z")
self:Dyn_Emit("RM[4] = Y[1]")
self:Dyn_Emit("RM[5] = Y[2]")
self:Dyn_Emit("RM[6] = Y[3]")
self:Dyn_Emit("RM[7] = -Y[1]*EYE.x + -Y[2]*EYE.y + -Y[3]*EYE.z")
self:Dyn_Emit("RM[8] = Z[1]")
self:Dyn_Emit("RM[9] = Z[2]")
self:Dyn_Emit("RM[10] = Z[3]")
self:Dyn_Emit("RM[11] = -Z[1]*EYE.x + -Z[2]*EYE.y + -Z[3]*EYE.z")
self:Dyn_Emit("RM[12] = 0")
self:Dyn_Emit("RM[13] = 0")
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_EmitInterruptCheck()
end
ZVM.OpcodeTable[268] = function(self) --MMOV
self:Dyn_Emit("$L M = VM:ReadMatrix($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")")
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit("VM:WriteMatrix($1 + VM."..(self.EmitOperandSegment[1] or "DS")..",M)")
self:Dyn_EmitInterruptCheck()
end
ZVM.OpcodeTable[269] = function(self) --VLEN
self:Dyn_Emit("if VM.VMODE == 2 then")
self:Dyn_Emit("$L V = VM:ReadVector2f($2 + VM."..(self.EmitOperandSegment[2] or "DS")..")")
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_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
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_EmitInterruptCheck()
end
ZVM.OpcodeTable[273] = function(self) --VMODE
self:Dyn_Emit("VM.VMODE = $1")
end
--------------------------------------------------------------------------------
ZVM.OpcodeTable[295] = function(self) --VDIV
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_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_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_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_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"))
self:Dyn_Emit [[
local V = {0, 0, 0, 1}
if address_1~=0 then
for i = 1, VM.VMODE do
V[i] = VM:ReadCell(address_1 + i - 1) or 0
end
end
]]
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit [[local M = VM:ReadMatrix(address_2)]]
self:Dyn_EmitInterruptCheck()
self:Dyn_Emit [[
for i = 0, VM.VMODE-1 do
local result = M[i*4 + 0] * V[1] +
M[i*4 + 1] * V[2] +
M[i*4 + 2] * V[3] +
M[i*4 + 3] * V[4]
VM:WriteCell(address_1 + i, result)
end
]]
self:Dyn_EmitInterruptCheck()
end