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
7 local _ceil
, _pow
= math
.ceil, math
.pow
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
15 elseif _type(x
) ~= "table" then
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
)
30 if pending
then r
= r
.. pending
; pending
= nil end
31 r
= r
.. "[" .. _dump(k
, unquote
) .. "] = " .. _dump(v
, unquote
)
40 local function readfile(n
)
41 local f
= _open(n
) or _open("tools/"..n
)
42 local ctnt
= f
:read("*a")
49 local testname
, outname
= ...
50 if (testname
== nil or testname
== "") then
51 testname
= "..\\src-lib\\x86\\src\\_x86_inslist.ltxt"
53 if outname
== nil or outname
== "" then
54 outname
= _match(testname
, "^(.-)%.[^.\\/]*$") .. ".dat"
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
]
69 for i
= 1, n
do v
= v
.. "(%w+)%s*" end
71 _cacheMatchWords
[n
] = v
75 local _cacheMatchID
= {}
76 local function matchID(w
, n
)
77 local v
= _cacheMatchID
[n
]
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*$"
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
]
106 local id
= (cachecount
[section
] or 0) + 1
107 data
= t
; data
.id
= id
; data
.sig
= sig
; subcache
[sig
] = data
; cachecount
[section
] = id
end
110 local function _opassert(cond
, op
, msg
, ...)
111 if cond
then return end
112 assert(false, _fmt("op %s: "..msg
, op
.name
, ...))
114 --------------------------------------
121 sse2
= {"sse", "mmxext"},
144 x64
= {"sse2","cmov"},
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
155 local function _parseISA(op
, data
)
156 _opassert(not op
.isa
, op
, "double ISA declaration")
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
162 _simplifyISA(iset
, i
)
165 for k
,v
in _pairs(iset
) do
169 for k
,v
in _pairs(iset
) do if not dep
[k
] then iset2
[#iset2
+ 1] = k
end end
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
)
178 for k
,v
in _ipairs(list
) do set
[v
]= k
end
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*",
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",
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
200 local tp
, fixedreg
, vname
, mode
= matchID(p
, "($ID%*?) { ($ID) } ($ID)/($ID)" )
202 tp
,vname
,mode
= matchID(p
, "($ID%*?) ($ID)/($ID)")
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
)
212 if (tp
== "GR8" or tp
== "GR16") and mode
== "o" then mode
= "io" end
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 "")
228 varlist
[ #varlist
+1 ]= {name
=vname
,type=tp
,fixed
=fixedreg
,mode
=mode
}
232 op
.operands
= varlist
234 --------------------------------------
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
= {},
246 local function _parseFlags(op
, data
)
247 _opassert(not op
.flags
, op
, "double flags declaration")
249 for i
in _gmatch(data
,"[%w_]+") do
250 _opassert(_flagset
[i
], op
, "invalid flag %s", i
)
253 if fset
.rwmem
then fset
.wmem
= true; fset
.rmem
= true; fset
.rwmem
= false end
255 for k
,v
in _pairs(fset
) do fset2
[#fset2
+ 1] = k
end
257 op
.flags
= unify("flags", fset2
)
259 --------------------------------------
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
))
272 --------------------------------------
273 local _extopcodeset
= {
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
))
285 --------------------------------------
286 local function _parseCoding(op
, data
)
287 _opassert(not op
.code
, op
, "double coding declaration")
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")
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")
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")
307 op
.sub
= op
.parm
% 32
308 op
.parm
= op
.parm
- op
.sub
311 result
[ #result
+1 ]= c
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
,
352 local function _parseFold(op
, data
)
354 local function _parseCommute(op
, data
)
357 --------------------------------------
359 local function _getValidVarSet( op
)
361 local vars
={ parm
="i8", sub
="i8" }
362 for _
,v
in _ipairs(op
.operands
) do vars
[v
.name
]= v
.type end
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
)
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")
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) %)")
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) %)")
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" )
416 x
,p1
,p2
= matchID(v
, "!RRM([RM])%( ($OP) , ($OP) %)")
418 local rm
= "r".._lower(x
)
419 _opassert(op
.rex
.mode
== rm
, op
, "RRM%s-rex mode mismatch", x
)
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
)
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
)
432 _opassert((op
.rex
.rm
or "0") == "0", op
, "RRM%s-rex rm mismatch", x
)
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
450 --print(op.name, dump(op.rex))
451 local function renameVar(v
)
452 local res
= renametab
[v
]
454 pnum
= (pnum
or 0) + 1
455 res
= {"p".._tostr(pnum
), pnum
}
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
465 if _ptrtype(v
.type) then
467 elseif _immtype(v
.type) then
469 elseif v
.type == "BB" then
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
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
505 local n
= renameVar(v
.name
)
508 op
.layout
= unify("layout", layout
)
509 op
.rename2layout
= renametab
512 local function _renameFromLayout(op
)
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
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
)
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
541 regs
[#regs
+ 1] = {v
.fixed
, t
[v
.mode
]}
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
= ""
560 if op
.pref
~= "" then r
= r
.. "-" .. op
.pref
end
561 if op
.extopcode
~= "" then r
= r
.. "-" .. op
.extopcode
end
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
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;
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
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;
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","")
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
598 function _getPrefixClass(op
)
599 local pcl
= {pref
= op
.pref
, rex
= op
.rex
, extopcode
= op
.extopcode
}
600 pcl
= unify("prefixclass", pcl
, _getPrefixSig
)
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
)
629 --------------------------------------
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 --------------------------------------
640 extopcode
= _parseExtOpcode
,
641 coding
= _parseCoding
,
643 learex
= _parseLEAREX
,
644 rexlea
= _parseLEAREX
,
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
668 _renameFromLayout(op
)
675 -----------------------------------------------------------------
677 -----------------------------------------------------------------
678 --local mode,file= ...
680 local ops
,opset
= {},{}
683 -----------------------------------------------------------------
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
)
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,
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
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
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
744 -----------------------------------------
746 -----------------------------------------
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",
753 i8
="T_I8", i16
= "T_I16", i32
= "T_I32", i64
= "T_I64",
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
781 local function _write_value(f
,x
,m
)
782 if _type(x
)=="string" then
783 f
:write(_fmt("%q",x
))
786 if _type(x
)=="table" then
787 f
:write(m
[x
] and m
[x
][2] or "$ERROR")
792 local function _write_index(f
,x
,m
)
793 if type(x
)=="string" and _match(x
, "^[%a_][%w_]*$") then
802 local function writedump(f
,x
)
803 if _type(x
) ~= "table" then
809 local m
= _scandump(x
, {})
811 -- create refs for all tables
812 f
:write("local l = {}; for i = 1, "..#m
.." do l[i] = {} end\n")
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
826 f
:write("return "..m
[x
][2].."\n")
829 local f
= io
.open(outname
, "w")