dasm_x86.lua 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274
  1. ------------------------------------------------------------------------------
  2. -- DynASM x86/x64 module.
  3. --
  4. -- Copyright (C) 2005-2016 Mike Pall. All rights reserved.
  5. -- See dynasm.lua for full copyright notice.
  6. ------------------------------------------------------------------------------
  7. local x64 = x64
  8. -- Module information:
  9. local _info = {
  10. arch = x64 and "x64" or "x86",
  11. description = "DynASM x86/x64 module",
  12. version = "1.4.0",
  13. vernum = 10400,
  14. release = "2015-10-18",
  15. author = "Mike Pall",
  16. license = "MIT",
  17. }
  18. -- Exported glue functions for the arch-specific module.
  19. local _M = { _info = _info }
  20. -- Cache library functions.
  21. local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
  22. local assert, unpack, setmetatable = assert, unpack or table.unpack, setmetatable
  23. local _s = string
  24. local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
  25. local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub
  26. local concat, sort, remove = table.concat, table.sort, table.remove
  27. local bit = bit or require("bit")
  28. local band, bxor, shl, shr = bit.band, bit.bxor, bit.lshift, bit.rshift
  29. -- Inherited tables and callbacks.
  30. local g_opt, g_arch
  31. local wline, werror, wfatal, wwarn
  32. -- Action name list.
  33. -- CHECK: Keep this in sync with the C code!
  34. local action_names = {
  35. -- int arg, 1 buffer pos:
  36. "DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB",
  37. -- action arg (1 byte), int arg, 1 buffer pos (reg/num):
  38. "VREG", "SPACE",
  39. -- ptrdiff_t arg, 1 buffer pos (address): !x64
  40. "SETLABEL", "REL_A",
  41. -- action arg (1 byte) or int arg, 2 buffer pos (link, offset):
  42. "REL_LG", "REL_PC",
  43. -- action arg (1 byte) or int arg, 1 buffer pos (link):
  44. "IMM_LG", "IMM_PC",
  45. -- action arg (1 byte) or int arg, 1 buffer pos (offset):
  46. "LABEL_LG", "LABEL_PC",
  47. -- action arg (1 byte), 1 buffer pos (offset):
  48. "ALIGN",
  49. -- action args (2 bytes), no buffer pos.
  50. "EXTERN",
  51. -- action arg (1 byte), no buffer pos.
  52. "ESC",
  53. -- no action arg, no buffer pos.
  54. "MARK",
  55. -- action arg (1 byte), no buffer pos, terminal action:
  56. "SECTION",
  57. -- no args, no buffer pos, terminal action:
  58. "STOP"
  59. }
  60. -- Maximum number of section buffer positions for dasm_put().
  61. -- CHECK: Keep this in sync with the C code!
  62. local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
  63. -- Action name -> action number (dynamically generated below).
  64. local map_action = {}
  65. -- First action number. Everything below does not need to be escaped.
  66. local actfirst = 256-#action_names
  67. -- Action list buffer and string (only used to remove dupes).
  68. local actlist = {}
  69. local actstr = ""
  70. -- Argument list for next dasm_put(). Start with offset 0 into action list.
  71. local actargs = { 0 }
  72. -- Current number of section buffer positions for dasm_put().
  73. local secpos = 1
  74. -- VREG kind encodings, pre-shifted by 5 bits.
  75. local map_vreg = {
  76. ["modrm.rm.m"] = 0x00,
  77. ["modrm.rm.r"] = 0x20,
  78. ["opcode"] = 0x20,
  79. ["sib.base"] = 0x20,
  80. ["sib.index"] = 0x40,
  81. ["modrm.reg"] = 0x80,
  82. ["vex.v"] = 0xa0,
  83. ["imm.hi"] = 0xc0,
  84. }
  85. -- Current number of VREG actions contributing to REX/VEX shrinkage.
  86. local vreg_shrink_count = 0
  87. ------------------------------------------------------------------------------
  88. -- Compute action numbers for action names.
  89. for n,name in ipairs(action_names) do
  90. local num = actfirst + n - 1
  91. map_action[name] = num
  92. end
  93. -- Dump action names and numbers.
  94. local function dumpactions(out)
  95. out:write("DynASM encoding engine action codes:\n")
  96. for n,name in ipairs(action_names) do
  97. local num = map_action[name]
  98. out:write(format(" %-10s %02X %d\n", name, num, num))
  99. end
  100. out:write("\n")
  101. end
  102. -- Write action list buffer as a huge static C array.
  103. local function writeactions(out, name)
  104. local nn = #actlist
  105. local last = actlist[nn] or 255
  106. actlist[nn] = nil -- Remove last byte.
  107. if nn == 0 then nn = 1 end
  108. out:write("static const unsigned char ", name, "[", nn, "] = {\n")
  109. local s = " "
  110. for n,b in ipairs(actlist) do
  111. s = s..b..","
  112. if #s >= 75 then
  113. assert(out:write(s, "\n"))
  114. s = " "
  115. end
  116. end
  117. out:write(s, last, "\n};\n\n") -- Add last byte back.
  118. end
  119. ------------------------------------------------------------------------------
  120. -- Add byte to action list.
  121. local function wputxb(n)
  122. assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range")
  123. actlist[#actlist+1] = n
  124. end
  125. -- Add action to list with optional arg. Advance buffer pos, too.
  126. local function waction(action, a, num)
  127. wputxb(assert(map_action[action], "bad action name `"..action.."'"))
  128. if a then actargs[#actargs+1] = a end
  129. if a or num then secpos = secpos + (num or 1) end
  130. end
  131. -- Optionally add a VREG action.
  132. local function wvreg(kind, vreg, psz, sk, defer)
  133. if not vreg then return end
  134. waction("VREG", vreg)
  135. local b = assert(map_vreg[kind], "bad vreg kind `"..vreg.."'")
  136. if b < (sk or 0) then
  137. vreg_shrink_count = vreg_shrink_count + 1
  138. end
  139. if not defer then
  140. b = b + vreg_shrink_count * 8
  141. vreg_shrink_count = 0
  142. end
  143. wputxb(b + (psz or 0))
  144. end
  145. -- Add call to embedded DynASM C code.
  146. local function wcall(func, args)
  147. wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true)
  148. end
  149. -- Delete duplicate action list chunks. A tad slow, but so what.
  150. local function dedupechunk(offset)
  151. local al, as = actlist, actstr
  152. local chunk = char(unpack(al, offset+1, #al))
  153. local orig = find(as, chunk, 1, true)
  154. if orig then
  155. actargs[1] = orig-1 -- Replace with original offset.
  156. for i=offset+1,#al do al[i] = nil end -- Kill dupe.
  157. else
  158. actstr = as..chunk
  159. end
  160. end
  161. -- Flush action list (intervening C code or buffer pos overflow).
  162. local function wflush(term)
  163. local offset = actargs[1]
  164. if #actlist == offset then return end -- Nothing to flush.
  165. if not term then waction("STOP") end -- Terminate action list.
  166. dedupechunk(offset)
  167. wcall("put", actargs) -- Add call to dasm_put().
  168. actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
  169. secpos = 1 -- The actionlist offset occupies a buffer position, too.
  170. end
  171. -- Put escaped byte.
  172. local function wputb(n)
  173. if n >= actfirst then waction("ESC") end -- Need to escape byte.
  174. wputxb(n)
  175. end
  176. ------------------------------------------------------------------------------
  177. -- Global label name -> global label number. With auto assignment on 1st use.
  178. local next_global = 10
  179. local map_global = setmetatable({}, { __index = function(t, name)
  180. if not match(name, "^[%a_][%w_@]*$") then werror("bad global label") end
  181. local n = next_global
  182. if n > 246 then werror("too many global labels") end
  183. next_global = n + 1
  184. t[name] = n
  185. return n
  186. end})
  187. -- Dump global labels.
  188. local function dumpglobals(out, lvl)
  189. local t = {}
  190. for name, n in pairs(map_global) do t[n] = name end
  191. out:write("Global labels:\n")
  192. for i=10,next_global-1 do
  193. out:write(format(" %s\n", t[i]))
  194. end
  195. out:write("\n")
  196. end
  197. -- Write global label enum.
  198. local function writeglobals(out, prefix)
  199. local t = {}
  200. for name, n in pairs(map_global) do t[n] = name end
  201. out:write("enum {\n")
  202. for i=10,next_global-1 do
  203. out:write(" ", prefix, gsub(t[i], "@.*", ""), ",\n")
  204. end
  205. out:write(" ", prefix, "_MAX\n};\n")
  206. end
  207. -- Write global label names.
  208. local function writeglobalnames(out, name)
  209. local t = {}
  210. for name, n in pairs(map_global) do t[n] = name end
  211. out:write("static const char *const ", name, "[] = {\n")
  212. for i=10,next_global-1 do
  213. out:write(" \"", t[i], "\",\n")
  214. end
  215. out:write(" (const char *)0\n};\n")
  216. end
  217. ------------------------------------------------------------------------------
  218. -- Extern label name -> extern label number. With auto assignment on 1st use.
  219. local next_extern = -1
  220. local map_extern = setmetatable({}, { __index = function(t, name)
  221. -- No restrictions on the name for now.
  222. local n = next_extern
  223. if n < -256 then werror("too many extern labels") end
  224. next_extern = n - 1
  225. t[name] = n
  226. return n
  227. end})
  228. -- Dump extern labels.
  229. local function dumpexterns(out, lvl)
  230. local t = {}
  231. for name, n in pairs(map_extern) do t[-n] = name end
  232. out:write("Extern labels:\n")
  233. for i=1,-next_extern-1 do
  234. out:write(format(" %s\n", t[i]))
  235. end
  236. out:write("\n")
  237. end
  238. -- Write extern label names.
  239. local function writeexternnames(out, name)
  240. local t = {}
  241. for name, n in pairs(map_extern) do t[-n] = name end
  242. out:write("static const char *const ", name, "[] = {\n")
  243. for i=1,-next_extern-1 do
  244. out:write(" \"", t[i], "\",\n")
  245. end
  246. out:write(" (const char *)0\n};\n")
  247. end
  248. ------------------------------------------------------------------------------
  249. -- Arch-specific maps.
  250. local map_archdef = {} -- Ext. register name -> int. name.
  251. local map_reg_rev = {} -- Int. register name -> ext. name.
  252. local map_reg_num = {} -- Int. register name -> register number.
  253. local map_reg_opsize = {} -- Int. register name -> operand size.
  254. local map_reg_valid_base = {} -- Int. register name -> valid base register?
  255. local map_reg_valid_index = {} -- Int. register name -> valid index register?
  256. local map_reg_needrex = {} -- Int. register name -> need rex vs. no rex.
  257. local reg_list = {} -- Canonical list of int. register names.
  258. local map_type = {} -- Type name -> { ctype, reg }
  259. local ctypenum = 0 -- Type number (for _PTx macros).
  260. local addrsize = x64 and "q" or "d" -- Size for address operands.
  261. -- Helper functions to fill register maps.
  262. local function mkrmap(sz, cl, names)
  263. local cname = format("@%s", sz)
  264. reg_list[#reg_list+1] = cname
  265. map_archdef[cl] = cname
  266. map_reg_rev[cname] = cl
  267. map_reg_num[cname] = -1
  268. map_reg_opsize[cname] = sz
  269. if sz == addrsize or sz == "d" then
  270. map_reg_valid_base[cname] = true
  271. map_reg_valid_index[cname] = true
  272. end
  273. if names then
  274. for n,name in ipairs(names) do
  275. local iname = format("@%s%x", sz, n-1)
  276. reg_list[#reg_list+1] = iname
  277. map_archdef[name] = iname
  278. map_reg_rev[iname] = name
  279. map_reg_num[iname] = n-1
  280. map_reg_opsize[iname] = sz
  281. if sz == "b" and n > 4 then map_reg_needrex[iname] = false end
  282. if sz == addrsize or sz == "d" then
  283. map_reg_valid_base[iname] = true
  284. map_reg_valid_index[iname] = true
  285. end
  286. end
  287. end
  288. for i=0,(x64 and sz ~= "f") and 15 or 7 do
  289. local needrex = sz == "b" and i > 3
  290. local iname = format("@%s%x%s", sz, i, needrex and "R" or "")
  291. if needrex then map_reg_needrex[iname] = true end
  292. local name
  293. if sz == "o" or sz == "y" then name = format("%s%d", cl, i)
  294. elseif sz == "f" then name = format("st%d", i)
  295. else name = format("r%d%s", i, sz == addrsize and "" or sz) end
  296. map_archdef[name] = iname
  297. if not map_reg_rev[iname] then
  298. reg_list[#reg_list+1] = iname
  299. map_reg_rev[iname] = name
  300. map_reg_num[iname] = i
  301. map_reg_opsize[iname] = sz
  302. if sz == addrsize or sz == "d" then
  303. map_reg_valid_base[iname] = true
  304. map_reg_valid_index[iname] = true
  305. end
  306. end
  307. end
  308. reg_list[#reg_list+1] = ""
  309. end
  310. -- Integer registers (qword, dword, word and byte sized).
  311. if x64 then
  312. mkrmap("q", "Rq", {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"})
  313. end
  314. mkrmap("d", "Rd", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"})
  315. mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"})
  316. mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"})
  317. map_reg_valid_index[map_archdef.esp] = false
  318. if x64 then map_reg_valid_index[map_archdef.rsp] = false end
  319. if x64 then map_reg_needrex[map_archdef.Rb] = true end
  320. map_archdef["Ra"] = "@"..addrsize
  321. -- FP registers (internally tword sized, but use "f" as operand size).
  322. mkrmap("f", "Rf")
  323. -- SSE registers (oword sized, but qword and dword accessible).
  324. mkrmap("o", "xmm")
  325. -- AVX registers (yword sized, but oword, qword and dword accessible).
  326. mkrmap("y", "ymm")
  327. -- Operand size prefixes to codes.
  328. local map_opsize = {
  329. byte = "b", word = "w", dword = "d", qword = "q", oword = "o", yword = "y",
  330. tword = "t", aword = addrsize,
  331. }
  332. -- Operand size code to number.
  333. local map_opsizenum = {
  334. b = 1, w = 2, d = 4, q = 8, o = 16, y = 32, t = 10,
  335. }
  336. -- Operand size code to name.
  337. local map_opsizename = {
  338. b = "byte", w = "word", d = "dword", q = "qword", o = "oword", y = "yword",
  339. t = "tword", f = "fpword",
  340. }
  341. -- Valid index register scale factors.
  342. local map_xsc = {
  343. ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3,
  344. }
  345. -- Condition codes.
  346. local map_cc = {
  347. o = 0, no = 1, b = 2, nb = 3, e = 4, ne = 5, be = 6, nbe = 7,
  348. s = 8, ns = 9, p = 10, np = 11, l = 12, nl = 13, le = 14, nle = 15,
  349. c = 2, nae = 2, nc = 3, ae = 3, z = 4, nz = 5, na = 6, a = 7,
  350. pe = 10, po = 11, nge = 12, ge = 13, ng = 14, g = 15,
  351. }
  352. -- Reverse defines for registers.
  353. function _M.revdef(s)
  354. return gsub(s, "@%w+", map_reg_rev)
  355. end
  356. -- Dump register names and numbers
  357. local function dumpregs(out)
  358. out:write("Register names, sizes and internal numbers:\n")
  359. for _,reg in ipairs(reg_list) do
  360. if reg == "" then
  361. out:write("\n")
  362. else
  363. local name = map_reg_rev[reg]
  364. local num = map_reg_num[reg]
  365. local opsize = map_opsizename[map_reg_opsize[reg]]
  366. out:write(format(" %-5s %-8s %s\n", name, opsize,
  367. num < 0 and "(variable)" or num))
  368. end
  369. end
  370. end
  371. ------------------------------------------------------------------------------
  372. -- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC).
  373. local function wputlabel(aprefix, imm, num)
  374. if type(imm) == "number" then
  375. if imm < 0 then
  376. waction("EXTERN")
  377. wputxb(aprefix == "IMM_" and 0 or 1)
  378. imm = -imm-1
  379. else
  380. waction(aprefix.."LG", nil, num);
  381. end
  382. wputxb(imm)
  383. else
  384. waction(aprefix.."PC", imm, num)
  385. end
  386. end
  387. -- Put signed byte or arg.
  388. local function wputsbarg(n)
  389. if type(n) == "number" then
  390. if n < -128 or n > 127 then
  391. werror("signed immediate byte out of range")
  392. end
  393. if n < 0 then n = n + 256 end
  394. wputb(n)
  395. else waction("IMM_S", n) end
  396. end
  397. -- Put unsigned byte or arg.
  398. local function wputbarg(n)
  399. if type(n) == "number" then
  400. if n < 0 or n > 255 then
  401. werror("unsigned immediate byte out of range")
  402. end
  403. wputb(n)
  404. else waction("IMM_B", n) end
  405. end
  406. -- Put unsigned word or arg.
  407. local function wputwarg(n)
  408. if type(n) == "number" then
  409. if shr(n, 16) ~= 0 then
  410. werror("unsigned immediate word out of range")
  411. end
  412. wputb(band(n, 255)); wputb(shr(n, 8));
  413. else waction("IMM_W", n) end
  414. end
  415. -- Put signed or unsigned dword or arg.
  416. local function wputdarg(n)
  417. local tn = type(n)
  418. if tn == "number" then
  419. wputb(band(n, 255))
  420. wputb(band(shr(n, 8), 255))
  421. wputb(band(shr(n, 16), 255))
  422. wputb(shr(n, 24))
  423. elseif tn == "table" then
  424. wputlabel("IMM_", n[1], 1)
  425. else
  426. waction("IMM_D", n)
  427. end
  428. end
  429. -- Put operand-size dependent number or arg (defaults to dword).
  430. local function wputszarg(sz, n)
  431. if not sz or sz == "d" or sz == "q" then wputdarg(n)
  432. elseif sz == "w" then wputwarg(n)
  433. elseif sz == "b" then wputbarg(n)
  434. elseif sz == "s" then wputsbarg(n)
  435. else werror("bad operand size") end
  436. end
  437. -- Put multi-byte opcode with operand-size dependent modifications.
  438. local function wputop(sz, op, rex, vex, vregr, vregxb)
  439. local psz, sk = 0, nil
  440. if vex then
  441. local tail
  442. if vex.m == 1 and band(rex, 11) == 0 then
  443. if x64 and vregxb then
  444. sk = map_vreg["modrm.reg"]
  445. else
  446. wputb(0xc5)
  447. tail = shl(bxor(band(rex, 4), 4), 5)
  448. psz = 3
  449. end
  450. end
  451. if not tail then
  452. wputb(0xc4)
  453. wputb(shl(bxor(band(rex, 7), 7), 5) + vex.m)
  454. tail = shl(band(rex, 8), 4)
  455. psz = 4
  456. end
  457. local reg, vreg = 0, nil
  458. if vex.v then
  459. reg = vex.v.reg
  460. if not reg then werror("bad vex operand") end
  461. if reg < 0 then reg = 0; vreg = vex.v.vreg end
  462. end
  463. if sz == "y" or vex.l then tail = tail + 4 end
  464. wputb(tail + shl(bxor(reg, 15), 3) + vex.p)
  465. wvreg("vex.v", vreg)
  466. rex = 0
  467. if op >= 256 then werror("bad vex opcode") end
  468. else
  469. if rex ~= 0 then
  470. if not x64 then werror("bad operand size") end
  471. elseif (vregr or vregxb) and x64 then
  472. rex = 0x10
  473. sk = map_vreg["vex.v"]
  474. end
  475. end
  476. local r
  477. if sz == "w" then wputb(102) end
  478. -- Needs >32 bit numbers, but only for crc32 eax, word [ebx]
  479. if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end
  480. if op >= 16777216 then wputb(shr(op, 24)); op = band(op, 0xffffff) end
  481. if op >= 65536 then
  482. if rex ~= 0 then
  483. local opc3 = band(op, 0xffff00)
  484. if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then
  485. wputb(64 + band(rex, 15)); rex = 0; psz = 2
  486. end
  487. end
  488. wputb(shr(op, 16)); op = band(op, 0xffff); psz = psz + 1
  489. end
  490. if op >= 256 then
  491. local b = shr(op, 8)
  492. if b == 15 and rex ~= 0 then wputb(64 + band(rex, 15)); rex = 0; psz = 2 end
  493. wputb(b); op = band(op, 255); psz = psz + 1
  494. end
  495. if rex ~= 0 then wputb(64 + band(rex, 15)); psz = 2 end
  496. if sz == "b" then op = op - 1 end
  497. wputb(op)
  498. return psz, sk
  499. end
  500. -- Put ModRM or SIB formatted byte.
  501. local function wputmodrm(m, s, rm, vs, vrm)
  502. assert(m < 4 and s < 16 and rm < 16, "bad modrm operands")
  503. wputb(shl(m, 6) + shl(band(s, 7), 3) + band(rm, 7))
  504. end
  505. -- Put ModRM/SIB plus optional displacement.
  506. local function wputmrmsib(t, imark, s, vsreg, psz, sk)
  507. local vreg, vxreg
  508. local reg, xreg = t.reg, t.xreg
  509. if reg and reg < 0 then reg = 0; vreg = t.vreg end
  510. if xreg and xreg < 0 then xreg = 0; vxreg = t.vxreg end
  511. if s < 0 then s = 0 end
  512. -- Register mode.
  513. if sub(t.mode, 1, 1) == "r" then
  514. wputmodrm(3, s, reg)
  515. wvreg("modrm.reg", vsreg, psz+1, sk, vreg)
  516. wvreg("modrm.rm.r", vreg, psz+1, sk)
  517. return
  518. end
  519. local disp = t.disp
  520. local tdisp = type(disp)
  521. -- No base register?
  522. if not reg then
  523. local riprel = false
  524. if xreg then
  525. -- Indexed mode with index register only.
  526. -- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp)
  527. wputmodrm(0, s, 4)
  528. if imark == "I" then waction("MARK") end
  529. wvreg("modrm.reg", vsreg, psz+1, sk, vxreg)
  530. wputmodrm(t.xsc, xreg, 5)
  531. wvreg("sib.index", vxreg, psz+2, sk)
  532. else
  533. -- Pure 32 bit displacement.
  534. if x64 and tdisp ~= "table" then
  535. wputmodrm(0, s, 4) -- [disp] -> (0, s, esp) (0, esp, ebp)
  536. wvreg("modrm.reg", vsreg, psz+1, sk)
  537. if imark == "I" then waction("MARK") end
  538. wputmodrm(0, 4, 5)
  539. else
  540. riprel = x64
  541. wputmodrm(0, s, 5) -- [disp|rip-label] -> (0, s, ebp)
  542. wvreg("modrm.reg", vsreg, psz+1, sk)
  543. if imark == "I" then waction("MARK") end
  544. end
  545. end
  546. if riprel then -- Emit rip-relative displacement.
  547. if match("UWSiI", imark) then
  548. werror("NYI: rip-relative displacement followed by immediate")
  549. end
  550. -- The previous byte in the action buffer cannot be 0xe9 or 0x80-0x8f.
  551. wputlabel("REL_", disp[1], 2)
  552. else
  553. wputdarg(disp)
  554. end
  555. return
  556. end
  557. local m
  558. if tdisp == "number" then -- Check displacement size at assembly time.
  559. if disp == 0 and band(reg, 7) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too)
  560. if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0]
  561. elseif disp >= -128 and disp <= 127 then m = 1
  562. else m = 2 end
  563. elseif tdisp == "table" then
  564. m = 2
  565. end
  566. -- Index register present or esp as base register: need SIB encoding.
  567. if xreg or band(reg, 7) == 4 then
  568. wputmodrm(m or 2, s, 4) -- ModRM.
  569. if m == nil or imark == "I" then waction("MARK") end
  570. wvreg("modrm.reg", vsreg, psz+1, sk, vxreg or vreg)
  571. wputmodrm(t.xsc or 0, xreg or 4, reg) -- SIB.
  572. wvreg("sib.index", vxreg, psz+2, sk, vreg)
  573. wvreg("sib.base", vreg, psz+2, sk)
  574. else
  575. wputmodrm(m or 2, s, reg) -- ModRM.
  576. if (imark == "I" and (m == 1 or m == 2)) or
  577. (m == nil and (vsreg or vreg)) then waction("MARK") end
  578. wvreg("modrm.reg", vsreg, psz+1, sk, vreg)
  579. wvreg("modrm.rm.m", vreg, psz+1, sk)
  580. end
  581. -- Put displacement.
  582. if m == 1 then wputsbarg(disp)
  583. elseif m == 2 then wputdarg(disp)
  584. elseif m == nil then waction("DISP", disp) end
  585. end
  586. ------------------------------------------------------------------------------
  587. -- Return human-readable operand mode string.
  588. local function opmodestr(op, args)
  589. local m = {}
  590. for i=1,#args do
  591. local a = args[i]
  592. m[#m+1] = sub(a.mode, 1, 1)..(a.opsize or "?")
  593. end
  594. return op.." "..concat(m, ",")
  595. end
  596. -- Convert number to valid integer or nil.
  597. local function toint(expr)
  598. local n = tonumber(expr)
  599. if n then
  600. if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then
  601. werror("bad integer number `"..expr.."'")
  602. end
  603. return n
  604. end
  605. end
  606. -- Parse immediate expression.
  607. local function immexpr(expr)
  608. -- &expr (pointer)
  609. if sub(expr, 1, 1) == "&" then
  610. return "iPJ", format("(ptrdiff_t)(%s)", sub(expr,2))
  611. end
  612. local prefix = sub(expr, 1, 2)
  613. -- =>expr (pc label reference)
  614. if prefix == "=>" then
  615. return "iJ", sub(expr, 3)
  616. end
  617. -- ->name (global label reference)
  618. if prefix == "->" then
  619. return "iJ", map_global[sub(expr, 3)]
  620. end
  621. -- [<>][1-9] (local label reference)
  622. local dir, lnum = match(expr, "^([<>])([1-9])$")
  623. if dir then -- Fwd: 247-255, Bkwd: 1-9.
  624. return "iJ", lnum + (dir == ">" and 246 or 0)
  625. end
  626. local extname = match(expr, "^extern%s+(%S+)$")
  627. if extname then
  628. return "iJ", map_extern[extname]
  629. end
  630. -- expr (interpreted as immediate)
  631. return "iI", expr
  632. end
  633. -- Parse displacement expression: +-num, +-expr, +-opsize*num
  634. local function dispexpr(expr)
  635. local disp = expr == "" and 0 or toint(expr)
  636. if disp then return disp end
  637. local c, dispt = match(expr, "^([+-])%s*(.+)$")
  638. if c == "+" then
  639. expr = dispt
  640. elseif not c then
  641. werror("bad displacement expression `"..expr.."'")
  642. end
  643. local opsize, tailops = match(dispt, "^(%w+)%s*%*%s*(.+)$")
  644. local ops, imm = map_opsize[opsize], toint(tailops)
  645. if ops and imm then
  646. if c == "-" then imm = -imm end
  647. return imm*map_opsizenum[ops]
  648. end
  649. local mode, iexpr = immexpr(dispt)
  650. if mode == "iJ" then
  651. if c == "-" then werror("cannot invert label reference") end
  652. return { iexpr }
  653. end
  654. return expr -- Need to return original signed expression.
  655. end
  656. -- Parse register or type expression.
  657. local function rtexpr(expr)
  658. if not expr then return end
  659. local tname, ovreg = match(expr, "^([%w_]+):(@[%w_]+)$")
  660. local tp = map_type[tname or expr]
  661. if tp then
  662. local reg = ovreg or tp.reg
  663. local rnum = map_reg_num[reg]
  664. if not rnum then
  665. werror("type `"..(tname or expr).."' needs a register override")
  666. end
  667. if not map_reg_valid_base[reg] then
  668. werror("bad base register override `"..(map_reg_rev[reg] or reg).."'")
  669. end
  670. return reg, rnum, tp
  671. end
  672. return expr, map_reg_num[expr]
  673. end
  674. -- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.
  675. local function parseoperand(param)
  676. local t = {}
  677. local expr = param
  678. local opsize, tailops = match(param, "^(%w+)%s*(.+)$")
  679. if opsize then
  680. t.opsize = map_opsize[opsize]
  681. if t.opsize then expr = tailops end
  682. end
  683. local br = match(expr, "^%[%s*(.-)%s*%]$")
  684. repeat
  685. if br then
  686. t.mode = "xm"
  687. -- [disp]
  688. t.disp = toint(br)
  689. if t.disp then
  690. t.mode = x64 and "xm" or "xmO"
  691. break
  692. end
  693. -- [reg...]
  694. local tp
  695. local reg, tailr = match(br, "^([@%w_:]+)%s*(.*)$")
  696. reg, t.reg, tp = rtexpr(reg)
  697. if not t.reg then
  698. -- [expr]
  699. t.mode = x64 and "xm" or "xmO"
  700. t.disp = dispexpr("+"..br)
  701. break
  702. end
  703. if t.reg == -1 then
  704. t.vreg, tailr = match(tailr, "^(%b())(.*)$")
  705. if not t.vreg then werror("bad variable register expression") end
  706. end
  707. -- [xreg*xsc] or [xreg*xsc+-disp] or [xreg*xsc+-expr]
  708. local xsc, tailsc = match(tailr, "^%*%s*([1248])%s*(.*)$")
  709. if xsc then
  710. if not map_reg_valid_index[reg] then
  711. werror("bad index register `"..map_reg_rev[reg].."'")
  712. end
  713. t.xsc = map_xsc[xsc]
  714. t.xreg = t.reg
  715. t.vxreg = t.vreg
  716. t.reg = nil
  717. t.vreg = nil
  718. t.disp = dispexpr(tailsc)
  719. break
  720. end
  721. if not map_reg_valid_base[reg] then
  722. werror("bad base register `"..map_reg_rev[reg].."'")
  723. end
  724. -- [reg] or [reg+-disp]
  725. t.disp = toint(tailr) or (tailr == "" and 0)
  726. if t.disp then break end
  727. -- [reg+xreg...]
  728. local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$")
  729. xreg, t.xreg, tp = rtexpr(xreg)
  730. if not t.xreg then
  731. -- [reg+-expr]
  732. t.disp = dispexpr(tailr)
  733. break
  734. end
  735. if not map_reg_valid_index[xreg] then
  736. werror("bad index register `"..map_reg_rev[xreg].."'")
  737. end
  738. if t.xreg == -1 then
  739. t.vxreg, tailx = match(tailx, "^(%b())(.*)$")
  740. if not t.vxreg then werror("bad variable register expression") end
  741. end
  742. -- [reg+xreg*xsc...]
  743. local xsc, tailsc = match(tailx, "^%*%s*([1248])%s*(.*)$")
  744. if xsc then
  745. t.xsc = map_xsc[xsc]
  746. tailx = tailsc
  747. end
  748. -- [...] or [...+-disp] or [...+-expr]
  749. t.disp = dispexpr(tailx)
  750. else
  751. -- imm or opsize*imm
  752. local imm = toint(expr)
  753. if not imm and sub(expr, 1, 1) == "*" and t.opsize then
  754. imm = toint(sub(expr, 2))
  755. if imm then
  756. imm = imm * map_opsizenum[t.opsize]
  757. t.opsize = nil
  758. end
  759. end
  760. if imm then
  761. if t.opsize then werror("bad operand size override") end
  762. local m = "i"
  763. if imm == 1 then m = m.."1" end
  764. if imm >= 4294967168 and imm <= 4294967295 then imm = imm-4294967296 end
  765. if imm >= -128 and imm <= 127 then m = m.."S" end
  766. t.imm = imm
  767. t.mode = m
  768. break
  769. end
  770. local tp
  771. local reg, tailr = match(expr, "^([@%w_:]+)%s*(.*)$")
  772. reg, t.reg, tp = rtexpr(reg)
  773. if t.reg then
  774. if t.reg == -1 then
  775. t.vreg, tailr = match(tailr, "^(%b())(.*)$")
  776. if not t.vreg then werror("bad variable register expression") end
  777. end
  778. -- reg
  779. if tailr == "" then
  780. if t.opsize then werror("bad operand size override") end
  781. t.opsize = map_reg_opsize[reg]
  782. if t.opsize == "f" then
  783. t.mode = t.reg == 0 and "fF" or "f"
  784. else
  785. if reg == "@w4" or (x64 and reg == "@d4") then
  786. wwarn("bad idea, try again with `"..(x64 and "rsp'" or "esp'"))
  787. end
  788. t.mode = t.reg == 0 and "rmR" or (reg == "@b1" and "rmC" or "rm")
  789. end
  790. t.needrex = map_reg_needrex[reg]
  791. break
  792. end
  793. -- type[idx], type[idx].field, type->field -> [reg+offset_expr]
  794. if not tp then werror("bad operand `"..param.."'") end
  795. t.mode = "xm"
  796. t.disp = format(tp.ctypefmt, tailr)
  797. else
  798. t.mode, t.imm = immexpr(expr)
  799. if sub(t.mode, -1) == "J" then
  800. if t.opsize and t.opsize ~= addrsize then
  801. werror("bad operand size override")
  802. end
  803. t.opsize = addrsize
  804. end
  805. end
  806. end
  807. until true
  808. return t
  809. end
  810. ------------------------------------------------------------------------------
  811. -- x86 Template String Description
  812. -- ===============================
  813. --
  814. -- Each template string is a list of [match:]pattern pairs,
  815. -- separated by "|". The first match wins. No match means a
  816. -- bad or unsupported combination of operand modes or sizes.
  817. --
  818. -- The match part and the ":" is omitted if the operation has
  819. -- no operands. Otherwise the first N characters are matched
  820. -- against the mode strings of each of the N operands.
  821. --
  822. -- The mode string for each operand type is (see parseoperand()):
  823. -- Integer register: "rm", +"R" for eax, ax, al, +"C" for cl
  824. -- FP register: "f", +"F" for st0
  825. -- Index operand: "xm", +"O" for [disp] (pure offset)
  826. -- Immediate: "i", +"S" for signed 8 bit, +"1" for 1,
  827. -- +"I" for arg, +"P" for pointer
  828. -- Any: +"J" for valid jump targets
  829. --
  830. -- So a match character "m" (mixed) matches both an integer register
  831. -- and an index operand (to be encoded with the ModRM/SIB scheme).
  832. -- But "r" matches only a register and "x" only an index operand
  833. -- (e.g. for FP memory access operations).
  834. --
  835. -- The operand size match string starts right after the mode match
  836. -- characters and ends before the ":". "dwb" or "qdwb" is assumed, if empty.
  837. -- The effective data size of the operation is matched against this list.
  838. --
  839. -- If only the regular "b", "w", "d", "q", "t" operand sizes are
  840. -- present, then all operands must be the same size. Unspecified sizes
  841. -- are ignored, but at least one operand must have a size or the pattern
  842. -- won't match (use the "byte", "word", "dword", "qword", "tword"
  843. -- operand size overrides. E.g.: mov dword [eax], 1).
  844. --
  845. -- If the list has a "1" or "2" prefix, the operand size is taken
  846. -- from the respective operand and any other operand sizes are ignored.
  847. -- If the list contains only ".", all operand sizes are ignored.
  848. -- If the list has a "/" prefix, the concatenated (mixed) operand sizes
  849. -- are compared to the match.
  850. --
  851. -- E.g. "rrdw" matches for either two dword registers or two word
  852. -- registers. "Fx2dq" matches an st0 operand plus an index operand
  853. -- pointing to a dword (float) or qword (double).
  854. --
  855. -- Every character after the ":" is part of the pattern string:
  856. -- Hex chars are accumulated to form the opcode (left to right).
  857. -- "n" disables the standard opcode mods
  858. -- (otherwise: -1 for "b", o16 prefix for "w", rex.w for "q")
  859. -- "X" Force REX.W.
  860. -- "r"/"R" adds the reg. number from the 1st/2nd operand to the opcode.
  861. -- "m"/"M" generates ModRM/SIB from the 1st/2nd operand.
  862. -- The spare 3 bits are either filled with the last hex digit or
  863. -- the result from a previous "r"/"R". The opcode is restored.
  864. -- "u" Use VEX encoding, vvvv unused.
  865. -- "v"/"V" Use VEX encoding, vvvv from 1st/2nd operand (the operand is
  866. -- removed from the list used by future characters).
  867. -- "L" Force VEX.L
  868. --
  869. -- All of the following characters force a flush of the opcode:
  870. -- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand.
  871. -- "s" stores a 4 bit immediate from the last register operand,
  872. -- followed by 4 zero bits.
  873. -- "S" stores a signed 8 bit immediate from the last operand.
  874. -- "U" stores an unsigned 8 bit immediate from the last operand.
  875. -- "W" stores an unsigned 16 bit immediate from the last operand.
  876. -- "i" stores an operand sized immediate from the last operand.
  877. -- "I" dito, but generates an action code to optionally modify
  878. -- the opcode (+2) for a signed 8 bit immediate.
  879. -- "J" generates one of the REL action codes from the last operand.
  880. --
  881. ------------------------------------------------------------------------------
  882. -- Template strings for x86 instructions. Ordered by first opcode byte.
  883. -- Unimplemented opcodes (deliberate omissions) are marked with *.
  884. local map_op = {
  885. -- 00-05: add...
  886. -- 06: *push es
  887. -- 07: *pop es
  888. -- 08-0D: or...
  889. -- 0E: *push cs
  890. -- 0F: two byte opcode prefix
  891. -- 10-15: adc...
  892. -- 16: *push ss
  893. -- 17: *pop ss
  894. -- 18-1D: sbb...
  895. -- 1E: *push ds
  896. -- 1F: *pop ds
  897. -- 20-25: and...
  898. es_0 = "26",
  899. -- 27: *daa
  900. -- 28-2D: sub...
  901. cs_0 = "2E",
  902. -- 2F: *das
  903. -- 30-35: xor...
  904. ss_0 = "36",
  905. -- 37: *aaa
  906. -- 38-3D: cmp...
  907. ds_0 = "3E",
  908. -- 3F: *aas
  909. inc_1 = x64 and "m:FF0m" or "rdw:40r|m:FF0m",
  910. dec_1 = x64 and "m:FF1m" or "rdw:48r|m:FF1m",
  911. push_1 = (x64 and "rq:n50r|rw:50r|mq:nFF6m|mw:FF6m" or
  912. "rdw:50r|mdw:FF6m").."|S.:6AS|ib:n6Ai|i.:68i",
  913. pop_1 = x64 and "rq:n58r|rw:58r|mq:n8F0m|mw:8F0m" or "rdw:58r|mdw:8F0m",
  914. -- 60: *pusha, *pushad, *pushaw
  915. -- 61: *popa, *popad, *popaw
  916. -- 62: *bound rdw,x
  917. -- 63: x86: *arpl mw,rw
  918. movsxd_2 = x64 and "rm/qd:63rM",
  919. fs_0 = "64",
  920. gs_0 = "65",
  921. o16_0 = "66",
  922. a16_0 = not x64 and "67" or nil,
  923. a32_0 = x64 and "67",
  924. -- 68: push idw
  925. -- 69: imul rdw,mdw,idw
  926. -- 6A: push ib
  927. -- 6B: imul rdw,mdw,S
  928. -- 6C: *insb
  929. -- 6D: *insd, *insw
  930. -- 6E: *outsb
  931. -- 6F: *outsd, *outsw
  932. -- 70-7F: jcc lb
  933. -- 80: add... mb,i
  934. -- 81: add... mdw,i
  935. -- 82: *undefined
  936. -- 83: add... mdw,S
  937. test_2 = "mr:85Rm|rm:85rM|Ri:A9ri|mi:F70mi",
  938. -- 86: xchg rb,mb
  939. -- 87: xchg rdw,mdw
  940. -- 88: mov mb,r
  941. -- 89: mov mdw,r
  942. -- 8A: mov r,mb
  943. -- 8B: mov r,mdw
  944. -- 8C: *mov mdw,seg
  945. lea_2 = "rx1dq:8DrM",
  946. -- 8E: *mov seg,mdw
  947. -- 8F: pop mdw
  948. nop_0 = "90",
  949. xchg_2 = "Rrqdw:90R|rRqdw:90r|rm:87rM|mr:87Rm",
  950. cbw_0 = "6698",
  951. cwde_0 = "98",
  952. cdqe_0 = "4898",
  953. cwd_0 = "6699",
  954. cdq_0 = "99",
  955. cqo_0 = "4899",
  956. -- 9A: *call iw:idw
  957. wait_0 = "9B",
  958. fwait_0 = "9B",
  959. pushf_0 = "9C",
  960. pushfd_0 = not x64 and "9C",
  961. pushfq_0 = x64 and "9C",
  962. popf_0 = "9D",
  963. popfd_0 = not x64 and "9D",
  964. popfq_0 = x64 and "9D",
  965. sahf_0 = "9E",
  966. lahf_0 = "9F",
  967. mov_2 = "OR:A3o|RO:A1O|mr:89Rm|rm:8BrM|rib:nB0ri|ridw:B8ri|mi:C70mi",
  968. movsb_0 = "A4",
  969. movsw_0 = "66A5",
  970. movsd_0 = "A5",
  971. cmpsb_0 = "A6",
  972. cmpsw_0 = "66A7",
  973. cmpsd_0 = "A7",
  974. -- A8: test Rb,i
  975. -- A9: test Rdw,i
  976. stosb_0 = "AA",
  977. stosw_0 = "66AB",
  978. stosd_0 = "AB",
  979. lodsb_0 = "AC",
  980. lodsw_0 = "66AD",
  981. lodsd_0 = "AD",
  982. scasb_0 = "AE",
  983. scasw_0 = "66AF",
  984. scasd_0 = "AF",
  985. -- B0-B7: mov rb,i
  986. -- B8-BF: mov rdw,i
  987. -- C0: rol... mb,i
  988. -- C1: rol... mdw,i
  989. ret_1 = "i.:nC2W",
  990. ret_0 = "C3",
  991. -- C4: *les rdw,mq
  992. -- C5: *lds rdw,mq
  993. -- C6: mov mb,i
  994. -- C7: mov mdw,i
  995. -- C8: *enter iw,ib
  996. leave_0 = "C9",
  997. -- CA: *retf iw
  998. -- CB: *retf
  999. int3_0 = "CC",
  1000. int_1 = "i.:nCDU",
  1001. into_0 = "CE",
  1002. -- CF: *iret
  1003. -- D0: rol... mb,1
  1004. -- D1: rol... mdw,1
  1005. -- D2: rol... mb,cl
  1006. -- D3: rol... mb,cl
  1007. -- D4: *aam ib
  1008. -- D5: *aad ib
  1009. -- D6: *salc
  1010. -- D7: *xlat
  1011. -- D8-DF: floating point ops
  1012. -- E0: *loopne
  1013. -- E1: *loope
  1014. -- E2: *loop
  1015. -- E3: *jcxz, *jecxz
  1016. -- E4: *in Rb,ib
  1017. -- E5: *in Rdw,ib
  1018. -- E6: *out ib,Rb
  1019. -- E7: *out ib,Rdw
  1020. call_1 = x64 and "mq:nFF2m|J.:E8nJ" or "md:FF2m|J.:E8J",
  1021. jmp_1 = x64 and "mq:nFF4m|J.:E9nJ" or "md:FF4m|J.:E9J", -- short: EB
  1022. -- EA: *jmp iw:idw
  1023. -- EB: jmp ib
  1024. -- EC: *in Rb,dx
  1025. -- ED: *in Rdw,dx
  1026. -- EE: *out dx,Rb
  1027. -- EF: *out dx,Rdw
  1028. lock_0 = "F0",
  1029. int1_0 = "F1",
  1030. repne_0 = "F2",
  1031. repnz_0 = "F2",
  1032. rep_0 = "F3",
  1033. repe_0 = "F3",
  1034. repz_0 = "F3",
  1035. -- F4: *hlt
  1036. cmc_0 = "F5",
  1037. -- F6: test... mb,i; div... mb
  1038. -- F7: test... mdw,i; div... mdw
  1039. clc_0 = "F8",
  1040. stc_0 = "F9",
  1041. -- FA: *cli
  1042. cld_0 = "FC",
  1043. std_0 = "FD",
  1044. -- FE: inc... mb
  1045. -- FF: inc... mdw
  1046. -- misc ops
  1047. not_1 = "m:F72m",
  1048. neg_1 = "m:F73m",
  1049. mul_1 = "m:F74m",
  1050. imul_1 = "m:F75m",
  1051. div_1 = "m:F76m",
  1052. idiv_1 = "m:F77m",
  1053. imul_2 = "rmqdw:0FAFrM|rIqdw:69rmI|rSqdw:6BrmS|riqdw:69rmi",
  1054. imul_3 = "rmIqdw:69rMI|rmSqdw:6BrMS|rmiqdw:69rMi",
  1055. movzx_2 = "rm/db:0FB6rM|rm/qb:|rm/wb:0FB6rM|rm/dw:0FB7rM|rm/qw:",
  1056. movsx_2 = "rm/db:0FBErM|rm/qb:|rm/wb:0FBErM|rm/dw:0FBFrM|rm/qw:",
  1057. bswap_1 = "rqd:0FC8r",
  1058. bsf_2 = "rmqdw:0FBCrM",
  1059. bsr_2 = "rmqdw:0FBDrM",
  1060. bt_2 = "mrqdw:0FA3Rm|miqdw:0FBA4mU",
  1061. btc_2 = "mrqdw:0FBBRm|miqdw:0FBA7mU",
  1062. btr_2 = "mrqdw:0FB3Rm|miqdw:0FBA6mU",
  1063. bts_2 = "mrqdw:0FABRm|miqdw:0FBA5mU",
  1064. shld_3 = "mriqdw:0FA4RmU|mrC/qq:0FA5Rm|mrC/dd:|mrC/ww:",
  1065. shrd_3 = "mriqdw:0FACRmU|mrC/qq:0FADRm|mrC/dd:|mrC/ww:",
  1066. rdtsc_0 = "0F31", -- P1+
  1067. rdpmc_0 = "0F33", -- P6+
  1068. cpuid_0 = "0FA2", -- P1+
  1069. -- floating point ops
  1070. fst_1 = "ff:DDD0r|xd:D92m|xq:nDD2m",
  1071. fstp_1 = "ff:DDD8r|xd:D93m|xq:nDD3m|xt:DB7m",
  1072. fld_1 = "ff:D9C0r|xd:D90m|xq:nDD0m|xt:DB5m",
  1073. fpop_0 = "DDD8", -- Alias for fstp st0.
  1074. fist_1 = "xw:nDF2m|xd:DB2m",
  1075. fistp_1 = "xw:nDF3m|xd:DB3m|xq:nDF7m",
  1076. fild_1 = "xw:nDF0m|xd:DB0m|xq:nDF5m",
  1077. fxch_0 = "D9C9",
  1078. fxch_1 = "ff:D9C8r",
  1079. fxch_2 = "fFf:D9C8r|Fff:D9C8R",
  1080. fucom_1 = "ff:DDE0r",
  1081. fucom_2 = "Fff:DDE0R",
  1082. fucomp_1 = "ff:DDE8r",
  1083. fucomp_2 = "Fff:DDE8R",
  1084. fucomi_1 = "ff:DBE8r", -- P6+
  1085. fucomi_2 = "Fff:DBE8R", -- P6+
  1086. fucomip_1 = "ff:DFE8r", -- P6+
  1087. fucomip_2 = "Fff:DFE8R", -- P6+
  1088. fcomi_1 = "ff:DBF0r", -- P6+
  1089. fcomi_2 = "Fff:DBF0R", -- P6+
  1090. fcomip_1 = "ff:DFF0r", -- P6+
  1091. fcomip_2 = "Fff:DFF0R", -- P6+
  1092. fucompp_0 = "DAE9",
  1093. fcompp_0 = "DED9",
  1094. fldenv_1 = "x.:D94m",
  1095. fnstenv_1 = "x.:D96m",
  1096. fstenv_1 = "x.:9BD96m",
  1097. fldcw_1 = "xw:nD95m",
  1098. fstcw_1 = "xw:n9BD97m",
  1099. fnstcw_1 = "xw:nD97m",
  1100. fstsw_1 = "Rw:n9BDFE0|xw:n9BDD7m",
  1101. fnstsw_1 = "Rw:nDFE0|xw:nDD7m",
  1102. fclex_0 = "9BDBE2",
  1103. fnclex_0 = "DBE2",
  1104. fnop_0 = "D9D0",
  1105. -- D9D1-D9DF: unassigned
  1106. fchs_0 = "D9E0",
  1107. fabs_0 = "D9E1",
  1108. -- D9E2: unassigned
  1109. -- D9E3: unassigned
  1110. ftst_0 = "D9E4",
  1111. fxam_0 = "D9E5",
  1112. -- D9E6: unassigned
  1113. -- D9E7: unassigned
  1114. fld1_0 = "D9E8",
  1115. fldl2t_0 = "D9E9",
  1116. fldl2e_0 = "D9EA",
  1117. fldpi_0 = "D9EB",
  1118. fldlg2_0 = "D9EC",
  1119. fldln2_0 = "D9ED",
  1120. fldz_0 = "D9EE",
  1121. -- D9EF: unassigned
  1122. f2xm1_0 = "D9F0",
  1123. fyl2x_0 = "D9F1",
  1124. fptan_0 = "D9F2",
  1125. fpatan_0 = "D9F3",
  1126. fxtract_0 = "D9F4",
  1127. fprem1_0 = "D9F5",
  1128. fdecstp_0 = "D9F6",
  1129. fincstp_0 = "D9F7",
  1130. fprem_0 = "D9F8",
  1131. fyl2xp1_0 = "D9F9",
  1132. fsqrt_0 = "D9FA",
  1133. fsincos_0 = "D9FB",
  1134. frndint_0 = "D9FC",
  1135. fscale_0 = "D9FD",
  1136. fsin_0 = "D9FE",
  1137. fcos_0 = "D9FF",
  1138. -- SSE, SSE2
  1139. andnpd_2 = "rmo:660F55rM",
  1140. andnps_2 = "rmo:0F55rM",
  1141. andpd_2 = "rmo:660F54rM",
  1142. andps_2 = "rmo:0F54rM",
  1143. clflush_1 = "x.:0FAE7m",
  1144. cmppd_3 = "rmio:660FC2rMU",
  1145. cmpps_3 = "rmio:0FC2rMU",
  1146. cmpsd_3 = "rrio:F20FC2rMU|rxi/oq:",
  1147. cmpss_3 = "rrio:F30FC2rMU|rxi/od:",
  1148. comisd_2 = "rro:660F2FrM|rx/oq:",
  1149. comiss_2 = "rro:0F2FrM|rx/od:",
  1150. cvtdq2pd_2 = "rro:F30FE6rM|rx/oq:",
  1151. cvtdq2ps_2 = "rmo:0F5BrM",
  1152. cvtpd2dq_2 = "rmo:F20FE6rM",
  1153. cvtpd2ps_2 = "rmo:660F5ArM",
  1154. cvtpi2pd_2 = "rx/oq:660F2ArM",
  1155. cvtpi2ps_2 = "rx/oq:0F2ArM",
  1156. cvtps2dq_2 = "rmo:660F5BrM",
  1157. cvtps2pd_2 = "rro:0F5ArM|rx/oq:",
  1158. cvtsd2si_2 = "rr/do:F20F2DrM|rr/qo:|rx/dq:|rxq:",
  1159. cvtsd2ss_2 = "rro:F20F5ArM|rx/oq:",
  1160. cvtsi2sd_2 = "rm/od:F20F2ArM|rm/oq:F20F2ArXM",
  1161. cvtsi2ss_2 = "rm/od:F30F2ArM|rm/oq:F30F2ArXM",
  1162. cvtss2sd_2 = "rro:F30F5ArM|rx/od:",
  1163. cvtss2si_2 = "rr/do:F30F2DrM|rr/qo:|rxd:|rx/qd:",
  1164. cvttpd2dq_2 = "rmo:660FE6rM",
  1165. cvttps2dq_2 = "rmo:F30F5BrM",
  1166. cvttsd2si_2 = "rr/do:F20F2CrM|rr/qo:|rx/dq:|rxq:",
  1167. cvttss2si_2 = "rr/do:F30F2CrM|rr/qo:|rxd:|rx/qd:",
  1168. fxsave_1 = "x.:0FAE0m",
  1169. fxrstor_1 = "x.:0FAE1m",
  1170. ldmxcsr_1 = "xd:0FAE2m",
  1171. lfence_0 = "0FAEE8",
  1172. maskmovdqu_2 = "rro:660FF7rM",
  1173. mfence_0 = "0FAEF0",
  1174. movapd_2 = "rmo:660F28rM|mro:660F29Rm",
  1175. movaps_2 = "rmo:0F28rM|mro:0F29Rm",
  1176. movd_2 = "rm/od:660F6ErM|rm/oq:660F6ErXM|mr/do:660F7ERm|mr/qo:",
  1177. movdqa_2 = "rmo:660F6FrM|mro:660F7FRm",
  1178. movdqu_2 = "rmo:F30F6FrM|mro:F30F7FRm",
  1179. movhlps_2 = "rro:0F12rM",
  1180. movhpd_2 = "rx/oq:660F16rM|xr/qo:n660F17Rm",
  1181. movhps_2 = "rx/oq:0F16rM|xr/qo:n0F17Rm",
  1182. movlhps_2 = "rro:0F16rM",
  1183. movlpd_2 = "rx/oq:660F12rM|xr/qo:n660F13Rm",
  1184. movlps_2 = "rx/oq:0F12rM|xr/qo:n0F13Rm",
  1185. movmskpd_2 = "rr/do:660F50rM",
  1186. movmskps_2 = "rr/do:0F50rM",
  1187. movntdq_2 = "xro:660FE7Rm",
  1188. movnti_2 = "xrqd:0FC3Rm",
  1189. movntpd_2 = "xro:660F2BRm",
  1190. movntps_2 = "xro:0F2BRm",
  1191. movq_2 = "rro:F30F7ErM|rx/oq:|xr/qo:n660FD6Rm",
  1192. movsd_2 = "rro:F20F10rM|rx/oq:|xr/qo:nF20F11Rm",
  1193. movss_2 = "rro:F30F10rM|rx/od:|xr/do:F30F11Rm",
  1194. movupd_2 = "rmo:660F10rM|mro:660F11Rm",
  1195. movups_2 = "rmo:0F10rM|mro:0F11Rm",
  1196. orpd_2 = "rmo:660F56rM",
  1197. orps_2 = "rmo:0F56rM",
  1198. pause_0 = "F390",
  1199. pextrw_3 = "rri/do:660FC5rMU|xri/wo:660F3A15nRmU", -- Mem op: SSE4.1 only.
  1200. pinsrw_3 = "rri/od:660FC4rMU|rxi/ow:",
  1201. pmovmskb_2 = "rr/do:660FD7rM",
  1202. prefetchnta_1 = "xb:n0F180m",
  1203. prefetcht0_1 = "xb:n0F181m",
  1204. prefetcht1_1 = "xb:n0F182m",
  1205. prefetcht2_1 = "xb:n0F183m",
  1206. pshufd_3 = "rmio:660F70rMU",
  1207. pshufhw_3 = "rmio:F30F70rMU",
  1208. pshuflw_3 = "rmio:F20F70rMU",
  1209. pslld_2 = "rmo:660FF2rM|rio:660F726mU",
  1210. pslldq_2 = "rio:660F737mU",
  1211. psllq_2 = "rmo:660FF3rM|rio:660F736mU",
  1212. psllw_2 = "rmo:660FF1rM|rio:660F716mU",
  1213. psrad_2 = "rmo:660FE2rM|rio:660F724mU",
  1214. psraw_2 = "rmo:660FE1rM|rio:660F714mU",
  1215. psrld_2 = "rmo:660FD2rM|rio:660F722mU",
  1216. psrldq_2 = "rio:660F733mU",
  1217. psrlq_2 = "rmo:660FD3rM|rio:660F732mU",
  1218. psrlw_2 = "rmo:660FD1rM|rio:660F712mU",
  1219. rcpps_2 = "rmo:0F53rM",
  1220. rcpss_2 = "rro:F30F53rM|rx/od:",
  1221. rsqrtps_2 = "rmo:0F52rM",
  1222. rsqrtss_2 = "rmo:F30F52rM",
  1223. sfence_0 = "0FAEF8",
  1224. shufpd_3 = "rmio:660FC6rMU",
  1225. shufps_3 = "rmio:0FC6rMU",
  1226. stmxcsr_1 = "xd:0FAE3m",
  1227. ucomisd_2 = "rro:660F2ErM|rx/oq:",
  1228. ucomiss_2 = "rro:0F2ErM|rx/od:",
  1229. unpckhpd_2 = "rmo:660F15rM",
  1230. unpckhps_2 = "rmo:0F15rM",
  1231. unpcklpd_2 = "rmo:660F14rM",
  1232. unpcklps_2 = "rmo:0F14rM",
  1233. xorpd_2 = "rmo:660F57rM",
  1234. xorps_2 = "rmo:0F57rM",
  1235. -- SSE3 ops
  1236. fisttp_1 = "xw:nDF1m|xd:DB1m|xq:nDD1m",
  1237. addsubpd_2 = "rmo:660FD0rM",
  1238. addsubps_2 = "rmo:F20FD0rM",
  1239. haddpd_2 = "rmo:660F7CrM",
  1240. haddps_2 = "rmo:F20F7CrM",
  1241. hsubpd_2 = "rmo:660F7DrM",
  1242. hsubps_2 = "rmo:F20F7DrM",
  1243. lddqu_2 = "rxo:F20FF0rM",
  1244. movddup_2 = "rmo:F20F12rM",
  1245. movshdup_2 = "rmo:F30F16rM",
  1246. movsldup_2 = "rmo:F30F12rM",
  1247. -- SSSE3 ops
  1248. pabsb_2 = "rmo:660F381CrM",
  1249. pabsd_2 = "rmo:660F381ErM",
  1250. pabsw_2 = "rmo:660F381DrM",
  1251. palignr_3 = "rmio:660F3A0FrMU",
  1252. phaddd_2 = "rmo:660F3802rM",
  1253. phaddsw_2 = "rmo:660F3803rM",
  1254. phaddw_2 = "rmo:660F3801rM",
  1255. phsubd_2 = "rmo:660F3806rM",
  1256. phsubsw_2 = "rmo:660F3807rM",
  1257. phsubw_2 = "rmo:660F3805rM",
  1258. pmaddubsw_2 = "rmo:660F3804rM",
  1259. pmulhrsw_2 = "rmo:660F380BrM",
  1260. pshufb_2 = "rmo:660F3800rM",
  1261. psignb_2 = "rmo:660F3808rM",
  1262. psignd_2 = "rmo:660F380ArM",
  1263. psignw_2 = "rmo:660F3809rM",
  1264. -- SSE4.1 ops
  1265. blendpd_3 = "rmio:660F3A0DrMU",
  1266. blendps_3 = "rmio:660F3A0CrMU",
  1267. blendvpd_3 = "rmRo:660F3815rM",
  1268. blendvps_3 = "rmRo:660F3814rM",
  1269. dppd_3 = "rmio:660F3A41rMU",
  1270. dpps_3 = "rmio:660F3A40rMU",
  1271. extractps_3 = "mri/do:660F3A17RmU|rri/qo:660F3A17RXmU",
  1272. insertps_3 = "rrio:660F3A41rMU|rxi/od:",
  1273. movntdqa_2 = "rxo:660F382ArM",
  1274. mpsadbw_3 = "rmio:660F3A42rMU",
  1275. packusdw_2 = "rmo:660F382BrM",
  1276. pblendvb_3 = "rmRo:660F3810rM",
  1277. pblendw_3 = "rmio:660F3A0ErMU",
  1278. pcmpeqq_2 = "rmo:660F3829rM",
  1279. pextrb_3 = "rri/do:660F3A14nRmU|rri/qo:|xri/bo:",
  1280. pextrd_3 = "mri/do:660F3A16RmU",
  1281. pextrq_3 = "mri/qo:660F3A16RmU",
  1282. -- pextrw is SSE2, mem operand is SSE4.1 only
  1283. phminposuw_2 = "rmo:660F3841rM",
  1284. pinsrb_3 = "rri/od:660F3A20nrMU|rxi/ob:",
  1285. pinsrd_3 = "rmi/od:660F3A22rMU",
  1286. pinsrq_3 = "rmi/oq:660F3A22rXMU",
  1287. pmaxsb_2 = "rmo:660F383CrM",
  1288. pmaxsd_2 = "rmo:660F383DrM",
  1289. pmaxud_2 = "rmo:660F383FrM",
  1290. pmaxuw_2 = "rmo:660F383ErM",
  1291. pminsb_2 = "rmo:660F3838rM",
  1292. pminsd_2 = "rmo:660F3839rM",
  1293. pminud_2 = "rmo:660F383BrM",
  1294. pminuw_2 = "rmo:660F383ArM",
  1295. pmovsxbd_2 = "rro:660F3821rM|rx/od:",
  1296. pmovsxbq_2 = "rro:660F3822rM|rx/ow:",
  1297. pmovsxbw_2 = "rro:660F3820rM|rx/oq:",
  1298. pmovsxdq_2 = "rro:660F3825rM|rx/oq:",
  1299. pmovsxwd_2 = "rro:660F3823rM|rx/oq:",
  1300. pmovsxwq_2 = "rro:660F3824rM|rx/od:",
  1301. pmovzxbd_2 = "rro:660F3831rM|rx/od:",
  1302. pmovzxbq_2 = "rro:660F3832rM|rx/ow:",
  1303. pmovzxbw_2 = "rro:660F3830rM|rx/oq:",
  1304. pmovzxdq_2 = "rro:660F3835rM|rx/oq:",
  1305. pmovzxwd_2 = "rro:660F3833rM|rx/oq:",
  1306. pmovzxwq_2 = "rro:660F3834rM|rx/od:",
  1307. pmuldq_2 = "rmo:660F3828rM",
  1308. pmulld_2 = "rmo:660F3840rM",
  1309. ptest_2 = "rmo:660F3817rM",
  1310. roundpd_3 = "rmio:660F3A09rMU",
  1311. roundps_3 = "rmio:660F3A08rMU",
  1312. roundsd_3 = "rrio:660F3A0BrMU|rxi/oq:",
  1313. roundss_3 = "rrio:660F3A0ArMU|rxi/od:",
  1314. -- SSE4.2 ops
  1315. crc32_2 = "rmqd:F20F38F1rM|rm/dw:66F20F38F1rM|rm/db:F20F38F0rM|rm/qb:",
  1316. pcmpestri_3 = "rmio:660F3A61rMU",
  1317. pcmpestrm_3 = "rmio:660F3A60rMU",
  1318. pcmpgtq_2 = "rmo:660F3837rM",
  1319. pcmpistri_3 = "rmio:660F3A63rMU",
  1320. pcmpistrm_3 = "rmio:660F3A62rMU",
  1321. popcnt_2 = "rmqdw:F30FB8rM",
  1322. -- SSE4a
  1323. extrq_2 = "rro:660F79rM",
  1324. extrq_3 = "riio:660F780mUU",
  1325. insertq_2 = "rro:F20F79rM",
  1326. insertq_4 = "rriio:F20F78rMUU",
  1327. lzcnt_2 = "rmqdw:F30FBDrM",
  1328. movntsd_2 = "xr/qo:nF20F2BRm",
  1329. movntss_2 = "xr/do:F30F2BRm",
  1330. -- popcnt is also in SSE4.2
  1331. -- AES-NI
  1332. aesdec_2 = "rmo:660F38DErM",
  1333. aesdeclast_2 = "rmo:660F38DFrM",
  1334. aesenc_2 = "rmo:660F38DCrM",
  1335. aesenclast_2 = "rmo:660F38DDrM",
  1336. aesimc_2 = "rmo:660F38DBrM",
  1337. aeskeygenassist_3 = "rmio:660F3ADFrMU",
  1338. pclmulqdq_3 = "rmio:660F3A44rMU",
  1339. -- AVX FP ops
  1340. vaddsubpd_3 = "rrmoy:660FVD0rM",
  1341. vaddsubps_3 = "rrmoy:F20FVD0rM",
  1342. vandpd_3 = "rrmoy:660FV54rM",
  1343. vandps_3 = "rrmoy:0FV54rM",
  1344. vandnpd_3 = "rrmoy:660FV55rM",
  1345. vandnps_3 = "rrmoy:0FV55rM",
  1346. vblendpd_4 = "rrmioy:660F3AV0DrMU",
  1347. vblendps_4 = "rrmioy:660F3AV0CrMU",
  1348. vblendvpd_4 = "rrmroy:660F3AV4BrMs",
  1349. vblendvps_4 = "rrmroy:660F3AV4ArMs",
  1350. vbroadcastf128_2 = "rx/yo:660F38u1ArM",
  1351. vcmppd_4 = "rrmioy:660FVC2rMU",
  1352. vcmpps_4 = "rrmioy:0FVC2rMU",
  1353. vcmpsd_4 = "rrrio:F20FVC2rMU|rrxi/ooq:",
  1354. vcmpss_4 = "rrrio:F30FVC2rMU|rrxi/ood:",
  1355. vcomisd_2 = "rro:660Fu2FrM|rx/oq:",
  1356. vcomiss_2 = "rro:0Fu2FrM|rx/od:",
  1357. vcvtdq2pd_2 = "rro:F30FuE6rM|rx/oq:|rm/yo:",
  1358. vcvtdq2ps_2 = "rmoy:0Fu5BrM",
  1359. vcvtpd2dq_2 = "rmoy:F20FuE6rM",
  1360. vcvtpd2ps_2 = "rmoy:660Fu5ArM",
  1361. vcvtps2dq_2 = "rmoy:660Fu5BrM",
  1362. vcvtps2pd_2 = "rro:0Fu5ArM|rx/oq:|rm/yo:",
  1363. vcvtsd2si_2 = "rr/do:F20Fu2DrM|rx/dq:|rr/qo:|rxq:",
  1364. vcvtsd2ss_3 = "rrro:F20FV5ArM|rrx/ooq:",
  1365. vcvtsi2sd_3 = "rrm/ood:F20FV2ArM|rrm/ooq:F20FVX2ArM",
  1366. vcvtsi2ss_3 = "rrm/ood:F30FV2ArM|rrm/ooq:F30FVX2ArM",
  1367. vcvtss2sd_3 = "rrro:F30FV5ArM|rrx/ood:",
  1368. vcvtss2si_2 = "rr/do:F30Fu2DrM|rxd:|rr/qo:|rx/qd:",
  1369. vcvttpd2dq_2 = "rmo:660FuE6rM|rm/oy:660FuLE6rM",
  1370. vcvttps2dq_2 = "rmoy:F30Fu5BrM",
  1371. vcvttsd2si_2 = "rr/do:F20Fu2CrM|rx/dq:|rr/qo:|rxq:",
  1372. vcvttss2si_2 = "rr/do:F30Fu2CrM|rxd:|rr/qo:|rx/qd:",
  1373. vdppd_4 = "rrmio:660F3AV41rMU",
  1374. vdpps_4 = "rrmioy:660F3AV40rMU",
  1375. vextractf128_3 = "mri/oy:660F3AuL19RmU",
  1376. vextractps_3 = "mri/do:660F3Au17RmU",
  1377. vhaddpd_3 = "rrmoy:660FV7CrM",
  1378. vhaddps_3 = "rrmoy:F20FV7CrM",
  1379. vhsubpd_3 = "rrmoy:660FV7DrM",
  1380. vhsubps_3 = "rrmoy:F20FV7DrM",
  1381. vinsertf128_4 = "rrmi/yyo:660F3AV18rMU",
  1382. vinsertps_4 = "rrrio:660F3AV21rMU|rrxi/ood:",
  1383. vldmxcsr_1 = "xd:0FuAE2m",
  1384. vmaskmovps_3 = "rrxoy:660F38V2CrM|xrroy:660F38V2ERm",
  1385. vmaskmovpd_3 = "rrxoy:660F38V2DrM|xrroy:660F38V2FRm",
  1386. vmovapd_2 = "rmoy:660Fu28rM|mroy:660Fu29Rm",
  1387. vmovaps_2 = "rmoy:0Fu28rM|mroy:0Fu29Rm",
  1388. vmovd_2 = "rm/od:660Fu6ErM|rm/oq:660FuX6ErM|mr/do:660Fu7ERm|mr/qo:",
  1389. vmovq_2 = "rro:F30Fu7ErM|rx/oq:|xr/qo:660FuD6Rm",
  1390. vmovddup_2 = "rmy:F20Fu12rM|rro:|rx/oq:",
  1391. vmovhlps_3 = "rrro:0FV12rM",
  1392. vmovhpd_2 = "xr/qo:660Fu17Rm",
  1393. vmovhpd_3 = "rrx/ooq:660FV16rM",
  1394. vmovhps_2 = "xr/qo:0Fu17Rm",
  1395. vmovhps_3 = "rrx/ooq:0FV16rM",
  1396. vmovlhps_3 = "rrro:0FV16rM",
  1397. vmovlpd_2 = "xr/qo:660Fu13Rm",
  1398. vmovlpd_3 = "rrx/ooq:660FV12rM",
  1399. vmovlps_2 = "xr/qo:0Fu13Rm",
  1400. vmovlps_3 = "rrx/ooq:0FV12rM",
  1401. vmovmskpd_2 = "rr/do:660Fu50rM|rr/dy:660FuL50rM",
  1402. vmovmskps_2 = "rr/do:0Fu50rM|rr/dy:0FuL50rM",
  1403. vmovntpd_2 = "xroy:660Fu2BRm",
  1404. vmovntps_2 = "xroy:0Fu2BRm",
  1405. vmovsd_2 = "rx/oq:F20Fu10rM|xr/qo:F20Fu11Rm",
  1406. vmovsd_3 = "rrro:F20FV10rM",
  1407. vmovshdup_2 = "rmoy:F30Fu16rM",
  1408. vmovsldup_2 = "rmoy:F30Fu12rM",
  1409. vmovss_2 = "rx/od:F30Fu10rM|xr/do:F30Fu11Rm",
  1410. vmovss_3 = "rrro:F30FV10rM",
  1411. vmovupd_2 = "rmoy:660Fu10rM|mroy:660Fu11Rm",
  1412. vmovups_2 = "rmoy:0Fu10rM|mroy:0Fu11Rm",
  1413. vorpd_3 = "rrmoy:660FV56rM",
  1414. vorps_3 = "rrmoy:0FV56rM",
  1415. vpermilpd_3 = "rrmoy:660F38V0DrM|rmioy:660F3Au05rMU",
  1416. vpermilps_3 = "rrmoy:660F38V0CrM|rmioy:660F3Au04rMU",
  1417. vperm2f128_4 = "rrmiy:660F3AV06rMU",
  1418. vptestpd_2 = "rmoy:660F38u0FrM",
  1419. vptestps_2 = "rmoy:660F38u0ErM",
  1420. vrcpps_2 = "rmoy:0Fu53rM",
  1421. vrcpss_3 = "rrro:F30FV53rM|rrx/ood:",
  1422. vrsqrtps_2 = "rmoy:0Fu52rM",
  1423. vrsqrtss_3 = "rrro:F30FV52rM|rrx/ood:",
  1424. vroundpd_3 = "rmioy:660F3AV09rMU",
  1425. vroundps_3 = "rmioy:660F3AV08rMU",
  1426. vroundsd_4 = "rrrio:660F3AV0BrMU|rrxi/ooq:",
  1427. vroundss_4 = "rrrio:660F3AV0ArMU|rrxi/ood:",
  1428. vshufpd_4 = "rrmioy:660FVC6rMU",
  1429. vshufps_4 = "rrmioy:0FVC6rMU",
  1430. vsqrtps_2 = "rmoy:0Fu51rM",
  1431. vsqrtss_2 = "rro:F30Fu51rM|rx/od:",
  1432. vsqrtpd_2 = "rmoy:660Fu51rM",
  1433. vsqrtsd_2 = "rro:F20Fu51rM|rx/oq:",
  1434. vstmxcsr_1 = "xd:0FuAE3m",
  1435. vucomisd_2 = "rro:660Fu2ErM|rx/oq:",
  1436. vucomiss_2 = "rro:0Fu2ErM|rx/od:",
  1437. vunpckhpd_3 = "rrmoy:660FV15rM",
  1438. vunpckhps_3 = "rrmoy:0FV15rM",
  1439. vunpcklpd_3 = "rrmoy:660FV14rM",
  1440. vunpcklps_3 = "rrmoy:0FV14rM",
  1441. vxorpd_3 = "rrmoy:660FV57rM",
  1442. vxorps_3 = "rrmoy:0FV57rM",
  1443. vzeroall_0 = "0FuL77",
  1444. vzeroupper_0 = "0Fu77",
  1445. -- AVX2 FP ops
  1446. vbroadcastss_2 = "rx/od:660F38u18rM|rx/yd:|rro:|rr/yo:",
  1447. vbroadcastsd_2 = "rx/yq:660F38u19rM|rr/yo:",
  1448. -- *vgather* (!vsib)
  1449. vpermpd_3 = "rmiy:660F3AuX01rMU",
  1450. vpermps_3 = "rrmy:660F38V16rM",
  1451. -- AVX, AVX2 integer ops
  1452. -- In general, xmm requires AVX, ymm requires AVX2.
  1453. vaesdec_3 = "rrmo:660F38VDErM",
  1454. vaesdeclast_3 = "rrmo:660F38VDFrM",
  1455. vaesenc_3 = "rrmo:660F38VDCrM",
  1456. vaesenclast_3 = "rrmo:660F38VDDrM",
  1457. vaesimc_2 = "rmo:660F38uDBrM",
  1458. vaeskeygenassist_3 = "rmio:660F3AuDFrMU",
  1459. vlddqu_2 = "rxoy:F20FuF0rM",
  1460. vmaskmovdqu_2 = "rro:660FuF7rM",
  1461. vmovdqa_2 = "rmoy:660Fu6FrM|mroy:660Fu7FRm",
  1462. vmovdqu_2 = "rmoy:F30Fu6FrM|mroy:F30Fu7FRm",
  1463. vmovntdq_2 = "xroy:660FuE7Rm",
  1464. vmovntdqa_2 = "rxoy:660F38u2ArM",
  1465. vmpsadbw_4 = "rrmioy:660F3AV42rMU",
  1466. vpabsb_2 = "rmoy:660F38u1CrM",
  1467. vpabsd_2 = "rmoy:660F38u1ErM",
  1468. vpabsw_2 = "rmoy:660F38u1DrM",
  1469. vpackusdw_3 = "rrmoy:660F38V2BrM",
  1470. vpalignr_4 = "rrmioy:660F3AV0FrMU",
  1471. vpblendvb_4 = "rrmroy:660F3AV4CrMs",
  1472. vpblendw_4 = "rrmioy:660F3AV0ErMU",
  1473. vpclmulqdq_4 = "rrmio:660F3AV44rMU",
  1474. vpcmpeqq_3 = "rrmoy:660F38V29rM",
  1475. vpcmpestri_3 = "rmio:660F3Au61rMU",
  1476. vpcmpestrm_3 = "rmio:660F3Au60rMU",
  1477. vpcmpgtq_3 = "rrmoy:660F38V37rM",
  1478. vpcmpistri_3 = "rmio:660F3Au63rMU",
  1479. vpcmpistrm_3 = "rmio:660F3Au62rMU",
  1480. vpextrb_3 = "rri/do:660F3Au14nRmU|rri/qo:|xri/bo:",
  1481. vpextrw_3 = "rri/do:660FuC5rMU|xri/wo:660F3Au15nRmU",
  1482. vpextrd_3 = "mri/do:660F3Au16RmU",
  1483. vpextrq_3 = "mri/qo:660F3Au16RmU",
  1484. vphaddw_3 = "rrmoy:660F38V01rM",
  1485. vphaddd_3 = "rrmoy:660F38V02rM",
  1486. vphaddsw_3 = "rrmoy:660F38V03rM",
  1487. vphminposuw_2 = "rmo:660F38u41rM",
  1488. vphsubw_3 = "rrmoy:660F38V05rM",
  1489. vphsubd_3 = "rrmoy:660F38V06rM",
  1490. vphsubsw_3 = "rrmoy:660F38V07rM",
  1491. vpinsrb_4 = "rrri/ood:660F3AV20rMU|rrxi/oob:",
  1492. vpinsrw_4 = "rrri/ood:660FVC4rMU|rrxi/oow:",
  1493. vpinsrd_4 = "rrmi/ood:660F3AV22rMU",
  1494. vpinsrq_4 = "rrmi/ooq:660F3AVX22rMU",
  1495. vpmaddubsw_3 = "rrmoy:660F38V04rM",
  1496. vpmaxsb_3 = "rrmoy:660F38V3CrM",
  1497. vpmaxsd_3 = "rrmoy:660F38V3DrM",
  1498. vpmaxuw_3 = "rrmoy:660F38V3ErM",
  1499. vpmaxud_3 = "rrmoy:660F38V3FrM",
  1500. vpminsb_3 = "rrmoy:660F38V38rM",
  1501. vpminsd_3 = "rrmoy:660F38V39rM",
  1502. vpminuw_3 = "rrmoy:660F38V3ArM",
  1503. vpminud_3 = "rrmoy:660F38V3BrM",
  1504. vpmovmskb_2 = "rr/do:660FuD7rM|rr/dy:660FuLD7rM",
  1505. vpmovsxbw_2 = "rroy:660F38u20rM|rx/oq:|rx/yo:",
  1506. vpmovsxbd_2 = "rroy:660F38u21rM|rx/od:|rx/yq:",
  1507. vpmovsxbq_2 = "rroy:660F38u22rM|rx/ow:|rx/yd:",
  1508. vpmovsxwd_2 = "rroy:660F38u23rM|rx/oq:|rx/yo:",
  1509. vpmovsxwq_2 = "rroy:660F38u24rM|rx/od:|rx/yq:",
  1510. vpmovsxdq_2 = "rroy:660F38u25rM|rx/oq:|rx/yo:",
  1511. vpmovzxbw_2 = "rroy:660F38u30rM|rx/oq:|rx/yo:",
  1512. vpmovzxbd_2 = "rroy:660F38u31rM|rx/od:|rx/yq:",
  1513. vpmovzxbq_2 = "rroy:660F38u32rM|rx/ow:|rx/yd:",
  1514. vpmovzxwd_2 = "rroy:660F38u33rM|rx/oq:|rx/yo:",
  1515. vpmovzxwq_2 = "rroy:660F38u34rM|rx/od:|rx/yq:",
  1516. vpmovzxdq_2 = "rroy:660F38u35rM|rx/oq:|rx/yo:",
  1517. vpmuldq_3 = "rrmoy:660F38V28rM",
  1518. vpmulhrsw_3 = "rrmoy:660F38V0BrM",
  1519. vpmulld_3 = "rrmoy:660F38V40rM",
  1520. vpshufb_3 = "rrmoy:660F38V00rM",
  1521. vpshufd_3 = "rmioy:660Fu70rMU",
  1522. vpshufhw_3 = "rmioy:F30Fu70rMU",
  1523. vpshuflw_3 = "rmioy:F20Fu70rMU",
  1524. vpsignb_3 = "rrmoy:660F38V08rM",
  1525. vpsignw_3 = "rrmoy:660F38V09rM",
  1526. vpsignd_3 = "rrmoy:660F38V0ArM",
  1527. vpslldq_3 = "rrioy:660Fv737mU",
  1528. vpsllw_3 = "rrmoy:660FVF1rM|rrioy:660Fv716mU",
  1529. vpslld_3 = "rrmoy:660FVF2rM|rrioy:660Fv726mU",
  1530. vpsllq_3 = "rrmoy:660FVF3rM|rrioy:660Fv736mU",
  1531. vpsraw_3 = "rrmoy:660FVE1rM|rrioy:660Fv714mU",
  1532. vpsrad_3 = "rrmoy:660FVE2rM|rrioy:660Fv724mU",
  1533. vpsrldq_3 = "rrioy:660Fv733mU",
  1534. vpsrlw_3 = "rrmoy:660FVD1rM|rrioy:660Fv712mU",
  1535. vpsrld_3 = "rrmoy:660FVD2rM|rrioy:660Fv722mU",
  1536. vpsrlq_3 = "rrmoy:660FVD3rM|rrioy:660Fv732mU",
  1537. vptest_2 = "rmoy:660F38u17rM",
  1538. -- AVX2 integer ops
  1539. vbroadcasti128_2 = "rx/yo:660F38u5ArM",
  1540. vinserti128_4 = "rrmi/yyo:660F3AV38rMU",
  1541. vextracti128_3 = "mri/oy:660F3AuL39RmU",
  1542. vpblendd_4 = "rrmioy:660F3AV02rMU",
  1543. vpbroadcastb_2 = "rro:660F38u78rM|rx/ob:|rr/yo:|rx/yb:",
  1544. vpbroadcastw_2 = "rro:660F38u79rM|rx/ow:|rr/yo:|rx/yw:",
  1545. vpbroadcastd_2 = "rro:660F38u58rM|rx/od:|rr/yo:|rx/yd:",
  1546. vpbroadcastq_2 = "rro:660F38u59rM|rx/oq:|rr/yo:|rx/yq:",
  1547. vpermd_3 = "rrmy:660F38V36rM",
  1548. vpermq_3 = "rmiy:660F3AuX00rMU",
  1549. -- *vpgather* (!vsib)
  1550. vperm2i128_4 = "rrmiy:660F3AV46rMU",
  1551. vpmaskmovd_3 = "rrxoy:660F38V8CrM|xrroy:660F38V8ERm",
  1552. vpmaskmovq_3 = "rrxoy:660F38VX8CrM|xrroy:660F38VX8ERm",
  1553. vpsllvd_3 = "rrmoy:660F38V47rM",
  1554. vpsllvq_3 = "rrmoy:660F38VX47rM",
  1555. vpsravd_3 = "rrmoy:660F38V46rM",
  1556. vpsrlvd_3 = "rrmoy:660F38V45rM",
  1557. vpsrlvq_3 = "rrmoy:660F38VX45rM",
  1558. -- Intel ADX
  1559. adcx_2 = "rmqd:660F38F6rM",
  1560. adox_2 = "rmqd:F30F38F6rM",
  1561. }
  1562. ------------------------------------------------------------------------------
  1563. -- Arithmetic ops.
  1564. for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3,
  1565. ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do
  1566. local n8 = shl(n, 3)
  1567. map_op[name.."_2"] = format(
  1568. "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi",
  1569. 1+n8, 3+n8, n, n, 5+n8, n)
  1570. end
  1571. -- Shift ops.
  1572. for name,n in pairs{ rol = 0, ror = 1, rcl = 2, rcr = 3,
  1573. shl = 4, shr = 5, sar = 7, sal = 4 } do
  1574. map_op[name.."_2"] = format("m1:D1%Xm|mC1qdwb:D3%Xm|mi:C1%XmU", n, n, n)
  1575. end
  1576. -- Conditional ops.
  1577. for cc,n in pairs(map_cc) do
  1578. map_op["j"..cc.."_1"] = format("J.:n0F8%XJ", n) -- short: 7%X
  1579. map_op["set"..cc.."_1"] = format("mb:n0F9%X2m", n)
  1580. map_op["cmov"..cc.."_2"] = format("rmqdw:0F4%XrM", n) -- P6+
  1581. end
  1582. -- FP arithmetic ops.
  1583. for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3,
  1584. sub = 4, subr = 5, div = 6, divr = 7 } do
  1585. local nc = 0xc0 + shl(n, 3)
  1586. local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8))
  1587. local fn = "f"..name
  1588. map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n)
  1589. if n == 2 or n == 3 then
  1590. map_op[fn.."_2"] = format("Fff:D8%02XR|Fx2d:D8%XM|Fx2q:nDC%XM", nc, n, n)
  1591. else
  1592. map_op[fn.."_2"] = format("Fff:D8%02XR|fFf:DC%02Xr|Fx2d:D8%XM|Fx2q:nDC%XM", nc, nr, n, n)
  1593. map_op[fn.."p_1"] = format("ff:DE%02Xr", nr)
  1594. map_op[fn.."p_2"] = format("fFf:DE%02Xr", nr)
  1595. end
  1596. map_op["fi"..name.."_1"] = format("xd:DA%Xm|xw:nDE%Xm", n, n)
  1597. end
  1598. -- FP conditional moves.
  1599. for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do
  1600. local nc = 0xdac0 + shl(band(n, 3), 3) + shl(band(n, 4), 6)
  1601. map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+
  1602. map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+
  1603. end
  1604. -- SSE / AVX FP arithmetic ops.
  1605. for name,n in pairs{ sqrt = 1, add = 8, mul = 9,
  1606. sub = 12, min = 13, div = 14, max = 15 } do
  1607. map_op[name.."ps_2"] = format("rmo:0F5%XrM", n)
  1608. map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n)
  1609. map_op[name.."pd_2"] = format("rmo:660F5%XrM", n)
  1610. map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n)
  1611. if n ~= 1 then
  1612. map_op["v"..name.."ps_3"] = format("rrmoy:0FV5%XrM", n)
  1613. map_op["v"..name.."ss_3"] = format("rrro:F30FV5%XrM|rrx/ood:", n)
  1614. map_op["v"..name.."pd_3"] = format("rrmoy:660FV5%XrM", n)
  1615. map_op["v"..name.."sd_3"] = format("rrro:F20FV5%XrM|rrx/ooq:", n)
  1616. end
  1617. end
  1618. -- SSE2 / AVX / AVX2 integer arithmetic ops (66 0F leaf).
  1619. for name,n in pairs{
  1620. paddb = 0xFC, paddw = 0xFD, paddd = 0xFE, paddq = 0xD4,
  1621. paddsb = 0xEC, paddsw = 0xED, packssdw = 0x6B,
  1622. packsswb = 0x63, packuswb = 0x67, paddusb = 0xDC,
  1623. paddusw = 0xDD, pand = 0xDB, pandn = 0xDF, pavgb = 0xE0,
  1624. pavgw = 0xE3, pcmpeqb = 0x74, pcmpeqd = 0x76,
  1625. pcmpeqw = 0x75, pcmpgtb = 0x64, pcmpgtd = 0x66,
  1626. pcmpgtw = 0x65, pmaddwd = 0xF5, pmaxsw = 0xEE,
  1627. pmaxub = 0xDE, pminsw = 0xEA, pminub = 0xDA,
  1628. pmulhuw = 0xE4, pmulhw = 0xE5, pmullw = 0xD5,
  1629. pmuludq = 0xF4, por = 0xEB, psadbw = 0xF6, psubb = 0xF8,
  1630. psubw = 0xF9, psubd = 0xFA, psubq = 0xFB, psubsb = 0xE8,
  1631. psubsw = 0xE9, psubusb = 0xD8, psubusw = 0xD9,
  1632. punpckhbw = 0x68, punpckhwd = 0x69, punpckhdq = 0x6A,
  1633. punpckhqdq = 0x6D, punpcklbw = 0x60, punpcklwd = 0x61,
  1634. punpckldq = 0x62, punpcklqdq = 0x6C, pxor = 0xEF
  1635. } do
  1636. map_op[name.."_2"] = format("rmo:660F%02XrM", n)
  1637. map_op["v"..name.."_3"] = format("rrmoy:660FV%02XrM", n)
  1638. end
  1639. ------------------------------------------------------------------------------
  1640. local map_vexarg = { u = false, v = 1, V = 2 }
  1641. -- Process pattern string.
  1642. local function dopattern(pat, args, sz, op, needrex)
  1643. local digit, addin, vex
  1644. local opcode = 0
  1645. local szov = sz
  1646. local narg = 1
  1647. local rex = 0
  1648. -- Limit number of section buffer positions used by a single dasm_put().
  1649. -- A single opcode needs a maximum of 6 positions.
  1650. if secpos+6 > maxsecpos then wflush() end
  1651. -- Process each character.
  1652. for c in gmatch(pat.."|", ".") do
  1653. if match(c, "%x") then -- Hex digit.
  1654. digit = byte(c) - 48
  1655. if digit > 48 then digit = digit - 39
  1656. elseif digit > 16 then digit = digit - 7 end
  1657. opcode = opcode*16 + digit
  1658. addin = nil
  1659. elseif c == "n" then -- Disable operand size mods for opcode.
  1660. szov = nil
  1661. elseif c == "X" then -- Force REX.W.
  1662. rex = 8
  1663. elseif c == "L" then -- Force VEX.L.
  1664. vex.l = true
  1665. elseif c == "r" then -- Merge 1st operand regno. into opcode.
  1666. addin = args[1]; opcode = opcode + (addin.reg % 8)
  1667. if narg < 2 then narg = 2 end
  1668. elseif c == "R" then -- Merge 2nd operand regno. into opcode.
  1669. addin = args[2]; opcode = opcode + (addin.reg % 8)
  1670. narg = 3
  1671. elseif c == "m" or c == "M" then -- Encode ModRM/SIB.
  1672. local s
  1673. if addin then
  1674. s = addin.reg
  1675. opcode = opcode - band(s, 7) -- Undo regno opcode merge.
  1676. else
  1677. s = band(opcode, 15) -- Undo last digit.
  1678. opcode = shr(opcode, 4)
  1679. end
  1680. local nn = c == "m" and 1 or 2
  1681. local t = args[nn]
  1682. if narg <= nn then narg = nn + 1 end
  1683. if szov == "q" and rex == 0 then rex = rex + 8 end
  1684. if t.reg and t.reg > 7 then rex = rex + 1 end
  1685. if t.xreg and t.xreg > 7 then rex = rex + 2 end
  1686. if s > 7 then rex = rex + 4 end
  1687. if needrex then rex = rex + 16 end
  1688. local psz, sk = wputop(szov, opcode, rex, vex, s < 0, t.vreg or t.vxreg)
  1689. opcode = nil
  1690. local imark = sub(pat, -1) -- Force a mark (ugly).
  1691. -- Put ModRM/SIB with regno/last digit as spare.
  1692. wputmrmsib(t, imark, s, addin and addin.vreg, psz, sk)
  1693. addin = nil
  1694. elseif map_vexarg[c] ~= nil then -- Encode using VEX prefix
  1695. local b = band(opcode, 255); opcode = shr(opcode, 8)
  1696. local m = 1
  1697. if b == 0x38 then m = 2
  1698. elseif b == 0x3a then m = 3 end
  1699. if m ~= 1 then b = band(opcode, 255); opcode = shr(opcode, 8) end
  1700. if b ~= 0x0f then
  1701. werror("expected `0F', `0F38', or `0F3A' to precede `"..c..
  1702. "' in pattern `"..pat.."' for `"..op.."'")
  1703. end
  1704. local v = map_vexarg[c]
  1705. if v then v = remove(args, v) end
  1706. b = band(opcode, 255)
  1707. local p = 0
  1708. if b == 0x66 then p = 1
  1709. elseif b == 0xf3 then p = 2
  1710. elseif b == 0xf2 then p = 3 end
  1711. if p ~= 0 then opcode = shr(opcode, 8) end
  1712. if opcode ~= 0 then wputop(nil, opcode, 0); opcode = 0 end
  1713. vex = { m = m, p = p, v = v }
  1714. else
  1715. if opcode then -- Flush opcode.
  1716. if szov == "q" and rex == 0 then rex = rex + 8 end
  1717. if needrex then rex = rex + 16 end
  1718. if addin and addin.reg == -1 then
  1719. local psz, sk = wputop(szov, opcode - 7, rex, vex, true)
  1720. wvreg("opcode", addin.vreg, psz, sk)
  1721. else
  1722. if addin and addin.reg > 7 then rex = rex + 1 end
  1723. wputop(szov, opcode, rex, vex)
  1724. end
  1725. opcode = nil
  1726. end
  1727. if c == "|" then break end
  1728. if c == "o" then -- Offset (pure 32 bit displacement).
  1729. wputdarg(args[1].disp); if narg < 2 then narg = 2 end
  1730. elseif c == "O" then
  1731. wputdarg(args[2].disp); narg = 3
  1732. else
  1733. -- Anything else is an immediate operand.
  1734. local a = args[narg]
  1735. narg = narg + 1
  1736. local mode, imm = a.mode, a.imm
  1737. if mode == "iJ" and not match("iIJ", c) then
  1738. werror("bad operand size for label")
  1739. end
  1740. if c == "S" then
  1741. wputsbarg(imm)
  1742. elseif c == "U" then
  1743. wputbarg(imm)
  1744. elseif c == "W" then
  1745. wputwarg(imm)
  1746. elseif c == "i" or c == "I" then
  1747. if mode == "iJ" then
  1748. wputlabel("IMM_", imm, 1)
  1749. elseif mode == "iI" and c == "I" then
  1750. waction(sz == "w" and "IMM_WB" or "IMM_DB", imm)
  1751. else
  1752. wputszarg(sz, imm)
  1753. end
  1754. elseif c == "J" then
  1755. if mode == "iPJ" then
  1756. waction("REL_A", imm) -- !x64 (secpos)
  1757. else
  1758. wputlabel("REL_", imm, 2)
  1759. end
  1760. elseif c == "s" then
  1761. local reg = a.reg
  1762. if reg < 0 then
  1763. wputb(0)
  1764. wvreg("imm.hi", a.vreg)
  1765. else
  1766. wputb(shl(reg, 4))
  1767. end
  1768. else
  1769. werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'")
  1770. end
  1771. end
  1772. end
  1773. end
  1774. end
  1775. ------------------------------------------------------------------------------
  1776. -- Mapping of operand modes to short names. Suppress output with '#'.
  1777. local map_modename = {
  1778. r = "reg", R = "eax", C = "cl", x = "mem", m = "mrm", i = "imm",
  1779. f = "stx", F = "st0", J = "lbl", ["1"] = "1",
  1780. I = "#", S = "#", O = "#",
  1781. }
  1782. -- Return a table/string showing all possible operand modes.
  1783. local function templatehelp(template, nparams)
  1784. if nparams == 0 then return "" end
  1785. local t = {}
  1786. for tm in gmatch(template, "[^%|]+") do
  1787. local s = map_modename[sub(tm, 1, 1)]
  1788. s = s..gsub(sub(tm, 2, nparams), ".", function(c)
  1789. return ", "..map_modename[c]
  1790. end)
  1791. if not match(s, "#") then t[#t+1] = s end
  1792. end
  1793. return t
  1794. end
  1795. -- Match operand modes against mode match part of template.
  1796. local function matchtm(tm, args)
  1797. for i=1,#args do
  1798. if not match(args[i].mode, sub(tm, i, i)) then return end
  1799. end
  1800. return true
  1801. end
  1802. -- Handle opcodes defined with template strings.
  1803. map_op[".template__"] = function(params, template, nparams)
  1804. if not params then return templatehelp(template, nparams) end
  1805. local args = {}
  1806. -- Zero-operand opcodes have no match part.
  1807. if #params == 0 then
  1808. dopattern(template, args, "d", params.op, nil)
  1809. return
  1810. end
  1811. -- Determine common operand size (coerce undefined size) or flag as mixed.
  1812. local sz, szmix, needrex
  1813. for i,p in ipairs(params) do
  1814. args[i] = parseoperand(p)
  1815. local nsz = args[i].opsize
  1816. if nsz then
  1817. if sz and sz ~= nsz then szmix = true else sz = nsz end
  1818. end
  1819. local nrex = args[i].needrex
  1820. if nrex ~= nil then
  1821. if needrex == nil then
  1822. needrex = nrex
  1823. elseif needrex ~= nrex then
  1824. werror("bad mix of byte-addressable registers")
  1825. end
  1826. end
  1827. end
  1828. -- Try all match:pattern pairs (separated by '|').
  1829. local gotmatch, lastpat
  1830. for tm in gmatch(template, "[^%|]+") do
  1831. -- Split off size match (starts after mode match) and pattern string.
  1832. local szm, pat = match(tm, "^(.-):(.*)$", #args+1)
  1833. if pat == "" then pat = lastpat else lastpat = pat end
  1834. if matchtm(tm, args) then
  1835. local prefix = sub(szm, 1, 1)
  1836. if prefix == "/" then -- Exactly match leading operand sizes.
  1837. for i = #szm,1,-1 do
  1838. if i == 1 then
  1839. dopattern(pat, args, sz, params.op, needrex) -- Process pattern.
  1840. return
  1841. elseif args[i-1].opsize ~= sub(szm, i, i) then
  1842. break
  1843. end
  1844. end
  1845. else -- Match common operand size.
  1846. local szp = sz
  1847. if szm == "" then szm = x64 and "qdwb" or "dwb" end -- Default sizes.
  1848. if prefix == "1" then szp = args[1].opsize; szmix = nil
  1849. elseif prefix == "2" then szp = args[2].opsize; szmix = nil end
  1850. if not szmix and (prefix == "." or match(szm, szp or "#")) then
  1851. dopattern(pat, args, szp, params.op, needrex) -- Process pattern.
  1852. return
  1853. end
  1854. end
  1855. gotmatch = true
  1856. end
  1857. end
  1858. local msg = "bad operand mode"
  1859. if gotmatch then
  1860. if szmix then
  1861. msg = "mixed operand size"
  1862. else
  1863. msg = sz and "bad operand size" or "missing operand size"
  1864. end
  1865. end
  1866. werror(msg.." in `"..opmodestr(params.op, args).."'")
  1867. end
  1868. ------------------------------------------------------------------------------
  1869. -- x64-specific opcode for 64 bit immediates and displacements.
  1870. if x64 then
  1871. function map_op.mov64_2(params)
  1872. if not params then return { "reg, imm", "reg, [disp]", "[disp], reg" } end
  1873. if secpos+2 > maxsecpos then wflush() end
  1874. local opcode, op64, sz, rex, vreg
  1875. local op64 = match(params[1], "^%[%s*(.-)%s*%]$")
  1876. if op64 then
  1877. local a = parseoperand(params[2])
  1878. if a.mode ~= "rmR" then werror("bad operand mode") end
  1879. sz = a.opsize
  1880. rex = sz == "q" and 8 or 0
  1881. opcode = 0xa3
  1882. else
  1883. op64 = match(params[2], "^%[%s*(.-)%s*%]$")
  1884. local a = parseoperand(params[1])
  1885. if op64 then
  1886. if a.mode ~= "rmR" then werror("bad operand mode") end
  1887. sz = a.opsize
  1888. rex = sz == "q" and 8 or 0
  1889. opcode = 0xa1
  1890. else
  1891. if sub(a.mode, 1, 1) ~= "r" or a.opsize ~= "q" then
  1892. werror("bad operand mode")
  1893. end
  1894. op64 = params[2]
  1895. if a.reg == -1 then
  1896. vreg = a.vreg
  1897. opcode = 0xb8
  1898. else
  1899. opcode = 0xb8 + band(a.reg, 7)
  1900. end
  1901. rex = a.reg > 7 and 9 or 8
  1902. end
  1903. end
  1904. local psz, sk = wputop(sz, opcode, rex, nil, vreg)
  1905. wvreg("opcode", vreg, psz, sk)
  1906. waction("IMM_D", format("(unsigned int)(%s)", op64))
  1907. waction("IMM_D", format("(unsigned int)((%s)>>32)", op64))
  1908. end
  1909. end
  1910. ------------------------------------------------------------------------------
  1911. -- Pseudo-opcodes for data storage.
  1912. local function op_data(params)
  1913. if not params then return "imm..." end
  1914. local sz = sub(params.op, 2, 2)
  1915. if sz == "a" then sz = addrsize end
  1916. for _,p in ipairs(params) do
  1917. local a = parseoperand(p)
  1918. if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then
  1919. werror("bad mode or size in `"..p.."'")
  1920. end
  1921. if a.mode == "iJ" then
  1922. wputlabel("IMM_", a.imm, 1)
  1923. else
  1924. wputszarg(sz, a.imm)
  1925. end
  1926. if secpos+2 > maxsecpos then wflush() end
  1927. end
  1928. end
  1929. map_op[".byte_*"] = op_data
  1930. map_op[".sbyte_*"] = op_data
  1931. map_op[".word_*"] = op_data
  1932. map_op[".dword_*"] = op_data
  1933. map_op[".aword_*"] = op_data
  1934. ------------------------------------------------------------------------------
  1935. -- Pseudo-opcode to mark the position where the action list is to be emitted.
  1936. map_op[".actionlist_1"] = function(params)
  1937. if not params then return "cvar" end
  1938. local name = params[1] -- No syntax check. You get to keep the pieces.
  1939. wline(function(out) writeactions(out, name) end)
  1940. end
  1941. -- Pseudo-opcode to mark the position where the global enum is to be emitted.
  1942. map_op[".globals_1"] = function(params)
  1943. if not params then return "prefix" end
  1944. local prefix = params[1] -- No syntax check. You get to keep the pieces.
  1945. wline(function(out) writeglobals(out, prefix) end)
  1946. end
  1947. -- Pseudo-opcode to mark the position where the global names are to be emitted.
  1948. map_op[".globalnames_1"] = function(params)
  1949. if not params then return "cvar" end
  1950. local name = params[1] -- No syntax check. You get to keep the pieces.
  1951. wline(function(out) writeglobalnames(out, name) end)
  1952. end
  1953. -- Pseudo-opcode to mark the position where the extern names are to be emitted.
  1954. map_op[".externnames_1"] = function(params)
  1955. if not params then return "cvar" end
  1956. local name = params[1] -- No syntax check. You get to keep the pieces.
  1957. wline(function(out) writeexternnames(out, name) end)
  1958. end
  1959. ------------------------------------------------------------------------------
  1960. -- Label pseudo-opcode (converted from trailing colon form).
  1961. map_op[".label_2"] = function(params)
  1962. if not params then return "[1-9] | ->global | =>pcexpr [, addr]" end
  1963. if secpos+2 > maxsecpos then wflush() end
  1964. local a = parseoperand(params[1])
  1965. local mode, imm = a.mode, a.imm
  1966. if type(imm) == "number" and (mode == "iJ" or (imm >= 1 and imm <= 9)) then
  1967. -- Local label (1: ... 9:) or global label (->global:).
  1968. waction("LABEL_LG", nil, 1)
  1969. wputxb(imm)
  1970. elseif mode == "iJ" then
  1971. -- PC label (=>pcexpr:).
  1972. waction("LABEL_PC", imm)
  1973. else
  1974. werror("bad label definition")
  1975. end
  1976. -- SETLABEL must immediately follow LABEL_LG/LABEL_PC.
  1977. local addr = params[2]
  1978. if addr then
  1979. local a = parseoperand(addr)
  1980. if a.mode == "iPJ" then
  1981. waction("SETLABEL", a.imm)
  1982. else
  1983. werror("bad label assignment")
  1984. end
  1985. end
  1986. end
  1987. map_op[".label_1"] = map_op[".label_2"]
  1988. ------------------------------------------------------------------------------
  1989. -- Alignment pseudo-opcode.
  1990. map_op[".align_1"] = function(params)
  1991. if not params then return "numpow2" end
  1992. if secpos+1 > maxsecpos then wflush() end
  1993. local align = tonumber(params[1]) or map_opsizenum[map_opsize[params[1]]]
  1994. if align then
  1995. local x = align
  1996. -- Must be a power of 2 in the range (2 ... 256).
  1997. for i=1,8 do
  1998. x = x / 2
  1999. if x == 1 then
  2000. waction("ALIGN", nil, 1)
  2001. wputxb(align-1) -- Action byte is 2**n-1.
  2002. return
  2003. end
  2004. end
  2005. end
  2006. werror("bad alignment")
  2007. end
  2008. -- Spacing pseudo-opcode.
  2009. map_op[".space_2"] = function(params)
  2010. if not params then return "num [, filler]" end
  2011. if secpos+1 > maxsecpos then wflush() end
  2012. waction("SPACE", params[1])
  2013. local fill = params[2]
  2014. if fill then
  2015. fill = tonumber(fill)
  2016. if not fill or fill < 0 or fill > 255 then werror("bad filler") end
  2017. end
  2018. wputxb(fill or 0)
  2019. end
  2020. map_op[".space_1"] = map_op[".space_2"]
  2021. ------------------------------------------------------------------------------
  2022. -- Pseudo-opcode for (primitive) type definitions (map to C types).
  2023. map_op[".type_3"] = function(params, nparams)
  2024. if not params then
  2025. return nparams == 2 and "name, ctype" or "name, ctype, reg"
  2026. end
  2027. local name, ctype, reg = params[1], params[2], params[3]
  2028. if not match(name, "^[%a_][%w_]*$") then
  2029. werror("bad type name `"..name.."'")
  2030. end
  2031. local tp = map_type[name]
  2032. if tp then
  2033. werror("duplicate type `"..name.."'")
  2034. end
  2035. if reg and not map_reg_valid_base[reg] then
  2036. werror("bad base register `"..(map_reg_rev[reg] or reg).."'")
  2037. end
  2038. -- Add #type to defines. A bit unclean to put it in map_archdef.
  2039. map_archdef["#"..name] = "sizeof("..ctype..")"
  2040. -- Add new type and emit shortcut define.
  2041. local num = ctypenum + 1
  2042. map_type[name] = {
  2043. ctype = ctype,
  2044. ctypefmt = format("Dt%X(%%s)", num),
  2045. reg = reg,
  2046. }
  2047. wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
  2048. ctypenum = num
  2049. end
  2050. map_op[".type_2"] = map_op[".type_3"]
  2051. -- Dump type definitions.
  2052. local function dumptypes(out, lvl)
  2053. local t = {}
  2054. for name in pairs(map_type) do t[#t+1] = name end
  2055. sort(t)
  2056. out:write("Type definitions:\n")
  2057. for _,name in ipairs(t) do
  2058. local tp = map_type[name]
  2059. local reg = tp.reg and map_reg_rev[tp.reg] or ""
  2060. out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
  2061. end
  2062. out:write("\n")
  2063. end
  2064. ------------------------------------------------------------------------------
  2065. -- Set the current section.
  2066. function _M.section(num)
  2067. waction("SECTION")
  2068. wputxb(num)
  2069. wflush(true) -- SECTION is a terminal action.
  2070. end
  2071. ------------------------------------------------------------------------------
  2072. -- Dump architecture description.
  2073. function _M.dumparch(out)
  2074. out:write(format("DynASM %s version %s, released %s\n\n",
  2075. _info.arch, _info.version, _info.release))
  2076. dumpregs(out)
  2077. dumpactions(out)
  2078. end
  2079. -- Dump all user defined elements.
  2080. function _M.dumpdef(out, lvl)
  2081. dumptypes(out, lvl)
  2082. dumpglobals(out, lvl)
  2083. dumpexterns(out, lvl)
  2084. end
  2085. ------------------------------------------------------------------------------
  2086. -- Pass callbacks from/to the DynASM core.
  2087. function _M.passcb(wl, we, wf, ww)
  2088. wline, werror, wfatal, wwarn = wl, we, wf, ww
  2089. return wflush
  2090. end
  2091. -- Setup the arch-specific module.
  2092. function _M.setup(arch, opt)
  2093. g_arch, g_opt = arch, opt
  2094. end
  2095. -- Merge the core maps and the arch-specific maps.
  2096. function _M.mergemaps(map_coreop, map_def)
  2097. setmetatable(map_op, { __index = map_coreop })
  2098. setmetatable(map_def, { __index = map_archdef })
  2099. return map_op, map_def
  2100. end
  2101. return _M
  2102. ------------------------------------------------------------------------------