wiremod-svn-archive/wire/lua/entities/gmod_wire_cpu/compiler_asm.lua
BlackPhoenix 713a26e2c0 [FIXED] NMI not working in CPU (trigger lua error)
[ADD] ZASM now shows revisions of its main files
[ADD] ZCPU now returns its SVN revision number instead of version on CPUID. Useful for checking for working version of CPU
2007-12-04 23:18:02 +00:00

879 lines
29 KiB
Lua

function ENT:InitASMOpcodes()
self.OpcodeCount = {}
for i=1,199 do
if ((i >= 1) && (i <= 9)) || (i == 69) then
self.OpcodeCount[i] = 1
elseif (i >= 10) && (i <= 19) then
self.OpcodeCount[i] = 2
elseif (i >= 20) && (i <= 29) then
self.OpcodeCount[i] = 1
elseif (i >= 30) && (i <= 39) then
self.OpcodeCount[i] = 1
elseif (i >= 40) && (i <= 49) then
self.OpcodeCount[i] = 0
elseif (i >= 50) && (i <= 59) then
self.OpcodeCount[i] = 2
elseif (i >= 60) && (i <= 68) then
self.OpcodeCount[i] = 2
elseif (i >= 70) && (i <= 79) then
self.OpcodeCount[i] = 1
elseif (i >= 80) && (i <= 89) then
self.OpcodeCount[i] = 2
elseif (i >= 90) && (i <= 99) then
self.OpcodeCount[i] = 1
elseif (i >= 100) && (i <= 109) then
self.OpcodeCount[i] = 1
elseif (i >= 110) && (i <= 119) then
self.OpcodeCount[i] = 0
end
end
end
function ENT:Core_Version()
local SVNString = "$Revision: 500 $"
return tonumber(string.sub(SVNString,12,14))
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 == "loop") then //LOOP X : IF ECX ~= 0 THEN JUMP X //2.00
return 24
elseif (opcode == "loopa") then //LOOP X : IF EAX ~= 0 THEN JUMP X //2.00
return 25
elseif (opcode == "loopb") then //LOOP X : IF EBX ~= 0 THEN JUMP X //2.00
return 26
elseif (opcode == "loopd") then //LOOP X : IF EDX ~= 0 THEN JUMP X //2.00
return 27
elseif (opcode == "spg") then //SRD X : PAGE(X) = READ ONLY //2.00
return 28
elseif (opcode == "cpg") then //CRD X : PAGE(X) = READ AND WRITE //2.00
return 29
//------------------------------------------------------------
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 == "fint") then //FINT X : X = FLOOR(X)
return 33
elseif (opcode == "frnd") then //FRND X : X = ROUND(X)
return 34
elseif (opcode == "ffrac") then //FFRAC 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 == "fshl") then //FSHL X : X = X * 2 //2.00
return 38
elseif (opcode == "fshr") then //FSHR X : X = X / 2 //2.00
return 39
//------------------------------------------------------------
elseif (opcode == "ret") then //RET : IP <- STACK
return 40
elseif (opcode == "iret") then //IRET : IP <- STACK //2.00
return 41
elseif (opcode == "sti") then //STI : IF = TRUE //2.00
return 42
elseif (opcode == "cli") then //CLI : IF = FALSE //2.00
return 43
elseif (opcode == "stp") then //STP : PF = TRUE //2.00
return 44
elseif (opcode == "clp") then //CLP : PF = FALSE //2.00
return 45
// elseif (opcode == "") then //RESERVED //2.00
// return 46
elseif (opcode == "RETF") then //RETF : IP,CS <- STACK //2.00
return 47
// elseif (opcode == "") then //RESERVED //2.00
// return 48
// elseif (opcode == "") then //RESERVED //2.00
// return 49
//------------------------------------------------------------
elseif (opcode == "and") then //FAND X,Y : X = X AND Y
return 50
elseif (opcode == "or") then //FOR X,Y : X = X OR Y
return 51
elseif (opcode == "xor") then //FXOR 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
elseif (opcode == "mod") then //MOD X,Y : X = X MOD Y //2.00
return 59
//------------------------------------------------------------
elseif (opcode == "bit") then //BIT X,Y : CMPR = BIT(X,Y) //2.00
return 60
elseif (opcode == "sbit") then //SBIT X,Y : BIT(X,Y) = 1 //2.00
return 61
elseif (opcode == "cbit") then //CBIT X,Y : BIT(X,Y) = 0 //2.00
return 62
elseif (opcode == "tbit") then //TBIT X,Y : BIT(X,Y) = ~BIT(X,Y)//2.00
return 63
elseif (opcode == "band") then //AND X,Y : X = X AND Y //2.00
return 64
elseif (opcode == "bor") then //OR X,Y : X = X OR Y //2.00
return 65
elseif (opcode == "bxor") then //XOR X,Y : X = X XOR Y //2.00
return 66
elseif (opcode == "bshl") then //SHL X,Y : X = X SHL Y //2.00
return 67
elseif (opcode == "bshr") then //SHR X,Y : X = X SHR Y //2.00
return 68
elseif (opcode == "jmpf") then //JMPF X,Y : CS = Y; IP = X //2.00
return 69
//------------------------------------------------------------
elseif (opcode == "cne") || (opcode == "cnz") then //CNE X : CALL(X), IF CMPR ~= 0 //2.00
return 71
elseif (opcode == "cg") || (opcode == "cnle") then //CG X : CALL(X), IF CMPR > 0 //2.00
return 73
elseif (opcode == "cge") || (opcode == "cnl") then //CGE X : CALL(X), IF CMPR >= 0 //2.00
return 74
elseif (opcode == "cl") || (opcode == "cnge") then //CL X : CALL(X), IF CMPR < 0 //2.00
return 75
elseif (opcode == "cle") || (opcode == "cng") then //CLE X : CALL(X), IF CMPR <= 0 //2.00
return 76
elseif (opcode == "ce") || (opcode == "cz") then //CE X : CALL(X), IF CMPR = 0 //2.00
return 77
elseif (opcode == "mcopy") then //MCOPY X : X BYTES(ESI) -> EDI //2.00
return 78
elseif (opcode == "mxchg") then //MXCHG X : X BYTES(ESI) <> EDI //2.00
return 79
//------------------------------------------------------------
elseif (opcode == "fpwr") then //FPWR X,Y : X = X ^ Y //2.00
return 80
elseif (opcode == "xchg") then //XCHG X,Y : X,Y = Y,X //2.00
return 81
elseif (opcode == "flog") then //FLOG X,Y : X = LOG(Y) //2.00
return 82
elseif (opcode == "flog10") then//FLOG10 X,Y : X = LOG10(Y) //2.00
return 83
elseif (opcode == "in") then //IN X,Y : X = PORT[Y] //2.00
return 84
elseif (opcode == "out") then //OUT X,Y : PORT[X] = Y //2.00
return 85
elseif (opcode == "fabs") then //FABS X,Y : X = ABS(Y) //2.00
return 86
elseif (opcode == "fsgn") then //FSGN X,Y : X = SIGN(Y) //2.00
return 87
elseif (opcode == "fexp") then //FEXP X,Y : X = EXP(Y) //2.00
return 88
elseif (opcode == "callf") then //CALLF X,Y : CS = Y; CALL(X) //2.00
return 89
//------------------------------------------------------------
elseif (opcode == "fpi") then //FPI X : X = PI //2.00
return 90
elseif (opcode == "fe") then //FE X : X = E //2.00
return 91
elseif (opcode == "int") then //INT X : INTERRUPT(X) //2.00
return 92
elseif (opcode == "tpg") then //TPG X : CMPR = TEST(PAGE(X))* //2.00
return 93
elseif (opcode == "fceil") then //FCEIL X : X = CEIL(X) //2.00
return 94
elseif (opcode == "erpg") then //ERPG X : ERASE ROM PAGE(X) //2.00
return 95
elseif (opcode == "wrpg") then //WRPG X : WRITE ROM PAGE(X) //2.00
return 96
elseif (opcode == "rdpg") then //RDPG X : READ ROM PAGE(X) //2.00
return 97
elseif (opcode == "timer") then //TIMER X : X = TIMER //2.00
return 98
elseif (opcode == "lidtr") then //LIDTR X : IDTR = X //2.00
return 99
//------------------------------------------------------------
elseif (opcode == "jner") || (opcode == "jnzr") then //JNE X : IP = IP+X, IF CMPR ~= 0 //2.00
return 101
elseif (opcode == "jmpr") then //JMP X : IP = IP+X //2.00
return 102
elseif (opcode == "jgr") || (opcode == "jnler") then //JG X : IP = IP+X, IF CMPR > 0 //2.00
return 103
elseif (opcode == "jger") || (opcode == "jnlr") then //JGE X : IP = IP+X, IF CMPR >= 0 //2.00
return 104
elseif (opcode == "jlr") || (opcode == "jnger") then //JL X : IP = IP+X, IF CMPR < 0 //2.00
return 105
elseif (opcode == "jler") || (opcode == "jngr") then //JLE X : IP = IP+X, IF CMPR <= 0 //2.00
return 106
elseif (opcode == "jer") || (opcode == "jzr") then //JE X : IP = IP+X, IF CMPR = 0 //2.00
return 107
elseif (opcode == "lneg") then //LNEG X : X = LOGNEGATE(X) //3.00
return 108
//------------------------------------------------------------
elseif (opcode == "nmiret") then //NMIRET X : NMIRESTORE; //2.00
return 110
end
return -1
end
function ENT:OpcodeParamCount( opcode )
if (self.OpcodeCount[opcode]) then
return self.OpcodeCount[opcode]
else
return 0
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 == ".") || (prefix == "-") ||
(prefix == "+")
end
function ENT:ValidNumber( line )
if (line) then
return self:Digit(string.sub(line,1,1))
else
return false
end
end
function ENT:Explode(seperator ,str)
local tble={}
ll=0
local prevll = 1
str = string.Trim(str)
while true do
l = string.find(str,seperator,ll+1,true)
if l~=nil then
local leftstr = string.Left(str,l)
local rightstr = string.Right(str,string.len(str)-l)
local cleft = 0
local cright = 0
for i = 1, string.len(leftstr) do
if (string.sub(leftstr,i,i) == "'") then
cleft = cleft + 1
end
end
for i = 1, string.len(rightstr) do
if (string.sub(rightstr,i,i) == "'") then
cright = cright + 1
end
end
if (cleft % 2 == 0) && (cright % 2 == 0) then
table.insert(tble, string.sub(str,ll,l-1))
prevll = ll+l+1
end
ll=l+1
else
table.insert(tble, string.sub(str,math.min(prevll,ll)))
break
end
end
return tble
end
function ENT:Lowercase(str)
local j = 1
local rstr = ""
while (j <= string.len(str)) do
local leftstr = string.Left(str,j)
local rightstr = string.Right(str,string.len(str)-j)
local cleft = 0
local cright = 0
for i = 1, string.len(leftstr) do
if (string.sub(leftstr,i,i) == "'") then
cleft = cleft + 1
end
end
for i = 1, string.len(rightstr) do
if (string.sub(rightstr,i,i) == "'") then
cright = cright + 1
end
end
if (cleft % 2 == 0) && (cright % 2 == 0) then
rstr = rstr..string.lower(string.sub(leftstr,j,j))
else
rstr = rstr..string.sub(leftstr,j,j)
end
j = j + 1
end
return rstr
end
function ENT:RemoveFuckingSpaces(str)
end
function ENT:Error( pl, error )
pl:PrintMessage(HUD_PRINTCONSOLE,"-> "..error)
pl:ConCommand("wire_cpu_editor_addlog \""..error.."\"")
end
function ENT:Compile_ASM( pl, line, linenumber, firstpass )
local opcodetable = self:Explode(" ", line or { } )
local dopcode = 0
local nextparams = false
local nextvariable = false
local nextorg = false
local nextdefine = false
local nextalloc = false
local nextdb = false
local programsize = 0
if (self.MakeDump) && (string.Trim(line) ~= "") && (not firstpass) then
self.Dump = self.Dump.."["..linenumber.."]"..self.WIP.." = "..line.."\n"
end
for _,opcode in pairs(opcodetable) do
opcode = string.Trim(opcode)
if (nextdefine) then
local deftable = self:Explode(",", opcode )
if (table.Count(deftable) == 2) then
if (not self.Labels[deftable[1]]) then
if (self:ValidNumber(deftable[2])) then
self.Labels[deftable[1]] = deftable[2]
//-self:Error(pl,"ZyeliosASM: Added define "..deftable[1].."["..deftable[2].."]\n")
else
self:Error(pl,"ZyeliosASM: Error (E270) at line "..linenumber..": Attempt to define a non-number\n")
return false
end
else
if (firstpass) then
self:Error(pl,"ZyeliosASM: Error (E236) at line "..linenumber..": Define "..deftable[1].." already exists\n")
return false
end
end
else
self:Error(pl,"ZyeliosASM: Error (E335) at line "..linenumber..": Invalid number of parameters in DEFINE macro\n")
return false
end
elseif (nextdb) then
// Msg("db explode:"..opcode..";\n")
local dbtable = self:Explode(",", opcode )
// PrintTable(dbtable)
// Msg("db start\n")
// for _,dbvalue in pairs(dbtable) do
for i=0,table.Count(dbtable) do
local dbvalue = dbtable[i]
if (dbvalue) && (dbvalue ~= "") then
dbvalue = string.Trim(dbvalue)
// Msg("dbvalue:"..dbvalue..";\n")
if self:ValidNumber(dbvalue) then
self:Write(dbvalue)
else
if (string.sub(dbvalue,1,1) == "'") && (string.sub(dbvalue,-1,-1) == "'") then
local string = string.sub(dbvalue,2,-2)
for i = 1, string.len(string) do
self:Write(string.byte(string,i))
end
else
if (self.Labels[dbvalue]) then
self:Write(self.Labels[dbvalue])
elseif (self.Labels[dbvalue..":"]) then
self:Write(self.Labels[dbvalue..":"])
else
if (not firstpass) then
self:Error(pl,"ZyeliosASM: Error (E450) at line "..linenumber..": Invalid parameter in DB macro\n")
return false
end
//self:Write(0)
end
end
end
end
end
elseif (nextorg) then
if self:ValidNumber(opcode) then
self.WIP = tonumber(opcode)
else
self:Error(pl,"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
//-self:Error(pl,"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
//-self:Error(pl,"ZyeliosASM: Allocated variable ".."["..alloctable[1].."] ["..self.WIP.."]\n")
for i = 0,alloctable[1]-1 do
self:Write( 0 )
end
else
if (not self.Labels[alloctable[1]]) then
self.Labels[alloctable[1]] = self.WIP
//-self:Error(pl,"ZyeliosASM: Allocated new variable "..alloctable[1].." ["..self.WIP.."]\n")
self:Write( 0 )
else
if (firstpass) then
self:Error(pl,"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
//-self:Error(pl,"ZyeliosASM: Allocated new variable "..alloctable[1].."["..alloctable[2].."] ["..self.WIP.."]\n")
self:Write( alloctable[2] )
else
if (firstpass) then
self:Error(pl,"ZyeliosASM: Error (E231) at line "..linenumber..": Variable "..opcode.." already exists\n")
return false
else
self:Write( alloctable[2] )
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
//-self:Error(pl,"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
self:Error(pl,"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
local segment1 = -1
local segment2 = -1
if (table.Count(paramtable) ~= self:OpcodeParamCount( dopcode )) then
self:Error(pl,"ZyeliosASM: Error (E245) at line "..linenumber..": wrong number of parameters for opcode\n")
self:Error(pl,"Code: ["..linenumber.."]"..self.WIP.." = "..line.."\n")
return false
end
paramtable[1] = string.Trim(paramtable[1])
if (self:ValidNumber(paramtable[1])) then
drm1 = 0
elseif (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] == "cs") then drm1 = 9
elseif (paramtable[1] == "ss") then drm1 = 10
elseif (paramtable[1] == "ds") then drm1 = 11
elseif (paramtable[1] == "es") then drm1 = 12
elseif (paramtable[1] == "gs") then drm1 = 13
elseif (paramtable[1] == "fs") then drm1 = 14
elseif (string.sub(paramtable[1],1,4) == "port") then
drm1 = 1000+string.sub(paramtable[1],5)
else
local prefix = string.find(paramtable[1],"#")
local postprefix = paramtable[1]
if (prefix) then
postprefix = string.sub(paramtable[1],2)
end
local segmentprefix2 = string.find(paramtable[1],":")
if (segmentprefix2) then
local segmentprefix = string.sub(paramtable[1],1,segmentprefix2-1)
if (not self:ValidNumber(segmentprefix)) then
if (segmentprefix == "cs") then
segment1 = -2
elseif (segmentprefix == "ss") then
segment1 = -3
elseif (segmentprefix == "ds") then
segment1 = -4
elseif (segmentprefix == "es") then
segment1 = -5
elseif (segmentprefix == "gs") then
segment1 = -6
elseif (segmentprefix == "fs") then
segment1 = -7
end
else
segment1 = segmentprefix
end
prefix = string.find(paramtable[1],"#",segmentprefix2)
if (prefix) then
postprefix = string.sub(paramtable[1],prefix+1)
else
postprefix = string.sub(paramtable[1],segmentprefix2+1)
end
end
if (prefix == nil) && (not self:ValidNumber(paramtable[1])) then
if (self.Labels[postprefix..":"]) then
paramtable[1] = self.Labels[postprefix..":"]
elseif (self.Labels[postprefix]) then
paramtable[1] = self.Labels[postprefix]
else
if (not firstpass) then
self:Error(pl,"ZyeliosASM: Error (E235) at line "..linenumber..": No such label: "..postprefix.."!\n")
return false
end
end
end
if (prefix ~= nil) 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 == "ebp") 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
self:Error(pl,"ZyeliosASM: Error (E236) at line "..linenumber..": No such variable: "..postprefix.."!\n") //I'm teh pirate yarr!
return false
end
end
drm1 = 25
disp1 = postprefix
else
self:Error(pl,"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 (self:ValidNumber(paramtable[2])) then
drm2 = 0
elseif (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] == "cs") then drm2 = 9
elseif (paramtable[2] == "ss") then drm2 = 10
elseif (paramtable[2] == "ds") then drm2 = 11
elseif (paramtable[2] == "es") then drm2 = 12
elseif (paramtable[2] == "gs") then drm2 = 13
elseif (paramtable[2] == "fs") then drm2 = 14
elseif (string.sub(paramtable[2],1,4) == "port") then
drm2 = 1000+string.sub(paramtable[2],5)
else
local prefix = string.find(paramtable[2],"#")
local postprefix = paramtable[2]
if (prefix) then
postprefix = string.sub(paramtable[2],2)
end
local segmentprefix2 = string.find(paramtable[2],":")
if (segmentprefix2) then
local segmentprefix = string.sub(paramtable[2],1,segmentprefix2-1)
if (not self:ValidNumber(segmentprefix)) then
if (segmentprefix == "cs") then
segment2 = -2
elseif (segmentprefix == "ss") then
segment2 = -3
elseif (segmentprefix == "ds") then
segment2 = -4
elseif (segmentprefix == "es") then
segment2 = -5
elseif (segmentprefix == "gs") then
segment2 = -6
elseif (segmentprefix == "fs") then
segment2 = -7
end
else
segment2 = segmentprefix
end
prefix = string.find(paramtable[2],"#",segmentprefix2)
if (prefix) then
postprefix = string.sub(paramtable[2],prefix+1)
else
postprefix = string.sub(paramtable[2],segmentprefix2+1)
end
end
if (prefix == nil) && (not self:ValidNumber(paramtable[2])) then
if (self.Labels[postprefix..":"]) then
paramtable[2] = self.Labels[postprefix..":"]
elseif (self.Labels[postprefix]) then
paramtable[2] = self.Labels[postprefix]
else
if (not firstpass) then
self:Error(pl,"ZyeliosASM: Error (E232) at line "..linenumber..": No such label: "..postprefix.."!\n")
return false
end
end
end
if (prefix ~= nil) 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 == "ebp") 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
self:Error(pl,"ZyeliosASM: Error (E231) at line "..linenumber..": No such variable: "..postprefix.."!\n")
return false
end
end
drm2 = 25
disp2 = postprefix
else
self:Error(pl,"ZyeliosASM: Error (E490) at line "..linenumber..": Wrong memory reference syntax!\n")
end
end
end
end
end
local rm = drm1 + drm2*10000
local sopcode = dopcode
if (segment1 ~= -1) then
dopcode = dopcode + 1000
end
if (segment2 ~= -1) then
dopcode = dopcode + 10000
end
self:Write( dopcode )
self:Write( rm )
programsize = programsize + 2
if (segment1 ~= -1) then
self:Write( segment1 )
end
if (segment2 ~= -1) then
self:Write( segment2 )
end
if (drm1 == 0) then
self:Write( paramtable[1] )
programsize = programsize + 1
end
if (drm1 == 25) then
self:Write( disp1 )
end
if (self:OpcodeParamCount( sopcode ) > 1) && (drm2 == 0) then
self:Write( paramtable[2] )
programsize = programsize + 1
end
if (drm2 == 25) then
self:Write( disp2 )
end
nextparams = false
else
if ( opcode == "alloc" ) then
nextalloc = true
elseif (opcode == "db") then
nextdb = true
elseif ( opcode == "org" ) then
nextorg = true
elseif ( opcode == "define" ) then
nextdefine = true
elseif ( opcode == "code" ) then
if (self.Labels["codestart"]) then
if (firstpass) then
self:Error(pl,"ZyeliosASM: Error (E600) at line "..linenumber..": CODESTART label exists - cant use CODE macro\n")
return false
end
end
self.Labels["codestart"] = self.WIP
elseif ( opcode == "data" ) then
if (self.Labels["datastart"]) then
if (firstpass) then
self:Error(pl,"ZyeliosASM: Error (E601) at line "..linenumber..": DATASTART label exists - cant use DATA macro\n")
return false
end
end
self.Labels["datastart"] = self.WIP
self:Write(2)
self:Write(0)
if (self.Labels["codestart"]) then
self:Write(self.Labels["codestart"])
else
self:Write(0)
if (not firstpass) then
self:Error(pl,"ZyeliosASM: Error (E602) at line "..linenumber..": No CODE macro, cant use DATA macro\n")
return false
end
end
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)
local labelname = string.sub(opcode,1,string.len(opcode)-1)
if (lastsymbol == ":") then
if (not self.Labels[labelname]) then
self.Labels[labelname] = self.WIP
//self:Error(pl,"ZyeliosASM: Added label "..opcode.."["..self.WIP.."]\n")
else
if (firstpass) then
self:Error(pl,"ZyeliosASM: Error (E200) at line "..linenumber..": Label "..opcode.." already exists\n")
return false
end
end
else
if (opcode ~= "") && (opcode ~= " ") then
self:Error(pl,"ZyeliosASM: Error (E500) at line "..linenumber..": unknown opcode: "..opcode.."\n")
return false
end
end
end
end
end
end
return true
end
function ENT:ParseProgram_ASM( pl, programtext, parsedline, firstpass )
if (self.FatalError) then
return false
end
if (programtext == nil) then
return
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_ASM( pl, self:Lowercase(line), parsedline, firstpass )) then
self.FatalError = true
self.Memory[0] = 0 //FIXME
end
end
end