xref: /php-src/ext/opcache/jit/ir/dynasm/dasm_mips.lua (revision 2ab1c3d5)
1------------------------------------------------------------------------------
2-- DynASM MIPS32/MIPS64 module.
3--
4-- Copyright (C) 2005-2023 Mike Pall. All rights reserved.
5-- See dynasm.lua for full copyright notice.
6------------------------------------------------------------------------------
7
8local mips64 = mips64
9local mipsr6 = _map_def.MIPSR6
10
11-- Module information:
12local _info = {
13  arch =	mips64 and "mips64" or "mips",
14  description =	"DynASM MIPS32/MIPS64 module",
15  version =	"1.5.0",
16  vernum =	 10500,
17  release =	"2021-05-02",
18  author =	"Mike Pall",
19  license =	"MIT",
20}
21
22-- Exported glue functions for the arch-specific module.
23local _M = { _info = _info }
24
25-- Cache library functions.
26local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
27local assert, setmetatable = assert, setmetatable
28local _s = string
29local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
30local match, gmatch = _s.match, _s.gmatch
31local concat, sort = table.concat, table.sort
32local bit = bit or require("bit")
33local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
34local tohex = bit.tohex
35
36-- Inherited tables and callbacks.
37local g_opt, g_arch
38local wline, werror, wfatal, wwarn
39
40-- Action name list.
41-- CHECK: Keep this in sync with the C code!
42local action_names = {
43  "STOP", "SECTION", "ESC", "REL_EXT",
44  "ALIGN", "REL_LG", "LABEL_LG",
45  "REL_PC", "LABEL_PC", "IMM", "IMMS",
46}
47
48-- Maximum number of section buffer positions for dasm_put().
49-- CHECK: Keep this in sync with the C code!
50local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
51
52-- Action name -> action number.
53local map_action = {}
54for n,name in ipairs(action_names) do
55  map_action[name] = n-1
56end
57
58-- Action list buffer.
59local actlist = {}
60
61-- Argument list for next dasm_put(). Start with offset 0 into action list.
62local actargs = { 0 }
63
64-- Current number of section buffer positions for dasm_put().
65local secpos = 1
66
67------------------------------------------------------------------------------
68
69-- Dump action names and numbers.
70local function dumpactions(out)
71  out:write("DynASM encoding engine action codes:\n")
72  for n,name in ipairs(action_names) do
73    local num = map_action[name]
74    out:write(format("  %-10s %02X  %d\n", name, num, num))
75  end
76  out:write("\n")
77end
78
79-- Write action list buffer as a huge static C array.
80local function writeactions(out, name)
81  local nn = #actlist
82  if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
83  out:write("static const unsigned int ", name, "[", nn, "] = {\n")
84  for i = 1,nn-1 do
85    assert(out:write("0x", tohex(actlist[i]), ",\n"))
86  end
87  assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
88end
89
90------------------------------------------------------------------------------
91
92-- Add word to action list.
93local function wputxw(n)
94  assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
95  actlist[#actlist+1] = n
96end
97
98-- Add action to list with optional arg. Advance buffer pos, too.
99local function waction(action, val, a, num)
100  local w = assert(map_action[action], "bad action name `"..action.."'")
101  wputxw(0xff000000 + w * 0x10000 + (val or 0))
102  if a then actargs[#actargs+1] = a end
103  if a or num then secpos = secpos + (num or 1) end
104end
105
106-- Flush action list (intervening C code or buffer pos overflow).
107local function wflush(term)
108  if #actlist == actargs[1] then return end -- Nothing to flush.
109  if not term then waction("STOP") end -- Terminate action list.
110  wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
111  actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
112  secpos = 1 -- The actionlist offset occupies a buffer position, too.
113end
114
115-- Put escaped word.
116local function wputw(n)
117  if n >= 0xff000000 then waction("ESC") end
118  wputxw(n)
119end
120
121-- Reserve position for word.
122local function wpos()
123  local pos = #actlist+1
124  actlist[pos] = ""
125  return pos
126end
127
128-- Store word to reserved position.
129local function wputpos(pos, n)
130  assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
131  actlist[pos] = n
132end
133
134------------------------------------------------------------------------------
135
136-- Global label name -> global label number. With auto assignment on 1st use.
137local next_global = 20
138local map_global = setmetatable({}, { __index = function(t, name)
139  if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
140  local n = next_global
141  if n > 2047 then werror("too many global labels") end
142  next_global = n + 1
143  t[name] = n
144  return n
145end})
146
147-- Dump global labels.
148local function dumpglobals(out, lvl)
149  local t = {}
150  for name, n in pairs(map_global) do t[n] = name end
151  out:write("Global labels:\n")
152  for i=20,next_global-1 do
153    out:write(format("  %s\n", t[i]))
154  end
155  out:write("\n")
156end
157
158-- Write global label enum.
159local function writeglobals(out, prefix)
160  local t = {}
161  for name, n in pairs(map_global) do t[n] = name end
162  out:write("enum {\n")
163  for i=20,next_global-1 do
164    out:write("  ", prefix, t[i], ",\n")
165  end
166  out:write("  ", prefix, "_MAX\n};\n")
167end
168
169-- Write global label names.
170local function writeglobalnames(out, name)
171  local t = {}
172  for name, n in pairs(map_global) do t[n] = name end
173  out:write("static const char *const ", name, "[] = {\n")
174  for i=20,next_global-1 do
175    out:write("  \"", t[i], "\",\n")
176  end
177  out:write("  (const char *)0\n};\n")
178end
179
180------------------------------------------------------------------------------
181
182-- Extern label name -> extern label number. With auto assignment on 1st use.
183local next_extern = 0
184local map_extern_ = {}
185local map_extern = setmetatable({}, { __index = function(t, name)
186  -- No restrictions on the name for now.
187  local n = next_extern
188  if n > 2047 then werror("too many extern labels") end
189  next_extern = n + 1
190  t[name] = n
191  map_extern_[n] = name
192  return n
193end})
194
195-- Dump extern labels.
196local function dumpexterns(out, lvl)
197  out:write("Extern labels:\n")
198  for i=0,next_extern-1 do
199    out:write(format("  %s\n", map_extern_[i]))
200  end
201  out:write("\n")
202end
203
204-- Write extern label names.
205local function writeexternnames(out, name)
206  out:write("static const char *const ", name, "[] = {\n")
207  for i=0,next_extern-1 do
208    out:write("  \"", map_extern_[i], "\",\n")
209  end
210  out:write("  (const char *)0\n};\n")
211end
212
213------------------------------------------------------------------------------
214
215-- Arch-specific maps.
216local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name.
217
218local map_type = {}		-- Type name -> { ctype, reg }
219local ctypenum = 0		-- Type number (for Dt... macros).
220
221-- Reverse defines for registers.
222function _M.revdef(s)
223  if s == "r29" then return "sp"
224  elseif s == "r31" then return "ra" end
225  return s
226end
227
228------------------------------------------------------------------------------
229
230-- Template strings for MIPS instructions.
231local map_op = {
232  -- First-level opcodes.
233  j_1 =		"08000000J",
234  jal_1 =	"0c000000J",
235  b_1 =		"10000000B",
236  beqz_2 =	"10000000SB",
237  beq_3 =	"10000000STB",
238  bnez_2 =	"14000000SB",
239  bne_3 =	"14000000STB",
240  blez_2 =	"18000000SB",
241  bgtz_2 =	"1c000000SB",
242  li_2 =	"24000000TI",
243  addiu_3 =	"24000000TSI",
244  slti_3 =	"28000000TSI",
245  sltiu_3 =	"2c000000TSI",
246  andi_3 =	"30000000TSU",
247  lu_2 =	"34000000TU",
248  ori_3 =	"34000000TSU",
249  xori_3 =	"38000000TSU",
250  lui_2 =	"3c000000TU",
251  daddiu_3 =	mips64 and "64000000TSI",
252  ldl_2 =	mips64 and "68000000TO",
253  ldr_2 =	mips64 and "6c000000TO",
254  lb_2 =	"80000000TO",
255  lh_2 =	"84000000TO",
256  lw_2 =	"8c000000TO",
257  lbu_2 =	"90000000TO",
258  lhu_2 =	"94000000TO",
259  lwu_2 =	mips64 and "9c000000TO",
260  sb_2 =	"a0000000TO",
261  sh_2 =	"a4000000TO",
262  sw_2 =	"ac000000TO",
263  lwc1_2 =	"c4000000HO",
264  ldc1_2 =	"d4000000HO",
265  ld_2 =	mips64 and "dc000000TO",
266  swc1_2 =	"e4000000HO",
267  sdc1_2 =	"f4000000HO",
268  sd_2 =	mips64 and "fc000000TO",
269
270  -- Opcode SPECIAL.
271  nop_0 =	"00000000",
272  sll_3 =	"00000000DTA",
273  sextw_2 =	"00000000DT",
274  srl_3 =	"00000002DTA",
275  rotr_3 =	"00200002DTA",
276  sra_3 =	"00000003DTA",
277  sllv_3 =	"00000004DTS",
278  srlv_3 =	"00000006DTS",
279  rotrv_3 =	"00000046DTS",
280  drotrv_3 =	mips64 and "00000056DTS",
281  srav_3 =	"00000007DTS",
282  jalr_1 =	"0000f809S",
283  jalr_2 =	"00000009DS",
284  syscall_0 =	"0000000c",
285  syscall_1 =	"0000000cY",
286  break_0 =	"0000000d",
287  break_1 =	"0000000dY",
288  sync_0 =	"0000000f",
289  dsllv_3 =	mips64 and "00000014DTS",
290  dsrlv_3 =	mips64 and "00000016DTS",
291  dsrav_3 =	mips64 and "00000017DTS",
292  add_3 =	"00000020DST",
293  move_2 =	mips64 and "00000025DS" or "00000021DS",
294  addu_3 =	"00000021DST",
295  sub_3 =	"00000022DST",
296  negu_2 =	mips64 and "0000002fDT" or "00000023DT",
297  subu_3 =	"00000023DST",
298  and_3 =	"00000024DST",
299  or_3 =	"00000025DST",
300  xor_3 =	"00000026DST",
301  not_2 =	"00000027DS",
302  nor_3 =	"00000027DST",
303  slt_3 =	"0000002aDST",
304  sltu_3 =	"0000002bDST",
305  dadd_3 =	mips64 and "0000002cDST",
306  daddu_3 =	mips64 and "0000002dDST",
307  dsub_3 =	mips64 and "0000002eDST",
308  dsubu_3 =	mips64 and "0000002fDST",
309  tge_2 =	"00000030ST",
310  tge_3 =	"00000030STZ",
311  tgeu_2 =	"00000031ST",
312  tgeu_3 =	"00000031STZ",
313  tlt_2 =	"00000032ST",
314  tlt_3 =	"00000032STZ",
315  tltu_2 =	"00000033ST",
316  tltu_3 =	"00000033STZ",
317  teq_2 =	"00000034ST",
318  teq_3 =	"00000034STZ",
319  tne_2 =	"00000036ST",
320  tne_3 =	"00000036STZ",
321  dsll_3 =	mips64 and "00000038DTa",
322  dsrl_3 =	mips64 and "0000003aDTa",
323  drotr_3 =	mips64 and "0020003aDTa",
324  dsra_3 =	mips64 and "0000003bDTa",
325  dsll32_3 =	mips64 and "0000003cDTA",
326  dsrl32_3 =	mips64 and "0000003eDTA",
327  drotr32_3 =	mips64 and "0020003eDTA",
328  dsra32_3 =	mips64 and "0000003fDTA",
329
330  -- Opcode REGIMM.
331  bltz_2 =	"04000000SB",
332  bgez_2 =	"04010000SB",
333  bltzl_2 =	"04020000SB",
334  bgezl_2 =	"04030000SB",
335  bal_1 =	"04110000B",
336  synci_1 =	"041f0000O",
337
338  -- Opcode SPECIAL3.
339  ext_4 =	"7c000000TSAM", -- Note: last arg is msbd = size-1
340  dextm_4 =	mips64 and "7c000001TSAM", -- Args: pos    | size-1-32
341  dextu_4 =	mips64 and "7c000002TSAM", -- Args: pos-32 | size-1
342  dext_4 =	mips64 and "7c000003TSAM", -- Args: pos    | size-1
343  zextw_2 =	mips64 and "7c00f803TS",
344  ins_4 =	"7c000004TSAM", -- Note: last arg is msb = pos+size-1
345  dinsm_4 =	mips64 and "7c000005TSAM", -- Args: pos    | pos+size-33
346  dinsu_4 =	mips64 and "7c000006TSAM", -- Args: pos-32 | pos+size-33
347  dins_4 =	mips64 and "7c000007TSAM", -- Args: pos    | pos+size-1
348  wsbh_2 =	"7c0000a0DT",
349  dsbh_2 =	mips64 and "7c0000a4DT",
350  dshd_2 =	mips64 and "7c000164DT",
351  seb_2 =	"7c000420DT",
352  seh_2 =	"7c000620DT",
353  rdhwr_2 =	"7c00003bTD",
354
355  -- Opcode COP0.
356  mfc0_2 =	"40000000TD",
357  mfc0_3 =	"40000000TDW",
358  dmfc0_2 =	mips64 and "40200000TD",
359  dmfc0_3 =	mips64 and "40200000TDW",
360  mtc0_2 =	"40800000TD",
361  mtc0_3 =	"40800000TDW",
362  dmtc0_2 =	mips64 and "40a00000TD",
363  dmtc0_3 =	mips64 and "40a00000TDW",
364  rdpgpr_2 =	"41400000DT",
365  di_0 =	"41606000",
366  di_1 =	"41606000T",
367  ei_0 =	"41606020",
368  ei_1 =	"41606020T",
369  wrpgpr_2 =	"41c00000DT",
370  tlbr_0 =	"42000001",
371  tlbwi_0 =	"42000002",
372  tlbwr_0 =	"42000006",
373  tlbp_0 =	"42000008",
374  eret_0 =	"42000018",
375  deret_0 =	"4200001f",
376  wait_0 =	"42000020",
377
378  -- Opcode COP1.
379  mfc1_2 =	"44000000TG",
380  dmfc1_2 =	mips64 and "44200000TG",
381  cfc1_2 =	"44400000TG",
382  mfhc1_2 =	"44600000TG",
383  mtc1_2 =	"44800000TG",
384  dmtc1_2 =	mips64 and "44a00000TG",
385  ctc1_2 =	"44c00000TG",
386  mthc1_2 =	"44e00000TG",
387
388  ["add.s_3"] =		"46000000FGH",
389  ["sub.s_3"] =		"46000001FGH",
390  ["mul.s_3"] =		"46000002FGH",
391  ["div.s_3"] =		"46000003FGH",
392  ["sqrt.s_2"] =	"46000004FG",
393  ["abs.s_2"] =		"46000005FG",
394  ["mov.s_2"] =		"46000006FG",
395  ["neg.s_2"] =		"46000007FG",
396  ["round.l.s_2"] =	"46000008FG",
397  ["trunc.l.s_2"] =	"46000009FG",
398  ["ceil.l.s_2"] =	"4600000aFG",
399  ["floor.l.s_2"] =	"4600000bFG",
400  ["round.w.s_2"] =	"4600000cFG",
401  ["trunc.w.s_2"] =	"4600000dFG",
402  ["ceil.w.s_2"] =	"4600000eFG",
403  ["floor.w.s_2"] =	"4600000fFG",
404  ["recip.s_2"] =	"46000015FG",
405  ["rsqrt.s_2"] =	"46000016FG",
406  ["cvt.d.s_2"] =	"46000021FG",
407  ["cvt.w.s_2"] =	"46000024FG",
408  ["cvt.l.s_2"] =	"46000025FG",
409  ["add.d_3"] =		"46200000FGH",
410  ["sub.d_3"] =		"46200001FGH",
411  ["mul.d_3"] =		"46200002FGH",
412  ["div.d_3"] =		"46200003FGH",
413  ["sqrt.d_2"] =	"46200004FG",
414  ["abs.d_2"] =		"46200005FG",
415  ["mov.d_2"] =		"46200006FG",
416  ["neg.d_2"] =		"46200007FG",
417  ["round.l.d_2"] =	"46200008FG",
418  ["trunc.l.d_2"] =	"46200009FG",
419  ["ceil.l.d_2"] =	"4620000aFG",
420  ["floor.l.d_2"] =	"4620000bFG",
421  ["round.w.d_2"] =	"4620000cFG",
422  ["trunc.w.d_2"] =	"4620000dFG",
423  ["ceil.w.d_2"] =	"4620000eFG",
424  ["floor.w.d_2"] =	"4620000fFG",
425  ["recip.d_2"] =	"46200015FG",
426  ["rsqrt.d_2"] =	"46200016FG",
427  ["cvt.s.d_2"] =	"46200020FG",
428  ["cvt.w.d_2"] =	"46200024FG",
429  ["cvt.l.d_2"] =	"46200025FG",
430  ["cvt.s.w_2"] =	"46800020FG",
431  ["cvt.d.w_2"] =	"46800021FG",
432  ["cvt.s.l_2"] =	"46a00020FG",
433  ["cvt.d.l_2"] =	"46a00021FG",
434}
435
436if mipsr6 then -- Instructions added with MIPSR6.
437
438  for k,v in pairs({
439
440    -- Add immediate to upper bits.
441    aui_3 =	"3c000000TSI",
442    daui_3 =	mips64 and "74000000TSI",
443    dahi_2 =	mips64 and "04060000SI",
444    dati_2 =	mips64 and "041e0000SI",
445
446    -- TODO: addiupc, auipc, aluipc, lwpc, lwupc, ldpc.
447
448    -- Compact branches.
449    blezalc_2 =	"18000000TB",	-- rt != 0.
450    bgezalc_2 =	"18000000T=SB",	-- rt != 0.
451    bgtzalc_2 =	"1c000000TB",	-- rt != 0.
452    bltzalc_2 =	"1c000000T=SB",	-- rt != 0.
453
454    blezc_2 =	"58000000TB",	-- rt != 0.
455    bgezc_2 =	"58000000T=SB",	-- rt != 0.
456    bgec_3 =	"58000000STB",	-- rs != rt.
457    blec_3 =	"58000000TSB",	-- rt != rs.
458
459    bgtzc_2 =	"5c000000TB",	-- rt != 0.
460    bltzc_2 =	"5c000000T=SB",	-- rt != 0.
461    bltc_3 =	"5c000000STB",	-- rs != rt.
462    bgtc_3 =	"5c000000TSB",	-- rt != rs.
463
464    bgeuc_3 =	"18000000STB",	-- rs != rt.
465    bleuc_3 =	"18000000TSB",	-- rt != rs.
466    bltuc_3 =	"1c000000STB",	-- rs != rt.
467    bgtuc_3 =	"1c000000TSB",	-- rt != rs.
468
469    beqzalc_2 =	"20000000TB",	-- rt != 0.
470    bnezalc_2 =	"60000000TB",	-- rt != 0.
471    beqc_3 =	"20000000STB",	-- rs < rt.
472    bnec_3 =	"60000000STB",	-- rs < rt.
473    bovc_3 =	"20000000STB",	-- rs >= rt.
474    bnvc_3 =	"60000000STB",	-- rs >= rt.
475
476    beqzc_2 =	"d8000000SK",	-- rs != 0.
477    bnezc_2 =	"f8000000SK",	-- rs != 0.
478    jic_2 =	"d8000000TI",
479    jialc_2 =	"f8000000TI",
480    bc_1 =	"c8000000L",
481    balc_1 =	"e8000000L",
482
483    -- Opcode SPECIAL.
484    jr_1 =	"00000009S",
485    sdbbp_0 =	"0000000e",
486    sdbbp_1 =	"0000000eY",
487    lsa_4 =	"00000005DSTA",
488    dlsa_4 =	mips64 and "00000015DSTA",
489    seleqz_3 =	"00000035DST",
490    selnez_3 =	"00000037DST",
491    clz_2 =	"00000050DS",
492    clo_2 =	"00000051DS",
493    dclz_2 =	mips64 and "00000052DS",
494    dclo_2 =	mips64 and "00000053DS",
495    mul_3 =	"00000098DST",
496    muh_3 =	"000000d8DST",
497    mulu_3 =	"00000099DST",
498    muhu_3 =	"000000d9DST",
499    div_3 =	"0000009aDST",
500    mod_3 =	"000000daDST",
501    divu_3 =	"0000009bDST",
502    modu_3 =	"000000dbDST",
503    dmul_3 =	mips64 and "0000009cDST",
504    dmuh_3 =	mips64 and "000000dcDST",
505    dmulu_3 =	mips64 and "0000009dDST",
506    dmuhu_3 =	mips64 and "000000ddDST",
507    ddiv_3 =	mips64 and "0000009eDST",
508    dmod_3 =	mips64 and "000000deDST",
509    ddivu_3 =	mips64 and "0000009fDST",
510    dmodu_3 =	mips64 and "000000dfDST",
511
512    -- Opcode SPECIAL3.
513    align_4 =		"7c000220DSTA",
514    dalign_4 =		mips64 and "7c000224DSTA",
515    bitswap_2 =		"7c000020DT",
516    dbitswap_2 =	mips64 and "7c000024DT",
517
518    -- Opcode COP1.
519    bc1eqz_2 =	"45200000HB",
520    bc1nez_2 =	"45a00000HB",
521
522    ["sel.s_3"] =	"46000010FGH",
523    ["seleqz.s_3"] =	"46000014FGH",
524    ["selnez.s_3"] =	"46000017FGH",
525    ["maddf.s_3"] =	"46000018FGH",
526    ["msubf.s_3"] =	"46000019FGH",
527    ["rint.s_2"] =	"4600001aFG",
528    ["class.s_2"] =	"4600001bFG",
529    ["min.s_3"] =	"4600001cFGH",
530    ["mina.s_3"] =	"4600001dFGH",
531    ["max.s_3"] =	"4600001eFGH",
532    ["maxa.s_3"] =	"4600001fFGH",
533    ["cmp.af.s_3"] =	"46800000FGH",
534    ["cmp.un.s_3"] =	"46800001FGH",
535    ["cmp.or.s_3"] =	"46800011FGH",
536    ["cmp.eq.s_3"] =	"46800002FGH",
537    ["cmp.une.s_3"] =	"46800012FGH",
538    ["cmp.ueq.s_3"] =	"46800003FGH",
539    ["cmp.ne.s_3"] =	"46800013FGH",
540    ["cmp.lt.s_3"] =	"46800004FGH",
541    ["cmp.ult.s_3"] =	"46800005FGH",
542    ["cmp.le.s_3"] =	"46800006FGH",
543    ["cmp.ule.s_3"] =	"46800007FGH",
544    ["cmp.saf.s_3"] =	"46800008FGH",
545    ["cmp.sun.s_3"] =	"46800009FGH",
546    ["cmp.sor.s_3"] =	"46800019FGH",
547    ["cmp.seq.s_3"] =	"4680000aFGH",
548    ["cmp.sune.s_3"] =	"4680001aFGH",
549    ["cmp.sueq.s_3"] =	"4680000bFGH",
550    ["cmp.sne.s_3"] =	"4680001bFGH",
551    ["cmp.slt.s_3"] =	"4680000cFGH",
552    ["cmp.sult.s_3"] =	"4680000dFGH",
553    ["cmp.sle.s_3"] =	"4680000eFGH",
554    ["cmp.sule.s_3"] =	"4680000fFGH",
555
556    ["sel.d_3"] =	"46200010FGH",
557    ["seleqz.d_3"] =	"46200014FGH",
558    ["selnez.d_3"] =	"46200017FGH",
559    ["maddf.d_3"] =	"46200018FGH",
560    ["msubf.d_3"] =	"46200019FGH",
561    ["rint.d_2"] =	"4620001aFG",
562    ["class.d_2"] =	"4620001bFG",
563    ["min.d_3"] =	"4620001cFGH",
564    ["mina.d_3"] =	"4620001dFGH",
565    ["max.d_3"] =	"4620001eFGH",
566    ["maxa.d_3"] =	"4620001fFGH",
567    ["cmp.af.d_3"] =	"46a00000FGH",
568    ["cmp.un.d_3"] =	"46a00001FGH",
569    ["cmp.or.d_3"] =	"46a00011FGH",
570    ["cmp.eq.d_3"] =	"46a00002FGH",
571    ["cmp.une.d_3"] =	"46a00012FGH",
572    ["cmp.ueq.d_3"] =	"46a00003FGH",
573    ["cmp.ne.d_3"] =	"46a00013FGH",
574    ["cmp.lt.d_3"] =	"46a00004FGH",
575    ["cmp.ult.d_3"] =	"46a00005FGH",
576    ["cmp.le.d_3"] =	"46a00006FGH",
577    ["cmp.ule.d_3"] =	"46a00007FGH",
578    ["cmp.saf.d_3"] =	"46a00008FGH",
579    ["cmp.sun.d_3"] =	"46a00009FGH",
580    ["cmp.sor.d_3"] =	"46a00019FGH",
581    ["cmp.seq.d_3"] =	"46a0000aFGH",
582    ["cmp.sune.d_3"] =	"46a0001aFGH",
583    ["cmp.sueq.d_3"] =	"46a0000bFGH",
584    ["cmp.sne.d_3"] =	"46a0001bFGH",
585    ["cmp.slt.d_3"] =	"46a0000cFGH",
586    ["cmp.sult.d_3"] =	"46a0000dFGH",
587    ["cmp.sle.d_3"] =	"46a0000eFGH",
588    ["cmp.sule.d_3"] =	"46a0000fFGH",
589
590  }) do map_op[k] = v end
591
592else -- Instructions removed by MIPSR6.
593
594  for k,v in pairs({
595    -- Traps, don't use.
596    addi_3 =	"20000000TSI",
597    daddi_3 =	mips64 and "60000000TSI",
598
599    -- Branch on likely, don't use.
600    beqzl_2 =	"50000000SB",
601    beql_3 =	"50000000STB",
602    bnezl_2 =	"54000000SB",
603    bnel_3 =	"54000000STB",
604    blezl_2 =	"58000000SB",
605    bgtzl_2 =	"5c000000SB",
606
607    lwl_2 =	"88000000TO",
608    lwr_2 =	"98000000TO",
609    swl_2 =	"a8000000TO",
610    sdl_2 =	mips64 and "b0000000TO",
611    sdr_2 =	mips64 and "b1000000TO",
612    swr_2 =	"b8000000TO",
613    cache_2 =	"bc000000NO",
614    ll_2 =	"c0000000TO",
615    pref_2 =	"cc000000NO",
616    sc_2 =	"e0000000TO",
617    scd_2 =	mips64 and "f0000000TO",
618
619    -- Opcode SPECIAL.
620    movf_2 =	"00000001DS",
621    movf_3 =	"00000001DSC",
622    movt_2 =	"00010001DS",
623    movt_3 =	"00010001DSC",
624    jr_1 =	"00000008S",
625    movz_3 =	"0000000aDST",
626    movn_3 =	"0000000bDST",
627    mfhi_1 =	"00000010D",
628    mthi_1 =	"00000011S",
629    mflo_1 =	"00000012D",
630    mtlo_1 =	"00000013S",
631    mult_2 =	"00000018ST",
632    multu_2 =	"00000019ST",
633    div_3 =	"0000001aST",
634    divu_3 =	"0000001bST",
635    ddiv_3 =	mips64 and "0000001eST",
636    ddivu_3 =	mips64 and "0000001fST",
637    dmult_2 =	mips64 and "0000001cST",
638    dmultu_2 =	mips64 and "0000001dST",
639
640    -- Opcode REGIMM.
641    tgei_2 =	"04080000SI",
642    tgeiu_2 =	"04090000SI",
643    tlti_2 =	"040a0000SI",
644    tltiu_2 =	"040b0000SI",
645    teqi_2 =	"040c0000SI",
646    tnei_2 =	"040e0000SI",
647    bltzal_2 =	"04100000SB",
648    bgezal_2 =	"04110000SB",
649    bltzall_2 =	"04120000SB",
650    bgezall_2 =	"04130000SB",
651
652    -- Opcode SPECIAL2.
653    madd_2 =	"70000000ST",
654    maddu_2 =	"70000001ST",
655    mul_3 =	"70000002DST",
656    msub_2 =	"70000004ST",
657    msubu_2 =	"70000005ST",
658    clz_2 =	"70000020D=TS",
659    clo_2 =	"70000021D=TS",
660    dclz_2 =	mips64 and "70000024D=TS",
661    dclo_2 =	mips64 and "70000025D=TS",
662    sdbbp_0 =	"7000003f",
663    sdbbp_1 =	"7000003fY",
664
665    -- Opcode COP1.
666    bc1f_1 =	"45000000B",
667    bc1f_2 =	"45000000CB",
668    bc1t_1 =	"45010000B",
669    bc1t_2 =	"45010000CB",
670    bc1fl_1 =	"45020000B",
671    bc1fl_2 =	"45020000CB",
672    bc1tl_1 =	"45030000B",
673    bc1tl_2 =	"45030000CB",
674
675    ["movf.s_2"] =	"46000011FG",
676    ["movf.s_3"] =	"46000011FGC",
677    ["movt.s_2"] =	"46010011FG",
678    ["movt.s_3"] =	"46010011FGC",
679    ["movz.s_3"] =	"46000012FGT",
680    ["movn.s_3"] =	"46000013FGT",
681    ["cvt.ps.s_3"] =	"46000026FGH",
682    ["c.f.s_2"] =	"46000030GH",
683    ["c.f.s_3"] =	"46000030VGH",
684    ["c.un.s_2"] =	"46000031GH",
685    ["c.un.s_3"] =	"46000031VGH",
686    ["c.eq.s_2"] =	"46000032GH",
687    ["c.eq.s_3"] =	"46000032VGH",
688    ["c.ueq.s_2"] =	"46000033GH",
689    ["c.ueq.s_3"] =	"46000033VGH",
690    ["c.olt.s_2"] =	"46000034GH",
691    ["c.olt.s_3"] =	"46000034VGH",
692    ["c.ult.s_2"] =	"46000035GH",
693    ["c.ult.s_3"] =	"46000035VGH",
694    ["c.ole.s_2"] =	"46000036GH",
695    ["c.ole.s_3"] =	"46000036VGH",
696    ["c.ule.s_2"] =	"46000037GH",
697    ["c.ule.s_3"] =	"46000037VGH",
698    ["c.sf.s_2"] =	"46000038GH",
699    ["c.sf.s_3"] =	"46000038VGH",
700    ["c.ngle.s_2"] =	"46000039GH",
701    ["c.ngle.s_3"] =	"46000039VGH",
702    ["c.seq.s_2"] =	"4600003aGH",
703    ["c.seq.s_3"] =	"4600003aVGH",
704    ["c.ngl.s_2"] =	"4600003bGH",
705    ["c.ngl.s_3"] =	"4600003bVGH",
706    ["c.lt.s_2"] =	"4600003cGH",
707    ["c.lt.s_3"] =	"4600003cVGH",
708    ["c.nge.s_2"] =	"4600003dGH",
709    ["c.nge.s_3"] =	"4600003dVGH",
710    ["c.le.s_2"] =	"4600003eGH",
711    ["c.le.s_3"] =	"4600003eVGH",
712    ["c.ngt.s_2"] =	"4600003fGH",
713    ["c.ngt.s_3"] =	"4600003fVGH",
714    ["movf.d_2"] =	"46200011FG",
715    ["movf.d_3"] =	"46200011FGC",
716    ["movt.d_2"] =	"46210011FG",
717    ["movt.d_3"] =	"46210011FGC",
718    ["movz.d_3"] =	"46200012FGT",
719    ["movn.d_3"] =	"46200013FGT",
720    ["c.f.d_2"] =	"46200030GH",
721    ["c.f.d_3"] =	"46200030VGH",
722    ["c.un.d_2"] =	"46200031GH",
723    ["c.un.d_3"] =	"46200031VGH",
724    ["c.eq.d_2"] =	"46200032GH",
725    ["c.eq.d_3"] =	"46200032VGH",
726    ["c.ueq.d_2"] =	"46200033GH",
727    ["c.ueq.d_3"] =	"46200033VGH",
728    ["c.olt.d_2"] =	"46200034GH",
729    ["c.olt.d_3"] =	"46200034VGH",
730    ["c.ult.d_2"] =	"46200035GH",
731    ["c.ult.d_3"] =	"46200035VGH",
732    ["c.ole.d_2"] =	"46200036GH",
733    ["c.ole.d_3"] =	"46200036VGH",
734    ["c.ule.d_2"] =	"46200037GH",
735    ["c.ule.d_3"] =	"46200037VGH",
736    ["c.sf.d_2"] =	"46200038GH",
737    ["c.sf.d_3"] =	"46200038VGH",
738    ["c.ngle.d_2"] =	"46200039GH",
739    ["c.ngle.d_3"] =	"46200039VGH",
740    ["c.seq.d_2"] =	"4620003aGH",
741    ["c.seq.d_3"] =	"4620003aVGH",
742    ["c.ngl.d_2"] =	"4620003bGH",
743    ["c.ngl.d_3"] =	"4620003bVGH",
744    ["c.lt.d_2"] =	"4620003cGH",
745    ["c.lt.d_3"] =	"4620003cVGH",
746    ["c.nge.d_2"] =	"4620003dGH",
747    ["c.nge.d_3"] =	"4620003dVGH",
748    ["c.le.d_2"] =	"4620003eGH",
749    ["c.le.d_3"] =	"4620003eVGH",
750    ["c.ngt.d_2"] =	"4620003fGH",
751    ["c.ngt.d_3"] =	"4620003fVGH",
752    ["add.ps_3"] =	"46c00000FGH",
753    ["sub.ps_3"] =	"46c00001FGH",
754    ["mul.ps_3"] =	"46c00002FGH",
755    ["abs.ps_2"] =	"46c00005FG",
756    ["mov.ps_2"] =	"46c00006FG",
757    ["neg.ps_2"] =	"46c00007FG",
758    ["movf.ps_2"] =	"46c00011FG",
759    ["movf.ps_3"] =	"46c00011FGC",
760    ["movt.ps_2"] =	"46c10011FG",
761    ["movt.ps_3"] =	"46c10011FGC",
762    ["movz.ps_3"] =	"46c00012FGT",
763    ["movn.ps_3"] =	"46c00013FGT",
764    ["cvt.s.pu_2"] =	"46c00020FG",
765    ["cvt.s.pl_2"] =	"46c00028FG",
766    ["pll.ps_3"] =	"46c0002cFGH",
767    ["plu.ps_3"] =	"46c0002dFGH",
768    ["pul.ps_3"] =	"46c0002eFGH",
769    ["puu.ps_3"] =	"46c0002fFGH",
770    ["c.f.ps_2"] =	"46c00030GH",
771    ["c.f.ps_3"] =	"46c00030VGH",
772    ["c.un.ps_2"] =	"46c00031GH",
773    ["c.un.ps_3"] =	"46c00031VGH",
774    ["c.eq.ps_2"] =	"46c00032GH",
775    ["c.eq.ps_3"] =	"46c00032VGH",
776    ["c.ueq.ps_2"] =	"46c00033GH",
777    ["c.ueq.ps_3"] =	"46c00033VGH",
778    ["c.olt.ps_2"] =	"46c00034GH",
779    ["c.olt.ps_3"] =	"46c00034VGH",
780    ["c.ult.ps_2"] =	"46c00035GH",
781    ["c.ult.ps_3"] =	"46c00035VGH",
782    ["c.ole.ps_2"] =	"46c00036GH",
783    ["c.ole.ps_3"] =	"46c00036VGH",
784    ["c.ule.ps_2"] =	"46c00037GH",
785    ["c.ule.ps_3"] =	"46c00037VGH",
786    ["c.sf.ps_2"] =	"46c00038GH",
787    ["c.sf.ps_3"] =	"46c00038VGH",
788    ["c.ngle.ps_2"] =	"46c00039GH",
789    ["c.ngle.ps_3"] =	"46c00039VGH",
790    ["c.seq.ps_2"] =	"46c0003aGH",
791    ["c.seq.ps_3"] =	"46c0003aVGH",
792    ["c.ngl.ps_2"] =	"46c0003bGH",
793    ["c.ngl.ps_3"] =	"46c0003bVGH",
794    ["c.lt.ps_2"] =	"46c0003cGH",
795    ["c.lt.ps_3"] =	"46c0003cVGH",
796    ["c.nge.ps_2"] =	"46c0003dGH",
797    ["c.nge.ps_3"] =	"46c0003dVGH",
798    ["c.le.ps_2"] =	"46c0003eGH",
799    ["c.le.ps_3"] =	"46c0003eVGH",
800    ["c.ngt.ps_2"] =	"46c0003fGH",
801    ["c.ngt.ps_3"] =	"46c0003fVGH",
802
803    -- Opcode COP1X.
804    lwxc1_2 =	"4c000000FX",
805    ldxc1_2 =	"4c000001FX",
806    luxc1_2 =	"4c000005FX",
807    swxc1_2 =	"4c000008FX",
808    sdxc1_2 =	"4c000009FX",
809    suxc1_2 =	"4c00000dFX",
810    prefx_2 =	"4c00000fMX",
811    ["alnv.ps_4"] =	"4c00001eFGHS",
812    ["madd.s_4"] =	"4c000020FRGH",
813    ["madd.d_4"] =	"4c000021FRGH",
814    ["madd.ps_4"] =	"4c000026FRGH",
815    ["msub.s_4"] =	"4c000028FRGH",
816    ["msub.d_4"] =	"4c000029FRGH",
817    ["msub.ps_4"] =	"4c00002eFRGH",
818    ["nmadd.s_4"] =	"4c000030FRGH",
819    ["nmadd.d_4"] =	"4c000031FRGH",
820    ["nmadd.ps_4"] =	"4c000036FRGH",
821    ["nmsub.s_4"] =	"4c000038FRGH",
822    ["nmsub.d_4"] =	"4c000039FRGH",
823    ["nmsub.ps_4"] =	"4c00003eFRGH",
824
825  }) do map_op[k] = v end
826
827end
828
829------------------------------------------------------------------------------
830
831local function parse_gpr(expr)
832  local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$")
833  local tp = map_type[tname or expr]
834  if tp then
835    local reg = ovreg or tp.reg
836    if not reg then
837      werror("type `"..(tname or expr).."' needs a register override")
838    end
839    expr = reg
840  end
841  local r = match(expr, "^r([1-3]?[0-9])$")
842  if r then
843    r = tonumber(r)
844    if r <= 31 then return r, tp end
845  end
846  werror("bad register name `"..expr.."'")
847end
848
849local function parse_fpr(expr)
850  local r = match(expr, "^f([1-3]?[0-9])$")
851  if r then
852    r = tonumber(r)
853    if r <= 31 then return r end
854  end
855  werror("bad register name `"..expr.."'")
856end
857
858local function parse_imm(imm, bits, shift, scale, signed, action)
859  local n = tonumber(imm)
860  if n then
861    local m = sar(n, scale)
862    if shl(m, scale) == n then
863      if signed then
864	local s = sar(m, bits-1)
865	if s == 0 then return shl(m, shift)
866	elseif s == -1 then return shl(m + shl(1, bits), shift) end
867      else
868	if sar(m, bits) == 0 then return shl(m, shift) end
869      end
870    end
871    werror("out of range immediate `"..imm.."'")
872  elseif match(imm, "^[rf]([1-3]?[0-9])$") or
873	 match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then
874    werror("expected immediate operand, got register")
875  else
876    waction(action or "IMM",
877	    (signed and 32768 or 0)+shl(scale, 10)+shl(bits, 5)+shift, imm)
878    return 0
879  end
880end
881
882local function parse_disp(disp)
883  local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
884  if imm then
885    local r = shl(parse_gpr(reg), 21)
886    local extname = match(imm, "^extern%s+(%S+)$")
887    if extname then
888      waction("REL_EXT", map_extern[extname], nil, 1)
889      return r
890    else
891      return r + parse_imm(imm, 16, 0, 0, true)
892    end
893  end
894  local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
895  if reg and tailr ~= "" then
896    local r, tp = parse_gpr(reg)
897    if tp then
898      waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
899      return shl(r, 21)
900    end
901  end
902  werror("bad displacement `"..disp.."'")
903end
904
905local function parse_index(idx)
906  local rt, rs = match(idx, "^(.*)%(([%w_:]+)%)$")
907  if rt then
908    rt = parse_gpr(rt)
909    rs = parse_gpr(rs)
910    return shl(rt, 16) + shl(rs, 21)
911  end
912  werror("bad index `"..idx.."'")
913end
914
915local function parse_label(label, def)
916  local prefix = sub(label, 1, 2)
917  -- =>label (pc label reference)
918  if prefix == "=>" then
919    return "PC", 0, sub(label, 3)
920  end
921  -- ->name (global label reference)
922  if prefix == "->" then
923    return "LG", map_global[sub(label, 3)]
924  end
925  if def then
926    -- [1-9] (local label definition)
927    if match(label, "^[1-9]$") then
928      return "LG", 10+tonumber(label)
929    end
930  else
931    -- [<>][1-9] (local label reference)
932    local dir, lnum = match(label, "^([<>])([1-9])$")
933    if dir then -- Fwd: 1-9, Bkwd: 11-19.
934      return "LG", lnum + (dir == ">" and 0 or 10)
935    end
936    -- extern label (extern label reference)
937    local extname = match(label, "^extern%s+(%S+)$")
938    if extname then
939      return "EXT", map_extern[extname]
940    end
941  end
942  werror("bad label `"..label.."'")
943end
944
945------------------------------------------------------------------------------
946
947-- Handle opcodes defined with template strings.
948map_op[".template__"] = function(params, template, nparams)
949  if not params then return sub(template, 9) end
950  local op = tonumber(sub(template, 1, 8), 16)
951  local n = 1
952
953  -- Limit number of section buffer positions used by a single dasm_put().
954  -- A single opcode needs a maximum of 2 positions (ins/ext).
955  if secpos+2 > maxsecpos then wflush() end
956  local pos = wpos()
957
958  -- Process each character.
959  for p in gmatch(sub(template, 9), ".") do
960    if p == "D" then
961      op = op + shl(parse_gpr(params[n]), 11); n = n + 1
962    elseif p == "T" then
963      op = op + shl(parse_gpr(params[n]), 16); n = n + 1
964    elseif p == "S" then
965      op = op + shl(parse_gpr(params[n]), 21); n = n + 1
966    elseif p == "F" then
967      op = op + shl(parse_fpr(params[n]), 6); n = n + 1
968    elseif p == "G" then
969      op = op + shl(parse_fpr(params[n]), 11); n = n + 1
970    elseif p == "H" then
971      op = op + shl(parse_fpr(params[n]), 16); n = n + 1
972    elseif p == "R" then
973      op = op + shl(parse_fpr(params[n]), 21); n = n + 1
974    elseif p == "I" then
975      op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
976    elseif p == "U" then
977      op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1
978    elseif p == "O" then
979      op = op + parse_disp(params[n]); n = n + 1
980    elseif p == "X" then
981      op = op + parse_index(params[n]); n = n + 1
982    elseif p == "B" or p == "J" or p == "K" or p == "L" then
983      local mode, m, s = parse_label(params[n], false)
984      if p == "J" then m = m + 0xa800
985      elseif p == "K" then m = m + 0x5000
986      elseif p == "L" then m = m + 0xa000 end
987      waction("REL_"..mode, m, s, 1)
988      n = n + 1
989    elseif p == "A" then
990      op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1
991    elseif p == "a" then
992      local m = parse_imm(params[n], 6, 6, 0, false, "IMMS"); n = n + 1
993      op = op + band(m, 0x7c0) + band(shr(m, 9), 4)
994    elseif p == "M" then
995      op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1
996    elseif p == "N" then
997      op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1
998    elseif p == "C" then
999      op = op + parse_imm(params[n], 3, 18, 0, false); n = n + 1
1000    elseif p == "V" then
1001      op = op + parse_imm(params[n], 3, 8, 0, false); n = n + 1
1002    elseif p == "W" then
1003      op = op + parse_imm(params[n], 3, 0, 0, false); n = n + 1
1004    elseif p == "Y" then
1005      op = op + parse_imm(params[n], 20, 6, 0, false); n = n + 1
1006    elseif p == "Z" then
1007      op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
1008    elseif p == "=" then
1009      n = n - 1 -- Re-use previous parameter for next template char.
1010    else
1011      assert(false)
1012    end
1013  end
1014  wputpos(pos, op)
1015end
1016
1017------------------------------------------------------------------------------
1018
1019-- Pseudo-opcode to mark the position where the action list is to be emitted.
1020map_op[".actionlist_1"] = function(params)
1021  if not params then return "cvar" end
1022  local name = params[1] -- No syntax check. You get to keep the pieces.
1023  wline(function(out) writeactions(out, name) end)
1024end
1025
1026-- Pseudo-opcode to mark the position where the global enum is to be emitted.
1027map_op[".globals_1"] = function(params)
1028  if not params then return "prefix" end
1029  local prefix = params[1] -- No syntax check. You get to keep the pieces.
1030  wline(function(out) writeglobals(out, prefix) end)
1031end
1032
1033-- Pseudo-opcode to mark the position where the global names are to be emitted.
1034map_op[".globalnames_1"] = function(params)
1035  if not params then return "cvar" end
1036  local name = params[1] -- No syntax check. You get to keep the pieces.
1037  wline(function(out) writeglobalnames(out, name) end)
1038end
1039
1040-- Pseudo-opcode to mark the position where the extern names are to be emitted.
1041map_op[".externnames_1"] = function(params)
1042  if not params then return "cvar" end
1043  local name = params[1] -- No syntax check. You get to keep the pieces.
1044  wline(function(out) writeexternnames(out, name) end)
1045end
1046
1047------------------------------------------------------------------------------
1048
1049-- Label pseudo-opcode (converted from trailing colon form).
1050map_op[".label_1"] = function(params)
1051  if not params then return "[1-9] | ->global | =>pcexpr" end
1052  if secpos+1 > maxsecpos then wflush() end
1053  local mode, n, s = parse_label(params[1], true)
1054  if mode == "EXT" then werror("bad label definition") end
1055  waction("LABEL_"..mode, n, s, 1)
1056end
1057
1058------------------------------------------------------------------------------
1059
1060-- Pseudo-opcodes for data storage.
1061map_op[".long_*"] = function(params)
1062  if not params then return "imm..." end
1063  for _,p in ipairs(params) do
1064    local n = tonumber(p)
1065    if not n then werror("bad immediate `"..p.."'") end
1066    if n < 0 then n = n + 2^32 end
1067    wputw(n)
1068    if secpos+2 > maxsecpos then wflush() end
1069  end
1070end
1071
1072-- Alignment pseudo-opcode.
1073map_op[".align_1"] = function(params)
1074  if not params then return "numpow2" end
1075  if secpos+1 > maxsecpos then wflush() end
1076  local align = tonumber(params[1])
1077  if align then
1078    local x = align
1079    -- Must be a power of 2 in the range (2 ... 256).
1080    for i=1,8 do
1081      x = x / 2
1082      if x == 1 then
1083	waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
1084	return
1085      end
1086    end
1087  end
1088  werror("bad alignment")
1089end
1090
1091------------------------------------------------------------------------------
1092
1093-- Pseudo-opcode for (primitive) type definitions (map to C types).
1094map_op[".type_3"] = function(params, nparams)
1095  if not params then
1096    return nparams == 2 and "name, ctype" or "name, ctype, reg"
1097  end
1098  local name, ctype, reg = params[1], params[2], params[3]
1099  if not match(name, "^[%a_][%w_]*$") then
1100    werror("bad type name `"..name.."'")
1101  end
1102  local tp = map_type[name]
1103  if tp then
1104    werror("duplicate type `"..name.."'")
1105  end
1106  -- Add #type to defines. A bit unclean to put it in map_archdef.
1107  map_archdef["#"..name] = "sizeof("..ctype..")"
1108  -- Add new type and emit shortcut define.
1109  local num = ctypenum + 1
1110  map_type[name] = {
1111    ctype = ctype,
1112    ctypefmt = format("Dt%X(%%s)", num),
1113    reg = reg,
1114  }
1115  wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
1116  ctypenum = num
1117end
1118map_op[".type_2"] = map_op[".type_3"]
1119
1120-- Dump type definitions.
1121local function dumptypes(out, lvl)
1122  local t = {}
1123  for name in pairs(map_type) do t[#t+1] = name end
1124  sort(t)
1125  out:write("Type definitions:\n")
1126  for _,name in ipairs(t) do
1127    local tp = map_type[name]
1128    local reg = tp.reg or ""
1129    out:write(format("  %-20s %-20s %s\n", name, tp.ctype, reg))
1130  end
1131  out:write("\n")
1132end
1133
1134------------------------------------------------------------------------------
1135
1136-- Set the current section.
1137function _M.section(num)
1138  waction("SECTION", num)
1139  wflush(true) -- SECTION is a terminal action.
1140end
1141
1142------------------------------------------------------------------------------
1143
1144-- Dump architecture description.
1145function _M.dumparch(out)
1146  out:write(format("DynASM %s version %s, released %s\n\n",
1147    _info.arch, _info.version, _info.release))
1148  dumpactions(out)
1149end
1150
1151-- Dump all user defined elements.
1152function _M.dumpdef(out, lvl)
1153  dumptypes(out, lvl)
1154  dumpglobals(out, lvl)
1155  dumpexterns(out, lvl)
1156end
1157
1158------------------------------------------------------------------------------
1159
1160-- Pass callbacks from/to the DynASM core.
1161function _M.passcb(wl, we, wf, ww)
1162  wline, werror, wfatal, wwarn = wl, we, wf, ww
1163  return wflush
1164end
1165
1166-- Setup the arch-specific module.
1167function _M.setup(arch, opt)
1168  g_arch, g_opt = arch, opt
1169end
1170
1171-- Merge the core maps and the arch-specific maps.
1172function _M.mergemaps(map_coreop, map_def)
1173  setmetatable(map_op, { __index = map_coreop })
1174  setmetatable(map_def, { __index = map_archdef })
1175  return map_op, map_def
1176end
1177
1178return _M
1179
1180------------------------------------------------------------------------------
1181
1182