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