Changed current relation from BasicBlock to BasicBlockImpl, and Function
[jitcs.git] / tools / x86_inslist2data.lua
blob13bdaa2fbee9c7c04013f1272d103c7359854baf
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"] = {},
264 ["66f2"] = {}, -- only for crc32_16
266 local function _parsePref(op, data)
267 _opassert(not op.pref, op, "double prefix declaration")
268 if data == "" then op.pref = ""; return end
269 local p = _match(data, "^([%w_]+)$")
270 _opassert(p and _prefset[p], op, "invalid prefix %s", _tostr(p))
271 op.pref = p
273 --------------------------------------
274 local _extopcodeset= {
275 ["0f"] = {},
276 ["0f38"] = {},
277 ["0f3a"] = {},
279 local function _parseExtOpcode(op, data)
280 _opassert(not op.extopcode, op, "double extended opcode declaration")
281 if data == "" then op.extopcode = ""; return end
282 local p = _match(data, "^([%w_]+)$")
283 _opassert(p and _extopcodeset[p], op, "invalid extended opcode %s", _tostr(p))
284 op.extopcode = p
286 --------------------------------------
287 local function _parseCoding(op, data)
288 _opassert(not op.code, op, "double coding declaration")
289 local result= {}
290 for c in _gmatch(data, "%S+") do
291 local cnt = {}
292 _gsub(c, "[%(%)]", function (m) cnt[m] = (cnt[m] or 0) + 1 end)
293 _opassert(cnt["("] == cnt[")"], op, "unbalanced parenthesis in coding")
295 c = _gsub(c, "!par%((%w+)%)", function (p)
296 _opassert(not op.parm, op, "double !par declaration")
297 _opassert(_tonum(p), op, "invalid !par value")
298 op.parm = _tonum(p)
299 return "$parm"
300 end)
301 c = _gsub(c, "!sub%((%w+)%)", function (p)
302 _opassert(not op.sub, op, "double !sub declaration")
303 _opassert(_tonum(p), op, "invalid !sub value")
304 op.sub = _tonum(p)
305 return "$sub"
306 end)
307 c = _gsub(c, "!parsub%((%w+)%)", function (p)
308 _opassert(not op.par, op, "double !par declaration")
309 _opassert(not op.sub, op, "double !sub declaration")
310 _opassert(_tonum(p), op, "invalid !parsub value")
311 op.parm = _tonum(p)
312 op.sub = op.parm % 32
313 op.parm = op.parm - op.sub
314 return "$parm+$sub"
315 end)
316 result[ #result+1 ]= c
318 op.code = result
320 --------------------------------------
321 local function _parseLEAREX(op, data)
322 _opassert(not op.rex, op, "double rex/vex declaration in op "..op.name)
323 local w, reg, base, index = matchWords(data,4)
324 _opassert(reg, op, "invalid rexlea parameters")
325 _opassert(w == "0" or w == "1", op, "invalid rex w field")
326 op.rex = {mode = "lea", reg = reg, rmb = base, rmi = index, r64 = w}
328 local function _parseREX(op, data)
329 _opassert(not op.rex, op, "double rex/vex declaration in op "..op.name)
330 local rm, w, rmr, rmm = matchWords(data,4)
331 _opassert(rm, op, "invalid rex parameters")
332 _opassert(rm == "rr" or rm == "rm", op, "invalid rex rm field")
333 _opassert(w == "0" or w == "1", op, "invalid rex w field")
334 op.rex = {mode = rm, reg = rmr, rm = rmm, r64 = w}
336 local function _parseVEX(op, data)
337 _opassert(not op.rex, op, "double rex/vex declaration")
338 local rm, w, src1, rmr, rmm, l = matchWords(data,6)
339 _opassert(rm, op, "invalid rex parameters")
340 _opassert(rm == "rr" or rm == "rm", op, "invalid vex rm field")
341 _opassert(w == "0" or w == "1", op, "invalid vex w field")
342 _opassert(l == "0" or l == "1", op, "invalid vex l field")
343 op.rex = {vex = true, mode = rm, reg = rmr, rm = rmm, r64 = w, l = l, src1 = src1}
345 local function _parseEVEX(op, data)
346 _opassert(not op.rex, op, "double rex/vex declaration in op "..op.name)
347 local rm, w, src1, rmr, rmm, l, k, z, b = matchWords(data,9)
348 _opassert(rm, op, "invalid rex parameters")
349 _opassert(rm == "rr" or rm == "rm", op, "invalid evex rm field")
350 _opassert(w == "0" or w == "1", op, "invalid evex w field")
351 _opassert(l == "0" or l == "1" or l == "2" or l == "3", op, "invalid evex l field")
352 _opassert(z == "0" or z == "1", op, "invalid evex z field")
353 _opassert(b == "0" or b == "1", op, "invalid evex b field")
354 op.rex = {evex = true, mode = rm, reg = rmr, rm = rmm, r64 = w, l = l, src1 = src1,
355 k = k, z = z, b = b}
357 local function _parseFold(op, data)
359 local function _parseCommute(op, data)
362 --------------------------------------
364 local function _getValidVarSet( op )
365 --print( op.name )
366 local vars={ parm="i8", sub="i8" }
367 for _,v in _ipairs(op.operands) do vars[v.name]= v.type end
368 return vars
371 local function _ptrtype(s)
372 return s and _sub(s,-1,-1)=="*"
374 local function _immtype(s)
375 return s and _sub(s,1,1)=="i" and not _ptrtype(s)
377 local function _regtype(s)
378 return s and not _ptrtype(s) and not _immtype(s)
381 local function _checkOp( op )
382 local vars= _getValidVarSet(op)
384 local memops = 0
385 for _,v in _ipairs(op.operands) do
386 if _ptrtype(v.type) then
387 _opassert(v.mode == "i", op, "memory operands are input only")
388 _opassert(memops == 0, op, "only one memory operand allowed")
389 memops = memops + 1
393 for _,v in _ipairs(op.code) do
394 for vv in _gmatch(v, "%$(%a%w*)") do
395 _opassert(vars[vv], op, "invalid variable %s", vv)
398 local p1,p2,p3,p4,p5= matchID(v,"!RRMLEA%( ($OP) , ($OP) , ($OP) , ($OP) , ($OP) %)")
399 if p1 then
400 _opassert(op.rex.mode=="lea", op, "RRM?-rex mode mismatch" )
401 _opassert(not op.rex.vex and not op.rex.evex, op, "RRMLEA and vex don't mix" )
402 _opassert(_sub(p1,1,1)=="$" and vars[_sub(p1,2)], op, ": RRMLEA-reg error" )
403 _opassert(_sub(p1,2)==op.rex.reg, op, "RRMLEA-rex reg mismatch" )
404 _opassert(_sub(p2,1,1)=="$" and vars[_sub(p2,2)], op, "RRMLEA-rm base error" )
405 _opassert(_sub(p2,2)==op.rex.rmb, op, "RRMLEA-rex rm base mismatch" )
406 _opassert(_sub(p3,1,1)=="$" and vars[_sub(p3,2)], op, "RRMLEA-rm index error" )
407 _opassert(_sub(p3,2)==op.rex.rmi, op, "RRMLEA-rex rm index mismatch" )
410 p1,p2,p3= matchID(v, "!RRMMVSIB([RM])%( ($OP) , ($OP) , ($OP) %)")
411 if p1 then
412 _opassert(op.rex.mode=="rm", op, "RRMMVSIB-rex mode mismatch" )
413 _opassert(op.rex.vex or op.rex.evex, op, "RRMMVSIB requires vex" )
414 _opassert(_sub(p1,1,1)=="$" and vars[_sub(p1,2)], op, ": RRMMVSIB-reg error" )
415 _opassert(_sub(p1,2)==op.rex.reg, op, "RRMMVSIB-rex reg mismatch" )
416 _opassert(_sub(p2,1,1)=="$" and vars[_sub(p2,2)], op, "RRMMVSIB-rm base error" )
417 _opassert(_sub(p2,2)==op.rex.rm, op, "RRMMVSIB-rex rm base mismatch" )
418 _opassert(_sub(p3,1,1)=="$" and vars[_sub(p3,2)], op, "RRMMVSIB-vsib index error" )
420 local x
421 x,p1,p2= matchID(v, "!RRM([RM])%( ($OP) , ($OP) %)")
422 if x then
423 local rm = "r".._lower(x)
424 _opassert(op.rex.mode == rm, op, "RRM%s-rex mode mismatch", x)
425 if _tonum(p1) then
426 _opassert( op.rex.reg==p1, op, "RRM%s-rex reg(#) mismatch", x)
427 elseif p1=="$parm" then
428 _opassert( op.parm>=0 and op.parm<8 and op.rex.reg=="0", op, "RRM%s-rex reg(parm) mismatch", x)
429 elseif p1=="$sub" then
430 local sub= op.sub or 0
431 _opassert( sub>=0 and sub<8 and op.rex.reg=="0", op, "RRM%s-rex reg(parm) mismatch", x)
432 else
433 _opassert(_sub(p1,1,1)=="$" and vars[_sub(p1,2)], op, "RRM%s-reg error", x)
434 _opassert(_sub(p1,2)==op.rex.reg, op, "RRM%s-rex reg mismatch", x)
436 if _tonum(p2) then
437 _opassert((op.rex.rm or "0") == "0", op, "RRM%s-rex rm mismatch", x)
438 else
439 _opassert(_sub(p2,1,1)=="$" and vars[_sub(p2,2)], op, "RRM%s-rm error", x)
440 _opassert(_sub(p2,2)==op.rex.rm, op, "RRM%s-rex rm mismatch", x)
444 _opassert( op.rex.reg=="0" or _regtype(vars[op.rex.reg]), op, "rex-reg error" )
445 if op.rex.mode=="rr" then
446 _opassert( op.rex.rm=="0" or _regtype(vars[op.rex.rm]), op, "rex-rmr error" )
447 elseif op.rex.mode=="rm" then
448 _opassert( op.rex.mode=="rm" and _ptrtype(vars[op.rex.rm]), op, "rex-rmm error" )
452 local function _createLayout(op)
453 local layout, renametab, pnum = {}, {}, nil
454 local indices = {}
455 --print(op.name, dump(op.rex))
456 local function renameVar(v)
457 local res = renametab[v]
458 if not res then
459 pnum = (pnum or 0) + 1
460 res = {"p".._tostr(pnum), pnum}
461 renametab[v] = res
463 return res[1]
465 local function add2layout(v, defuse)
466 if v.fixed then return end
467 local n = renameVar(v.name)
468 if indices[v.name] then return end
469 local mode, lp3
470 if _ptrtype(v.type) then
471 mode = "MemId"
472 elseif _immtype(v.type) then
473 mode, lp3 = "Imm", 0
474 elseif v.type == "BB" then
475 mode = "BBId"
476 else
477 mode, lp3 = "RegId", nil
478 if v.type == "GR8" then lp3 = "GR8" end
479 --if v.type == "GR16" or v.type == "GR32" or v.type == "GR64" or v.type == "GR" then lp3 = "GR" end
480 --if v.type == "VR128" or v.type == "VR256" or v.type == "VR512" then lp3 = "VR" end
482 layout[#layout + 1] = {mode, defuse, n, lp3};
483 indices[v.name] = #layout
484 if v.type == "i64" then
485 layout[#layout + 1] = {"Imm", "use", n, 32}
489 -- make sure, memory operands are the first parameter
490 -- this preferred order should simplify the code generator a bit
491 for _,v in _ipairs(op.operands) do
492 if _ptrtype(v.type) then add2layout(v, "use") end
494 local orderedlayout = {}
495 if op.rex.rm and not _tonum(op.rex.rm) then orderedlayout[#orderedlayout+1] = op.rex.rm end
496 if op.rex.reg and not _tonum(op.rex.reg) then orderedlayout[#orderedlayout+1] = op.rex.reg end
497 if op.rex.src1 and not _tonum(op.rex.src1) then orderedlayout[#orderedlayout+1] = op.rex.src1 end
498 if op.rex.msk and not _tonum(op.rex.msk) then orderedlayout[#orderedlayout+1] = op.rex.msk end
499 local t = {i = "use", o = "def", io = "use/def"}
500 for _1,v1 in _ipairs(orderedlayout) do
501 for _,v in _ipairs(op.operands) do
502 if v.name == v1 then
503 add2layout(v, t[v.mode])
508 for _,v in _ipairs(op.operands) do
509 add2layout(v, t[v.mode])
511 for _,v in _ipairs(op.operands) do
512 if v.fixed then
513 local n = renameVar(v.name)
516 op.layout = unify("layout", layout)
517 op.rename2layout = renametab
520 local function _renameFromLayout(op)
521 op.orgnames = {}
522 for i,v in _ipairs(op.operands) do
523 op.orgnames[i] = v.name
524 v.name = op.rename2layout[v.name][1]
526 for _,v in _ipairs{"reg", "rm", "src1", "msk", "rmb", "rmi"} do
527 if op.rex[v] and op.rename2layout[op.rex[v]] then
528 op.rex[v] = op.rename2layout[op.rex[v]][1]
531 for i,v in _ipairs(op.code) do
532 op.code[i] = _gsub(v, "%$(%a%w*)", function (vv)
533 if op.rename2layout[vv] then return "$"..op.rename2layout[vv][1] end
534 end)
537 op.operands = unify("operands", op.operands)
538 op.orgnames = unify("orgnames", op.orgnames)
539 op.rex = unify("rex", op.rex)
540 op.code = unify("code", op.code)
541 op.rename2layout = nil
543 local function _createImpRegs(op)
544 local regs = {}
545 local t = {i = "use", o = "def", io = "use/def"}
546 for _,v in _ipairs(op.operands) do
547 if not _ptrtype(v.type) and not _immtype(v.type) and not (v.type == "BB") then
548 if v.fixed then
549 regs[#regs + 1] = {v.fixed, t[v.mode]}
552 end
553 -- flag comes last
554 local flagin, flagout = false, false
555 for _,v in _ipairs(op.flags) do
556 flagin = flagin or _flagset[v].flagin
557 flagout = flagout or _flagset[v].flagout
559 if flagin or flagout then
560 regs[#regs + 1] = {"FLAGS", flagout and (flagin and "use/def" or "def") or "use"}
562 op.impregs = unify("impregs", regs)
564 function _getPrefixSig(op)
565 local r, pending = ""
566 if op.rex.vex then
567 r = "vex"
568 if op.pref ~= "" then r = r .. "-" .. op.pref end
569 if op.extopcode ~= "" then r = r .. "-" .. op.extopcode end
570 r = r .. "-"
571 if tonumber(op.rex.l) > 0 then r = r .. (128 * _pow(2,tonumber(op.rex.l))) .. "." end
572 if tonumber(op.rex.r64) > 0 then r = r .. "W" end
573 if not tonumber(op.rex.reg) then r = r .. "R".._gsub(op.rex.reg,"p","") end
574 if not tonumber(op.rex.rm) then
575 r = r .. (op.rex.mode == "rr" and "B" or "M").._gsub(op.rex.rm,"p","")
577 if not tonumber(op.rex.src1) then r = r .. "S".._gsub(op.rex.src1,"p","") end
578 else
579 if op.pref ~= "" then r = r .. op.pref; pending = "-" end
580 if op.rex.mode == "lea" then
581 if pending then r = r .. pending; pending = nil end;
582 r = r .. "lea"
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.rmb) then r = r .. "B".._gsub(op.rex.rmb,"p","") end
586 if not tonumber(op.rex.rmi) then r = r .. "I".._gsub(op.rex.rmi,"p","") end
587 pending = "-"
588 elseif tonumber(op.rex.r64) or not tonumber(op.rex.reg) or not tonumber(op.rex.rm) then
589 if pending then r = r .. pending; pending = nil end;
590 r = r .. "rex"
591 if tonumber(op.rex.r64) > 0 then r = r .. "W" end
592 if not tonumber(op.rex.reg) then r = r .. "R".._gsub(op.rex.reg,"p","") end
593 if not tonumber(op.rex.rm) then
594 r = r .. (op.rex.mode == "rr" and "B" or "M").._gsub(op.rex.rm,"p","")
596 pending = "-"
598 if op.extopcode ~= "" then
599 if pending then r = r .. pending; pending = nil end;
600 r = r .. op.extopcode
602 if r == "" then r = "none" end
604 return r
606 function _getPrefixClass(op)
607 local pcl = {pref = op.pref, rex = op.rex, extopcode = op.extopcode}
608 pcl = unify("prefixclass", pcl, _getPrefixSig)
609 -- print(dump(pcl))
610 op.prefixclass = pcl
611 op.pref = nil
612 op.rex = nil
613 op.extopcode = nil
616 function _getOpClassSig(op)
617 return op.isa.sig .. "|" .. op.layout.sig .. "|" .. op.impregs.sig
618 .. "|" .. op.prefixclass.sig .. "|" .. op.code.sig
619 .. "|" .. _fmt("PAR%2X",op.parm or 0)
620 .. "|" .. op.flags.sig
622 function _getOpClass(op)
623 local cl = {isa = op.isa, layout = op.layout, impregs = op.impregs,
624 prefixclass = op.prefixclass, code = op.code, parm = op.parm, flags = op.flags}
625 cl = unify("opclass", cl, _getOpClassSig)
626 -- print(dump(pcl))
627 op.opclass = cl
628 op.isa = nil
629 op.layout = nil
630 op.impregs = nil
631 op.prefixclass = nil
632 op.code = nil
633 op.parm = nil
634 op.flags = nil
637 --------------------------------------
638 --KORW_KKK
639 -- {isa avx512f; ops KR dst/o, KR src1/i, KR src/i;
640 -- pref ; %(VEXDS({"avx",256,"rr"},"S")); extopcode 0f; coding !parsub(0x45) !RRMR($dst,$src)}
641 --------------------------------------
643 local _parsePart = {
644 isa = _parseISA,
645 ops = _parseOps,
646 flags = _parseFlags,
647 pref = _parsePref,
648 extopcode = _parseExtOpcode,
649 coding = _parseCoding,
650 rex = _parseREX,
651 learex = _parseLEAREX,
652 rexlea = _parseLEAREX,
653 vex = _parseVEX,
654 evex = _parseEVEX,
655 fold = _parseFold,
656 commute = _parseCommute,
659 local function parseLine(name, defs)
660 local op= { name = name }
661 for part,info in _gmatch(defs,"%s*(%w+)%s+([^;]*);?") do
662 info = _match(info, "^%s*(.-)%s*$")
663 _assert(_parsePart[part], "invalid option "..part.." in opcode "..name)
664 _parsePart[part](op, info)
666 if not op.isa then op.isa = unify("isa", {}) end
667 if not op.operands then op.operands = {} end
668 if not op.flags then op.flags = unify("flags", {}) end
669 if not op.pref then op.pref = "" end
670 if not op.rex then op.rex = {mode = "rr", reg = "0", rm = "0", r64 = "0"} end
671 if not op.extopcode then op.extopcode = "" end
672 if not op.code then op.code = {} end
673 if op.pref == "66f2" then _assert(not op.rex.vex and not op.rex.evex) end
674 --print(1, dump(op))
675 _checkOp(op)
676 _createLayout(op)
677 _renameFromLayout(op)
678 _createImpRegs(op)
679 _getPrefixClass(op)
680 _getOpClass(op)
681 return op
684 -----------------------------------------------------------------
686 -----------------------------------------------------------------
687 --local mode,file= ...
689 local ops,opset= {},{}
690 local opclasses = {}
692 -----------------------------------------------------------------
693 -- output functions
694 -----------------------------------------------------------------
695 inslist= _gsub(inslist, "(//[^\r\n]*)([\r\n])","%2")
696 inslist= _gsub(inslist, "(/%*.-%*/)","" )
698 local prevopname
699 for opname, def in _gmatch(inslist, "%s*([%w_]+)%s*(%b{})") do
700 def = _sub(_gsub(def,"[\r\n]"," "),2,-2)
701 _assert( not opset[opname],"double definition of "..opname )
702 local ok, op = pcall(parseLine,opname, def)
703 if (ok) then
704 prevopname = opname
705 if not op then print("error in parseLine: ", opname, prevopname) end
706 ops[ #ops+1 ]= op
707 opset[op.name]= op
708 --print(_dump(op))
709 else
710 print(op)
713 for k,v in _pairs(cache.opclass) do
714 opclasses[#opclasses + 1] = v
716 -- before avx2: 120 prefix (prefix + rex + extopcode/vex) classes, 60 coding classes
717 -- total: isa 39, rex 37, code 73, defuse 42, flags 61, layout 96, operands 321, orgnames 40
718 -- bits: isa 6, rex 6, code 7, defuse 6, flags 7, layout 7 -> sum 39 bits
719 -- class: to check if op is available): isa + 1 bit per opcodesubmask checking
720 -- prefix encoding: pref + rex + extopcode
721 -- main encoding: code
722 -- data flow: defuse + ???
723 -- register class is setup at construction time (of the vregs), and as such, not
724 -- relevant for def use. instruction constructors do the type checking for us.
725 -- allocation and data flow is done for virtual and fixed regs.so we have fixed registers to worry about,
727 --local
729 local function opclassid(op)
730 if op.flags.rmem then r = r .. "R" end
731 if op.flags.wmem then r = r .. "W" end
732 if op.flags.usemem then r = r .. "U" end
733 return r
734 -- if cl.subs[op.sub or 0] then
735 -- print("class "..(op.class or op.name).." contains the sub "..(op.sub or 0).." multiple times")
738 local function _compareISA(a, b)
739 if a == b then return false end
740 if (a.x64 or false) ~= (b.x64 or false) then return b.x64 end
741 if (a.x32only or false) ~= (b.x32only or false) then return b.x32only end
742 if a.sig ~= b.sig then return a.sig < b.sig end
743 _assert("comparing ISA failed")
745 _sort(opclasses,function(a,b)
746 if a.isa ~= b.isa then return _compareISA(a.isa, b.isa) end
747 return a.sig < b.sig
748 end)
749 for i,v in _ipairs(opclasses) do v.id = i end
751 _sort(ops,function(a,b)
752 if a.opclass.isa ~= b.opclass.isa then return _compareISA(a.opclass.isa, b.opclass.isa) end
753 return a.name < b.name
754 end)
756 -----------------------------------------
757 -- selector
758 -----------------------------------------
759 local type2type={
760 GR8="T_I8", GR16= "T_I16", GR32= "T_I32", GR64= "T_I64",
761 VRI64="T_V1I64", VRI128="T_V2I64", VRI256="T_V4I64", VRI128Z="T_V2I64", VRI512="T_V8I64",
762 VR4F32="T_V4F32", VR2F64= "T_V2F64", VR8F32="T_V8F32", VR4F64= "T_V4F64",
763 VR4F32Z="T_V4F32", VR2F64Z= "T_V2F64", VR16F32="T_V16F32", VR8F64 = "T_V8F64",
764 BB="T_BBLOCK",
765 i8="T_I8", i16= "T_I16", i32= "T_I32", i64= "T_I64",
767 local ptr2type={
768 ["i8*"]= "T_I8", ["i16*"]= "T_I16", ["i32*"]= "T_I32", ["i64*"]= "T_I64",
769 ["VI16*"]= "T_I16", ["VI32*"]= "T_I32", ["VI64*"]= "T_V1I64",
770 ["VI128*"]= "T_V2I64", ["VI256*"]= "T_V4I64", ["VI512*"]= "T_V8I64",
771 ["V2F32*"]= "T_V2F32", ["V4F32*"]= "T_V4F32", ["V2F64*"]= "T_V2F64",
772 ["V8F32*"]= "T_V8F32", ["V4F64*"]= "T_V4F64",
773 ["V16F32*"]= "T_V16F32", ["V8F64*"]= "T_V8F64",
774 ["f32*"]= "T_F32", ["f64*"]= "T_F64", ["V1F64*"]= "T_F64",
776 --local data = {ops=ops,type2type=type2type,ptr2type=ptr2type,opclasses=opclasses}
777 local data = {ops=ops,opclasses=opclasses}
778 -- lib for creating/loading/storing/changing memory blocks
780 ---------------------------------------------
781 local function _scandump(x, m)
782 if _type(x) == "table" then
783 if not m[x] then m[#m + 1] = x; m[x] = {0, "l["..#m.."]"}; end
784 m[x][1] = m[x][1] + 1
785 if (m[x][1] > 1) then return m end
786 for k,v in _pairs(x) do
787 _scandump(k, m)
788 _scandump(v, m)
791 return m
793 local function _write_value(f,x,m)
794 if _type(x)=="string" then
795 f:write(_fmt("%q",x))
796 return
798 if _type(x)=="table" then
799 f:write(m[x] and m[x][2] or "$ERROR")
800 return
802 f:write(tostring(x))
804 local function _write_index(f,x,m)
805 if type(x)=="string" and _match(x, "^[%a_][%w_]*$") then
806 f:write(".")
807 f:write(x)
808 return
810 f:write("[")
811 _write_value(f,x,m)
812 f:write("]")
814 local function writedump(f,x)
815 if _type(x) ~= "table" then
816 f:write("return ")
817 _write_value(f,x)
818 f:write("\n")
819 return
821 local m = _scandump(x, {})
822 local i = 0
823 -- create refs for all tables
824 f:write("local l = {}; for i = 1, "..#m.." do l[i] = {} end\n")
825 -- fill fields
826 for k,v in _ipairs(m) do
827 f:write("do local k = "..m[v][2].."\n")
828 for kk,vv in _pairs(v) do
829 -- f:write(m[v][2])
830 f:write("k")
831 _write_index(f,kk,m)
832 f:write(" = ")
833 _write_value(f,vv,m)
834 f:write("\n")
836 f:write("end\n")
838 f:write("return "..m[x][2].."\n")
841 local f = io.open(outname, "w")
842 writedump(f, data)
843 f:close()