First effort to revive BasicBlock and Function classes and
[jitcs.git] / tools / x86_inslist2data.lua
blob4f3345d6e8c7a1f79105aeb9b10965e322a863e2
1 local _type, _ipairs, _pairs, _tonum, _tostr, _assert, _error = type, ipairs, pairs, tonumber, tostring, assert, error
2 local _loadstr = loadstring
3 local _match, _gmatch, _sub, _lower, _upper = string.match, string.gmatch, string.sub, string.lower, string.upper
4 local _fmt, _gsub = string.format, string.gsub
5 local _sort = table.sort
6 local _open = io.open
7 local _ceil, _pow = math.ceil, math.pow
9 require"dump"
11 local _trim = function(s) return _match(s, "^%s*(.-)%s*$") or s end
12 function _dump(x, unquote)
13 if not unquote and _type(x) == "string" then
14 return _fmt("%q", x)
15 elseif _type(x) ~= "table" then
16 return tostring(x)
17 else
18 local r = "{"
19 local n = #x
20 for i = 1,n do r = r .. (i > 1 and ", " or "") .. _dump(x[i], unquote) end
21 local pending = n > 0 and ";"
22 for k,v in _pairs(x) do
23 if _type(k) == "number" and k == _ceil(k) and k >= 1 and k <=n then
25 elseif _type(k) == "string" and _match(k,"^%a[%w_]*$") then
26 if pending then r = r .. pending; pending = nil end
27 r = r .. k .. " = " .. _dump(v, unquote)
28 pending = ","
29 else
30 if pending then r = r .. pending; pending = nil end
31 r = r .. "[" .. _dump(k, unquote) .. "] = " .. _dump(v, unquote)
32 pending = ","
33 end
34 end
35 r = r .. "}"
36 return r
37 end
38 end
39 --------------
40 local function readfile(n)
41 local f = _open(n) or _open("tools/"..n)
42 local ctnt = f:read("*a")
43 f:close()
44 return ctnt
45 end
47 print("PAR",...)
49 local testname, outname = ...
50 if (testname == nil or testname == "") then
51 testname = "..\\src-lib\\x86\\src\\_x86_inslist.ltxt"
52 end
53 if outname == nil or outname == "" then
54 outname = _match(testname, "^(.-)%.[^.\\/]*$") .. ".dat"
55 end
57 local emblua = _loadstr(readfile("emblua.lua"))
58 local inslist = emblua(testname,{type="string"})
59 --local inslist = readfile("..\\evm\\x86\\src\\_x86_inslist.txt")
60 -----------------------------------------------------------------
62 -----------------------------------------------------------------
64 local _cacheMatchWords = {}
65 local function matchWords(w, n)
66 local v = _cacheMatchWords[n]
67 if not v then
68 v = "^%s*"
69 for i = 1, n do v = v .. "(%w+)%s*" end
70 v = v .. "$"
71 _cacheMatchWords[n] = v
72 end
73 return _match(w, v)
74 end
75 local _cacheMatchID = {}
76 local function matchID(w, n)
77 local v = _cacheMatchID[n]
78 if not v then
79 v = _gsub(n, "$ID", "%%a[%%w_]*")
80 v = _gsub(v, "$NUM", "%%d+")
81 v = _gsub(v, "$OP", "[^,]-")
82 v = _gsub(v, " ", "%%s*")
83 v = "^%s*" .. v .. "%s*$"
84 _cacheMatchID[n] = v
85 end
86 return _match(w, v)
87 end
90 -----------------------------------------------------------------
92 -----------------------------------------------------------------
95 -----------------------------------------------------------------
97 -----------------------------------------------------------------
99 local cache, cachecount = {}, {}
100 local function unify(section, t, pred)
101 local subcache = cache[section]
102 if not subcache then subcache = {}; cache[section] = subcache end
103 local sig = (pred or _dump)(t, true)
104 local data = subcache[sig]
105 if not data then
106 local id = (cachecount[section] or 0) + 1
107 data = t; data.id = id; data.sig = sig; subcache[sig] = data; cachecount[section] = id end
108 return data
110 local function _opassert(cond, op, msg, ...)
111 if cond then return end
112 assert(false, _fmt("op %s: "..msg, op.name, ...))
114 --------------------------------------
115 local _isetset= {
116 def = {},
117 cmov = {},
118 mmx = {},
119 mmxext = {"mmx"},
120 sse = {},
121 sse2 = {"sse", "mmxext"},
122 sse3 = {"sse2"},
123 ssse3 = {"sse3"},
124 sse41 = {"ssse3"},
125 sse42 = {"sse41"},
126 avx = {"sse42"},
127 avx2 = {"avx"},
128 fma3 = {"avx"},
129 aes = {"sse2"},
130 clmul = {"sse2"},
131 hle = {},
132 rtm = {},
133 bmi1 = {"avx"},
134 bmi2 = {"avx"},
135 movbe = {},
136 lzcnt = {},
137 popcnt = {},
138 rdrand = {},
139 clflush = {},
140 rdtsc = {},
141 rdtscp = {},
142 f16c = {"avx"},
143 x32only = {},
144 x64 = {"sse2","cmov"},
145 x64only = {"x64"},
146 avx512f = {"avx2","f16c","fma3"}}
147 local function _simplifyISA(t, v)
148 --if not _isetset[v] then return end
149 for k,vv in _ipairs(_isetset[v]) do
150 t[vv] = true
151 _simplifyISA(t, vv)
155 local function _parseISA(op, data)
156 _opassert(not op.isa, op, "double ISA declaration")
157 local iset = {}
158 for i in _gmatch(data,"[%w_]+") do
159 _opassert(_isetset[i], op, "invalid isa %s", i)
160 if i == "x64only" then i = "x64" end
161 iset[i] = true
162 _simplifyISA(iset, i)
164 local dep = {}
165 for k,v in _pairs(iset) do
166 _simplifyISA(dep, k)
168 local iset2 = {}
169 for k,v in _pairs(iset) do if not dep[k] then iset2[#iset2 + 1] = k end end
170 _sort(iset2)
171 op.isa = unify("isa", iset2)
172 if iset.x64 then op.isa.x64 = true end
173 if iset.x32only then op.isa.x32only = true end
175 --------------------------------------
176 local function list2set( list )
177 local set= {}
178 for k,v in _ipairs(list) do set[v]= k end
179 return set
181 local _typeset= list2set{"GR8","GR16","GR32","GR64","VR128","VR256","VR512","KR",
182 "i8","i16","i32","i64",
183 "i8*","i16*","i32*","i64*","i128*","i256*","i512*",
184 "BB"}
185 local _fixedregs = {
186 al = "rax", ah = "rax", ax = "rax", eax = "rax", rax = "rax",
187 cl = "rcx", ecx = "rcx", rcx = "rcx",
188 dx = "rdx", edx = "rdx", rdx = "rdx",
189 ebx = "rbx", rbx = "rbx",
190 edi = "rdi", rdi = "rdi",
191 esp = "rsp",
192 xmm0 = "xmm0",
194 local function _parseOps(op, data)
195 _opassert(not op.ops, op, "double operands declaration")
196 local varlist, varset = {}, {}
197 for p in _gmatch(data, "[^,]+") do
198 p = _trim(p)
199 if p ~= "" then
200 local tp, fixedreg, vname, mode = matchID(p, "($ID%*?) { ($ID) } ($ID)/($ID)" )
201 if not tp then
202 tp,vname,mode= matchID(p, "($ID%*?) ($ID)/($ID)")
203 fixedreg= nil
205 fixedreg = fixedreg and _lower(fixedreg)
206 _opassert(tp and vname, op, "invalid operand \"%s\"", p)
207 _opassert(_typeset[tp], op, "invalid type %s", tp)
208 _opassert(not varset[vname], op, "double declaration of operand %s", vname)
209 _opassert(mode == "i" or mode == "o" or mode == "io",
210 op, "operand %s uses invalid mode %s", vname, mode)
211 varset[vname]= true
212 if (tp == "GR8" or tp == "GR16") and mode == "o" then mode = "io" end
213 local skip = false
214 if fixedreg then
215 _opassert(_fixedregs[fixedreg], op, "unsupported fixed reg %s", fixedreg)
216 fixedreg = _fixedregs[fixedreg]
217 for i,v in _ipairs(varlist) do
218 if v.fixed == fixedreg then
219 local mi = _match(v.mode, "i") or _match(mode, "i")
220 local mo = _match(v.mode, "o") or _match(mode, "o")
221 v.mode = (mi and "i" or "")..(mo and "o" or "")
222 skip = true
223 break
227 if not skip then
228 varlist[ #varlist+1 ]= {name=vname,type=tp,fixed=fixedreg,mode=mode}
232 op.operands = varlist
234 --------------------------------------
235 local _flagset= {
236 rflags = {flagin = true}, rflag_c = {flagin = true}, rflag_o = {flagin = true},
237 rflag_s = {flagin = true}, rflag_z = {flagin = true}, rflag_p = {flagin = true},
238 wflags = {flagout = true},
239 wflag_c = {flagin = true, flagout = true}, wflag_o = {flagin = true, flagout = true},
240 subflags = {flagin = true},
241 wmem = {}, rmem = {}, rwmem = {}, usemem = {}, amem = {}, umem = {},
242 cf_jmp = {}, cf_call = {}, cf_ret = {}, cf_fallthru = {},
243 vsib = {},
246 local function _parseFlags(op, data)
247 _opassert(not op.flags, op, "double flags declaration")
248 local fset = {}
249 for i in _gmatch(data,"[%w_]+") do
250 _opassert(_flagset[i], op, "invalid flag %s", i)
251 fset[i] = true
253 if fset.rwmem then fset.wmem = true; fset.rmem = true; fset.rwmem = false end
254 local fset2 = {}
255 for k,v in _pairs(fset) do fset2[#fset2 + 1] = k end
256 _sort(fset2)
257 op.flags = unify("flags", fset2)
259 --------------------------------------
260 local _prefset= {
261 ["66"] = {},
262 ["f2"] = {},
263 ["f3"] = {},
265 local function _parsePref(op, data)
266 _opassert(not op.pref, op, "double prefix declaration")
267 if data == "" then op.pref = ""; return end
268 local p = _match(data, "^([%w_]+)$")
269 _opassert(p and _prefset[p], op, "invalid prefix %s", _tostr(p))
270 op.pref = p
272 --------------------------------------
273 local _extopcodeset= {
274 ["0f"] = {},
275 ["0f38"] = {},
276 ["0f3a"] = {},
278 local function _parseExtOpcode(op, data)
279 _opassert(not op.extopcode, op, "double extended opcode declaration")
280 if data == "" then op.extopcode = ""; return end
281 local p = _match(data, "^([%w_]+)$")
282 _opassert(p and _extopcodeset[p], op, "invalid extended opcode %s", _tostr(p))
283 op.extopcode = p
285 --------------------------------------
286 local function _parseCoding(op, data)
287 _opassert(not op.code, op, "double coding declaration")
288 local result= {}
289 for c in _gmatch(data, "%S+") do
290 c = _gsub(c, "!par%((%w+)%)", function (p)
291 _opassert(not op.parm, op, "double !par declaration")
292 _opassert(_tonum(p), op, "invalid !par value")
293 op.parm = _tonum(p)
294 return "$parm"
295 end)
296 c = _gsub(c, "!sub%((%w+)%)", function (p)
297 _opassert(not op.sub, op, "double !sub declaration")
298 _opassert(_tonum(p), op, "invalid !sub value")
299 op.sub = _tonum(p)
300 return "$sub"
301 end)
302 c = _gsub(c, "!parsub%((%w+)%)", function (p)
303 _opassert(not op.par, op, "double !par declaration")
304 _opassert(not op.sub, op, "double !sub declaration")
305 _opassert(_tonum(p), op, "invalid !parsub value")
306 op.parm = _tonum(p)
307 op.sub = op.parm % 32
308 op.parm = op.parm - op.sub
309 return "$parm+$sub"
310 end)
311 result[ #result+1 ]= c
313 op.code = result
315 --------------------------------------
316 local function _parseLEAREX(op, data)
317 _opassert(not op.rex, op, "double rex/vex declaration in op "..op.name)
318 local w, reg, base, index = matchWords(data,4)
319 _opassert(reg, op, "invalid rexlea parameters")
320 _opassert(w == "0" or w == "1", op, "invalid rex w field")
321 op.rex = {mode = "lea", reg = reg, rmb = base, rmi = index, r64 = w}
323 local function _parseREX(op, data)
324 _opassert(not op.rex, op, "double rex/vex declaration in op "..op.name)
325 local rm, w, rmr, rmm = matchWords(data,4)
326 _opassert(rm, op, "invalid rex parameters")
327 _opassert(rm == "rr" or rm == "rm", op, "invalid rex rm field")
328 _opassert(w == "0" or w == "1", op, "invalid rex w field")
329 op.rex = {mode = rm, reg = rmr, rm = rmm, r64 = w}
331 local function _parseVEX(op, data)
332 _opassert(not op.rex, op, "double rex/vex declaration")
333 local rm, w, src1, rmr, rmm, l = matchWords(data,6)
334 _opassert(rm, op, "invalid rex parameters")
335 _opassert(rm == "rr" or rm == "rm", op, "invalid vex rm field")
336 _opassert(w == "0" or w == "1", op, "invalid vex w field")
337 _opassert(l == "0" or l == "1", op, "invalid vex l field")
338 op.rex = {vex = true, mode = rm, reg = rmr, rm = rmm, r64 = w, l = l, src1 = src1}
340 local function _parseEVEX(op, data)
341 _opassert(not op.rex, op, "double rex/vex declaration in op "..op.name)
342 local rm, w, src1, rmr, rmm, l, k, z, b = matchWords(data,9)
343 _opassert(rm, op, "invalid rex parameters")
344 _opassert(rm == "rr" or rm == "rm", op, "invalid evex rm field")
345 _opassert(w == "0" or w == "1", op, "invalid evex w field")
346 _opassert(l == "0" or l == "1" or l == "2" or l == "3", op, "invalid evex l field")
347 _opassert(z == "0" or z == "1", op, "invalid evex z field")
348 _opassert(b == "0" or b == "1", op, "invalid evex b field")
349 op.rex = {evex = true, mode = rm, reg = rmr, rm = rmm, r64 = w, l = l, src1 = src1,
350 k = k, z = z, b = b}
352 local function _parseFold(op, data)
354 local function _parseCommute(op, data)
357 --------------------------------------
359 local function _getValidVarSet( op )
360 --print( op.name )
361 local vars={ parm="i8", sub="i8" }
362 for _,v in _ipairs(op.operands) do vars[v.name]= v.type end
363 return vars
366 local function _ptrtype(s)
367 return s and _sub(s,-1,-1)=="*"
369 local function _immtype(s)
370 return s and _sub(s,1,1)=="i" and not _ptrtype(s)
372 local function _regtype(s)
373 return s and not _ptrtype(s) and not _immtype(s)
376 local function _checkOp( op )
377 local vars= _getValidVarSet(op)
379 local memops = 0
380 for _,v in _ipairs(op.operands) do
381 if _ptrtype(v.type) then
382 _opassert(v.mode == "i", op, "memory operands are input only")
383 _opassert(memops == 0, op, "only one memory operand allowed")
384 memops = memops + 1
388 for _,v in _ipairs(op.code) do
389 for vv in _gmatch(v, "%$(%a%w*)") do
390 _opassert(vars[vv], op, "invalid variable %s", vv)
393 local p1,p2,p3,p4,p5= matchID(v,"!RRMLEA%( ($OP) , ($OP) , ($OP) , ($OP) , ($OP) %)")
394 if p1 then
395 _opassert(op.rex.mode=="lea", op, "RRM?-rex mode mismatch" )
396 _opassert(not op.rex.vex and not op.rex.evex, op, "RRMLEA and vex don't mix" )
397 _opassert(_sub(p1,1,1)=="$" and vars[_sub(p1,2)], op, ": RRMLEA-reg error" )
398 _opassert(_sub(p1,2)==op.rex.reg, op, "RRMLEA-rex reg mismatch" )
399 _opassert(_sub(p2,1,1)=="$" and vars[_sub(p2,2)], op, "RRMLEA-rm base error" )
400 _opassert(_sub(p2,2)==op.rex.rmb, op, "RRMLEA-rex rm base mismatch" )
401 _opassert(_sub(p3,1,1)=="$" and vars[_sub(p3,2)], op, "RRMLEA-rm index error" )
402 _opassert(_sub(p3,2)==op.rex.rmi, op, "RRMLEA-rex rm index mismatch" )
405 p1,p2,p3= matchID(v, "!RRMMVSIB([RM])%( ($OP) , ($OP) , ($OP) %)")
406 if p1 then
407 _opassert(op.rex.mode=="rm", op, "RRMMVSIB-rex mode mismatch" )
408 _opassert(op.rex.vex or op.rex.evex, op, "RRMMVSIB requires vex" )
409 _opassert(_sub(p1,1,1)=="$" and vars[_sub(p1,2)], op, ": RRMMVSIB-reg error" )
410 _opassert(_sub(p1,2)==op.rex.reg, op, "RRMMVSIB-rex reg mismatch" )
411 _opassert(_sub(p2,1,1)=="$" and vars[_sub(p2,2)], op, "RRMMVSIB-rm base error" )
412 _opassert(_sub(p2,2)==op.rex.rm, op, "RRMMVSIB-rex rm base mismatch" )
413 _opassert(_sub(p3,1,1)=="$" and vars[_sub(p3,2)], op, "RRMMVSIB-vsib index error" )
415 local x
416 x,p1,p2= matchID(v, "!RRM([RM])%( ($OP) , ($OP) %)")
417 if x then
418 local rm = "r".._lower(x)
419 _opassert(op.rex.mode == rm, op, "RRM%s-rex mode mismatch", x)
420 if _tonum(p1) then
421 _opassert( op.rex.reg==p1, op, "RRM%s-rex reg(#) mismatch", x)
422 elseif p1=="$parm" then
423 _opassert( op.parm>=0 and op.parm<8 and op.rex.reg=="0", op, "RRM%s-rex reg(parm) mismatch", x)
424 elseif p1=="$sub" then
425 local sub= op.sub or 0
426 _opassert( sub>=0 and sub<8 and op.rex.reg=="0", op, "RRM%s-rex reg(parm) mismatch", x)
427 else
428 _opassert(_sub(p1,1,1)=="$" and vars[_sub(p1,2)], op, "RRM%s-reg error", x)
429 _opassert(_sub(p1,2)==op.rex.reg, op, "RRM%s-rex reg mismatch", x)
431 if _tonum(p2) then
432 _opassert((op.rex.rm or "0") == "0", op, "RRM%s-rex rm mismatch", x)
433 else
434 _opassert(_sub(p2,1,1)=="$" and vars[_sub(p2,2)], op, "RRM%s-rm error", x)
435 _opassert(_sub(p2,2)==op.rex.rm, op, "RRM%s-rex rm mismatch", x)
439 _opassert( op.rex.reg=="0" or _regtype(vars[op.rex.reg]), op, "rex-reg error" )
440 if op.rex.mode=="rr" then
441 _opassert( op.rex.rm=="0" or _regtype(vars[op.rex.rm]), op, "rex-rmr error" )
442 elseif op.rex.mode=="rm" then
443 _opassert( op.rex.mode=="rm" and _ptrtype(vars[op.rex.rm]), op, "rex-rmm error" )
447 local function _createLayout(op)
448 local layout, renametab, pnum = {}, {}, nil
449 local indices = {}
450 --print(op.name, dump(op.rex))
451 local function renameVar(v)
452 local res = renametab[v]
453 if not res then
454 pnum = (pnum or 0) + 1
455 res = {"p".._tostr(pnum), pnum}
456 renametab[v] = res
458 return res[1]
460 local function add2layout(v, defuse)
461 if v.fixed then return end
462 local n = renameVar(v.name)
463 if indices[v.name] then return end
464 local mode, lp3
465 if _ptrtype(v.type) then
466 mode = "MemId"
467 elseif _immtype(v.type) then
468 mode, lp3 = "Imm", 0
469 elseif v.type == "BB" then
470 mode = "BBId"
471 else
472 mode, lp3 = "RegId", v.fixed
474 layout[#layout + 1] = {mode, defuse, n, lp3};
475 indices[v.name] = #layout
476 if v.type == "i64" then
477 layout[#layout + 1] = {"Imm", "use", n, 32}
481 -- make sure, memory operands are the first parameter
482 -- this preferred order should simplify the code generator a bit
483 for _,v in _ipairs(op.operands) do
484 if _ptrtype(v.type) then add2layout(v, "use") end
486 local orderedlayout = {}
487 if op.rex.rm and not _tonum(op.rex.rm) then orderedlayout[#orderedlayout+1] = op.rex.rm end
488 if op.rex.reg and not _tonum(op.rex.reg) then orderedlayout[#orderedlayout+1] = op.rex.reg end
489 if op.rex.src1 and not _tonum(op.rex.src1) then orderedlayout[#orderedlayout+1] = op.rex.src1 end
490 if op.rex.msk and not _tonum(op.rex.msk) then orderedlayout[#orderedlayout+1] = op.rex.msk end
491 local t = {i = "use", o = "def", io = "use/def"}
492 for _1,v1 in _ipairs(orderedlayout) do
493 for _,v in _ipairs(op.operands) do
494 if v.name == v1 then
495 add2layout(v, t[v.mode])
500 for _,v in _ipairs(op.operands) do
501 add2layout(v, t[v.mode])
503 for _,v in _ipairs(op.operands) do
504 if v.fixed then
505 local n = renameVar(v.name)
508 op.layout = unify("layout", layout)
509 op.rename2layout = renametab
512 local function _renameFromLayout(op)
513 op.orgnames = {}
514 for i,v in _ipairs(op.operands) do
515 op.orgnames[i] = v.name
516 v.name = op.rename2layout[v.name][1]
518 for _,v in _ipairs{"reg", "rm", "src1", "msk", "rmb", "rmi"} do
519 if op.rex[v] and op.rename2layout[op.rex[v]] then
520 op.rex[v] = op.rename2layout[op.rex[v]][1]
523 for i,v in _ipairs(op.code) do
524 op.code[i] = _gsub(v, "%$(%a%w*)", function (vv)
525 if op.rename2layout[vv] then return "$"..op.rename2layout[vv][1] end
526 end)
529 op.operands = unify("operands", op.operands)
530 op.orgnames = unify("orgnames", op.orgnames)
531 op.rex = unify("rex", op.rex)
532 op.code = unify("code", op.code)
533 op.rename2layout = nil
535 local function _createImpRegs(op)
536 local regs = {}
537 local t = {i = "use", o = "def", io = "use/def"}
538 for _,v in _ipairs(op.operands) do
539 if not _ptrtype(v.type) and not _immtype(v.type) and not (v.type == "BB") then
540 if v.fixed then
541 regs[#regs + 1] = {v.fixed, t[v.mode]}
544 end
545 -- flag comes last
546 local flagin, flagout = false, false
547 for _,v in _ipairs(op.flags) do
548 flagin = flagin or _flagset[v].flagin
549 flagout = flagout or _flagset[v].flagout
551 if flagin or flagout then
552 regs[#regs + 1] = {"FLAGS", flagout and (flagin and "use/def" or "def") or "use"}
554 op.impregs = unify("impregs", regs)
556 function _getPrefixSig(op)
557 local r, pending = ""
558 if op.rex.vex then
559 r = "vex"
560 if op.pref ~= "" then r = r .. "-" .. op.pref end
561 if op.extopcode ~= "" then r = r .. "-" .. op.extopcode end
562 r = r .. "-"
563 if tonumber(op.rex.l) > 0 then r = r .. _pow(128,tonumber(op.rex.l)) .. "." end
564 if tonumber(op.rex.r64) > 0 then r = r .. "W" end
565 if not tonumber(op.rex.reg) then r = r .. "R".._gsub(op.rex.reg,"p","") end
566 if not tonumber(op.rex.rm) then
567 r = r .. (op.rex.mode == "rr" and "B" or "M").._gsub(op.rex.rm,"p","")
569 if not tonumber(op.rex.src1) then r = r .. "S".._gsub(op.rex.src1,"p","") end
570 else
571 if op.pref ~= "" then r = r .. op.pref; pending = "-" end
572 if op.rex.mode == "lea" then
573 if pending then r = r .. pending; pending = nil end;
574 r = r .. "lea"
575 if tonumber(op.rex.r64) > 0 then r = r .. "W" end
576 if not tonumber(op.rex.reg) then r = r .. "R".._gsub(op.rex.reg,"p","") end
577 if not tonumber(op.rex.rmb) then r = r .. "B".._gsub(op.rex.rmb,"p","") end
578 if not tonumber(op.rex.rmi) then r = r .. "I".._gsub(op.rex.rmi,"p","") end
579 pending = "-"
580 elseif tonumber(op.rex.r64) or not tonumber(op.rex.reg) or not tonumber(op.rex.rm) then
581 if pending then r = r .. pending; pending = nil end;
582 r = r .. "rex"
583 if tonumber(op.rex.r64) > 0 then r = r .. "W" end
584 if not tonumber(op.rex.reg) then r = r .. "R".._gsub(op.rex.reg,"p","") end
585 if not tonumber(op.rex.rm) then
586 r = r .. (op.rex.mode == "rr" and "B" or "M").._gsub(op.rex.rm,"p","")
588 pending = "-"
590 if op.extopcode ~= "" then
591 if pending then r = r .. pending; pending = nil end;
592 r = r .. op.extopcode
594 if r == "" then r = "none" end
596 return r
598 function _getPrefixClass(op)
599 local pcl = {pref = op.pref, rex = op.rex, extopcode = op.extopcode}
600 pcl = unify("prefixclass", pcl, _getPrefixSig)
601 -- print(dump(pcl))
602 op.prefixclass = pcl
603 op.pref = nil
604 op.rex = nil
605 op.extopcode = nil
608 function _getOpClassSig(op)
609 return op.isa.sig .. "|" .. op.layout.sig .. "|" .. op.impregs.sig
610 .. "|" .. op.prefixclass.sig .. "|" .. op.code.sig
611 .. "|" .. _fmt("PAR%2X",op.parm or 0)
612 .. "|" .. op.flags.sig
614 function _getOpClass(op)
615 local cl = {isa = op.isa, layout = op.layout, impregs = op.impregs,
616 prefixclass = op.prefixclass, code = op.code, parm = op.parm, flags = op.flags}
617 cl = unify("opclass", cl, _getOpClassSig)
618 -- print(dump(pcl))
619 op.opclass = cl
620 op.isa = nil
621 op.layout = nil
622 op.impregs = nil
623 op.prefixclass = nil
624 op.code = nil
625 op.parm = nil
626 op.flags = nil
629 --------------------------------------
630 --KORW_KKK
631 -- {isa avx512f; ops KR dst/o, KR src1/i, KR src/i;
632 -- pref ; %(VEXDS({"avx",256,"rr"},"S")); extopcode 0f; coding !parsub(0x45) !RRMR($dst,$src)}
633 --------------------------------------
635 local _parsePart = {
636 isa = _parseISA,
637 ops = _parseOps,
638 flags = _parseFlags,
639 pref = _parsePref,
640 extopcode = _parseExtOpcode,
641 coding = _parseCoding,
642 rex = _parseREX,
643 learex = _parseLEAREX,
644 rexlea = _parseLEAREX,
645 vex = _parseVEX,
646 evex = _parseEVEX,
647 fold = _parseFold,
648 commute = _parseCommute,
651 local function parseLine(name, defs)
652 local op= { name = name }
653 for part,info in _gmatch(defs,"%s*(%w+)%s+([^;]*);?") do
654 info = _match(info, "^%s*(.-)%s*$")
655 _assert(_parsePart[part], "invalid option "..part.." in opcode "..name)
656 _parsePart[part](op, info)
658 if not op.isa then op.isa = unify("isa", {}) end
659 if not op.operands then op.operands = {} end
660 if not op.flags then op.flags = unify("flags", {}) end
661 if not op.pref then op.pref = "" end
662 if not op.rex then op.rex = {mode = "rr", reg = "0", rm = "0", r64 = "0"} end
663 if not op.extopcode then op.extopcode = "" end
664 if not op.code then op.code = {} end
665 --print(1, dump(op))
666 _checkOp(op)
667 _createLayout(op)
668 _renameFromLayout(op)
669 _createImpRegs(op)
670 _getPrefixClass(op)
671 _getOpClass(op)
672 return op
675 -----------------------------------------------------------------
677 -----------------------------------------------------------------
678 --local mode,file= ...
680 local ops,opset= {},{}
681 local opclasses = {}
683 -----------------------------------------------------------------
684 -- output functions
685 -----------------------------------------------------------------
686 inslist= _gsub(inslist, "(//[^\r\n]*)([\r\n])","%2")
687 inslist= _gsub(inslist, "(/%*.-%*/)","" )
689 for opname, def in _gmatch(inslist, "%s*([%w_]+)%s*(%b{})") do
690 def = _sub(_gsub(def,"[\r\n]"," "),2,-2)
691 _assert( not opset[opname],"double definition of "..opname )
692 local ok, op = pcall(parseLine,opname, def)
693 if (ok) then
694 ops[ #ops+1 ]= op
695 opset[op.name]= op
696 --print(_dump(op))
697 else
698 print(op)
701 for k,v in _pairs(cache.opclass) do
702 opclasses[#opclasses + 1] = v
704 -- before avx2: 120 prefix (prefix + rex + extopcode/vex) classes, 60 coding classes
705 -- total: isa 39, rex 37, code 73, defuse 42, flags 61, layout 96, operands 321, orgnames 40
706 -- bits: isa 6, rex 6, code 7, defuse 6, flags 7, layout 7 -> sum 39 bits
707 -- class: to check if op is available): isa + 1 bit per opcodesubmask checking
708 -- prefix encoding: pref + rex + extopcode
709 -- main encoding: code
710 -- data flow: defuse + ???
711 -- register class is setup at construction time (of the vregs), and as such, not
712 -- relevant for def use. instruction constructors do the type checking for us.
713 -- allocation and data flow is done for virtual and fixed regs.so we have fixed registers to worry about,
715 --local
717 local function opclassid(op)
718 if op.flags.rmem then r = r .. "R" end
719 if op.flags.wmem then r = r .. "W" end
720 if op.flags.usemem then r = r .. "U" end
721 return r
722 -- if cl.subs[op.sub or 0] then
723 -- print("class "..(op.class or op.name).." contains the sub "..(op.sub or 0).." multiple times")
726 local function _compareISA(a, b)
727 if a == b then return false end
728 if (a.x64 or false) ~= (b.x64 or false) then return b.x64 end
729 if (a.x32only or false) ~= (b.x32only or false) then return b.x32only end
730 if a.sig ~= b.sig then return a.sig < b.sig end
731 _assert("comparing ISA failed")
733 _sort(opclasses,function(a,b)
734 if a.isa ~= b.isa then return _compareISA(a.isa, b.isa) end
735 return a.sig < b.sig
736 end)
737 for i,v in _ipairs(opclasses) do v.id = i end
739 _sort(ops,function(a,b)
740 if a.opclass.isa ~= b.opclass.isa then return _compareISA(a.opclass.isa, b.opclass.isa) end
741 return a.name < b.name
742 end)
744 -----------------------------------------
745 -- selector
746 -----------------------------------------
747 local type2type={
748 GR8="T_I8", GR16= "T_I16", GR32= "T_I32", GR64= "T_I64",
749 VRI64="T_V1I64", VRI128="T_V2I64", VRI256="T_V4I64", VRI128Z="T_V2I64", VRI512="T_V8I64",
750 VR4F32="T_V4F32", VR2F64= "T_V2F64", VR8F32="T_V8F32", VR4F64= "T_V4F64",
751 VR4F32Z="T_V4F32", VR2F64Z= "T_V2F64", VR16F32="T_V16F32", VR8F64 = "T_V8F64",
752 BB="T_BBLOCK",
753 i8="T_I8", i16= "T_I16", i32= "T_I32", i64= "T_I64",
755 local ptr2type={
756 ["i8*"]= "T_I8", ["i16*"]= "T_I16", ["i32*"]= "T_I32", ["i64*"]= "T_I64",
757 ["VI16*"]= "T_I16", ["VI32*"]= "T_I32", ["VI64*"]= "T_V1I64",
758 ["VI128*"]= "T_V2I64", ["VI256*"]= "T_V4I64", ["VI512*"]= "T_V8I64",
759 ["V2F32*"]= "T_V2F32", ["V4F32*"]= "T_V4F32", ["V2F64*"]= "T_V2F64",
760 ["V8F32*"]= "T_V8F32", ["V4F64*"]= "T_V4F64",
761 ["V16F32*"]= "T_V16F32", ["V8F64*"]= "T_V8F64",
762 ["f32*"]= "T_F32", ["f64*"]= "T_F64", ["V1F64*"]= "T_F64",
764 --local data = {ops=ops,type2type=type2type,ptr2type=ptr2type,opclasses=opclasses}
765 local data = {ops=ops,opclasses=opclasses}
766 -- lib for creating/loading/storing/changing memory blocks
768 ---------------------------------------------
769 local function _scandump(x, m)
770 if _type(x) == "table" then
771 if not m[x] then m[#m + 1] = x; m[x] = {0, "l["..#m.."]"}; end
772 m[x][1] = m[x][1] + 1
773 if (m[x][1] > 1) then return m end
774 for k,v in _pairs(x) do
775 _scandump(k, m)
776 _scandump(v, m)
779 return m
781 local function _write_value(f,x,m)
782 if _type(x)=="string" then
783 f:write(_fmt("%q",x))
784 return
786 if _type(x)=="table" then
787 f:write(m[x] and m[x][2] or "$ERROR")
788 return
790 f:write(tostring(x))
792 local function _write_index(f,x,m)
793 if type(x)=="string" and _match(x, "^[%a_][%w_]*$") then
794 f:write(".")
795 f:write(x)
796 return
798 f:write("[")
799 _write_value(f,x,m)
800 f:write("]")
802 local function writedump(f,x)
803 if _type(x) ~= "table" then
804 f:write("return ")
805 _write_value(f,x)
806 f:write("\n")
807 return
809 local m = _scandump(x, {})
810 local i = 0
811 -- create refs for all tables
812 f:write("local l = {}; for i = 1, "..#m.." do l[i] = {} end\n")
813 -- fill fields
814 for k,v in _ipairs(m) do
815 f:write("do local k = "..m[v][2].."\n")
816 for kk,vv in _pairs(v) do
817 -- f:write(m[v][2])
818 f:write("k")
819 _write_index(f,kk,m)
820 f:write(" = ")
821 _write_value(f,vv,m)
822 f:write("\n")
824 f:write("end\n")
826 f:write("return "..m[x][2].."\n")
829 local f = io.open(outname, "w")
830 writedump(f, data)
831 f:close()