dasm_x86.lua 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799
  1. ------------------------------------------------------------------------------
  2. -- DynASM x86 module.
  3. --
  4. -- Copyright (C) 2005-2009 Mike Pall. All rights reserved.
  5. -- See dynasm.lua for full copyright notice.
  6. ------------------------------------------------------------------------------
  7. -- Module information:
  8. local _info = {
  9. arch = "x86",
  10. description = "DynASM x86 (i386) module",
  11. version = "1.2.1",
  12. vernum = 10201,
  13. release = "2009-04-16",
  14. author = "Mike Pall",
  15. license = "MIT",
  16. }
  17. -- Exported glue functions for the arch-specific module.
  18. local _M = { _info = _info }
  19. -- Cache library functions.
  20. local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
  21. local assert, unpack = assert, unpack
  22. local _s = string
  23. local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
  24. local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub
  25. local concat, sort = table.concat, table.sort
  26. local char, unpack = string.char, unpack
  27. -- Inherited tables and callbacks.
  28. local g_opt, g_arch
  29. local wline, werror, wfatal, wwarn
  30. -- Action name list.
  31. -- CHECK: Keep this in sync with the C code!
  32. local action_names = {
  33. -- int arg, 1 buffer pos:
  34. "DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB",
  35. -- action arg (1 byte), int arg, 1 buffer pos (reg/num):
  36. "VREG", "SPACE",
  37. -- ptrdiff_t arg, 1 buffer pos (address): !x64
  38. "SETLABEL", "REL_A",
  39. -- action arg (1 byte) or int arg, 2 buffer pos (link, offset):
  40. "REL_LG", "REL_PC",
  41. -- action arg (1 byte) or int arg, 1 buffer pos (link):
  42. "IMM_LG", "IMM_PC",
  43. -- action arg (1 byte) or int arg, 1 buffer pos (offset):
  44. "LABEL_LG", "LABEL_PC",
  45. -- action arg (1 byte), 1 buffer pos (offset):
  46. "ALIGN",
  47. -- action args (2 bytes), no buffer pos.
  48. "EXTERN",
  49. -- action arg (1 byte), no buffer pos.
  50. "ESC",
  51. -- no action arg, no buffer pos.
  52. "MARK",
  53. -- action arg (1 byte), no buffer pos, terminal action:
  54. "SECTION",
  55. -- no args, no buffer pos, terminal action:
  56. "STOP"
  57. }
  58. -- Maximum number of section buffer positions for dasm_put().
  59. -- CHECK: Keep this in sync with the C code!
  60. local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
  61. -- Action name -> action number (dynamically generated below).
  62. local map_action = {}
  63. -- First action number. Everything below does not need to be escaped.
  64. local actfirst = 256-#action_names
  65. -- Action list buffer and string (only used to remove dupes).
  66. local actlist = {}
  67. local actstr = ""
  68. -- Argument list for next dasm_put(). Start with offset 0 into action list.
  69. local actargs = { 0 }
  70. -- Current number of section buffer positions for dasm_put().
  71. local secpos = 1
  72. ------------------------------------------------------------------------------
  73. -- Compute action numbers for action names.
  74. for n,name in ipairs(action_names) do
  75. local num = actfirst + n - 1
  76. map_action[name] = num
  77. end
  78. -- Dump action names and numbers.
  79. local function dumpactions(out)
  80. out:write("DynASM encoding engine action codes:\n")
  81. for n,name in ipairs(action_names) do
  82. local num = map_action[name]
  83. out:write(format(" %-10s %02X %d\n", name, num, num))
  84. end
  85. out:write("\n")
  86. end
  87. -- Write action list buffer as a huge static C array.
  88. local function writeactions(out, name)
  89. local nn = #actlist
  90. local last = actlist[nn] or 255
  91. actlist[nn] = nil -- Remove last byte.
  92. if nn == 0 then nn = 1 end
  93. out:write("static const unsigned char ", name, "[", nn, "] = {\n")
  94. local s = " "
  95. for n,b in ipairs(actlist) do
  96. s = s..b..","
  97. if #s >= 75 then
  98. assert(out:write(s, "\n"))
  99. s = " "
  100. end
  101. end
  102. out:write(s, last, "\n};\n\n") -- Add last byte back.
  103. end
  104. ------------------------------------------------------------------------------
  105. -- Add byte to action list.
  106. local function wputxb(n)
  107. assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range")
  108. actlist[#actlist+1] = n
  109. end
  110. -- Add action to list with optional arg. Advance buffer pos, too.
  111. local function waction(action, a, num)
  112. wputxb(assert(map_action[action], "bad action name `"..action.."'"))
  113. if a then actargs[#actargs+1] = a end
  114. if a or num then secpos = secpos + (num or 1) end
  115. end
  116. -- Add call to embedded DynASM C code.
  117. local function wcall(func, args)
  118. wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true)
  119. end
  120. -- Delete duplicate action list chunks. A tad slow, but so what.
  121. local function dedupechunk(offset)
  122. local al, as = actlist, actstr
  123. local chunk = char(unpack(al, offset+1, #al))
  124. local orig = find(as, chunk, 1, true)
  125. if orig then
  126. actargs[1] = orig-1 -- Replace with original offset.
  127. for i=offset+1,#al do al[i] = nil end -- Kill dupe.
  128. else
  129. actstr = as..chunk
  130. end
  131. end
  132. -- Flush action list (intervening C code or buffer pos overflow).
  133. local function wflush(term)
  134. local offset = actargs[1]
  135. if #actlist == offset then return end -- Nothing to flush.
  136. if not term then waction("STOP") end -- Terminate action list.
  137. dedupechunk(offset)
  138. wcall("put", actargs) -- Add call to dasm_put().
  139. actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
  140. secpos = 1 -- The actionlist offset occupies a buffer position, too.
  141. end
  142. -- Put escaped byte.
  143. local function wputb(n)
  144. if n >= actfirst then waction("ESC") end -- Need to escape byte.
  145. wputxb(n)
  146. end
  147. ------------------------------------------------------------------------------
  148. -- Global label name -> global label number. With auto assignment on 1st use.
  149. local next_global = 10
  150. local map_global = setmetatable({}, { __index = function(t, name)
  151. if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
  152. local n = next_global
  153. if n > 246 then werror("too many global labels") end
  154. next_global = n + 1
  155. t[name] = n
  156. return n
  157. end})
  158. -- Dump global labels.
  159. local function dumpglobals(out, lvl)
  160. local t = {}
  161. for name, n in pairs(map_global) do t[n] = name end
  162. out:write("Global labels:\n")
  163. for i=10,next_global-1 do
  164. out:write(format(" %s\n", t[i]))
  165. end
  166. out:write("\n")
  167. end
  168. -- Write global label enum.
  169. local function writeglobals(out, prefix)
  170. local t = {}
  171. for name, n in pairs(map_global) do t[n] = name end
  172. out:write("enum {\n")
  173. for i=10,next_global-1 do
  174. out:write(" ", prefix, t[i], ",\n")
  175. end
  176. out:write(" ", prefix, "_MAX\n};\n")
  177. end
  178. -- Write global label names.
  179. local function writeglobalnames(out, name)
  180. local t = {}
  181. for name, n in pairs(map_global) do t[n] = name end
  182. out:write("static const char *const ", name, "[] = {\n")
  183. for i=10,next_global-1 do
  184. out:write(" \"", t[i], "\",\n")
  185. end
  186. out:write(" (const char *)0\n};\n")
  187. end
  188. ------------------------------------------------------------------------------
  189. -- Extern label name -> extern label number. With auto assignment on 1st use.
  190. local next_extern = -1
  191. local map_extern = setmetatable({}, { __index = function(t, name)
  192. -- No restrictions on the name for now.
  193. local n = next_extern
  194. if n < -256 then werror("too many extern labels") end
  195. next_extern = n - 1
  196. t[name] = n
  197. return n
  198. end})
  199. -- Dump extern labels.
  200. local function dumpexterns(out, lvl)
  201. local t = {}
  202. for name, n in pairs(map_extern) do t[-n] = name end
  203. out:write("Extern labels:\n")
  204. for i=1,-next_extern-1 do
  205. out:write(format(" %s\n", t[i]))
  206. end
  207. out:write("\n")
  208. end
  209. -- Write extern label names.
  210. local function writeexternnames(out, name)
  211. local t = {}
  212. for name, n in pairs(map_extern) do t[-n] = name end
  213. out:write("static const char *const ", name, "[] = {\n")
  214. for i=1,-next_extern-1 do
  215. out:write(" \"", t[i], "\",\n")
  216. end
  217. out:write(" (const char *)0\n};\n")
  218. end
  219. ------------------------------------------------------------------------------
  220. -- Arch-specific maps.
  221. local map_archdef = {} -- Ext. register name -> int. name.
  222. local map_reg_rev = {} -- Int. register name -> ext. name.
  223. local map_reg_num = {} -- Int. register name -> register number.
  224. local map_reg_opsize = {} -- Int. register name -> operand size.
  225. local map_reg_valid_base = {} -- Int. register name -> valid base register?
  226. local map_reg_valid_index = {} -- Int. register name -> valid index register?
  227. local reg_list = {} -- Canonical list of int. register names.
  228. local map_type = {} -- Type name -> { ctype, reg }
  229. local ctypenum = 0 -- Type number (for _PTx macros).
  230. local addrsize = "d" -- Size for address operands. !x64
  231. -- Helper function to fill register maps.
  232. local function mkrmap(sz, cl, names)
  233. local cname = format("@%s", sz)
  234. reg_list[#reg_list+1] = cname
  235. map_archdef[cl] = cname
  236. map_reg_rev[cname] = cl
  237. map_reg_num[cname] = -1
  238. map_reg_opsize[cname] = sz
  239. if sz == addrsize then
  240. map_reg_valid_base[cname] = true
  241. map_reg_valid_index[cname] = true
  242. end
  243. for n,name in ipairs(names) do
  244. local iname = format("@%s%x", sz, n-1)
  245. reg_list[#reg_list+1] = iname
  246. map_archdef[name] = iname
  247. map_reg_rev[iname] = name
  248. map_reg_num[iname] = n-1
  249. map_reg_opsize[iname] = sz
  250. if sz == addrsize then
  251. map_reg_valid_base[iname] = true
  252. map_reg_valid_index[iname] = true
  253. end
  254. end
  255. reg_list[#reg_list+1] = ""
  256. end
  257. -- Integer registers (dword, word and byte sized).
  258. mkrmap("d", "Rd", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"})
  259. map_reg_valid_index[map_archdef.esp] = false
  260. mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"})
  261. mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"})
  262. map_archdef["Ra"] = "@"..addrsize
  263. -- FP registers (internally tword sized, but use "f" as operand size).
  264. mkrmap("f", "Rf", {"st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"})
  265. -- SSE registers (oword sized, but qword and dword accessible).
  266. mkrmap("o", "xmm", {"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7"})
  267. -- Operand size prefixes to codes.
  268. local map_opsize = {
  269. byte = "b", word = "w", dword = "d", qword = "q", oword = "o", tword = "t",
  270. aword = addrsize,
  271. }
  272. -- Operand size code to number.
  273. local map_opsizenum = {
  274. b = 1, w = 2, d = 4, q = 8, o = 16, t = 10,
  275. }
  276. -- Operand size code to name.
  277. local map_opsizename = {
  278. b = "byte", w = "word", d = "dword", q = "qword", o = "oword", t = "tword",
  279. f = "fpword",
  280. }
  281. -- Valid index register scale factors.
  282. local map_xsc = {
  283. ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3,
  284. }
  285. -- Condition codes.
  286. local map_cc = {
  287. o = 0, no = 1, b = 2, nb = 3, e = 4, ne = 5, be = 6, nbe = 7,
  288. s = 8, ns = 9, p = 10, np = 11, l = 12, nl = 13, le = 14, nle = 15,
  289. c = 2, nae = 2, nc = 3, ae = 3, z = 4, nz = 5, na = 6, a = 7,
  290. pe = 10, po = 11, nge = 12, ge = 13, ng = 14, g = 15,
  291. }
  292. -- Reverse defines for registers.
  293. function _M.revdef(s)
  294. return gsub(s, "@%w+", map_reg_rev)
  295. end
  296. -- Dump register names and numbers
  297. local function dumpregs(out)
  298. out:write("Register names, sizes and internal numbers:\n")
  299. for _,reg in ipairs(reg_list) do
  300. if reg == "" then
  301. out:write("\n")
  302. else
  303. local name = map_reg_rev[reg]
  304. local num = map_reg_num[reg]
  305. local opsize = map_opsizename[map_reg_opsize[reg]]
  306. out:write(format(" %-5s %-8s %s\n", name, opsize,
  307. num < 0 and "(variable)" or num))
  308. end
  309. end
  310. end
  311. ------------------------------------------------------------------------------
  312. -- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC).
  313. local function wputlabel(aprefix, imm, num)
  314. if type(imm) == "number" then
  315. if imm < 0 then
  316. waction("EXTERN")
  317. wputxb(aprefix == "IMM_" and 0 or 1)
  318. imm = -imm-1
  319. else
  320. waction(aprefix.."LG", nil, num);
  321. end
  322. wputxb(imm)
  323. else
  324. waction(aprefix.."PC", imm, num)
  325. end
  326. end
  327. -- Put signed byte or arg.
  328. local function wputsbarg(n)
  329. if type(n) == "number" then
  330. if n < -128 or n > 127 then
  331. werror("signed immediate byte out of range")
  332. end
  333. if n < 0 then n = n + 256 end
  334. wputb(n)
  335. else waction("IMM_S", n) end
  336. end
  337. -- Put unsigned byte or arg.
  338. local function wputbarg(n)
  339. if type(n) == "number" then
  340. if n < 0 or n > 255 then
  341. werror("unsigned immediate byte out of range")
  342. end
  343. wputb(n)
  344. else waction("IMM_B", n) end
  345. end
  346. -- Put unsigned word or arg.
  347. local function wputwarg(n)
  348. if type(n) == "number" then
  349. if n < 0 or n > 65535 then
  350. werror("unsigned immediate word out of range")
  351. end
  352. local r = n%256; n = (n-r)/256; wputb(r); wputb(n);
  353. else waction("IMM_W", n) end
  354. end
  355. -- Put signed or unsigned dword or arg.
  356. local function wputdarg(n)
  357. local tn = type(n)
  358. if tn == "number" then
  359. if n < 0 then n = n + 4294967296 end
  360. local r = n%256; n = (n-r)/256; wputb(r);
  361. r = n%256; n = (n-r)/256; wputb(r);
  362. r = n%256; n = (n-r)/256; wputb(r); wputb(n);
  363. elseif tn == "table" then
  364. wputlabel("IMM_", n[1], 1)
  365. else
  366. waction("IMM_D", n)
  367. end
  368. end
  369. -- Put operand-size dependent number or arg (defaults to dword).
  370. local function wputszarg(sz, n)
  371. if not sz or sz == "d" then wputdarg(n)
  372. elseif sz == "w" then wputwarg(n)
  373. elseif sz == "b" then wputbarg(n)
  374. elseif sz == "s" then wputsbarg(n)
  375. else werror("bad operand size") end
  376. end
  377. -- Put multi-byte opcode with operand-size dependent modifications.
  378. local function wputop(sz, op)
  379. local r
  380. if sz == "w" then wputb(102) end
  381. -- Needs >32 bit numbers, but only for crc32 eax, word [ebx]
  382. if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end
  383. if op >= 16777216 then r = op % 16777216 wputb((op-r) / 16777216) op = r end
  384. if op >= 65536 then r = op % 65536 wputb((op-r) / 65536) op = r end
  385. if op >= 256 then r = op % 256 wputb((op-r) / 256) op = r end
  386. if sz == "b" then op = op - 1 end
  387. wputb(op)
  388. end
  389. -- Put ModRM or SIB formatted byte.
  390. local function wputmodrm(m, s, rm, vs, vrm)
  391. assert(m < 4 and s < 8 and rm < 8, "bad modrm operands")
  392. wputb(64*m + 8*s + rm)
  393. end
  394. -- Put ModRM/SIB plus optional displacement.
  395. local function wputmrmsib(t, imark, s, vsreg)
  396. local vreg, vxreg
  397. local reg, xreg = t.reg, t.xreg
  398. if reg and reg < 0 then reg = 0; vreg = t.vreg end
  399. if xreg and xreg < 0 then xreg = 0; vxreg = t.vxreg end
  400. if s < 0 then s = 0 end
  401. -- Register mode.
  402. if sub(t.mode, 1, 1) == "r" then
  403. wputmodrm(3, s, reg)
  404. if vsreg then waction("VREG", vsreg); wputxb(2) end
  405. if vreg then waction("VREG", vreg); wputxb(0) end
  406. return
  407. end
  408. local disp = t.disp
  409. local tdisp = type(disp)
  410. -- No base register?
  411. if not reg then
  412. if xreg then
  413. -- Indexed mode with index register only.
  414. -- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp)
  415. wputmodrm(0, s, 4)
  416. if imark then waction("MARK") end
  417. if vsreg then waction("VREG", vsreg); wputxb(2) end
  418. wputmodrm(t.xsc, xreg, 5)
  419. if vxreg then waction("VREG", vxreg); wputxb(3) end
  420. else
  421. -- Pure displacement.
  422. wputmodrm(0, s, 5) -- [disp] -> (0, s, ebp)
  423. if imark then waction("MARK") end
  424. if vsreg then waction("VREG", vsreg); wputxb(2) end
  425. end
  426. wputdarg(disp)
  427. return
  428. end
  429. local m
  430. if tdisp == "number" then -- Check displacement size at assembly time.
  431. if disp == 0 and reg ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too)
  432. if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0]
  433. elseif disp >= -128 and disp <= 127 then m = 1
  434. else m = 2 end
  435. elseif tdisp == "table" then
  436. m = 2
  437. end
  438. -- Index register present or esp as base register: need SIB encoding.
  439. if xreg or reg == 4 then
  440. wputmodrm(m or 2, s, 4) -- ModRM.
  441. if m == nil or imark then waction("MARK") end
  442. if vsreg then waction("VREG", vsreg); wputxb(2) end
  443. wputmodrm(t.xsc or 0, xreg or 4, reg) -- SIB.
  444. if vxreg then waction("VREG", vxreg); wputxb(3) end
  445. if vreg then waction("VREG", vreg); wputxb(1) end
  446. else
  447. wputmodrm(m or 2, s, reg) -- ModRM.
  448. if (imark and (m == 1 or m == 2)) or
  449. (m == nil and (vsreg or vreg)) then waction("MARK") end
  450. if vsreg then waction("VREG", vsreg); wputxb(2) end
  451. if vreg then waction("VREG", vreg); wputxb(1) end
  452. end
  453. -- Put displacement.
  454. if m == 1 then wputsbarg(disp)
  455. elseif m == 2 then wputdarg(disp)
  456. elseif m == nil then waction("DISP", disp) end
  457. end
  458. ------------------------------------------------------------------------------
  459. -- Return human-readable operand mode string.
  460. local function opmodestr(op, args)
  461. local m = {}
  462. for i=1,#args do
  463. local a = args[i]
  464. m[#m+1] = sub(a.mode, 1, 1)..(a.opsize or "?")
  465. end
  466. return op.." "..concat(m, ",")
  467. end
  468. -- Convert number to valid integer or nil.
  469. local function toint(expr)
  470. local n = tonumber(expr)
  471. if n then
  472. if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then
  473. werror("bad integer number `"..expr.."'")
  474. end
  475. return n
  476. end
  477. end
  478. -- Parse immediate expression.
  479. local function immexpr(expr)
  480. -- &expr (pointer)
  481. if sub(expr, 1, 1) == "&" then
  482. return "iPJ", format("(ptrdiff_t)(%s)", sub(expr,2))
  483. end
  484. local prefix = sub(expr, 1, 2)
  485. -- =>expr (pc label reference)
  486. if prefix == "=>" then
  487. return "iJ", sub(expr, 3)
  488. end
  489. -- ->name (global label reference)
  490. if prefix == "->" then
  491. return "iJ", map_global[sub(expr, 3)]
  492. end
  493. -- [<>][1-9] (local label reference)
  494. local dir, lnum = match(expr, "^([<>])([1-9])$")
  495. if dir then -- Fwd: 247-255, Bkwd: 1-9.
  496. return "iJ", lnum + (dir == ">" and 246 or 0)
  497. end
  498. local extname = match(expr, "^extern%s+(%S+)$")
  499. if extname then
  500. return "iJ", map_extern[extname]
  501. end
  502. -- expr (interpreted as immediate)
  503. return "iI", expr
  504. end
  505. -- Parse displacement expression: +-num, +-expr, +-opsize*num
  506. local function dispexpr(expr)
  507. local disp = expr == "" and 0 or toint(expr)
  508. if disp then return disp end
  509. local c, dispt = match(expr, "^([+-])%s*(.+)$")
  510. if c == "+" then
  511. expr = dispt
  512. elseif not c then
  513. werror("bad displacement expression `"..expr.."'")
  514. end
  515. local opsize, tailops = match(dispt, "^(%w+)%s*%*%s*(.+)$")
  516. local ops, imm = map_opsize[opsize], toint(tailops)
  517. if ops and imm then
  518. if c == "-" then imm = -imm end
  519. return imm*map_opsizenum[ops]
  520. end
  521. local mode, iexpr = immexpr(dispt)
  522. if mode == "iJ" then
  523. if c == "-" then werror("cannot invert label reference") end
  524. return { iexpr }
  525. end
  526. return expr -- Need to return original signed expression.
  527. end
  528. -- Parse register or type expression.
  529. local function rtexpr(expr)
  530. if not expr then return end
  531. local tname, ovreg = match(expr, "^([%w_]+):(@[%w_]+)$")
  532. local tp = map_type[tname or expr]
  533. if tp then
  534. local reg = ovreg or tp.reg
  535. local rnum = map_reg_num[reg]
  536. if not rnum then
  537. werror("type `"..(tname or expr).."' needs a register override")
  538. end
  539. if not map_reg_valid_base[reg] then
  540. werror("bad base register override `"..(map_reg_rev[reg] or reg).."'")
  541. end
  542. return reg, rnum, tp
  543. end
  544. return expr, map_reg_num[expr]
  545. end
  546. -- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.
  547. local function parseoperand(param)
  548. local t = {}
  549. local expr = param
  550. local opsize, tailops = match(param, "^(%w+)%s*(.+)$")
  551. if opsize then
  552. t.opsize = map_opsize[opsize]
  553. if t.opsize then expr = tailops end
  554. end
  555. local br = match(expr, "^%[%s*(.-)%s*%]$")
  556. repeat
  557. if br then
  558. t.mode = "xm"
  559. -- [disp]
  560. t.disp = toint(br)
  561. if t.disp then
  562. t.mode = "xmO"
  563. break
  564. end
  565. -- [reg...]
  566. local tp
  567. local reg, tailr = match(br, "^([@%w_:]+)%s*(.*)$")
  568. reg, t.reg, tp = rtexpr(reg)
  569. if not t.reg then
  570. -- [expr]
  571. t.mode = "xmO"
  572. t.disp = dispexpr("+"..br)
  573. break
  574. end
  575. if t.reg == -1 then
  576. t.vreg, tailr = match(tailr, "^(%b())(.*)$")
  577. if not t.vreg then werror("bad variable register expression") end
  578. end
  579. -- [xreg*xsc] or [xreg*xsc+-disp] or [xreg*xsc+-expr]
  580. local xsc, tailsc = match(tailr, "^%*%s*([1248])%s*(.*)$")
  581. if xsc then
  582. if not map_reg_valid_index[reg] then
  583. werror("bad index register `"..map_reg_rev[reg].."'")
  584. end
  585. t.xsc = map_xsc[xsc]
  586. t.xreg = t.reg
  587. t.vxreg = t.vreg
  588. t.reg = nil
  589. t.vreg = nil
  590. t.disp = dispexpr(tailsc)
  591. break
  592. end
  593. if not map_reg_valid_base[reg] then
  594. werror("bad base register `"..map_reg_rev[reg].."'")
  595. end
  596. -- [reg] or [reg+-disp]
  597. t.disp = toint(tailr) or (tailr == "" and 0)
  598. if t.disp then break end
  599. -- [reg+xreg...]
  600. local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$")
  601. xreg, t.xreg, tp = rtexpr(xreg)
  602. if not t.xreg then
  603. -- [reg+-expr]
  604. t.disp = dispexpr(tailr)
  605. break
  606. end
  607. if not map_reg_valid_index[xreg] then
  608. werror("bad index register `"..map_reg_rev[xreg].."'")
  609. end
  610. if t.xreg == -1 then
  611. t.vxreg, tailx = match(tailx, "^(%b())(.*)$")
  612. if not t.vxreg then werror("bad variable register expression") end
  613. end
  614. -- [reg+xreg*xsc...]
  615. local xsc, tailsc = match(tailx, "^%*%s*([1248])%s*(.*)$")
  616. if xsc then
  617. t.xsc = map_xsc[xsc]
  618. tailx = tailsc
  619. end
  620. -- [...] or [...+-disp] or [...+-expr]
  621. t.disp = dispexpr(tailx)
  622. else
  623. -- imm or opsize*imm
  624. local imm = toint(expr)
  625. if not imm and sub(expr, 1, 1) == "*" and t.opsize then
  626. imm = toint(sub(expr, 2))
  627. if imm then
  628. imm = imm * map_opsizenum[t.opsize]
  629. t.opsize = nil
  630. end
  631. end
  632. if imm then
  633. if t.opsize then werror("bad operand size override") end
  634. local m = "i"
  635. if imm == 1 then m = m.."1" end
  636. if imm >= 4294967168 and imm <= 4294967295 then imm = imm-4294967296 end
  637. if imm >= -128 and imm <= 127 then m = m.."S" end
  638. t.imm = imm
  639. t.mode = m
  640. break
  641. end
  642. local tp
  643. local reg, tailr = match(expr, "^([@%w_:]+)%s*(.*)$")
  644. reg, t.reg, tp = rtexpr(reg)
  645. if t.reg then
  646. if t.reg == -1 then
  647. t.vreg, tailr = match(tailr, "^(%b())(.*)$")
  648. if not t.vreg then werror("bad variable register expression") end
  649. end
  650. -- reg
  651. if tailr == "" then
  652. if t.opsize then werror("bad operand size override") end
  653. t.opsize = map_reg_opsize[reg]
  654. if t.opsize == "f" then
  655. t.mode = t.reg == 0 and "fF" or "f"
  656. else
  657. if reg == "@w4" then wwarn("bad idea, try again with `esp'") end
  658. t.mode = t.reg == 0 and "rmR" or (reg == "@b1" and "rmC" or "rm")
  659. end
  660. break
  661. end
  662. -- type[idx], type[idx].field, type->field -> [reg+offset_expr]
  663. if not tp then werror("bad operand `"..param.."'") end
  664. t.mode = "xm"
  665. t.disp = format(tp.ctypefmt, tailr)
  666. else
  667. t.mode, t.imm = immexpr(expr)
  668. if sub(t.mode, -1) == "J" then
  669. if t.opsize and t.opsize ~= addrsize then
  670. werror("bad operand size override")
  671. end
  672. t.opsize = addrsize
  673. end
  674. end
  675. end
  676. until true
  677. return t
  678. end
  679. ------------------------------------------------------------------------------
  680. -- x86 Template String Description
  681. -- ===============================
  682. --
  683. -- Each template string is a list of [match:]pattern pairs,
  684. -- separated by "|". The first match wins. No match means a
  685. -- bad or unsupported combination of operand modes or sizes.
  686. --
  687. -- The match part and the ":" is omitted if the operation has
  688. -- no operands. Otherwise the first N characters are matched
  689. -- against the mode strings of each of the N operands.
  690. --
  691. -- The mode string for each operand type is (see parseoperand()):
  692. -- Integer register: "rm", +"R" for eax, ax, al, +"C" for cl
  693. -- FP register: "f", +"F" for st0
  694. -- Index operand: "xm", +"O" for [disp] (pure offset)
  695. -- Immediate: "i", +"S" for signed 8 bit, +"1" for 1,
  696. -- +"I" for arg, +"P" for pointer
  697. -- Any: +"J" for valid jump targets
  698. --
  699. -- So a match character "m" (mixed) matches both an integer register
  700. -- and an index operand (to be encoded with the ModRM/SIB scheme).
  701. -- But "r" matches only a register and "x" only an index operand
  702. -- (e.g. for FP memory access operations).
  703. --
  704. -- The operand size match string starts right after the mode match
  705. -- characters and ends before the ":". "dwb" is assumed, if empty.
  706. -- The effective data size of the operation is matched against this list.
  707. --
  708. -- If only the regular "b", "w", "d", "q", "t" operand sizes are
  709. -- present, then all operands must be the same size. Unspecified sizes
  710. -- are ignored, but at least one operand must have a size or the pattern
  711. -- won't match (use the "byte", "word", "dword", "qword", "tword"
  712. -- operand size overrides. E.g.: mov dword [eax], 1).
  713. --
  714. -- If the list has a "1" or "2" prefix, the operand size is taken
  715. -- from the respective operand and any other operand sizes are ignored.
  716. -- If the list contains only ".", all operand sizes are ignored.
  717. -- If the list has a "/" prefix, the concatenated (mixed) operand sizes
  718. -- are compared to the match.
  719. --
  720. -- E.g. "rrdw" matches for either two dword registers or two word
  721. -- registers. "Fx2dq" matches an st0 operand plus an index operand
  722. -- pointing to a dword (float) or qword (double).
  723. --
  724. -- Every character after the ":" is part of the pattern string:
  725. -- Hex chars are accumulated to form the opcode (left to right).
  726. -- "n" disables the standard opcode mods
  727. -- (otherwise: -1 for "b", o16 prefix for "w")
  728. -- "r"/"R" adds the reg. number from the 1st/2nd operand to the opcode.
  729. -- "m"/"M" generates ModRM/SIB from the 1st/2nd operand.
  730. -- The spare 3 bits are either filled with the last hex digit or
  731. -- the result from a previous "r"/"R". The opcode is restored.
  732. --
  733. -- All of the following characters force a flush of the opcode:
  734. -- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand.
  735. -- "S" stores a signed 8 bit immediate from the last operand.
  736. -- "U" stores an unsigned 8 bit immediate from the last operand.
  737. -- "W" stores an unsigned 16 bit immediate from the last operand.
  738. -- "i" stores an operand sized immediate from the last operand.
  739. -- "I" dito, but generates an action code to optionally modify
  740. -- the opcode (+2) for a signed 8 bit immediate.
  741. -- "J" generates one of the REL action codes from the last operand.
  742. --
  743. ------------------------------------------------------------------------------
  744. -- Template strings for x86 instructions. Ordered by first opcode byte.
  745. -- Unimplemented opcodes (deliberate omissions) are marked with *.
  746. local map_op = {
  747. -- 00-05: add...
  748. -- 06: *push es
  749. -- 07: *pop es
  750. -- 08-0D: or...
  751. -- 0E: *push cs
  752. -- 0F: two byte opcode prefix
  753. -- 10-15: adc...
  754. -- 16: *push ss
  755. -- 17: *pop ss
  756. -- 18-1D: sbb...
  757. -- 1E: *push ds
  758. -- 1F: *pop ds
  759. -- 20-25: and...
  760. es_0 = "26",
  761. -- 27: *daa
  762. -- 28-2D: sub...
  763. cs_0 = "2E",
  764. -- 2F: *das
  765. -- 30-35: xor...
  766. ss_0 = "36",
  767. -- 37: *aaa
  768. -- 38-3D: cmp...
  769. ds_0 = "3E",
  770. -- 3F: *aas
  771. inc_1 = "rdw:40r|m:FF0m",
  772. dec_1 = "rdw:48r|m:FF1m",
  773. push_1 = "rdw:50r|mdw:FF6m|S.:6AS|ib:n6Ai|i.:68i",
  774. pop_1 = "rdw:58r|mdw:8F0m",
  775. -- 60: *pusha, *pushad, *pushaw
  776. -- 61: *popa, *popad, *popaw
  777. -- 62: *bound rdw,x
  778. -- 63: *arpl mw,rw
  779. fs_0 = "64",
  780. gs_0 = "65",
  781. o16_0 = "66",
  782. a16_0 = "67",
  783. -- 68: push idw
  784. -- 69: imul rdw,mdw,idw
  785. -- 6A: push ib
  786. -- 6B: imul rdw,mdw,S
  787. -- 6C: *insb
  788. -- 6D: *insd, *insw
  789. -- 6E: *outsb
  790. -- 6F: *outsd, *outsw
  791. -- 70-7F: jcc lb
  792. -- 80: add... mb,i
  793. -- 81: add... mdw,i
  794. -- 82: *undefined
  795. -- 83: add... mdw,S
  796. test_2 = "mr:85Rm|rm:85rM|Ri:A9ri|mi:F70mi",
  797. -- 86: xchg rb,mb
  798. -- 87: xchg rdw,mdw
  799. -- 88: mov mb,r
  800. -- 89: mov mdw,r
  801. -- 8A: mov r,mb
  802. -- 8B: mov r,mdw
  803. -- 8C: *mov mdw,seg
  804. lea_2 = "rxd:8DrM",
  805. -- 8E: *mov seg,mdw
  806. -- 8F: pop mdw
  807. nop_0 = "90",
  808. xchg_2 = "Rrdw:90R|rRdw:90r|rm:87rM|mr:87Rm",
  809. cbw_0 = "6698",
  810. cwde_0 = "98",
  811. cwd_0 = "6699",
  812. cdq_0 = "99",
  813. -- 9A: *call iw:idw
  814. wait_0 = "9B",
  815. fwait_0 = "9B",
  816. pushf_0 = "9C",
  817. pushfw_0 = "669C",
  818. pushfd_0 = "9C",
  819. popf_0 = "9D",
  820. popfw_0 = "669D",
  821. popfd_0 = "9D",
  822. sahf_0 = "9E",
  823. lahf_0 = "9F",
  824. mov_2 = "OR:A3o|RO:A1O|mr:89Rm|rm:8BrM|rib:nB0ri|ridw:B8ri|mi:C70mi",
  825. movsb_0 = "A4",
  826. movsw_0 = "66A5",
  827. movsd_0 = "A5",
  828. cmpsb_0 = "A6",
  829. cmpsw_0 = "66A7",
  830. cmpsd_0 = "A7",
  831. -- A8: test Rb,i
  832. -- A9: test Rdw,i
  833. stosb_0 = "AA",
  834. stosw_0 = "66AB",
  835. stosd_0 = "AB",
  836. lodsb_0 = "AC",
  837. lodsw_0 = "66AD",
  838. lodsd_0 = "AD",
  839. scasb_0 = "AE",
  840. scasw_0 = "66AF",
  841. scasd_0 = "AF",
  842. -- B0-B7: mov rb,i
  843. -- B8-BF: mov rdw,i
  844. -- C0: rol... mb,i
  845. -- C1: rol... mdw,i
  846. ret_1 = "i.:nC2W",
  847. ret_0 = "C3",
  848. -- C4: *les rdw,mq
  849. -- C5: *lds rdw,mq
  850. -- C6: mov mb,i
  851. -- C7: mov mdw,i
  852. -- C8: *enter iw,ib
  853. leave_0 = "C9",
  854. -- CA: *retf iw
  855. -- CB: *retf
  856. int3_0 = "CC",
  857. int_1 = "i.:nCDU",
  858. into_0 = "CE",
  859. -- CF: *iret
  860. -- D0: rol... mb,1
  861. -- D1: rol... mdw,1
  862. -- D2: rol... mb,cl
  863. -- D3: rol... mb,cl
  864. -- D4: *aam ib
  865. -- D5: *aad ib
  866. -- D6: *salc
  867. -- D7: *xlat
  868. -- D8-DF: floating point ops
  869. -- E0: *loopne
  870. -- E1: *loope
  871. -- E2: *loop
  872. -- E3: *jcxz, *jecxz
  873. -- E4: *in Rb,ib
  874. -- E5: *in Rdw,ib
  875. -- E6: *out ib,Rb
  876. -- E7: *out ib,Rdw
  877. call_1 = "md:FF2m|J.:E8J",
  878. jmp_1 = "md:FF4m|J.:E9J", -- short: EB
  879. -- EA: *jmp iw:idw
  880. -- EB: jmp ib
  881. -- EC: *in Rb,dx
  882. -- ED: *in Rdw,dx
  883. -- EE: *out dx,Rb
  884. -- EF: *out dx,Rdw
  885. -- F0: *lock
  886. int1_0 = "F1",
  887. repne_0 = "F2",
  888. repnz_0 = "F2",
  889. rep_0 = "F3",
  890. repe_0 = "F3",
  891. repz_0 = "F3",
  892. -- F4: *hlt
  893. cmc_0 = "F5",
  894. -- F6: test... mb,i; div... mb
  895. -- F7: test... mdw,i; div... mdw
  896. clc_0 = "F8",
  897. stc_0 = "F9",
  898. -- FA: *cli
  899. cld_0 = "FC",
  900. std_0 = "FD",
  901. -- FE: inc... mb
  902. -- FF: inc... mdw
  903. -- misc ops
  904. not_1 = "m:F72m",
  905. neg_1 = "m:F73m",
  906. mul_1 = "m:F74m",
  907. imul_1 = "m:F75m",
  908. div_1 = "m:F76m",
  909. idiv_1 = "m:F77m",
  910. imul_2 = "rmdw:0FAFrM|rIdw:69rmI|rSdw:6BrmS|ridw:69rmi",
  911. imul_3 = "rmIdw:69rMI|rmSdw:6BrMS|rmidw:69rMi",
  912. movzx_2 = "rm/db:0FB6rM|rm/wb:0FB6rM|rm/dw:0FB7rM",
  913. movsx_2 = "rm/db:0FBErM|rm/wb:0FBErM|rm/dw:0FBFrM",
  914. bswap_1 = "rd:0FC8r",
  915. bsf_2 = "rmdw:0FBCrM",
  916. bsr_2 = "rmdw:0FBDrM",
  917. bt_2 = "mrdw:0FA3Rm|midw:0FBA4mU",
  918. btc_2 = "mrdw:0FBBRm|midw:0FBA7mU",
  919. btr_2 = "mrdw:0FB3Rm|midw:0FBA6mU",
  920. bts_2 = "mrdw:0FABRm|midw:0FBA5mU",
  921. rdtsc_0 = "0F31", -- P1+
  922. cpuid_0 = "0FA2", -- P1+
  923. -- floating point ops
  924. fst_1 = "ff:DDD0r|xd:D92m|xq:DD2m",
  925. fstp_1 = "ff:DDD8r|xd:D93m|xq:DD3m|xt:DB7m",
  926. fld_1 = "ff:D9C0r|xd:D90m|xq:DD0m|xt:DB5m",
  927. fpop_0 = "DDD8", -- Alias for fstp st0.
  928. fist_1 = "xw:nDF2m|xd:DB2m",
  929. fistp_1 = "xw:nDF3m|xd:DB3m|xq:DF7m",
  930. fild_1 = "xw:nDF0m|xd:DB0m|xq:DF5m",
  931. fxch_0 = "D9C9",
  932. fxch_1 = "ff:D9C8r",
  933. fxch_2 = "fFf:D9C8r|Fff:D9C8R",
  934. fucom_1 = "ff:DDE0r",
  935. fucom_2 = "Fff:DDE0R",
  936. fucomp_1 = "ff:DDE8r",
  937. fucomp_2 = "Fff:DDE8R",
  938. fucomi_1 = "ff:DBE8r", -- P6+
  939. fucomi_2 = "Fff:DBE8R", -- P6+
  940. fucomip_1 = "ff:DFE8r", -- P6+
  941. fucomip_2 = "Fff:DFE8R", -- P6+
  942. fcomi_1 = "ff:DBF0r", -- P6+
  943. fcomi_2 = "Fff:DBF0R", -- P6+
  944. fcomip_1 = "ff:DFF0r", -- P6+
  945. fcomip_2 = "Fff:DFF0R", -- P6+
  946. fucompp_0 = "DAE9",
  947. fcompp_0 = "DED9",
  948. fldcw_1 = "xw:nD95m",
  949. fstcw_1 = "xw:n9BD97m",
  950. fnstcw_1 = "xw:nD97m",
  951. fstsw_1 = "Rw:n9BDFE0|xw:n9BDD7m",
  952. fnstsw_1 = "Rw:nDFE0|xw:nDD7m",
  953. fclex_0 = "9BDBE2",
  954. fnclex_0 = "DBE2",
  955. fnop_0 = "D9D0",
  956. -- D9D1-D9DF: unassigned
  957. fchs_0 = "D9E0",
  958. fabs_0 = "D9E1",
  959. -- D9E2: unassigned
  960. -- D9E3: unassigned
  961. ftst_0 = "D9E4",
  962. fxam_0 = "D9E5",
  963. -- D9E6: unassigned
  964. -- D9E7: unassigned
  965. fld1_0 = "D9E8",
  966. fldl2t_0 = "D9E9",
  967. fldl2e_0 = "D9EA",
  968. fldpi_0 = "D9EB",
  969. fldlg2_0 = "D9EC",
  970. fldln2_0 = "D9ED",
  971. fldz_0 = "D9EE",
  972. -- D9EF: unassigned
  973. f2xm1_0 = "D9F0",
  974. fyl2x_0 = "D9F1",
  975. fptan_0 = "D9F2",
  976. fpatan_0 = "D9F3",
  977. fxtract_0 = "D9F4",
  978. fprem1_0 = "D9F5",
  979. fdecstp_0 = "D9F6",
  980. fincstp_0 = "D9F7",
  981. fprem_0 = "D9F8",
  982. fyl2xp1_0 = "D9F9",
  983. fsqrt_0 = "D9FA",
  984. fsincos_0 = "D9FB",
  985. frndint_0 = "D9FC",
  986. fscale_0 = "D9FD",
  987. fsin_0 = "D9FE",
  988. fcos_0 = "D9FF",
  989. -- SSE, SSE2
  990. andnpd_2 = "rmo:660F55rM",
  991. andnps_2 = "rmo:0F55rM",
  992. andpd_2 = "rmo:660F54rM",
  993. andps_2 = "rmo:0F54rM",
  994. clflush_1 = "x.:0FAE7m",
  995. cmppd_3 = "rmio:660FC2rMU",
  996. cmpps_3 = "rmio:0FC2rMU",
  997. cmpsd_3 = "rmio:F20FC2rMU",
  998. cmpss_3 = "rmio:F30FC2rMU",
  999. comisd_2 = "rmo:660F2FrM",
  1000. comiss_2 = "rmo:0F2FrM",
  1001. cvtdq2pd_2 = "rro:F30FE6rM|rx/oq:",
  1002. cvtdq2ps_2 = "rmo:0F5BrM",
  1003. cvtpd2dq_2 = "rmo:F20FE6rM",
  1004. cvtpd2ps_2 = "rmo:660F5ArM",
  1005. cvtpi2pd_2 = "rx/oq:660F2ArM",
  1006. cvtpi2ps_2 = "rx/oq:0F2ArM",
  1007. cvtps2dq_2 = "rmo:660F5BrM",
  1008. cvtps2pd_2 = "rro:0F5ArM|rx/oq:",
  1009. cvtsd2si_2 = "rr/do:F20F2DrM|rx/dq:",
  1010. cvtsd2ss_2 = "rro:F20F5ArM|rx/oq:",
  1011. cvtsi2sd_2 = "rm/od:F20F2ArM",
  1012. cvtsi2ss_2 = "rm/od:F30F2ArM",
  1013. cvtss2sd_2 = "rro:F30F5ArM|rx/od:",
  1014. cvtss2si_2 = "rr/do:F20F2CrM|rx/dd:",
  1015. cvttpd2dq_2 = "rmo:660FE6rM",
  1016. cvttps2dq_2 = "rmo:F30F5BrM",
  1017. cvttsd2si_2 = "rr/do:F20F2CrM|rx/dq:",
  1018. cvttss2si_2 = "rr/do:F30F2CrM|rx/dd:",
  1019. ldmxcsr_1 = "xd:0FAE2m",
  1020. lfence_0 = "0FAEE8",
  1021. maskmovdqu_2 = "rro:660FF7rM",
  1022. mfence_0 = "0FAEF0",
  1023. movapd_2 = "rmo:660F28rM|mro:660F29Rm",
  1024. movaps_2 = "rmo:0F28rM|mro:0F29Rm",
  1025. movd_2 = "rm/od:660F6ErM|mr/do:660F7ERm",
  1026. movdqa_2 = "rmo:660F6FrM|mro:660F7FRm",
  1027. movdqu_2 = "rmo:F30F6FrM|mro:F30F7FRm",
  1028. movhlps_2 = "rro:0F12rM",
  1029. movhpd_2 = "rx/oq:660F16rM|xr/qo:660F17Rm",
  1030. movhps_2 = "rx/oq:0F16rM|xr/qo:0F17Rm",
  1031. movlhps_2 = "rro:0F16rM",
  1032. movlpd_2 = "rx/oq:660F12rM|xr/qo:660F13Rm",
  1033. movlps_2 = "rx/oq:0F12rM|xr/qo:0F13Rm",
  1034. movmskpd_2 = "rr/do:660F50rM",
  1035. movmskps_2 = "rr/do:0F50rM",
  1036. movntdq_2 = "xro:660FE7Rm",
  1037. movnti_2 = "xrd:0FC3Rm",
  1038. movntpd_2 = "xro:660F2BRm",
  1039. movntps_2 = "xro:0F2BRm",
  1040. movq_2 = "rro:F30F7ErM|rx/oq:|xr/qo:660FD6Rm",
  1041. movsd_2 = "rro:F20F10rM|rx/oq:|xr/qo:F20F11Rm",
  1042. movss_2 = "rro:F30F10rM|rx/od:|xr/do:F30F11Rm",
  1043. movupd_2 = "rmo:660F10rM|mro:660F11Rm",
  1044. movups_2 = "rmo:0F10rM|mro:0F11Rm",
  1045. orpd_2 = "rmo:660F56rM",
  1046. orps_2 = "rmo:0F56rM",
  1047. packssdw_2 = "rmo:660F6BrM",
  1048. packsswb_2 = "rmo:660F63rM",
  1049. packuswb_2 = "rmo:660F67rM",
  1050. paddb_2 = "rmo:660FFCrM",
  1051. paddd_2 = "rmo:660FFErM",
  1052. paddq_2 = "rmo:660FD4rM",
  1053. paddsb_2 = "rmo:660FECrM",
  1054. paddsw_2 = "rmo:660FEDrM",
  1055. paddusb_2 = "rmo:660FDCrM",
  1056. paddusw_2 = "rmo:660FDDrM",
  1057. paddw_2 = "rmo:660FFDrM",
  1058. pand_2 = "rmo:660FDBrM",
  1059. pandn_2 = "rmo:660FDFrM",
  1060. pause_0 = "F390",
  1061. pavgb_2 = "rmo:660FE0rM",
  1062. pavgw_2 = "rmo:660FE3rM",
  1063. pcmpeqb_2 = "rmo:660F74rM",
  1064. pcmpeqd_2 = "rmo:660F76rM",
  1065. pcmpeqw_2 = "rmo:660F75rM",
  1066. pcmpgtb_2 = "rmo:660F64rM",
  1067. pcmpgtd_2 = "rmo:660F66rM",
  1068. pcmpgtw_2 = "rmo:660F65rM",
  1069. pextrw_3 = "rri/do:660FC5rMU|xri/wo:660F3A15nrMU", -- Mem op: SSE4.1 only.
  1070. pinsrw_3 = "rri/od:660FC4rMU|rxi/ow:",
  1071. pmaddwd_2 = "rmo:660FF5rM",
  1072. pmaxsw_2 = "rmo:660FEErM",
  1073. pmaxub_2 = "rmo:660FDErM",
  1074. pminsw_2 = "rmo:660FEArM",
  1075. pminub_2 = "rmo:660FDArM",
  1076. pmovmskb_2 = "rr/do:660FD7rM",
  1077. pmulhuw_2 = "rmo:660FE4rM",
  1078. pmulhw_2 = "rmo:660FE5rM",
  1079. pmullw_2 = "rmo:660FD5rM",
  1080. pmuludq_2 = "rmo:660FF4rM",
  1081. por_2 = "rmo:660FEBrM",
  1082. prefetchnta_1 = "xb:n0F180m",
  1083. prefetcht0_1 = "xb:n0F181m",
  1084. prefetcht1_1 = "xb:n0F182m",
  1085. prefetcht2_1 = "xb:n0F183m",
  1086. psadbw_2 = "rmo:660FF6rM",
  1087. pshufd_3 = "rmio:660F70rMU",
  1088. pshufhw_3 = "rmio:F30F70rMU",
  1089. pshuflw_3 = "rmio:F20F70rMU",
  1090. pslld_2 = "rmo:660FF2rM|rio:660F726mU",
  1091. pslldq_2 = "rio:660F737mU",
  1092. psllq_2 = "rmo:660FF3rM|rio:660F736mU",
  1093. psllw_2 = "rmo:660FF1rM|rio:660F716mU",
  1094. psrad_2 = "rmo:660FE2rM|rio:660F724mU",
  1095. psraw_2 = "rmo:660FE1rM|rio:660F714mU",
  1096. psrld_2 = "rmo:660FD2rM|rio:660F722mU",
  1097. psrldq_2 = "rio:660F733mU",
  1098. psrlq_2 = "rmo:660FD3rM|rio:660F732mU",
  1099. psrlw_2 = "rmo:660FD1rM|rio:660F712mU",
  1100. psubb_2 = "rmo:660FF8rM",
  1101. psubd_2 = "rmo:660FFArM",
  1102. psubq_2 = "rmo:660FFBrM",
  1103. psubsb_2 = "rmo:660FE8rM",
  1104. psubsw_2 = "rmo:660FE9rM",
  1105. psubusb_2 = "rmo:660FD8rM",
  1106. psubusw_2 = "rmo:660FD9rM",
  1107. psubw_2 = "rmo:660FF9rM",
  1108. punpckhbw_2 = "rmo:660F68rM",
  1109. punpckhdq_2 = "rmo:660F6ArM",
  1110. punpckhqdq_2 = "rmo:660F6DrM",
  1111. punpckhwd_2 = "rmo:660F69rM",
  1112. punpcklbw_2 = "rmo:660F60rM",
  1113. punpckldq_2 = "rmo:660F62rM",
  1114. punpcklqdq_2 = "rmo:660F6CrM",
  1115. punpcklwd_2 = "rmo:660F61rM",
  1116. pxor_2 = "rmo:660FEFrM",
  1117. rcpps_2 = "rmo:0F53rM",
  1118. rcpss_2 = "rmo:F30F53rM",
  1119. rsqrtps_2 = "rmo:0F52rM",
  1120. rsqrtss_2 = "rmo:F30F52rM",
  1121. sfence_0 = "0FAEF8",
  1122. shufpd_3 = "rmio:660FC6rMU",
  1123. shufps_3 = "rmio:0FC6rMU",
  1124. stmxcsr_1 = "xd:0FAE3m",
  1125. ucomisd_2 = "rmo:660F2ErM",
  1126. ucomiss_2 = "rmo:0F2ErM",
  1127. unpckhpd_2 = "rmo:660F15rM",
  1128. unpckhps_2 = "rmo:0F15rM",
  1129. unpcklpd_2 = "rmo:660F14rM",
  1130. unpcklps_2 = "rmo:0F14rM",
  1131. xorpd_2 = "rmo:660F57rM",
  1132. xorps_2 = "rmo:0F57rM",
  1133. -- SSE3 ops
  1134. fisttp_1 = "xw:nDF1m|xd:DB1m|xq:DD1m",
  1135. addsubpd_2 = "rmo:660FD0rM",
  1136. addsubps_2 = "rmo:F20FD0rM",
  1137. haddpd_2 = "rmo:660F7CrM",
  1138. haddps_2 = "rmo:F20F7CrM",
  1139. hsubpd_2 = "rmo:660F7DrM",
  1140. hsubps_2 = "rmo:F20F7DrM",
  1141. lddqu_2 = "rxo:F20FF0rM",
  1142. movddup_2 = "rmo:F20F12rM",
  1143. movshdup_2 = "rmo:F30F16rM",
  1144. movsldup_2 = "rmo:F30F12rM",
  1145. -- SSSE3 ops
  1146. pabsb_2 = "rmo:660F381CrM",
  1147. pabsd_2 = "rmo:660F381ErM",
  1148. pabsw_2 = "rmo:660F381DrM",
  1149. palignr_3 = "rmio:660F3A0FrMU",
  1150. phaddd_2 = "rmo:660F3802rM",
  1151. phaddsw_2 = "rmo:660F3803rM",
  1152. phaddw_2 = "rmo:660F3801rM",
  1153. phsubd_2 = "rmo:660F3806rM",
  1154. phsubsw_2 = "rmo:660F3807rM",
  1155. phsubw_2 = "rmo:660F3805rM",
  1156. pmaddubsw_2 = "rmo:660F3804rM",
  1157. pmulhrsw_2 = "rmo:660F380BrM",
  1158. pshufb_2 = "rmo:660F3800rM",
  1159. psignb_2 = "rmo:660F3808rM",
  1160. psignd_2 = "rmo:660F380ArM",
  1161. psignw_2 = "rmo:660F3809rM",
  1162. -- SSE4.1 ops
  1163. blendpd_3 = "rmio:660F3A0DrMU",
  1164. blendps_3 = "rmio:660F3A0CrMU",
  1165. blendvpd_3 = "rmRo:660F3815rM",
  1166. blendvps_3 = "rmRo:660F3814rM",
  1167. dppd_3 = "rmio:660F3A41rMU",
  1168. dpps_3 = "rmio:660F3A40rMU",
  1169. extractps_3 = "mri/do:660F3A17RmU",
  1170. insertps_3 = "rrio:660F3A41rMU|rxi/od:",
  1171. movntdqa_2 = "rmo:660F382ArM",
  1172. mpsadbw_3 = "rmio:660F3A42rMU",
  1173. packusdw_2 = "rmo:660F382BrM",
  1174. pblendvb_3 = "rmRo:660F3810rM",
  1175. pblendw_3 = "rmio:660F3A0ErMU",
  1176. pcmpeqq_2 = "rmo:660F3829rM",
  1177. pextrb_3 = "rri/do:660F3A14nRmU|xri/bo:",
  1178. pextrd_3 = "mri/do:660F3A16RmU",
  1179. -- x64: pextrq
  1180. -- pextrw is SSE2, mem operand is SSE4.1 only
  1181. phminposuw_2 = "rmo:660F3841rM",
  1182. pinsrb_3 = "rri/od:660F3A20nrMU|rxi/ob:",
  1183. pinsrd_3 = "rmi/od:660F3A22rMU",
  1184. -- x64: pinsrq
  1185. pmaxsb_2 = "rmo:660F383CrM",
  1186. pmaxsd_2 = "rmo:660F383DrM",
  1187. pmaxud_2 = "rmo:660F383FrM",
  1188. pmaxuw_2 = "rmo:660F383ErM",
  1189. pminsb_2 = "rmo:660F3838rM",
  1190. pminsd_2 = "rmo:660F3839rM",
  1191. pminud_2 = "rmo:660F383BrM",
  1192. pminuw_2 = "rmo:660F383ArM",
  1193. pmovsxbd_2 = "rro:660F3821rM|rx/od:",
  1194. pmovsxbq_2 = "rro:660F3822rM|rx/ow:",
  1195. pmovsxbw_2 = "rro:660F3820rM|rx/oq:",
  1196. pmovsxdq_2 = "rro:660F3825rM|rx/oq:",
  1197. pmovsxwd_2 = "rro:660F3823rM|rx/oq:",
  1198. pmovsxwq_2 = "rro:660F3824rM|rx/od:",
  1199. pmovzxbd_2 = "rro:660F3831rM|rx/od:",
  1200. pmovzxbq_2 = "rro:660F3832rM|rx/ow:",
  1201. pmovzxbw_2 = "rro:660F3830rM|rx/oq:",
  1202. pmovzxdq_2 = "rro:660F3835rM|rx/oq:",
  1203. pmovzxwd_2 = "rro:660F3833rM|rx/oq:",
  1204. pmovzxwq_2 = "rro:660F3834rM|rx/od:",
  1205. pmuldq_2 = "rmo:660F3828rM",
  1206. pmulld_2 = "rmo:660F3840rM",
  1207. ptest_2 = "rmo:660F3817rM",
  1208. roundpd_3 = "rmio:660F3A09rMU",
  1209. roundps_3 = "rmio:660F3A08rMU",
  1210. roundsd_3 = "rrio:660F3A0BrMU|rxi/oq:",
  1211. roundss_3 = "rrio:660F3A0ArMU|rxi/od:",
  1212. -- SSE4.2 ops
  1213. crc32_2 = "rmd:F20F38F1rM|rm/dw:66F20F38F1rM|rm/db:F20F38F0nrM",
  1214. pcmpestri_3 = "rmio:660F3A61rMU",
  1215. pcmpestrm_3 = "rmio:660F3A60rMU",
  1216. pcmpgtq_2 = "rmo:660F3837rM",
  1217. pcmpistri_3 = "rmio:660F3A63rMU",
  1218. pcmpistrm_3 = "rmio:660F3A62rMU",
  1219. popcnt_2 = "rmdw:F30FB8rM",
  1220. -- SSE4a
  1221. extrq_2 = "rro:660F79rM",
  1222. extrq_3 = "riio:660F780mUU",
  1223. insertq_2 = "rro:F20F79rM",
  1224. insertq_4 = "rriio:F20F78rMUU",
  1225. lzcnt_2 = "rmdw:F30FBDrM",
  1226. movntsd_2 = "xr/qo:F20F2BRm",
  1227. movntss_2 = "xr/do:F30F2BRm",
  1228. -- popcnt is also in SSE4.2
  1229. }
  1230. ------------------------------------------------------------------------------
  1231. -- Arithmetic ops.
  1232. for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3,
  1233. ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do
  1234. local n8 = n * 8
  1235. map_op[name.."_2"] = format(
  1236. "mr:%02XRm|rm:%02XrM|mI1dw:81%XmI|mS1dw:83%XmS|Ri1dwb:%02Xri|mi1dwb:81%Xmi",
  1237. 1+n8, 3+n8, n, n, 5+n8, n)
  1238. end
  1239. -- Shift ops.
  1240. for name,n in pairs{ rol = 0, ror = 1, rcl = 2, rcr = 3,
  1241. shl = 4, shr = 5, sar = 7, sal = 4 } do
  1242. map_op[name.."_2"] = format("m1:D1%Xm|mC1dwb:D3%Xm|mi:C1%XmU", n, n, n)
  1243. end
  1244. -- Conditional ops.
  1245. for cc,n in pairs(map_cc) do
  1246. map_op["j"..cc.."_1"] = format("J.:0F8%XJ", n) -- short: 7%X
  1247. map_op["set"..cc.."_1"] = format("mb:n0F9%X2m", n)
  1248. map_op["cmov"..cc.."_2"] = format("rmdw:0F4%XrM", n) -- P6+
  1249. end
  1250. -- FP arithmetic ops.
  1251. for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3,
  1252. sub = 4, subr = 5, div = 6, divr = 7 } do
  1253. local nc = 192 + n * 8
  1254. local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8))
  1255. local fn = "f"..name
  1256. map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:DC%Xm", nc, n, n)
  1257. if n == 2 or n == 3 then
  1258. map_op[fn.."_2"] = format("Fff:D8%02XR|Fx2d:D8%XM|Fx2q:DC%XM", nc, n, n)
  1259. else
  1260. map_op[fn.."_2"] = format("Fff:D8%02XR|fFf:DC%02Xr|Fx2d:D8%XM|Fx2q:DC%XM", nc, nr, n, n)
  1261. map_op[fn.."p_1"] = format("ff:DE%02Xr", nr)
  1262. map_op[fn.."p_2"] = format("fFf:DE%02Xr", nr)
  1263. end
  1264. map_op["fi"..name.."_1"] = format("xd:DA%Xm|xw:nDE%Xm", n, n)
  1265. end
  1266. -- FP conditional moves.
  1267. for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do
  1268. local n4 = n % 4
  1269. local nc = 56000 + n4 * 8 + (n-n4) * 64
  1270. map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+
  1271. map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+
  1272. end
  1273. -- SSE FP arithmetic ops.
  1274. for name,n in pairs{ sqrt = 1, add = 8, mul = 9,
  1275. sub = 12, min = 13, div = 14, max = 15 } do
  1276. map_op[name.."ps_2"] = format("rmo:0F5%XrM", n)
  1277. map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n)
  1278. map_op[name.."pd_2"] = format("rmo:660F5%XrM", n)
  1279. map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n)
  1280. end
  1281. ------------------------------------------------------------------------------
  1282. -- Process pattern string.
  1283. local function dopattern(pat, args, sz, op)
  1284. local digit, addin
  1285. local opcode = 0
  1286. local szov = sz
  1287. local narg = 1
  1288. -- Limit number of section buffer positions used by a single dasm_put().
  1289. -- A single opcode needs a maximum of 2 positions. !x64
  1290. if secpos+2 > maxsecpos then wflush() end
  1291. -- Process each character.
  1292. for c in gmatch(pat.."|", ".") do
  1293. if match(c, "%x") then -- Hex digit.
  1294. digit = byte(c) - 48
  1295. if digit > 48 then digit = digit - 39
  1296. elseif digit > 16 then digit = digit - 7 end
  1297. opcode = opcode*16 + digit
  1298. addin = nil
  1299. elseif c == "n" then -- Disable operand size mods for opcode.
  1300. szov = nil
  1301. elseif c == "r" then -- Merge 1st operand regno. into opcode.
  1302. addin = args[1]; opcode = opcode + addin.reg
  1303. if narg < 2 then narg = 2 end
  1304. elseif c == "R" then -- Merge 2nd operand regno. into opcode.
  1305. addin = args[2]; opcode = opcode + addin.reg
  1306. narg = 3
  1307. elseif c == "m" or c == "M" then -- Encode ModRM/SIB.
  1308. local s
  1309. if addin then
  1310. s = addin.reg
  1311. opcode = opcode - s -- Undo regno opcode merge.
  1312. else
  1313. s = opcode % 16 -- Undo last digit.
  1314. opcode = (opcode - s) / 16
  1315. end
  1316. wputop(szov, opcode); opcode = nil
  1317. local imark = (sub(pat, -1) == "I") -- Force a mark (ugly).
  1318. -- Put ModRM/SIB with regno/last digit as spare.
  1319. local nn = c == "m" and 1 or 2
  1320. wputmrmsib(args[nn], imark, s, addin and addin.vreg)
  1321. if narg <= nn then narg = nn + 1 end
  1322. addin = nil
  1323. else
  1324. if opcode then -- Flush opcode.
  1325. if addin and addin.reg == -1 then
  1326. wputop(szov, opcode + 1)
  1327. waction("VREG", addin.vreg); wputxb(0)
  1328. else
  1329. wputop(szov, opcode)
  1330. end
  1331. opcode = nil
  1332. end
  1333. if c == "|" then break end
  1334. if c == "o" then -- Offset (pure 32 bit displacement).
  1335. wputdarg(args[1].disp); if narg < 2 then narg = 2 end
  1336. elseif c == "O" then
  1337. wputdarg(args[2].disp); narg = 3
  1338. else
  1339. -- Anything else is an immediate operand.
  1340. local a = args[narg]
  1341. narg = narg + 1
  1342. local mode, imm = a.mode, a.imm
  1343. if mode == "iJ" and not match("iIJ", c) then
  1344. werror("bad operand size for label")
  1345. end
  1346. if c == "S" then
  1347. wputsbarg(imm)
  1348. elseif c == "U" then
  1349. wputbarg(imm)
  1350. elseif c == "W" then
  1351. wputwarg(imm)
  1352. elseif c == "i" or c == "I" then
  1353. if mode == "iJ" then
  1354. wputlabel("IMM_", imm, 1)
  1355. elseif mode == "iI" and c == "I" then
  1356. waction(sz == "w" and "IMM_WB" or "IMM_DB", imm)
  1357. else
  1358. wputszarg(sz, imm)
  1359. end
  1360. elseif c == "J" then
  1361. if mode == "iPJ" then
  1362. waction("REL_A", imm) -- !x64 (secpos)
  1363. else
  1364. wputlabel("REL_", imm, 2)
  1365. end
  1366. else
  1367. werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'")
  1368. end
  1369. end
  1370. end
  1371. end
  1372. end
  1373. ------------------------------------------------------------------------------
  1374. -- Mapping of operand modes to short names. Suppress output with '#'.
  1375. local map_modename = {
  1376. r = "reg", R = "eax", C = "cl", x = "mem", m = "mrm", i = "imm",
  1377. f = "stx", F = "st0", J = "lbl", ["1"] = "1",
  1378. I = "#", S = "#", O = "#",
  1379. }
  1380. -- Return a table/string showing all possible operand modes.
  1381. local function templatehelp(template, nparams)
  1382. if nparams == 0 then return "" end
  1383. local t = {}
  1384. for tm in gmatch(template, "[^%|]+") do
  1385. local s = map_modename[sub(tm, 1, 1)]
  1386. s = s..gsub(sub(tm, 2, nparams), ".", function(c)
  1387. return ", "..map_modename[c]
  1388. end)
  1389. if not match(s, "#") then t[#t+1] = s end
  1390. end
  1391. return t
  1392. end
  1393. -- Match operand modes against mode match part of template.
  1394. local function matchtm(tm, args)
  1395. for i=1,#args do
  1396. if not match(args[i].mode, sub(tm, i, i)) then return end
  1397. end
  1398. return true
  1399. end
  1400. -- Handle opcodes defined with template strings.
  1401. map_op[".template__"] = function(params, template, nparams)
  1402. if not params then return templatehelp(template, nparams) end
  1403. local args = {}
  1404. -- Zero-operand opcodes have no match part.
  1405. if #params == 0 then
  1406. dopattern(template, args, "d", params.op)
  1407. return
  1408. end
  1409. -- Determine common operand size (coerce undefined size) or flag as mixed.
  1410. local sz, szmix
  1411. for i,p in ipairs(params) do
  1412. args[i] = parseoperand(p)
  1413. local nsz = args[i].opsize
  1414. if nsz then
  1415. if sz and sz ~= nsz then szmix = true else sz = nsz end
  1416. end
  1417. end
  1418. -- Try all match:pattern pairs (separated by '|').
  1419. local gotmatch, lastpat
  1420. for tm in gmatch(template, "[^%|]+") do
  1421. -- Split off size match (starts after mode match) and pattern string.
  1422. local szm, pat = match(tm, "^(.-):(.*)$", #args+1)
  1423. if pat == "" then pat = lastpat else lastpat = pat end
  1424. if matchtm(tm, args) then
  1425. local prefix = sub(szm, 1, 1)
  1426. if prefix == "/" then -- Match both operand sizes.
  1427. if args[1].opsize == sub(szm, 2, 2) and
  1428. args[2].opsize == sub(szm, 3, 3) then
  1429. dopattern(pat, args, sz, params.op) -- Process pattern string.
  1430. return
  1431. end
  1432. else -- Match common operand size.
  1433. local szp = sz
  1434. if szm == "" then szm = "dwb" end -- Default size match.
  1435. if prefix == "1" then szp = args[1].opsize; szmix = nil
  1436. elseif prefix == "2" then szp = args[2].opsize; szmix = nil end
  1437. if not szmix and (prefix == "." or match(szm, szp or "#")) then
  1438. dopattern(pat, args, szp, params.op) -- Process pattern string.
  1439. return
  1440. end
  1441. end
  1442. gotmatch = true
  1443. end
  1444. end
  1445. local msg = "bad operand mode"
  1446. if gotmatch then
  1447. if szmix then
  1448. msg = "mixed operand size"
  1449. else
  1450. msg = sz and "bad operand size" or "missing operand size"
  1451. end
  1452. end
  1453. werror(msg.." in `"..opmodestr(params.op, args).."'")
  1454. end
  1455. ------------------------------------------------------------------------------
  1456. -- Pseudo-opcodes for data storage.
  1457. local function op_data(params)
  1458. if not params then return "imm..." end
  1459. local sz = sub(params.op, 2, 2)
  1460. if sz == "a" then sz = addrsize end
  1461. for _,p in ipairs(params) do
  1462. local a = parseoperand(p)
  1463. if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then
  1464. werror("bad mode or size in `"..p.."'")
  1465. end
  1466. if a.mode == "iJ" then
  1467. wputlabel("IMM_", a.imm, 1)
  1468. else
  1469. wputszarg(sz, a.imm)
  1470. end
  1471. end
  1472. end
  1473. map_op[".byte_*"] = op_data
  1474. map_op[".sbyte_*"] = op_data
  1475. map_op[".word_*"] = op_data
  1476. map_op[".dword_*"] = op_data
  1477. map_op[".aword_*"] = op_data
  1478. ------------------------------------------------------------------------------
  1479. -- Pseudo-opcode to mark the position where the action list is to be emitted.
  1480. map_op[".actionlist_1"] = function(params)
  1481. if not params then return "cvar" end
  1482. local name = params[1] -- No syntax check. You get to keep the pieces.
  1483. wline(function(out) writeactions(out, name) end)
  1484. end
  1485. -- Pseudo-opcode to mark the position where the global enum is to be emitted.
  1486. map_op[".globals_1"] = function(params)
  1487. if not params then return "prefix" end
  1488. local prefix = params[1] -- No syntax check. You get to keep the pieces.
  1489. wline(function(out) writeglobals(out, prefix) end)
  1490. end
  1491. -- Pseudo-opcode to mark the position where the global names are to be emitted.
  1492. map_op[".globalnames_1"] = function(params)
  1493. if not params then return "cvar" end
  1494. local name = params[1] -- No syntax check. You get to keep the pieces.
  1495. wline(function(out) writeglobalnames(out, name) end)
  1496. end
  1497. -- Pseudo-opcode to mark the position where the extern names are to be emitted.
  1498. map_op[".externnames_1"] = function(params)
  1499. if not params then return "cvar" end
  1500. local name = params[1] -- No syntax check. You get to keep the pieces.
  1501. wline(function(out) writeexternnames(out, name) end)
  1502. end
  1503. ------------------------------------------------------------------------------
  1504. -- Label pseudo-opcode (converted from trailing colon form).
  1505. map_op[".label_2"] = function(params)
  1506. if not params then return "[1-9] | ->global | =>pcexpr [, addr]" end
  1507. local a = parseoperand(params[1])
  1508. local mode, imm = a.mode, a.imm
  1509. if type(imm) == "number" and (mode == "iJ" or (imm >= 1 and imm <= 9)) then
  1510. -- Local label (1: ... 9:) or global label (->global:).
  1511. waction("LABEL_LG", nil, 1)
  1512. wputxb(imm)
  1513. elseif mode == "iJ" then
  1514. -- PC label (=>pcexpr:).
  1515. waction("LABEL_PC", imm)
  1516. else
  1517. werror("bad label definition")
  1518. end
  1519. -- SETLABEL must immediately follow LABEL_LG/LABEL_PC.
  1520. local addr = params[2]
  1521. if addr then
  1522. local a = parseoperand(params[2])
  1523. if a.mode == "iPJ" then
  1524. waction("SETLABEL", a.imm) -- !x64 (secpos)
  1525. else
  1526. werror("bad label assignment")
  1527. end
  1528. end
  1529. end
  1530. map_op[".label_1"] = map_op[".label_2"]
  1531. ------------------------------------------------------------------------------
  1532. -- Alignment pseudo-opcode.
  1533. map_op[".align_1"] = function(params)
  1534. if not params then return "numpow2" end
  1535. local align = tonumber(params[1]) or map_opsizenum[map_opsize[params[1]]]
  1536. if align then
  1537. local x = align
  1538. -- Must be a power of 2 in the range (2 ... 256).
  1539. for i=1,8 do
  1540. x = x / 2
  1541. if x == 1 then
  1542. waction("ALIGN", nil, 1)
  1543. wputxb(align-1) -- Action byte is 2**n-1.
  1544. return
  1545. end
  1546. end
  1547. end
  1548. werror("bad alignment")
  1549. end
  1550. -- Spacing pseudo-opcode.
  1551. map_op[".space_2"] = function(params)
  1552. if not params then return "num [, filler]" end
  1553. waction("SPACE", params[1])
  1554. local fill = params[2]
  1555. if fill then
  1556. fill = tonumber(fill)
  1557. if not fill or fill < 0 or fill > 255 then werror("bad filler") end
  1558. end
  1559. wputxb(fill or 0)
  1560. end
  1561. map_op[".space_1"] = map_op[".space_2"]
  1562. ------------------------------------------------------------------------------
  1563. -- Pseudo-opcode for (primitive) type definitions (map to C types).
  1564. map_op[".type_3"] = function(params, nparams)
  1565. if not params then
  1566. return nparams == 2 and "name, ctype" or "name, ctype, reg"
  1567. end
  1568. local name, ctype, reg = params[1], params[2], params[3]
  1569. if not match(name, "^[%a_][%w_]*$") then
  1570. werror("bad type name `"..name.."'")
  1571. end
  1572. local tp = map_type[name]
  1573. if tp then
  1574. werror("duplicate type `"..name.."'")
  1575. end
  1576. if reg and not map_reg_valid_base[reg] then
  1577. werror("bad base register `"..(map_reg_rev[reg] or reg).."'")
  1578. end
  1579. -- Add #type to defines. A bit unclean to put it in map_archdef.
  1580. map_archdef["#"..name] = "sizeof("..ctype..")"
  1581. -- Add new type and emit shortcut define.
  1582. local num = ctypenum + 1
  1583. map_type[name] = {
  1584. ctype = ctype,
  1585. ctypefmt = format("Dt%X(%%s)", num),
  1586. reg = reg,
  1587. }
  1588. wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
  1589. ctypenum = num
  1590. end
  1591. map_op[".type_2"] = map_op[".type_3"]
  1592. -- Dump type definitions.
  1593. local function dumptypes(out, lvl)
  1594. local t = {}
  1595. for name in pairs(map_type) do t[#t+1] = name end
  1596. sort(t)
  1597. out:write("Type definitions:\n")
  1598. for _,name in ipairs(t) do
  1599. local tp = map_type[name]
  1600. local reg = tp.reg and map_reg_rev[tp.reg] or ""
  1601. out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
  1602. end
  1603. out:write("\n")
  1604. end
  1605. ------------------------------------------------------------------------------
  1606. -- Set the current section.
  1607. function _M.section(num)
  1608. waction("SECTION")
  1609. wputxb(num)
  1610. wflush(true) -- SECTION is a terminal action.
  1611. end
  1612. ------------------------------------------------------------------------------
  1613. -- Dump architecture description.
  1614. function _M.dumparch(out)
  1615. out:write(format("DynASM %s version %s, released %s\n\n",
  1616. _info.arch, _info.version, _info.release))
  1617. dumpregs(out)
  1618. dumpactions(out)
  1619. end
  1620. -- Dump all user defined elements.
  1621. function _M.dumpdef(out, lvl)
  1622. dumptypes(out, lvl)
  1623. dumpglobals(out, lvl)
  1624. dumpexterns(out, lvl)
  1625. end
  1626. ------------------------------------------------------------------------------
  1627. -- Pass callbacks from/to the DynASM core.
  1628. function _M.passcb(wl, we, wf, ww)
  1629. wline, werror, wfatal, wwarn = wl, we, wf, ww
  1630. return wflush
  1631. end
  1632. -- Setup the arch-specific module.
  1633. function _M.setup(arch, opt)
  1634. g_arch, g_opt = arch, opt
  1635. end
  1636. -- Merge the core maps and the arch-specific maps.
  1637. function _M.mergemaps(map_coreop, map_def)
  1638. setmetatable(map_op, { __index = map_coreop })
  1639. setmetatable(map_def, { __index = map_archdef })
  1640. return map_op, map_def
  1641. end
  1642. return _M
  1643. ------------------------------------------------------------------------------