Initial commit
[jitcs.git] / tools / x86_inslist2data.lua
blob4d0ae4382a9ef5c6594f67071dffdb69c15bd173
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)
42 local ctnt = f:read("*a")
43 f:close()
44 return ctnt
45 end
47 local testname, outname = ...
48 if (testname == nil or testname == "") then
49 testname = "..\\src-lib\\x86\\src\\_x86_inslist.ltxt"
50 end
51 if outname == nil or outname == "" then
52 outname = _match(testname, "^(.-)%.[^.\\/]*$") .. ".dat"
53 end
55 local emblua = _loadstr(readfile("emblua.lua"))
56 local inslist = emblua(testname,{type="string"})
57 --local inslist = readfile("..\\evm\\x86\\src\\_x86_inslist.txt")
58 -----------------------------------------------------------------
60 -----------------------------------------------------------------
62 local _cacheMatchWords = {}
63 local function matchWords(w, n)
64 local v = _cacheMatchWords[n]
65 if not v then
66 v = "^%s*"
67 for i = 1, n do v = v .. "(%w+)%s*" end
68 v = v .. "$"
69 _cacheMatchWords[n] = v
70 end
71 return _match(w, v)
72 end
73 local _cacheMatchID = {}
74 local function matchID(w, n)
75 local v = _cacheMatchID[n]
76 if not v then
77 v = _gsub(n, "$ID", "%%a[%%w_]*")
78 v = _gsub(v, "$NUM", "%%d+")
79 v = _gsub(v, "$OP", "[^,]-")
80 v = _gsub(v, " ", "%%s*")
81 v = "^%s*" .. v .. "%s*$"
82 _cacheMatchID[n] = v
83 end
84 return _match(w, v)
85 end
88 -----------------------------------------------------------------
90 -----------------------------------------------------------------
93 -----------------------------------------------------------------
95 -----------------------------------------------------------------
97 local cache, cachecount = {}, {}
98 local function unify(section, t, pred)
99 local subcache = cache[section]
100 if not subcache then subcache = {}; cache[section] = subcache end
101 local sig = (pred or _dump)(t, true)
102 local data = subcache[sig]
103 if not data then
104 local id = (cachecount[section] or 0) + 1
105 data = t; data.id = id; data.sig = sig; subcache[sig] = data; cachecount[section] = id end
106 return data
108 local function _opassert(cond, op, msg, ...)
109 if cond then return end
110 assert(false, _fmt("op %s: "..msg, op.name, ...))
112 --------------------------------------
113 local _isetset= {
114 def = {},
115 cmov = {},
116 mmx = {},
117 mmxext = {"mmx"},
118 sse = {},
119 sse2 = {"sse", "mmxext"},
120 sse3 = {"sse2"},
121 ssse3 = {"sse3"},
122 sse41 = {"ssse3"},
123 sse42 = {"sse41"},
124 avx = {"sse42"},
125 avx2 = {"avx"},
126 fma3 = {"avx"},
127 aes = {"sse2"},
128 clmul = {"sse2"},
129 hle = {},
130 rtm = {},
131 bmi1 = {"avx"},
132 bmi2 = {"avx"},
133 movbe = {},
134 lzcnt = {},
135 popcnt = {},
136 rdrand = {},
137 clflush = {},
138 rdtsc = {},
139 rdtscp = {},
140 f16c = {"avx"},
141 x32only = {},
142 x64 = {"sse2","cmov"},
143 x64only = {"x64"},
144 avx512f = {"avx2","f16c","fma3"}}
145 local function _simplifyISA(t, v)
146 --if not _isetset[v] then return end
147 for k,vv in _ipairs(_isetset[v]) do
148 t[vv] = true
149 _simplifyISA(t, vv)
153 local function _parseISA(op, data)
154 _opassert(not op.isa, op, "double ISA declaration")
155 local iset = {}
156 for i in _gmatch(data,"[%w_]+") do
157 _opassert(_isetset[i], op, "invalid isa %s", i)
158 if i == "x64only" then i = "x64" end
159 iset[i] = true
160 _simplifyISA(iset, i)
162 local dep = {}
163 for k,v in _pairs(iset) do
164 _simplifyISA(dep, k)
166 local iset2 = {}
167 for k,v in _pairs(iset) do if not dep[k] then iset2[#iset2 + 1] = k end end
168 _sort(iset2)
169 op.isa = unify("isa", iset2)
170 if iset.x64 then op.isa.x64 = true end
171 if iset.x32only then op.isa.x32only = true end
173 --------------------------------------
174 local function list2set( list )
175 local set= {}
176 for k,v in _ipairs(list) do set[v]= k end
177 return set
179 local _typeset= list2set{"GR8","GR16","GR32","GR64","VR128","VR256","VR512","KR",
180 "i8","i16","i32","i64",
181 "i8*","i16*","i32*","i64*","i128*","i256*","i512*",
182 "BB"}
183 local _fixedregs = {
184 al = "rax", ah = "rax", ax = "rax", eax = "rax", rax = "rax",
185 cl = "rcx", ecx = "rcx", rcx = "rcx",
186 dx = "rdx", edx = "rdx", rdx = "rdx",
187 ebx = "rbx", rbx = "rbx",
188 edi = "rdi", rdi = "rdi",
189 esp = "rsp",
190 xmm0 = "xmm0",
192 local function _parseOps(op, data)
193 _opassert(not op.ops, op, "double operands declaration")
194 local varlist, varset = {}, {}
195 for p in _gmatch(data, "[^,]+") do
196 p = _trim(p)
197 if p ~= "" then
198 local tp, fixedreg, vname, mode = matchID(p, "($ID%*?) { ($ID) } ($ID)/($ID)" )
199 if not tp then
200 tp,vname,mode= matchID(p, "($ID%*?) ($ID)/($ID)")
201 fixedreg= nil
203 fixedreg = fixedreg and _lower(fixedreg)
204 _opassert(tp and vname, op, "invalid operand \"%s\"", p)
205 _opassert(_typeset[tp], op, "invalid type %s", tp)
206 _opassert(not varset[vname], op, "double declaration of operand %s", vname)
207 _opassert(mode == "i" or mode == "o" or mode == "io",
208 op, "operand %s uses invalid mode %s", vname, mode)
209 varset[vname]= true
210 if (tp == "GR8" or tp == "GR16") and mode == "o" then mode = "io" end
211 local skip = false
212 if fixedreg then
213 _opassert(_fixedregs[fixedreg], op, "unsupported fixed reg %s", fixedreg)
214 fixedreg = _fixedregs[fixedreg]
215 for i,v in _ipairs(varlist) do
216 if v.fixed == fixedreg then
217 local mi = _match(v.mode, "i") or _match(mode, "i")
218 local mo = _match(v.mode, "o") or _match(mode, "o")
219 v.mode = (mi and "i" or "")..(mo and "o" or "")
220 skip = true
221 break
225 if not skip then
226 varlist[ #varlist+1 ]= {name=vname,type=tp,fixed=fixedreg,mode=mode}
230 op.operands = varlist
232 --------------------------------------
233 local _flagset= {
234 rflags = {flagin = true}, rflag_c = {flagin = true}, rflag_o = {flagin = true},
235 rflag_s = {flagin = true}, rflag_z = {flagin = true}, rflag_p = {flagin = true},
236 wflags = {flagout = true},
237 wflag_c = {flagin = true, flagout = true}, wflag_o = {flagin = true, flagout = true},
238 subflags = {flagin = true},
239 wmem = {}, rmem = {}, rwmem = {}, usemem = {}, amem = {}, umem = {},
240 cf_jmp = {}, cf_call = {}, cf_ret = {}, cf_fallthru = {},
241 vsib = {},
244 local function _parseFlags(op, data)
245 _opassert(not op.flags, op, "double flags declaration")
246 local fset = {}
247 for i in _gmatch(data,"[%w_]+") do
248 _opassert(_flagset[i], op, "invalid flag %s", i)
249 fset[i] = true
251 if fset.rwmem then fset.wmem = true; fset.rmem = true; fset.rwmem = false end
252 local fset2 = {}
253 for k,v in _pairs(fset) do fset2[#fset2 + 1] = k end
254 _sort(fset2)
255 op.flags = unify("flags", fset2)
257 --------------------------------------
258 local _prefset= {
259 ["66"] = {},
260 ["f2"] = {},
261 ["f3"] = {},
263 local function _parsePref(op, data)
264 _opassert(not op.pref, op, "double prefix declaration")
265 if data == "" then op.pref = ""; return end
266 local p = _match(data, "^([%w_]+)$")
267 _opassert(p and _prefset[p], op, "invalid prefix %s", _tostr(p))
268 op.pref = p
270 --------------------------------------
271 local _extopcodeset= {
272 ["0f"] = {},
273 ["0f38"] = {},
274 ["0f3a"] = {},
276 local function _parseExtOpcode(op, data)
277 _opassert(not op.extopcode, op, "double extended opcode declaration")
278 if data == "" then op.extopcode = ""; return end
279 local p = _match(data, "^([%w_]+)$")
280 _opassert(p and _extopcodeset[p], op, "invalid extended opcode %s", _tostr(p))
281 op.extopcode = p
283 --------------------------------------
284 local function _parseCoding(op, data)
285 _opassert(not op.code, op, "double coding declaration")
286 local result= {}
287 for c in _gmatch(data, "%S+") do
288 c = _gsub(c, "!par%((%w+)%)", function (p)
289 _opassert(not op.parm, op, "double !par declaration")
290 _opassert(_tonum(p), op, "invalid !par value")
291 op.parm = _tonum(p)
292 return "$parm"
293 end)
294 c = _gsub(c, "!sub%((%w+)%)", function (p)
295 _opassert(not op.sub, op, "double !sub declaration")
296 _opassert(_tonum(p), op, "invalid !sub value")
297 op.sub = _tonum(p)
298 return "$sub"
299 end)
300 c = _gsub(c, "!parsub%((%w+)%)", function (p)
301 _opassert(not op.par, op, "double !par declaration")
302 _opassert(not op.sub, op, "double !sub declaration")
303 _opassert(_tonum(p), op, "invalid !parsub value")
304 op.parm = _tonum(p)
305 op.sub = op.parm % 32
306 op.parm = op.parm - op.sub
307 return "$parm+$sub"
308 end)
309 result[ #result+1 ]= c
311 op.code = result
313 --------------------------------------
314 local function _parseLEAREX(op, data)
315 _opassert(not op.rex, op, "double rex/vex declaration in op "..op.name)
316 local w, reg, base, index = matchWords(data,4)
317 _opassert(reg, op, "invalid rexlea parameters")
318 _opassert(w == "0" or w == "1", op, "invalid rex w field")
319 op.rex = {mode = "lea", reg = reg, rmb = base, rmi = index, r64 = w}
321 local function _parseREX(op, data)
322 _opassert(not op.rex, op, "double rex/vex declaration in op "..op.name)
323 local rm, w, rmr, rmm = matchWords(data,4)
324 _opassert(rm, op, "invalid rex parameters")
325 _opassert(rm == "rr" or rm == "rm", op, "invalid rex rm field")
326 _opassert(w == "0" or w == "1", op, "invalid rex w field")
327 op.rex = {mode = rm, reg = rmr, rm = rmm, r64 = w}
329 local function _parseVEX(op, data)
330 _opassert(not op.rex, op, "double rex/vex declaration")
331 local rm, w, src1, rmr, rmm, l = matchWords(data,6)
332 _opassert(rm, op, "invalid rex parameters")
333 _opassert(rm == "rr" or rm == "rm", op, "invalid vex rm field")
334 _opassert(w == "0" or w == "1", op, "invalid vex w field")
335 _opassert(l == "0" or l == "1", op, "invalid vex l field")
336 op.rex = {vex = true, mode = rm, reg = rmr, rm = rmm, r64 = w, l = l, src1 = src1}
338 local function _parseEVEX(op, data)
339 _opassert(not op.rex, op, "double rex/vex declaration in op "..op.name)
340 local rm, w, src1, rmr, rmm, l, k, z, b = matchWords(data,9)
341 _opassert(rm, op, "invalid rex parameters")
342 _opassert(rm == "rr" or rm == "rm", op, "invalid evex rm field")
343 _opassert(w == "0" or w == "1", op, "invalid evex w field")
344 _opassert(l == "0" or l == "1" or l == "2" or l == "3", op, "invalid evex l field")
345 _opassert(z == "0" or z == "1", op, "invalid evex z field")
346 _opassert(b == "0" or b == "1", op, "invalid evex b field")
347 op.rex = {evex = true, mode = rm, reg = rmr, rm = rmm, r64 = w, l = l, src1 = src1,
348 k = k, z = z, b = b}
350 local function _parseFold(op, data)
352 local function _parseCommute(op, data)
355 --------------------------------------
357 local function _getValidVarSet( op )
358 --print( op.name )
359 local vars={ parm="i8", sub="i8" }
360 for _,v in _ipairs(op.operands) do vars[v.name]= v.type end
361 return vars
364 local function _ptrtype(s)
365 return s and _sub(s,-1,-1)=="*"
367 local function _immtype(s)
368 return s and _sub(s,1,1)=="i" and not _ptrtype(s)
370 local function _regtype(s)
371 return s and not _ptrtype(s) and not _immtype(s)
374 local function _checkOp( op )
375 local vars= _getValidVarSet(op)
377 local memops = 0
378 for _,v in _ipairs(op.operands) do
379 if _ptrtype(v.type) then
380 _opassert(v.mode == "i", op, "memory operands are input only")
381 _opassert(memops == 0, op, "only one memory operand allowed")
382 memops = memops + 1
386 for _,v in _ipairs(op.code) do
387 for vv in _gmatch(v, "%$(%a%w*)") do
388 _opassert(vars[vv], op, "invalid variable %s", vv)
391 local p1,p2,p3,p4,p5= matchID(v,"!RRMLEA%( ($OP) , ($OP) , ($OP) , ($OP) , ($OP) %)")
392 if p1 then
393 _opassert(op.rex.mode=="lea", op, "RRM?-rex mode mismatch" )
394 _opassert(not op.rex.vex and not op.rex.evex, op, "RRMLEA and vex don't mix" )
395 _opassert(_sub(p1,1,1)=="$" and vars[_sub(p1,2)], op, ": RRMLEA-reg error" )
396 _opassert(_sub(p1,2)==op.rex.reg, op, "RRMLEA-rex reg mismatch" )
397 _opassert(_sub(p2,1,1)=="$" and vars[_sub(p2,2)], op, "RRMLEA-rm base error" )
398 _opassert(_sub(p2,2)==op.rex.rmb, op, "RRMLEA-rex rm base mismatch" )
399 _opassert(_sub(p3,1,1)=="$" and vars[_sub(p3,2)], op, "RRMLEA-rm index error" )
400 _opassert(_sub(p3,2)==op.rex.rmi, op, "RRMLEA-rex rm index mismatch" )
403 p1,p2,p3= matchID(v, "!RRMMVSIB([RM])%( ($OP) , ($OP) , ($OP) %)")
404 if p1 then
405 _opassert(op.rex.mode=="rm", op, "RRMMVSIB-rex mode mismatch" )
406 _opassert(op.rex.vex or op.rex.evex, op, "RRMMVSIB requires vex" )
407 _opassert(_sub(p1,1,1)=="$" and vars[_sub(p1,2)], op, ": RRMMVSIB-reg error" )
408 _opassert(_sub(p1,2)==op.rex.reg, op, "RRMMVSIB-rex reg mismatch" )
409 _opassert(_sub(p2,1,1)=="$" and vars[_sub(p2,2)], op, "RRMMVSIB-rm base error" )
410 _opassert(_sub(p2,2)==op.rex.rm, op, "RRMMVSIB-rex rm base mismatch" )
411 _opassert(_sub(p3,1,1)=="$" and vars[_sub(p3,2)], op, "RRMMVSIB-vsib index error" )
413 local x
414 x,p1,p2= matchID(v, "!RRM([RM])%( ($OP) , ($OP) %)")
415 if x then
416 local rm = "r".._lower(x)
417 _opassert(op.rex.mode == rm, op, "RRM%s-rex mode mismatch", x)
418 if _tonum(p1) then
419 _opassert( op.rex.reg==p1, op, "RRM%s-rex reg(#) mismatch", x)
420 elseif p1=="$parm" then
421 _opassert( op.parm>=0 and op.parm<8 and op.rex.reg=="0", op, "RRM%s-rex reg(parm) mismatch", x)
422 elseif p1=="$sub" then
423 local sub= op.sub or 0
424 _opassert( sub>=0 and sub<8 and op.rex.reg=="0", op, "RRM%s-rex reg(parm) mismatch", x)
425 else
426 _opassert(_sub(p1,1,1)=="$" and vars[_sub(p1,2)], op, "RRM%s-reg error", x)
427 _opassert(_sub(p1,2)==op.rex.reg, op, "RRM%s-rex reg mismatch", x)
429 if _tonum(p2) then
430 _opassert((op.rex.rm or "0") == "0", op, "RRM%s-rex rm mismatch", x)
431 else
432 _opassert(_sub(p2,1,1)=="$" and vars[_sub(p2,2)], op, "RRM%s-rm error", x)
433 _opassert(_sub(p2,2)==op.rex.rm, op, "RRM%s-rex rm mismatch", x)
437 _opassert( op.rex.reg=="0" or _regtype(vars[op.rex.reg]), op, "rex-reg error" )
438 if op.rex.mode=="rr" then
439 _opassert( op.rex.rm=="0" or _regtype(vars[op.rex.rm]), op, "rex-rmr error" )
440 elseif op.rex.mode=="rm" then
441 _opassert( op.rex.mode=="rm" and _ptrtype(vars[op.rex.rm]), op, "rex-rmm error" )
445 local function _createLayout(op)
446 local layout, renametab, pnum = {}, {}, nil
447 local indices = {}
448 --print(op.name, dump(op.rex))
449 local function renameVar(v)
450 local res = renametab[v]
451 if not res then
452 pnum = (pnum or 0) + 1
453 res = {"p".._tostr(pnum), pnum}
454 renametab[v] = res
456 return res[1]
458 local function add2layout(v, defuse)
459 if v.fixed then return end
460 local n = renameVar(v.name)
461 if indices[v.name] then return end
462 local mode, lp3
463 if _ptrtype(v.type) then
464 mode = "MemId"
465 elseif _immtype(v.type) then
466 mode, lp3 = "Imm", 0
467 elseif v.type == "BB" then
468 mode = "BBId"
469 else
470 mode, lp3 = "RegId", v.fixed
472 layout[#layout + 1] = {mode, defuse, n, lp3};
473 indices[v.name] = #layout
474 if v.type == "i64" then
475 layout[#layout + 1] = {"Imm", "use", n, 32}
479 -- make sure, memory operands are the first parameter
480 -- this preferred order should simplify the code generator a bit
481 for _,v in _ipairs(op.operands) do
482 if _ptrtype(v.type) then add2layout(v, "use") end
484 local orderedlayout = {}
485 if op.rex.rm and not _tonum(op.rex.rm) then orderedlayout[#orderedlayout+1] = op.rex.rm end
486 if op.rex.reg and not _tonum(op.rex.reg) then orderedlayout[#orderedlayout+1] = op.rex.reg end
487 if op.rex.src1 and not _tonum(op.rex.src1) then orderedlayout[#orderedlayout+1] = op.rex.src1 end
488 if op.rex.msk and not _tonum(op.rex.msk) then orderedlayout[#orderedlayout+1] = op.rex.msk end
489 local t = {i = "use", o = "def", io = "use/def"}
490 for _1,v1 in _ipairs(orderedlayout) do
491 for _,v in _ipairs(op.operands) do
492 if v.name == v1 then
493 add2layout(v, t[v.mode])
498 for _,v in _ipairs(op.operands) do
499 add2layout(v, t[v.mode])
501 for _,v in _ipairs(op.operands) do
502 if v.fixed then
503 local n = renameVar(v.name)
506 op.layout = unify("layout", layout)
507 op.rename2layout = renametab
510 local function _renameFromLayout(op)
511 op.orgnames = {}
512 for i,v in _ipairs(op.operands) do
513 op.orgnames[i] = v.name
514 v.name = op.rename2layout[v.name][1]
516 for _,v in _ipairs{"reg", "rm", "src1", "msk", "rmb", "rmi"} do
517 if op.rex[v] and op.rename2layout[op.rex[v]] then
518 op.rex[v] = op.rename2layout[op.rex[v]][1]
521 for i,v in _ipairs(op.code) do
522 op.code[i] = _gsub(v, "%$(%a%w*)", function (vv)
523 if op.rename2layout[vv] then return "$"..op.rename2layout[vv][1] end
524 end)
527 op.operands = unify("operands", op.operands)
528 op.orgnames = unify("orgnames", op.orgnames)
529 op.rex = unify("rex", op.rex)
530 op.code = unify("code", op.code)
531 op.rename2layout = nil
533 local function _createImpRegs(op)
534 local regs = {}
535 local t = {i = "use", o = "def", io = "use/def"}
536 for _,v in _ipairs(op.operands) do
537 if not _ptrtype(v.type) and not _immtype(v.type) and not (v.type == "BB") then
538 if v.fixed then
539 regs[#regs + 1] = {v.fixed, t[v.mode]}
542 end
543 -- flag comes last
544 local flagin, flagout = false, false
545 for _,v in _ipairs(op.flags) do
546 flagin = flagin or _flagset[v].flagin
547 flagout = flagout or _flagset[v].flagout
549 if flagin or flagout then
550 regs[#regs + 1] = {"FLAGS", flagout and (flagin and "use/def" or "def") or "use"}
552 op.impregs = unify("impregs", regs)
554 function _getPrefixSig(op)
555 local r, pending = ""
556 if op.rex.vex then
557 r = "vex"
558 if op.pref ~= "" then r = r .. "-" .. op.pref end
559 if op.extopcode ~= "" then r = r .. "-" .. op.extopcode end
560 r = r .. "-"
561 if tonumber(op.rex.l) > 0 then r = r .. _pow(128,tonumber(op.rex.l)) .. "." end
562 if tonumber(op.rex.r64) > 0 then r = r .. "W" end
563 if not tonumber(op.rex.reg) then r = r .. "R".._gsub(op.rex.reg,"p","") end
564 if not tonumber(op.rex.rm) then
565 r = r .. (op.rex.mode == "rr" and "B" or "M").._gsub(op.rex.rm,"p","")
567 if not tonumber(op.rex.src1) then r = r .. "S".._gsub(op.rex.src1,"p","") end
568 else
569 if op.pref ~= "" then r = r .. op.pref; pending = "-" end
570 if op.rex.mode == "lea" then
571 if pending then r = r .. pending; pending = nil end;
572 r = r .. "lea"
573 if tonumber(op.rex.r64) > 0 then r = r .. "W" end
574 if not tonumber(op.rex.reg) then r = r .. "R".._gsub(op.rex.reg,"p","") end
575 if not tonumber(op.rex.rmb) then r = r .. "B".._gsub(op.rex.rmb,"p","") end
576 if not tonumber(op.rex.rmi) then r = r .. "I".._gsub(op.rex.rmi,"p","") end
577 pending = "-"
578 elseif tonumber(op.rex.r64) or not tonumber(op.rex.reg) or not tonumber(op.rex.rm) then
579 if pending then r = r .. pending; pending = nil end;
580 r = r .. "rex"
581 if tonumber(op.rex.r64) > 0 then r = r .. "W" end
582 if not tonumber(op.rex.reg) then r = r .. "R".._gsub(op.rex.reg,"p","") end
583 if not tonumber(op.rex.rm) then
584 r = r .. (op.rex.mode == "rr" and "B" or "M").._gsub(op.rex.rm,"p","")
586 pending = "-"
588 if op.extopcode ~= "" then
589 if pending then r = r .. pending; pending = nil end;
590 r = r .. op.extopcode
592 if r == "" then r = "none" end
594 return r
596 function _getPrefixClass(op)
597 local pcl = {pref = op.pref, rex = op.rex, extopcode = op.extopcode}
598 pcl = unify("prefixclass", pcl, _getPrefixSig)
599 -- print(dump(pcl))
600 op.prefixclass = pcl
601 op.pref = nil
602 op.rex = nil
603 op.extopcode = nil
606 function _getOpClassSig(op)
607 return op.isa.sig .. "|" .. op.layout.sig .. "|" .. op.impregs.sig
608 .. "|" .. op.prefixclass.sig .. "|" .. op.code.sig
609 .. "|" .. _fmt("PAR%2X",op.parm or 0)
610 .. "|" .. op.flags.sig
612 function _getOpClass(op)
613 local cl = {isa = op.isa, layout = op.layout, impregs = op.impregs,
614 prefixclass = op.prefixclass, code = op.code, parm = op.parm, flags = op.flags}
615 cl = unify("opclass", cl, _getOpClassSig)
616 -- print(dump(pcl))
617 op.opclass = cl
618 op.isa = nil
619 op.layout = nil
620 op.impregs = nil
621 op.prefixclass = nil
622 op.code = nil
623 op.parm = nil
624 op.flags = nil
627 --------------------------------------
628 --KORW_KKK
629 -- {isa avx512f; ops KR dst/o, KR src1/i, KR src/i;
630 -- pref ; %(VEXDS({"avx",256,"rr"},"S")); extopcode 0f; coding !parsub(0x45) !RRMR($dst,$src)}
631 --------------------------------------
633 local _parsePart = {
634 isa = _parseISA,
635 ops = _parseOps,
636 flags = _parseFlags,
637 pref = _parsePref,
638 extopcode = _parseExtOpcode,
639 coding = _parseCoding,
640 rex = _parseREX,
641 learex = _parseLEAREX,
642 rexlea = _parseLEAREX,
643 vex = _parseVEX,
644 evex = _parseEVEX,
645 fold = _parseFold,
646 commute = _parseCommute,
649 local function parseLine(name, defs)
650 local op= { name = name }
651 for part,info in _gmatch(defs,"%s*(%w+)%s+([^;]*);?") do
652 info = _match(info, "^%s*(.-)%s*$")
653 _assert(_parsePart[part], "invalid option "..part.." in opcode "..name)
654 _parsePart[part](op, info)
656 if not op.isa then op.isa = unify("isa", {}) end
657 if not op.operands then op.operands = {} end
658 if not op.flags then op.flags = unify("flags", {}) end
659 if not op.pref then op.pref = "" end
660 if not op.rex then op.rex = {mode = "rr", reg = "0", rm = "0", r64 = "0"} end
661 if not op.extopcode then op.extopcode = "" end
662 if not op.code then op.code = {} end
663 --print(1, dump(op))
664 _checkOp(op)
665 _createLayout(op)
666 _renameFromLayout(op)
667 _createImpRegs(op)
668 _getPrefixClass(op)
669 _getOpClass(op)
670 return op
673 -----------------------------------------------------------------
675 -----------------------------------------------------------------
676 --local mode,file= ...
678 local ops,opset= {},{}
679 local opclasses = {}
681 -----------------------------------------------------------------
682 -- output functions
683 -----------------------------------------------------------------
684 inslist= _gsub(inslist, "(//[^\r\n]*)([\r\n])","%2")
685 inslist= _gsub(inslist, "(/%*.-%*/)","" )
687 for opname, def in _gmatch(inslist, "%s*([%w_]+)%s*(%b{})") do
688 def = _sub(_gsub(def,"[\r\n]"," "),2,-2)
689 _assert( not opset[opname],"double definition of "..opname )
690 local ok, op = pcall(parseLine,opname, def)
691 if (ok) then
692 ops[ #ops+1 ]= op
693 opset[op.name]= op
694 --print(_dump(op))
695 else
696 print(op)
699 for k,v in _pairs(cache.opclass) do
700 opclasses[#opclasses + 1] = v
702 -- before avx2: 120 prefix (prefix + rex + extopcode/vex) classes, 60 coding classes
703 -- total: isa 39, rex 37, code 73, defuse 42, flags 61, layout 96, operands 321, orgnames 40
704 -- bits: isa 6, rex 6, code 7, defuse 6, flags 7, layout 7 -> sum 39 bits
705 -- class: to check if op is available): isa + 1 bit per opcodesubmask checking
706 -- prefix encoding: pref + rex + extopcode
707 -- main encoding: code
708 -- data flow: defuse + ???
709 -- register class is setup at construction time (of the vregs), and as such, not
710 -- relevant for def use. instruction constructors do the type checking for us.
711 -- allocation and data flow is done for virtual and fixed regs.so we have fixed registers to worry about,
713 --local
715 local function opclassid(op)
716 if op.flags.rmem then r = r .. "R" end
717 if op.flags.wmem then r = r .. "W" end
718 if op.flags.usemem then r = r .. "U" end
719 return r
720 -- if cl.subs[op.sub or 0] then
721 -- print("class "..(op.class or op.name).." contains the sub "..(op.sub or 0).." multiple times")
724 local function _compareISA(a, b)
725 if a == b then return false end
726 if (a.x64 or false) ~= (b.x64 or false) then return b.x64 end
727 if (a.x32only or false) ~= (b.x32only or false) then return b.x32only end
728 if a.sig ~= b.sig then return a.sig < b.sig end
729 _assert("comparing ISA failed")
731 _sort(opclasses,function(a,b)
732 if a.isa ~= b.isa then return _compareISA(a.isa, b.isa) end
733 return a.sig < b.sig
734 end)
735 for i,v in _ipairs(opclasses) do v.id = i end
737 _sort(ops,function(a,b)
738 if a.opclass.isa ~= b.opclass.isa then return _compareISA(a.opclass.isa, b.opclass.isa) end
739 return a.name < b.name
740 end)
742 -----------------------------------------
743 -- selector
744 -----------------------------------------
745 local type2type={
746 GR8="T_I8", GR16= "T_I16", GR32= "T_I32", GR64= "T_I64",
747 VRI64="T_V1I64", VRI128="T_V2I64", VRI256="T_V4I64", VRI128Z="T_V2I64", VRI512="T_V8I64",
748 VR4F32="T_V4F32", VR2F64= "T_V2F64", VR8F32="T_V8F32", VR4F64= "T_V4F64",
749 VR4F32Z="T_V4F32", VR2F64Z= "T_V2F64", VR16F32="T_V16F32", VR8F64 = "T_V8F64",
750 BB="T_BBLOCK",
751 i8="T_I8", i16= "T_I16", i32= "T_I32", i64= "T_I64",
753 local ptr2type={
754 ["i8*"]= "T_I8", ["i16*"]= "T_I16", ["i32*"]= "T_I32", ["i64*"]= "T_I64",
755 ["VI16*"]= "T_I16", ["VI32*"]= "T_I32", ["VI64*"]= "T_V1I64",
756 ["VI128*"]= "T_V2I64", ["VI256*"]= "T_V4I64", ["VI512*"]= "T_V8I64",
757 ["V2F32*"]= "T_V2F32", ["V4F32*"]= "T_V4F32", ["V2F64*"]= "T_V2F64",
758 ["V8F32*"]= "T_V8F32", ["V4F64*"]= "T_V4F64",
759 ["V16F32*"]= "T_V16F32", ["V8F64*"]= "T_V8F64",
760 ["f32*"]= "T_F32", ["f64*"]= "T_F64", ["V1F64*"]= "T_F64",
762 --local data = {ops=ops,type2type=type2type,ptr2type=ptr2type,opclasses=opclasses}
763 local data = {ops=ops,opclasses=opclasses}
764 -- lib for creating/loading/storing/changing memory blocks
766 ---------------------------------------------
767 local function _scandump(x, m)
768 if _type(x) == "table" then
769 if not m[x] then m[#m + 1] = x; m[x] = {0, "l["..#m.."]"}; end
770 m[x][1] = m[x][1] + 1
771 if (m[x][1] > 1) then return m end
772 for k,v in _pairs(x) do
773 _scandump(k, m)
774 _scandump(v, m)
777 return m
779 local function _write_value(f,x,m)
780 if _type(x)=="string" then
781 f:write(_fmt("%q",x))
782 return
784 if _type(x)=="table" then
785 f:write(m[x] and m[x][2] or "$ERROR")
786 return
788 f:write(tostring(x))
790 local function _write_index(f,x,m)
791 if type(x)=="string" and _match(x, "^[%a_][%w_]*$") then
792 f:write(".")
793 f:write(x)
794 return
796 f:write("[")
797 _write_value(f,x,m)
798 f:write("]")
800 local function writedump(f,x)
801 if _type(x) ~= "table" then
802 f:write("return ")
803 _write_value(f,x)
804 f:write("\n")
805 return
807 local m = _scandump(x, {})
808 local i = 0
809 -- create refs for all tables
810 f:write("local l = {}; for i = 1, "..#m.." do l[i] = {} end\n")
811 -- fill fields
812 for k,v in _ipairs(m) do
813 f:write("do local k = "..m[v][2].."\n")
814 for kk,vv in _pairs(v) do
815 -- f:write(m[v][2])
816 f:write("k")
817 _write_index(f,kk,m)
818 f:write(" = ")
819 _write_value(f,vv,m)
820 f:write("\n")
822 f:write("end\n")
824 f:write("return "..m[x][2].."\n")
827 local f = io.open(outname, "w")
828 writedump(f, data)
829 f:close()