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
)
42 local ctnt
= f
:read("*a")
47 local testname
, outname
= ...
48 if (testname
== nil or testname
== "") then
49 testname
= "..\\src-lib\\x86\\src\\_x86_inslist.ltxt"
51 if outname
== nil or outname
== "" then
52 outname
= _match(testname
, "^(.-)%.[^.\\/]*$") .. ".dat"
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
]
67 for i
= 1, n
do v
= v
.. "(%w+)%s*" end
69 _cacheMatchWords
[n
] = v
73 local _cacheMatchID
= {}
74 local function matchID(w
, n
)
75 local v
= _cacheMatchID
[n
]
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*$"
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
]
104 local id
= (cachecount
[section
] or 0) + 1
105 data
= t
; data
.id
= id
; data
.sig
= sig
; subcache
[sig
] = data
; cachecount
[section
] = id
end
108 local function _opassert(cond
, op
, msg
, ...)
109 if cond
then return end
110 assert(false, _fmt("op %s: "..msg
, op
.name
, ...))
112 --------------------------------------
119 sse2
= {"sse", "mmxext"},
142 x64
= {"sse2","cmov"},
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
153 local function _parseISA(op
, data
)
154 _opassert(not op
.isa
, op
, "double ISA declaration")
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
160 _simplifyISA(iset
, i
)
163 for k
,v
in _pairs(iset
) do
167 for k
,v
in _pairs(iset
) do if not dep
[k
] then iset2
[#iset2
+ 1] = k
end end
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
)
176 for k
,v
in _ipairs(list
) do set
[v
]= k
end
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*",
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",
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
198 local tp
, fixedreg
, vname
, mode
= matchID(p
, "($ID%*?) { ($ID) } ($ID)/($ID)" )
200 tp
,vname
,mode
= matchID(p
, "($ID%*?) ($ID)/($ID)")
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
)
210 if (tp
== "GR8" or tp
== "GR16") and mode
== "o" then mode
= "io" end
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 "")
226 varlist
[ #varlist
+1 ]= {name
=vname
,type=tp
,fixed
=fixedreg
,mode
=mode
}
230 op
.operands
= varlist
232 --------------------------------------
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
= {},
244 local function _parseFlags(op
, data
)
245 _opassert(not op
.flags
, op
, "double flags declaration")
247 for i
in _gmatch(data
,"[%w_]+") do
248 _opassert(_flagset
[i
], op
, "invalid flag %s", i
)
251 if fset
.rwmem
then fset
.wmem
= true; fset
.rmem
= true; fset
.rwmem
= false end
253 for k
,v
in _pairs(fset
) do fset2
[#fset2
+ 1] = k
end
255 op
.flags
= unify("flags", fset2
)
257 --------------------------------------
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
))
270 --------------------------------------
271 local _extopcodeset
= {
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
))
283 --------------------------------------
284 local function _parseCoding(op
, data
)
285 _opassert(not op
.code
, op
, "double coding declaration")
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")
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")
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")
305 op
.sub
= op
.parm
% 32
306 op
.parm
= op
.parm
- op
.sub
309 result
[ #result
+1 ]= c
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
,
350 local function _parseFold(op
, data
)
352 local function _parseCommute(op
, data
)
355 --------------------------------------
357 local function _getValidVarSet( op
)
359 local vars
={ parm
="i8", sub
="i8" }
360 for _
,v
in _ipairs(op
.operands
) do vars
[v
.name
]= v
.type end
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
)
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")
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) %)")
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) %)")
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" )
414 x
,p1
,p2
= matchID(v
, "!RRM([RM])%( ($OP) , ($OP) %)")
416 local rm
= "r".._lower(x
)
417 _opassert(op
.rex
.mode
== rm
, op
, "RRM%s-rex mode mismatch", x
)
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
)
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
)
430 _opassert((op
.rex
.rm
or "0") == "0", op
, "RRM%s-rex rm mismatch", x
)
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
448 --print(op.name, dump(op.rex))
449 local function renameVar(v
)
450 local res
= renametab
[v
]
452 pnum
= (pnum
or 0) + 1
453 res
= {"p".._tostr(pnum
), pnum
}
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
463 if _ptrtype(v
.type) then
465 elseif _immtype(v
.type) then
467 elseif v
.type == "BB" then
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
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
503 local n
= renameVar(v
.name
)
506 op
.layout
= unify("layout", layout
)
507 op
.rename2layout
= renametab
510 local function _renameFromLayout(op
)
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
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
)
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
539 regs
[#regs
+ 1] = {v
.fixed
, t
[v
.mode
]}
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
= ""
558 if op
.pref
~= "" then r
= r
.. "-" .. op
.pref
end
559 if op
.extopcode
~= "" then r
= r
.. "-" .. op
.extopcode
end
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
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;
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
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;
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","")
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
596 function _getPrefixClass(op
)
597 local pcl
= {pref
= op
.pref
, rex
= op
.rex
, extopcode
= op
.extopcode
}
598 pcl
= unify("prefixclass", pcl
, _getPrefixSig
)
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
)
627 --------------------------------------
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 --------------------------------------
638 extopcode
= _parseExtOpcode
,
639 coding
= _parseCoding
,
641 learex
= _parseLEAREX
,
642 rexlea
= _parseLEAREX
,
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
666 _renameFromLayout(op
)
673 -----------------------------------------------------------------
675 -----------------------------------------------------------------
676 --local mode,file= ...
678 local ops
,opset
= {},{}
681 -----------------------------------------------------------------
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
)
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,
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
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
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
742 -----------------------------------------
744 -----------------------------------------
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",
751 i8
="T_I8", i16
= "T_I16", i32
= "T_I32", i64
= "T_I64",
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
779 local function _write_value(f
,x
,m
)
780 if _type(x
)=="string" then
781 f
:write(_fmt("%q",x
))
784 if _type(x
)=="table" then
785 f
:write(m
[x
] and m
[x
][2] or "$ERROR")
790 local function _write_index(f
,x
,m
)
791 if type(x
)=="string" and _match(x
, "^[%a_][%w_]*$") then
800 local function writedump(f
,x
)
801 if _type(x
) ~= "table" then
807 local m
= _scandump(x
, {})
809 -- create refs for all tables
810 f
:write("local l = {}; for i = 1, "..#m
.." do l[i] = {} end\n")
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
824 f
:write("return "..m
[x
][2].."\n")
827 local f
= io
.open(outname
, "w")