wiremod-svn-archive/wire/lua/entities/gmod_wire_cpu/init.lua

1047 lines
30 KiB
Lua
Raw Normal View History

2007-03-21 21:09:01 +00:00
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include('shared.lua')
ENT.WireDebugName = "CPU"
function ENT:Initialize()
self.Entity:PhysicsInit( SOLID_VPHYSICS )
self.Entity:SetMoveType( MOVETYPE_VPHYSICS )
self.Entity:SetSolid( SOLID_VPHYSICS )
self.Inputs = Wire_CreateInputs(self.Entity, { "Frequency", "Clk", "Reset", "ReadAddr", "WriteAddr", "Data", "WriteClk", "Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6", "Port7"})
self.Outputs = Wire_CreateOutputs(self.Entity, { "Error", "Data", "Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6", "Port7"})
self.Memory = {}
for i = 0, 65535 do
self.Memory[i] = 0
end
self.IP = 0
self.WIP = 0
self.Ports = {0, 0, 0, 0, 0, 0, 0, 0}
self.Clk = 0
self.EAX = 0
self.EBX = 0
self.ECX = 0
self.EDX = 0
self.ESI = 0
self.EDI = 0
self.ESP = 65535
self.EBP = 0
self.CMPR = 0
self.WriteAddr = 0
self.WriteData = 0
self.HaltPort = -1
//=================================
self.FatalError = false
self.Labels = {}
//=================================
self.ThinkTime = 10
Wire_TriggerOutput(self.Entity, "Error", 0.0)
end
function ENT:Write( value )
self.Memory[self.WIP] = value
self.WIP = self.WIP + 1
//Msg("-> ZyeliosASM: Wrote "..value.." at ["..self.WIP.."]\n")
end
function ENT:Read( )
self.IP = self.IP + 1
return self.Memory[self.IP - 1]
end
function ENT:DecodeOpcode( opcode )
//------------------------------------------------------------
if (opcode == "jne") || (opcode == "jnz") then //JNE X : IP = X, IF CMPR ~= 0
return 1
elseif (opcode == "jmp") then //JMP X : IP = X
return 2
elseif (opcode == "jg") || (opcode == "jnle") then //JG X : IP = X, IF CMPR > 0
return 3
elseif (opcode == "jge") || (opcode == "jnl") then //JGE X : IP = X, IF CMPR >= 0
return 4
elseif (opcode == "jl") || (opcode == "jnge") then //JL X : IP = X, IF CMPR < 0
return 5
elseif (opcode == "jle") || (opcode == "jng") then //JLE X : IP = X, IF CMPR <= 0
return 6
elseif (opcode == "je") || (opcode == "jz") then //JE X : IP = X, IF CMPR = 0
return 7
elseif (opcode == "cpuid") then //CPUID X : EAX -> CPUID[X]
return 8
elseif (opcode == "push") then //PUSH X : X -> STACK
return 9
//------------------------------------------------------------
elseif (opcode == "add") then //ADD X,Y : X = X + Y
return 10
elseif (opcode == "sub") then //SUB X,Y : X = X - Y
return 11
elseif (opcode == "mul") then //MUL X,Y : X = X * Y
return 12
elseif (opcode == "div") then //DIV X,Y : X = X / Y
return 13
elseif (opcode == "mov") then //MOV X,Y : X = Y
return 14
elseif (opcode == "cmp") then //CMP X,Y : CMPR = X - Y
return 15
elseif (opcode == "rd") then //RD X,Y : X = MEMORY[Y]
return 16
elseif (opcode == "wd") then //WD X,Y : MEMORY[X] = Y
return 17
elseif (opcode == "min") then //MIN X,Y : MIN(X,Y)
return 18
elseif (opcode == "max") then //MAX X,Y : MAX(X,Y)
return 19
//------------------------------------------------------------
elseif (opcode == "inc") then //INC X : X = X + 1
return 20
elseif (opcode == "dec") then //DEC X : X = X - 1
return 21
elseif (opcode == "neg") then //NEG X : X = -X
return 22
elseif (opcode == "rand") then //RAND X : X = Random(0..1)
return 23
//------------------------------------------------------------
elseif (opcode == "pop") then //POP X : X <- STACK
return 30
elseif (opcode == "call") then //CALL X : IP -> STACK; IP = X
return 31
elseif (opcode == "not") then //NOT X : X = not X
return 32
elseif (opcode == "int") then //INT X : X = FLOOR(X)
return 33
elseif (opcode == "rnd") then //RND X : X = ROUND(X)
return 34
elseif (opcode == "frac") then //FRAX X : X = X - FLOOR(X)
return 35
elseif (opcode == "finv") then //FINV X : X = 1 / X
return 36
elseif (opcode == "halt") then //HALT X : HALT UNTIL PORT[X]
return 37
//------------------------------------------------------------
elseif (opcode == "ret") then //RET : IP <- STACK
return 40
//------------------------------------------------------------
elseif (opcode == "and") then //AND X,Y : X = X AND Y
return 50
elseif (opcode == "or") then //OR X,Y : X = X OR Y
return 51
elseif (opcode == "xor") then //XOR X,Y : X = X XOR Y
return 52
elseif (opcode == "fsin") then //FSIN X,Y : X = SIN Y
return 53
elseif (opcode == "fcos") then //FCOS X,Y : X = COS Y
return 54
elseif (opcode == "ftan") then //FTAN X,Y : X = TAN Y
return 55
elseif (opcode == "fasin") then //FASIN X,Y : X = ASIN Y
return 56
elseif (opcode == "facos") then //FACOS X,Y : X = ACOS Y
return 57
elseif (opcode == "fatan") then //FATAN X,Y : X = ATAN Y
return 58
end
return -1
end
function ENT:OpcodeParamCount( opcode )
if (opcode >= 1) && (opcode <= 9) then
return 1
elseif (opcode >= 10) && (opcode <= 19) then
return 2
elseif (opcode >= 20) && (opcode <= 29) then
return 1
elseif (opcode >= 30) && (opcode <= 39) then
return 1
elseif (opcode >= 40) && (opcode <= 49) then
return 0
elseif (opcode >= 50) && (opcode <= 59) then
return 2
end
return 0
end
//ERROR VALUES TABLE
//Value | Error
//--------------------------------------------
//0.0 | No error
//2.0 | End of program execution
//3.0 | Division by zero
//4.0 | Unknown opcode
//5.0 | Internal error
//6.0 | Stack error
//--------------------------------------------
//
//CPUID
//Value | EAX
//--------------------------------------------
//0 | CPU Version
//1 | RAM Size
//--------------------------------------------
function ENT:Execute( )
if (self.HaltPort ~= -1) then
return
end
local opcode = self:Read( )
local rm = self:Read( )
local params = {0, 0}
local result = 0
local disp1,disp2 = 0
local drm2 = math.floor(rm / 100)
local drm1 = rm - drm2*100
if (self:OpcodeParamCount( opcode ) > 0) then
if (drm1 == 0) then
params[1] = self:Read( )
elseif (drm1 == 1) then
params[1] = self.EAX
elseif (drm1 == 2) then
params[1] = self.EBX
elseif (drm1 == 3) then
params[1] = self.ECX
elseif (drm1 == 4) then
params[1] = self.EDX
elseif (drm1 == 5) then
params[1] = self.ESI
elseif (drm1 == 6) then
params[1] = self.EDI
elseif (drm1 == 7) then
params[1] = self.ESP
elseif (drm1 == 8) then
params[1] = self.EBP
elseif (drm1 >= 9) && (drm1 <= 16) then
params[1] = self.Ports[drm1-9]
elseif (drm1 == 17) then
disp1 = math.floor(self.EAX)
elseif (drm1 == 18) then
disp1 = math.floor(self.EBX)
elseif (drm1 == 19) then
disp1 = math.floor(self.ECX)
elseif (drm1 == 20) then
disp1 = math.floor(self.EDX)
elseif (drm1 == 21) then
disp1 = math.floor(self.ESI)
elseif (drm1 == 22) then
disp1 = math.floor(self.EDI)
elseif (drm1 == 23) then
disp1 = math.floor(self.ESP)
elseif (drm1 == 24) then
disp1 = math.floor(self.EBP)
elseif (drm1 == 25) then
disp1 = math.floor(self:Read( ))
end
if (drm1 >= 17) && (drm1 <= 25) then
if (disp1 >= 0) && (disp1 <= 65535) then
params[1] = self.Memory[disp1]
end
end
end
if (self:OpcodeParamCount( opcode ) > 1) then
if (drm2 == 0) then
params[2] = self:Read( )
elseif (drm2 == 1) then
params[2] = self.EAX
elseif (drm2 == 2) then
params[2] = self.EBX
elseif (drm2 == 3) then
params[2] = self.ECX
elseif (drm2 == 4) then
params[2] = self.EDX
elseif (drm2 == 5) then
params[2] = self.ESI
elseif (drm2 == 6) then
params[2] = self.EDI
elseif (drm2 == 7) then
params[2] = self.ESP
elseif (drm2 == 8) then
params[2] = self.EBP
elseif (drm2 >= 9) && (drm2 <= 16) then
params[2] = self.Ports[drm2-9]
elseif (drm2 == 17) then
disp2 = math.floor(self.EAX)
elseif (drm2 == 18) then
disp2 = math.floor(self.EBX)
elseif (drm2 == 19) then
disp2 = math.floor(self.ECX)
elseif (drm2 == 20) then
disp2 = math.floor(self.EDX)
elseif (drm2 == 21) then
disp2 = math.floor(self.ESI)
elseif (drm2 == 22) then
disp2 = math.floor(self.EDI)
elseif (drm2 == 23) then
disp2 = math.floor(self.ESP)
elseif (drm2 == 24) then
disp2 = math.floor(self.EBP)
elseif (drm2 == 25) then
disp2 = math.floor(self:Read( ))
end
if (drm2 >= 17) && (drm2 <= 25) then
if (disp2 >= 0) && (disp2 <= 65535) then
params[2] = self.Memory[disp2]
end
end
end
local WriteBack = true
// ------------------------------------------------ //
//| OPCODES COME HERE: |//
// ------------------------------------------------ //
if (opcode == 0) then
Wire_TriggerOutput(self.Entity, "Error", 2.0)
self.Clk = 0
elseif (opcode == 1) then //JNE
if (self.CMPR ~= 0) then
self.IP = params[1]
end
WriteBack = false
elseif (opcode == 2) then //JMP
self.IP = params[1]
WriteBack = false
elseif (opcode == 3) then //JG
if (self.CMPR > 0) then
self.IP = params[1]
end
WriteBack = false
elseif (opcode == 4) then //JGE
if (self.CMPR >= 0) then
self.IP = params[1]
end
WriteBack = false
elseif (opcode == 5) then //JL
if (self.CMPR < 0) then
self.IP = params[1]
end
WriteBack = false
elseif (opcode == 6) then //JLE
if (self.CMPR <= 0) then
self.IP = params[1]
end
WriteBack = false
elseif (opcode == 7) then //JE
if (self.CMPR == 0) then
self.IP = params[1]
end
WriteBack = false
//============================================================
elseif (opcode == 8) then //CPUID
if (params[1] == 0) then //CPU VERSION
self.EAX = 150 //= 1.50
elseif (params[1] == 1) then //AMOUNT OF RAM
self.EAX = 65536 //= 64KB
elseif (params[1] == 2) then //TYPE (0 - ZCPU; 1 - ZGPU)
self.EAX = 0 //= ZCPU
else
self.EAX = 0
end
WriteBack = false
//============================================================
elseif (opcode == 9) then //PUSH
self.Memory[ESP] = params[1]
ESP = ESP - 1
if (ESP < 16384) then
Wire_TriggerOutput(self.Entity, "Error", 6.0)
self.Clk = 0
end
WriteBack = false
//------------------------------------------------------------
elseif (opcode == 10) then //ADD
result = params[1] + params[2]
elseif (opcode == 11) then //SUB
result = params[1] - params[2]
elseif (opcode == 12) then //MUL
result = params[1] * params[2]
elseif (opcode == 13) then //DIV
if (math.abs(params[2]) < 0.0001) then
Wire_TriggerOutput(self.Entity, "Error", 3.0)
self.Clk = 0
else
result = params[1] / params[2]
end
elseif (opcode == 14) then //MOV
result = params[2]
elseif (opcode == 15) then //CMP
self.CMPR = params[1] - params[2]
WriteBack = false
elseif (opcode == 16) then //RD
result = self.Memory[params[2]]
elseif (opcode == 17) then //WD
self.Memory[params[1]] = params[2]
WriteBack = false
elseif (opcode == 18) then //MIN
if (params[2] < params[1]) then
result = params[2]
else
result = params[1]
end
elseif (opcode == 19) then //MAX
if (params[2] > params[1]) then
result = params[2]
else
result = params[1]
end
//------------------------------------------------------------
elseif (opcode == 20) then //INC
result = params[1] + 1
elseif (opcode == 21) then //DEC
result = params[1] - 1
elseif (opcode == 22) then //NEG
result = -params[1]
elseif (opcode == 23) then //RAND
result = math.random()
//------------------------------------------------------------
elseif (opcode == 30) then //POP
self.ESP = self.ESP + 1
if (self.ESP > 65535) then
Wire_TriggerOutput(self.Entity, "Error", 6.0)
self.Clk = 0
else
result = self.Memory[self.ESP]
end
WriteBack = false
elseif (opcode == 31) then //CALL
self.Memory[self.ESP] = self.IP
self.ESP = self.ESP - 1
if (self.ESP < 16384) then
Wire_TriggerOutput(self.Entity, "Error", 6.0)
self.Clk = 0
else
self.IP = params[1]
end
WriteBack = false
elseif (opcode == 32) then //NOT
if params[1] <= 0 then
result = 1
else
result = 0
end
elseif (opcode == 33) then //INT
result = math.floor(params[1])
elseif (opcode == 34) then //RND
result = math.round(params[1])
elseif (opcode == 35) then //FLOOR
result = params[1] - math.floor(params[1])
elseif (opcode == 36) then //INV
if (math.abs(params[1]) < 0.0001) then
Wire_TriggerOutput(self.Entity, "Error", 3.0)
self.Clk = 0
else
result = 1 / params[1]
end
elseif (opcode == 37) then //HALT
self.HaltPort = math.floor(params[1])
if self.HaltPort > 7 then
self.HaltPort = 7
end
if self.HaltPort < 0 then
self.HaltPort = 0
end
WriteBack = false
elseif (opcode == 38) then
Wire_TriggerOutput(self.Entity, "Error", 5632663.0)
//------------------------------------------------------------
elseif (opcode == 40) then //RET
self.ESP = self.ESP + 1
if (self.ESP > 65535) then
Wire_TriggerOutput(self.Entity, "Error", 6.0)
self.Clk = 0
else
self.IP = self.Memory[self.ESP]
end
WriteBack = false
//------------------------------------------------------------
elseif (opcode == 50) then //AND
if (params[1] > 0) && (params[2] > 0) then
result = 1
else
result = 0
end
elseif (opcode == 51) then //OR
if (params[1] > 0) || (params[2] > 0) then
result = 1
else
result = 0
end
elseif (opcode == 52) then //XOR
if ((params[1] > 0) && (params[2] <= 0)) ||
((params[1] <= 0) && (params[2] > 0)) then
result = 1
else
result = 0
end
elseif (opcode == 53) then //FSIN
result = math.sin(params[2])
elseif (opcode == 54) then //FCOS
result = math.cos(params[2])
elseif (opcode == 55) then //FTAN
result = math.tan(params[2])
elseif (opcode == 56) then //FASIN
result = math.asin(params[2])
elseif (opcode == 57) then //FACOS
result = math.acos(params[2])
elseif (opcode == 58) then //FATAN
result = math.atan(params[2])
//------------------------------------------------------------
else
Wire_TriggerOutput(self.Entity, "Error", 4.0)
self.Clk = 0
end
// ------------------------------------------------ //
//| OPCODES END HERE |//
// ------------------------------------------------ //
if (self:OpcodeParamCount( opcode ) > 0) && (drm1 ~= 0) && (WriteBack) && (self.Clk == 1) then
if (drm1 == 1) then
self.EAX = result
elseif (drm1 == 2) then
self.EBX = result
elseif (drm1 == 3) then
self.ECX = result
elseif (drm1 == 4) then
self.EDX = result
elseif (drm1 == 5) then
self.ESI = result
elseif (drm1 == 6) then
self.EDI = result
elseif (drm1 == 7) then
self.ESP = result
elseif (drm1 == 8) then
self.EBP = result
elseif (drm1 >= 9) && (drm1 <= 16) then
local port = drm1 - 9
Wire_TriggerOutput(self.Entity, "Port"..port, result)
elseif (drm1 >= 17) && (drm1 <= 25) then
self.Memory[disp1] = result
end
end
end
function ENT:Digit( prefix )
return (prefix == "0") || (prefix == "1") || (prefix == "2") || (prefix == "3") ||
(prefix == "4") || (prefix == "5") || (prefix == "6") || (prefix == "7") ||
(prefix == "8") || (prefix == "9") || (prefix == ".")
end
function ENT:ValidNumber( line )
if (line) then
return self:Digit(string.sub(line,1,1))
else
return false;
end
end
function ENT:Compile( pl, line, linenumber, firstpass )
local opcodetable = string.Explode(" ", line or { } )
local dopcode = 0
local nextparams = false
local nextvariable = false
local nextorg = false
local nextdefine = false
local nextalloc = false
local programsize = 0
for _,opcode in pairs(opcodetable) do
opcode = string.Trim(opcode)
if (nextdefine) then
local deftable = string.Explode(",", opcode )
if (table.Count(deftable) == 2) then
if (not self.Labels[deftable[1]]) then
if (self:ValidNumber(opcode)) then
self.Labels[deftable[1]] = deftable[2]
else
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E270) at line "..linenumber..": Attempt to define a non-number\n")
return false
end
else
if (firstpass) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E236) at line "..linenumber..": Define "..deftable[1].." already exists\n")
return false
end
end
else
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E335) at line "..linenumber..": Invalid number of parameters in DEFINE macro\n")
return false
end
elseif (nextorg) then
if self:ValidNumber(opcode) then
self.WIP = opcode
else
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E333) at line "..linenumber..": Invalid parameter in ORG macro\n")
return false
end
elseif (nextalloc) then
local alloctable = string.Explode(",", opcode )
if (table.Count(alloctable) == 0) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Allocated new variable ".."0".." ["..self.WIP.."]\n")
self:Write( 0 )
end
if (table.Count(alloctable) == 1) then
alloctable[1] = string.Trim(alloctable[1])
local prefix = string.sub(alloctable[1],1,1)
if self:ValidNumber(alloctable[1]) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Allocated new array ".."0["..alloctable[1].."] ["..self.WIP.."]\n")
for i = 1, alloctable[1] do
self:Write( 0 )
end
else
if (not self.Labels[alloctable[1]]) then
self.Labels[alloctable[1]] = self.WIP
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Allocated new variable "..alloctable[1].." ["..self.WIP.."]\n")
self:Write( 0 )
else
if (firstpass) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E231) at line "..linenumber..": Variable "..opcode.." already exists\n")
return false
else
self:Write( 0 )
end
end
end
end
if (table.Count(alloctable) == 2) then
alloctable[1] = string.Trim(alloctable[1])
alloctable[2] = string.Trim(alloctable[2])
if (not self.Labels[alloctable[1]]) then
self.Labels[alloctable[1]] = self.WIP
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Allocated new array "..alloctable[1].."["..alloctable[2].."] ["..self.WIP.."]\n")
for i = 1, alloctable[2] do
self:Write( 0 )
end
else
if (firstpass) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E231) at line "..linenumber..": Variable "..opcode.." already exists\n")
return false
else
for i = 1, alloctable[2] do
self:Write( 0 )
end
end
end
end
if (table.Count(alloctable) == 3) then
alloctable[1] = string.Trim(alloctable[1])
alloctable[2] = string.Trim(alloctable[2])
alloctable[3] = string.Trim(alloctable[3])
if (not self.Labels[alloctable[1]]) then
self.Labels[alloctable[1]] = self.WIP
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Allocated new array "..alloctable[1].."["..alloctable[2].."] ["..self.WIP.."]\n")
for i = 1, alloctable[2] do
self:Write( alloctable[3] )
end
else
if (firstpass) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E231) at line "..linenumber..": Variable "..opcode.." already exists\n")
return false
else
for i = 1, alloctable[2] do
self:Write( alloctable[3] )
end
end
end
end
nextalloc = false
elseif (nextparams) then
local paramtable = string.Explode(",", opcode or {"none","none"} )
local drm1 = 0
local drm2 = 0
local disp1,disp2 = 0
if (table.Count(paramtable) ~= self:OpcodeParamCount( dopcode )) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E245) at line "..linenumber..": wrong number of parameters for opcode\n")
return false
end
paramtable[1] = string.Trim(paramtable[1])
if (paramtable[1] == "eax") then
drm1 = 1
elseif (paramtable[1] == "ebx") then
drm1 = 2
elseif (paramtable[1] == "ecx") then
drm1 = 3
elseif (paramtable[1] == "edx") then
drm1 = 4
elseif (paramtable[1] == "esi") then
drm1 = 5
elseif (paramtable[1] == "edi") then
drm1 = 6
elseif (paramtable[1] == "esp") then
drm1 = 7
elseif (paramtable[1] == "ebp") then
drm1 = 8
elseif (paramtable[1] == "port0") then
drm1 = 9
elseif (paramtable[1] == "port1") then
drm1 = 10
elseif (paramtable[1] == "port2") then
drm1 = 11
elseif (paramtable[1] == "port3") then
drm1 = 12
elseif (paramtable[1] == "port4") then
drm1 = 13
elseif (paramtable[1] == "port5") then
drm1 = 14
elseif (paramtable[1] == "port6") then
drm1 = 15
elseif (paramtable[1] == "port7") then
drm1 = 16
else
local prefix = string.sub(paramtable[1],1,1)
local postprefix = string.sub(paramtable[1],2)
if (prefix ~= "#") && (not self:ValidNumber(paramtable[1])) then
if (self.Labels[paramtable[1]..":"]) then
paramtable[1] = self.Labels[paramtable[1]..":"]
else
if (not firstpass) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E232) at line "..linenumber..": No such label: "..paramtable[1].."!\n")
return false
end
end
end
if (prefix == "#") then
if (postprefix == "eax") then
drm1 = 17
elseif (postprefix == "ebx") then
drm1 = 18
elseif (postprefix == "ecx") then
drm1 = 19
elseif (postprefix == "edx") then
drm1 = 20
elseif (postprefix == "esi") then
drm1 = 21
elseif (postprefix == "edi") then
drm1 = 22
elseif (postprefix == "esp") then
drm1 = 23
elseif (postprefix == "edp") then
drm1 = 24
elseif (self.Labels[postprefix..":"]) then
drm1 = 25
disp1 = self.Labels[postprefix..":"]
elseif (self.Labels[postprefix]) then
drm1 = 25
disp1 = self.Labels[postprefix]
else
if (postprefix) then
if (not self.ValidNumber(postprefix)) then
if (not firstpass) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E232) at line "..linenumber..": No such variable: "..postprefix.."!\n")
return false
end
end
drm1 = 25
disp1 = postprefix
else
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E490) at line "..linenumber..": Wrong memory reference syntax!\n")
end
end
end
end
if (self:OpcodeParamCount( dopcode ) > 1) && (paramtable[2] ~= "none") then
paramtable[2] = string.Trim(paramtable[2])
if (paramtable[2] == "eax") then
drm2 = 1
elseif (paramtable[2] == "ebx") then
drm2 = 2
elseif (paramtable[2] == "ecx") then
drm2 = 3
elseif (paramtable[2] == "edx") then
drm2 = 4
elseif (paramtable[2] == "esi") then
drm2 = 5
elseif (paramtable[2] == "edi") then
drm2 = 6
elseif (paramtable[2] == "esp") then
drm2 = 7
elseif (paramtable[2] == "ebp") then
drm2 = 8
elseif (paramtable[2] == "port0") then
drm2 = 9
elseif (paramtable[2] == "port1") then
drm2 = 10
elseif (paramtable[2] == "port2") then
drm2 = 11
elseif (paramtable[2] == "port3") then
drm2 = 12
elseif (paramtable[2] == "port4") then
drm2 = 13
elseif (paramtable[2] == "port5") then
drm2 = 14
elseif (paramtable[2] == "port6") then
drm2 = 15
elseif (paramtable[2] == "port7") then
drm2 = 16
else
local prefix = string.sub(paramtable[2],1,1)
local postprefix = string.sub(paramtable[2],2)
if (prefix ~= "#") && (not self:ValidNumber(paramtable[2])) then
if (self.Labels[paramtable[2]..":"]) then
paramtable[2] = self.Labels[paramtable[2]..":"]
else
if (not firstpass) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E232) at line "..linenumber..": No such label: "..paramtable[2].."!\n")
return false
end
end
end
if (prefix == "#") then
if (postprefix == "eax") then
drm2 = 17
elseif (postprefix == "ebx") then
drm2 = 18
elseif (postprefix == "ecx") then
drm2 = 19
elseif (postprefix == "edx") then
drm2 = 20
elseif (postprefix == "esi") then
drm2 = 21
elseif (postprefix == "edi") then
drm2 = 22
elseif (postprefix == "esp") then
drm2 = 23
elseif (postprefix == "edp") then
drm2 = 24
elseif (self.Labels[postprefix..":"]) then
drm2 = 25
disp2 = self.Labels[postprefix..":"]
elseif (self.Labels[postprefix]) then
drm2 = 25
disp2 = self.Labels[postprefix]
else
if (postprefix) then
if (not self.ValidNumber(postprefix)) then
if (not firstpass) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E231) at line "..linenumber..": No such variable: "..postprefix.."!\n")
return false
end
end
drm2 = 25
disp2 = postprefix
else
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E490) at line "..linenumber..": Wrong memory reference syntax!\n")
end
end
end
end
end
local rm = drm1 + drm2*100
self:Write( dopcode )
self:Write( rm )
programsize = programsize + 2
if (drm1 == 0) then
self:Write( paramtable[1] )
programsize = programsize + 1
end
if (self:OpcodeParamCount( dopcode ) > 1) && (drm2 == 0) then
self:Write( paramtable[2] )
programsize = programsize + 1
end
if (drm1 == 25) then
self:Write( disp1 )
end
if (drm2 == 25) then
self:Write( disp2 )
end
nextparams = false
else
if ( opcode == "alloc" ) then
nextalloc = true
elseif ( opcode == "org" ) then
nextorg = true
elseif ( opcode == "define" ) then
nextdefine = true
elseif ( opcode == "code" ) then
self.WIP = 0
self.Labels["codestart"] = 0
elseif ( opcode == "data" ) then
self.WIP = 8196
self.Labels["datastart"] = 8196
else
dopcode = self:DecodeOpcode( opcode )
if (dopcode ~= -1) then
if (self:OpcodeParamCount( dopcode ) > 0) then
nextparams = true
else
self:Write( dopcode )
self:Write( 0 )
programsize = programsize + 2
end
else
local lastsymbol = string.sub(opcode,-1,-1)
if (lastsymbol == ":") then
if (not self.Labels[opcode]) then
self.Labels[opcode] = self.WIP
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Added label "..opcode.."["..self.WIP.."]\n")
else
if (firstpass) then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E200) at line "..linenumber..": Label "..opcode.." already exists\n")
return false
end
end
else
if (opcode ~= "") && (opcode ~= " ") then
pl:PrintMessage(HUD_PRINTCONSOLE,"-> ZyeliosASM: Error (E500) at line "..linenumber..": unknown opcode: "..opcode.."\n")
return false
end
end
end
end
end
end
return true
end
function ENT:ParseProgram( pl, programtext, parsedline, firstpass )
if (self.FatalError) then
return false
end
//local programtext2 = string.gsub(programtext,"/*(.-)*/")
//Msg("!!: "..programtext2.."\n")
//local programtext2 = string.Implode(" ",tablenolines)
local comment = string.find(programtext,"//")
local programtext2 = programtext
if (comment) then
programtext2 = string.sub(programtext,1,comment-1)
end
local linestable = string.Explode(";", programtext2 or { } )
local linenumber = 0
for _,line in pairs(linestable) do
linenumber = linenumber + 1
if (not self:Compile( pl, string.lower(line), parsedline, firstpass )) then
self.FatalError = true
self.Memory[0] = 0 //FIXME
end
end
end
function ENT:Use()
end
function ENT:Think()
self.BaseClass.Think(self)
local timeout = self.ThinkTime
while (timeout > 0) && (self.Clk >= 1.0) do
self:Execute( )
timeout = timeout - 1
end
self.Entity:NextThink(CurTime()+0.01)
end
function ENT:TriggerInput(iname, value)
if (iname == "Clk") then
self.Clk = value
if (value >= 1.0) then
Wire_TriggerOutput(self.Entity, "Error", 0.0)
end
elseif (iname == "Frequency") then
if (value ~= 0) then
self.ThinkTime = value/100
end
elseif (iname == "Reset") then
if (value >= 1.0) then
self.IP = 0
self.EAX = 0
self.EBX = 0
self.ECX = 0
self.EDX = 0
self.ESI = 0
self.EDI = 0
self.ESP = 65535
self.EBP = 0
Wire_TriggerOutput(self.Entity, "Error", 0.0)
end
elseif (iname == "Port0") then
if (self.HaltPort == 0) then
self.HaltPort = -1
end
self.Ports[0] = value
elseif (iname == "Port1") then
if (self.HaltPort == 1) then
self.HaltPort = -1
end
self.Ports[1] = value
elseif (iname == "Port2") then
if (self.HaltPort == 2) then
self.HaltPort = -1
end
self.Ports[2] = value
elseif (iname == "Port3") then
if (self.HaltPort == 3) then
self.HaltPort = -1
end
self.Ports[3] = value
elseif (iname == "Port4") then
if (self.HaltPort == 4) then
self.HaltPort = -1
end
self.Ports[4] = value
elseif (iname == "Port5") then
if (self.HaltPort == 5) then
self.HaltPort = -1
end
self.Ports[5] = value
elseif (iname == "Port6") then
if (self.HaltPort == 6) then
self.HaltPort = -1
end
self.Ports[6] = value
elseif (iname == "Port7") then
if (self.HaltPort == 7) then
self.HaltPort = -1
end
self.Ports[7] = value
elseif (iname == "ReadAddr") then
if (value >= 0.0) and (value <= 65535.0) then
Wire_TriggerOutput(self.Entity, "Data", self.Memory[math.floor(value)])
end
elseif (iname == "WriteAddr") then
self.WriteAddr = math.floor(value)
elseif (iname == "Data") then
self.WriteData = value
elseif (iname == "WriteClk") then
if (value >= 1.0) then
self.Memory[self.WriteAddr] = self.WriteData
end
end
end