1------------------------------------------------------------------------------
2-- DynASM MIPS module.
3--
4-- Copyright (C) 2005-2014 Mike Pall. All rights reserved.
5-- See dynasm.lua for full copyright notice.
6------------------------------------------------------------------------------
7
8-- Module information:
9local _info = {
10  arch =	"mips",
11  description =	"DynASM MIPS module",
12  version =	"1.3.0",
13  vernum =	 10300,
14  release =	"2012-01-23",
15  author =	"Mike Pall",
16  license =	"MIT",
17}
18
19-- Exported glue functions for the arch-specific module.
20local _M = { _info = _info }
21
22-- Cache library functions.
23local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
24local assert, setmetatable = assert, setmetatable
25local _s = string
26local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
27local match, gmatch = _s.match, _s.gmatch
28local concat, sort = table.concat, table.sort
29local bit = bit or require("bit")
30local band, shl, sar, tohex = bit.band, bit.lshift, bit.arshift, bit.tohex
31
32-- Inherited tables and callbacks.
33local g_opt, g_arch
34local wline, werror, wfatal, wwarn
35
36-- Action name list.
37-- CHECK: Keep this in sync with the C code!
38local action_names = {
39  "STOP", "SECTION", "ESC", "REL_EXT",
40  "ALIGN", "REL_LG", "LABEL_LG",
41  "REL_PC", "LABEL_PC", "IMM",
42}
43
44-- Maximum number of section buffer positions for dasm_put().
45-- CHECK: Keep this in sync with the C code!
46local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
47
48-- Action name -> action number.
49local map_action = {}
50for n,name in ipairs(action_names) do
51  map_action[name] = n-1
52end
53
54-- Action list buffer.
55local actlist = {}
56
57-- Argument list for next dasm_put(). Start with offset 0 into action list.
58local actargs = { 0 }
59
60-- Current number of section buffer positions for dasm_put().
61local secpos = 1
62
63------------------------------------------------------------------------------
64
65-- Dump action names and numbers.
66local function dumpactions(out)
67  out:write("DynASM encoding engine action codes:\n")
68  for n,name in ipairs(action_names) do
69    local num = map_action[name]
70    out:write(format("  %-10s %02X  %d\n", name, num, num))
71  end
72  out:write("\n")
73end
74
75-- Write action list buffer as a huge static C array.
76local function writeactions(out, name)
77  local nn = #actlist
78  if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
79  out:write("static const unsigned int ", name, "[", nn, "] = {\n")
80  for i = 1,nn-1 do
81    assert(out:write("0x", tohex(actlist[i]), ",\n"))
82  end
83  assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
84end
85
86------------------------------------------------------------------------------
87
88-- Add word to action list.
89local function wputxw(n)
90  assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
91  actlist[#actlist+1] = n
92end
93
94-- Add action to list with optional arg. Advance buffer pos, too.
95local function waction(action, val, a, num)
96  local w = assert(map_action[action], "bad action name `"..action.."'")
97  wputxw(0xff000000 + w * 0x10000 + (val or 0))
98  if a then actargs[#actargs+1] = a end
99  if a or num then secpos = secpos + (num or 1) end
100end
101
102-- Flush action list (intervening C code or buffer pos overflow).
103local function wflush(term)
104  if #actlist == actargs[1] then return end -- Nothing to flush.
105  if not term then waction("STOP") end -- Terminate action list.
106  wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
107  actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
108  secpos = 1 -- The actionlist offset occupies a buffer position, too.
109end
110
111-- Put escaped word.
112local function wputw(n)
113  if n >= 0xff000000 then waction("ESC") end
114  wputxw(n)
115end
116
117-- Reserve position for word.
118local function wpos()
119  local pos = #actlist+1
120  actlist[pos] = ""
121  return pos
122end
123
124-- Store word to reserved position.
125local function wputpos(pos, n)
126  assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
127  actlist[pos] = n
128end
129
130------------------------------------------------------------------------------
131
132-- Global label name -> global label number. With auto assignment on 1st use.
133local next_global = 20
134local map_global = setmetatable({}, { __index = function(t, name)
135  if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
136  local n = next_global
137  if n > 2047 then werror("too many global labels") end
138  next_global = n + 1
139  t[name] = n
140  return n
141end})
142
143-- Dump global labels.
144local function dumpglobals(out, lvl)
145  local t = {}
146  for name, n in pairs(map_global) do t[n] = name end
147  out:write("Global labels:\n")
148  for i=20,next_global-1 do
149    out:write(format("  %s\n", t[i]))
150  end
151  out:write("\n")
152end
153
154-- Write global label enum.
155local function writeglobals(out, prefix)
156  local t = {}
157  for name, n in pairs(map_global) do t[n] = name end
158  out:write("enum {\n")
159  for i=20,next_global-1 do
160    out:write("  ", prefix, t[i], ",\n")
161  end
162  out:write("  ", prefix, "_MAX\n};\n")
163end
164
165-- Write global label names.
166local function writeglobalnames(out, name)
167  local t = {}
168  for name, n in pairs(map_global) do t[n] = name end
169  out:write("static const char *const ", name, "[] = {\n")
170  for i=20,next_global-1 do
171    out:write("  \"", t[i], "\",\n")
172  end
173  out:write("  (const char *)0\n};\n")
174end
175
176------------------------------------------------------------------------------
177
178-- Extern label name -> extern label number. With auto assignment on 1st use.
179local next_extern = 0
180local map_extern_ = {}
181local map_extern = setmetatable({}, { __index = function(t, name)
182  -- No restrictions on the name for now.
183  local n = next_extern
184  if n > 2047 then werror("too many extern labels") end
185  next_extern = n + 1
186  t[name] = n
187  map_extern_[n] = name
188  return n
189end})
190
191-- Dump extern labels.
192local function dumpexterns(out, lvl)
193  out:write("Extern labels:\n")
194  for i=0,next_extern-1 do
195    out:write(format("  %s\n", map_extern_[i]))
196  end
197  out:write("\n")
198end
199
200-- Write extern label names.
201local function writeexternnames(out, name)
202  out:write("static const char *const ", name, "[] = {\n")
203  for i=0,next_extern-1 do
204    out:write("  \"", map_extern_[i], "\",\n")
205  end
206  out:write("  (const char *)0\n};\n")
207end
208
209------------------------------------------------------------------------------
210
211-- Arch-specific maps.
212local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name.
213
214local map_type = {}		-- Type name -> { ctype, reg }
215local ctypenum = 0		-- Type number (for Dt... macros).
216
217-- Reverse defines for registers.
218function _M.revdef(s)
219  if s == "r29" then return "sp"
220  elseif s == "r31" then return "ra" end
221  return s
222end
223
224------------------------------------------------------------------------------
225
226-- Template strings for MIPS instructions.
227local map_op = {
228  -- First-level opcodes.
229  j_1 =		"08000000J",
230  jal_1 =	"0c000000J",
231  b_1 =		"10000000B",
232  beqz_2 =	"10000000SB",
233  beq_3 =	"10000000STB",
234  bnez_2 =	"14000000SB",
235  bne_3 =	"14000000STB",
236  blez_2 =	"18000000SB",
237  bgtz_2 =	"1c000000SB",
238  addi_3 =	"20000000TSI",
239  li_2 =	"24000000TI",
240  addiu_3 =	"24000000TSI",
241  slti_3 =	"28000000TSI",
242  sltiu_3 =	"2c000000TSI",
243  andi_3 =	"30000000TSU",
244  lu_2 =	"34000000TU",
245  ori_3 =	"34000000TSU",
246  xori_3 =	"38000000TSU",
247  lui_2 =	"3c000000TU",
248  beqzl_2 =	"50000000SB",
249  beql_3 =	"50000000STB",
250  bnezl_2 =	"54000000SB",
251  bnel_3 =	"54000000STB",
252  blezl_2 =	"58000000SB",
253  bgtzl_2 =	"5c000000SB",
254  lb_2 =	"80000000TO",
255  lh_2 =	"84000000TO",
256  lwl_2 =	"88000000TO",
257  lw_2 =	"8c000000TO",
258  lbu_2 =	"90000000TO",
259  lhu_2 =	"94000000TO",
260  lwr_2 =	"98000000TO",
261  sb_2 =	"a0000000TO",
262  sh_2 =	"a4000000TO",
263  swl_2 =	"a8000000TO",
264  sw_2 =	"ac000000TO",
265  swr_2 =	"b8000000TO",
266  cache_2 =	"bc000000NO",
267  ll_2 =	"c0000000TO",
268  lwc1_2 =	"c4000000HO",
269  pref_2 =	"cc000000NO",
270  ldc1_2 =	"d4000000HO",
271  sc_2 =	"e0000000TO",
272  swc1_2 =	"e4000000HO",
273  sdc1_2 =	"f4000000HO",
274
275  -- Opcode SPECIAL.
276  nop_0 =	"00000000",
277  sll_3 =	"00000000DTA",
278  movf_2 =	"00000001DS",
279  movf_3 =	"00000001DSC",
280  movt_2 =	"00010001DS",
281  movt_3 =	"00010001DSC",
282  srl_3 =	"00000002DTA",
283  rotr_3 =	"00200002DTA",
284  sra_3 =	"00000003DTA",
285  sllv_3 =	"00000004DTS",
286  srlv_3 =	"00000006DTS",
287  rotrv_3 =	"00000046DTS",
288  srav_3 =	"00000007DTS",
289  jr_1 =	"00000008S",
290  jalr_1 =	"0000f809S",
291  jalr_2 =	"00000009DS",
292  movz_3 =	"0000000aDST",
293  movn_3 =	"0000000bDST",
294  syscall_0 =	"0000000c",
295  syscall_1 =	"0000000cY",
296  break_0 =	"0000000d",
297  break_1 =	"0000000dY",
298  sync_0 =	"0000000f",
299  mfhi_1 =	"00000010D",
300  mthi_1 =	"00000011S",
301  mflo_1 =	"00000012D",
302  mtlo_1 =	"00000013S",
303  mult_2 =	"00000018ST",
304  multu_2 =	"00000019ST",
305  div_2 =	"0000001aST",
306  divu_2 =	"0000001bST",
307  add_3 =	"00000020DST",
308  move_2 =	"00000021DS",
309  addu_3 =	"00000021DST",
310  sub_3 =	"00000022DST",
311  negu_2 =	"00000023DT",
312  subu_3 =	"00000023DST",
313  and_3 =	"00000024DST",
314  or_3 =	"00000025DST",
315  xor_3 =	"00000026DST",
316  not_2 =	"00000027DS",
317  nor_3 =	"00000027DST",
318  slt_3 =	"0000002aDST",
319  sltu_3 =	"0000002bDST",
320  tge_2 =	"00000030ST",
321  tge_3 =	"00000030STZ",
322  tgeu_2 =	"00000031ST",
323  tgeu_3 =	"00000031STZ",
324  tlt_2 =	"00000032ST",
325  tlt_3 =	"00000032STZ",
326  tltu_2 =	"00000033ST",
327  tltu_3 =	"00000033STZ",
328  teq_2 =	"00000034ST",
329  teq_3 =	"00000034STZ",
330  tne_2 =	"00000036ST",
331  tne_3 =	"00000036STZ",
332
333  -- Opcode REGIMM.
334  bltz_2 =	"04000000SB",
335  bgez_2 =	"04010000SB",
336  bltzl_2 =	"04020000SB",
337  bgezl_2 =	"04030000SB",
338  tgei_2 =	"04080000SI",
339  tgeiu_2 =	"04090000SI",
340  tlti_2 =	"040a0000SI",
341  tltiu_2 =	"040b0000SI",
342  teqi_2 =	"040c0000SI",
343  tnei_2 =	"040e0000SI",
344  bltzal_2 =	"04100000SB",
345  bal_1 =	"04110000B",
346  bgezal_2 =	"04110000SB",
347  bltzall_2 =	"04120000SB",
348  bgezall_2 =	"04130000SB",
349  synci_1 =	"041f0000O",
350
351  -- Opcode SPECIAL2.
352  madd_2 =	"70000000ST",
353  maddu_2 =	"70000001ST",
354  mul_3 =	"70000002DST",
355  msub_2 =	"70000004ST",
356  msubu_2 =	"70000005ST",
357  clz_2 =	"70000020DS=",
358  clo_2 =	"70000021DS=",
359  sdbbp_0 =	"7000003f",
360  sdbbp_1 =	"7000003fY",
361
362  -- Opcode SPECIAL3.
363  ext_4 =	"7c000000TSAM", -- Note: last arg is msbd = size-1
364  ins_4 =	"7c000004TSAM", -- Note: last arg is msb = pos+size-1
365  wsbh_2 =	"7c0000a0DT",
366  seb_2 =	"7c000420DT",
367  seh_2 =	"7c000620DT",
368  rdhwr_2 =	"7c00003bTD",
369
370  -- Opcode COP0.
371  mfc0_2 =	"40000000TD",
372  mfc0_3 =	"40000000TDW",
373  mtc0_2 =	"40800000TD",
374  mtc0_3 =	"40800000TDW",
375  rdpgpr_2 =	"41400000DT",
376  di_0 =	"41606000",
377  di_1 =	"41606000T",
378  ei_0 =	"41606020",
379  ei_1 =	"41606020T",
380  wrpgpr_2 =	"41c00000DT",
381  tlbr_0 =	"42000001",
382  tlbwi_0 =	"42000002",
383  tlbwr_0 =	"42000006",
384  tlbp_0 =	"42000008",
385  eret_0 =	"42000018",
386  deret_0 =	"4200001f",
387  wait_0 =	"42000020",
388
389  -- Opcode COP1.
390  mfc1_2 =	"44000000TG",
391  cfc1_2 =	"44400000TG",
392  mfhc1_2 =	"44600000TG",
393  mtc1_2 =	"44800000TG",
394  ctc1_2 =	"44c00000TG",
395  mthc1_2 =	"44e00000TG",
396
397  bc1f_1 =	"45000000B",
398  bc1f_2 =	"45000000CB",
399  bc1t_1 =	"45010000B",
400  bc1t_2 =	"45010000CB",
401  bc1fl_1 =	"45020000B",
402  bc1fl_2 =	"45020000CB",
403  bc1tl_1 =	"45030000B",
404  bc1tl_2 =	"45030000CB",
405
406  ["add.s_3"] =		"46000000FGH",
407  ["sub.s_3"] =		"46000001FGH",
408  ["mul.s_3"] =		"46000002FGH",
409  ["div.s_3"] =		"46000003FGH",
410  ["sqrt.s_2"] =	"46000004FG",
411  ["abs.s_2"] =		"46000005FG",
412  ["mov.s_2"] =		"46000006FG",
413  ["neg.s_2"] =		"46000007FG",
414  ["round.l.s_2"] =	"46000008FG",
415  ["trunc.l.s_2"] =	"46000009FG",
416  ["ceil.l.s_2"] =	"4600000aFG",
417  ["floor.l.s_2"] =	"4600000bFG",
418  ["round.w.s_2"] =	"4600000cFG",
419  ["trunc.w.s_2"] =	"4600000dFG",
420  ["ceil.w.s_2"] =	"4600000eFG",
421  ["floor.w.s_2"] =	"4600000fFG",
422  ["movf.s_2"] =	"46000011FG",
423  ["movf.s_3"] =	"46000011FGC",
424  ["movt.s_2"] =	"46010011FG",
425  ["movt.s_3"] =	"46010011FGC",
426  ["movz.s_3"] =	"46000012FGT",
427  ["movn.s_3"] =	"46000013FGT",
428  ["recip.s_2"] =	"46000015FG",
429  ["rsqrt.s_2"] =	"46000016FG",
430  ["cvt.d.s_2"] =	"46000021FG",
431  ["cvt.w.s_2"] =	"46000024FG",
432  ["cvt.l.s_2"] =	"46000025FG",
433  ["cvt.ps.s_3"] =	"46000026FGH",
434  ["c.f.s_2"] =		"46000030GH",
435  ["c.f.s_3"] =		"46000030VGH",
436  ["c.un.s_2"] =	"46000031GH",
437  ["c.un.s_3"] =	"46000031VGH",
438  ["c.eq.s_2"] =	"46000032GH",
439  ["c.eq.s_3"] =	"46000032VGH",
440  ["c.ueq.s_2"] =	"46000033GH",
441  ["c.ueq.s_3"] =	"46000033VGH",
442  ["c.olt.s_2"] =	"46000034GH",
443  ["c.olt.s_3"] =	"46000034VGH",
444  ["c.ult.s_2"] =	"46000035GH",
445  ["c.ult.s_3"] =	"46000035VGH",
446  ["c.ole.s_2"] =	"46000036GH",
447  ["c.ole.s_3"] =	"46000036VGH",
448  ["c.ule.s_2"] =	"46000037GH",
449  ["c.ule.s_3"] =	"46000037VGH",
450  ["c.sf.s_2"] =	"46000038GH",
451  ["c.sf.s_3"] =	"46000038VGH",
452  ["c.ngle.s_2"] =	"46000039GH",
453  ["c.ngle.s_3"] =	"46000039VGH",
454  ["c.seq.s_2"] =	"4600003aGH",
455  ["c.seq.s_3"] =	"4600003aVGH",
456  ["c.ngl.s_2"] =	"4600003bGH",
457  ["c.ngl.s_3"] =	"4600003bVGH",
458  ["c.lt.s_2"] =	"4600003cGH",
459  ["c.lt.s_3"] =	"4600003cVGH",
460  ["c.nge.s_2"] =	"4600003dGH",
461  ["c.nge.s_3"] =	"4600003dVGH",
462  ["c.le.s_2"] =	"4600003eGH",
463  ["c.le.s_3"] =	"4600003eVGH",
464  ["c.ngt.s_2"] =	"4600003fGH",
465  ["c.ngt.s_3"] =	"4600003fVGH",
466
467  ["add.d_3"] =		"46200000FGH",
468  ["sub.d_3"] =		"46200001FGH",
469  ["mul.d_3"] =		"46200002FGH",
470  ["div.d_3"] =		"46200003FGH",
471  ["sqrt.d_2"] =	"46200004FG",
472  ["abs.d_2"] =		"46200005FG",
473  ["mov.d_2"] =		"46200006FG",
474  ["neg.d_2"] =		"46200007FG",
475  ["round.l.d_2"] =	"46200008FG",
476  ["trunc.l.d_2"] =	"46200009FG",
477  ["ceil.l.d_2"] =	"4620000aFG",
478  ["floor.l.d_2"] =	"4620000bFG",
479  ["round.w.d_2"] =	"4620000cFG",
480  ["trunc.w.d_2"] =	"4620000dFG",
481  ["ceil.w.d_2"] =	"4620000eFG",
482  ["floor.w.d_2"] =	"4620000fFG",
483  ["movf.d_2"] =	"46200011FG",
484  ["movf.d_3"] =	"46200011FGC",
485  ["movt.d_2"] =	"46210011FG",
486  ["movt.d_3"] =	"46210011FGC",
487  ["movz.d_3"] =	"46200012FGT",
488  ["movn.d_3"] =	"46200013FGT",
489  ["recip.d_2"] =	"46200015FG",
490  ["rsqrt.d_2"] =	"46200016FG",
491  ["cvt.s.d_2"] =	"46200020FG",
492  ["cvt.w.d_2"] =	"46200024FG",
493  ["cvt.l.d_2"] =	"46200025FG",
494  ["c.f.d_2"] =		"46200030GH",
495  ["c.f.d_3"] =		"46200030VGH",
496  ["c.un.d_2"] =	"46200031GH",
497  ["c.un.d_3"] =	"46200031VGH",
498  ["c.eq.d_2"] =	"46200032GH",
499  ["c.eq.d_3"] =	"46200032VGH",
500  ["c.ueq.d_2"] =	"46200033GH",
501  ["c.ueq.d_3"] =	"46200033VGH",
502  ["c.olt.d_2"] =	"46200034GH",
503  ["c.olt.d_3"] =	"46200034VGH",
504  ["c.ult.d_2"] =	"46200035GH",
505  ["c.ult.d_3"] =	"46200035VGH",
506  ["c.ole.d_2"] =	"46200036GH",
507  ["c.ole.d_3"] =	"46200036VGH",
508  ["c.ule.d_2"] =	"46200037GH",
509  ["c.ule.d_3"] =	"46200037VGH",
510  ["c.sf.d_2"] =	"46200038GH",
511  ["c.sf.d_3"] =	"46200038VGH",
512  ["c.ngle.d_2"] =	"46200039GH",
513  ["c.ngle.d_3"] =	"46200039VGH",
514  ["c.seq.d_2"] =	"4620003aGH",
515  ["c.seq.d_3"] =	"4620003aVGH",
516  ["c.ngl.d_2"] =	"4620003bGH",
517  ["c.ngl.d_3"] =	"4620003bVGH",
518  ["c.lt.d_2"] =	"4620003cGH",
519  ["c.lt.d_3"] =	"4620003cVGH",
520  ["c.nge.d_2"] =	"4620003dGH",
521  ["c.nge.d_3"] =	"4620003dVGH",
522  ["c.le.d_2"] =	"4620003eGH",
523  ["c.le.d_3"] =	"4620003eVGH",
524  ["c.ngt.d_2"] =	"4620003fGH",
525  ["c.ngt.d_3"] =	"4620003fVGH",
526
527  ["add.ps_3"] =	"46c00000FGH",
528  ["sub.ps_3"] =	"46c00001FGH",
529  ["mul.ps_3"] =	"46c00002FGH",
530  ["abs.ps_2"] =	"46c00005FG",
531  ["mov.ps_2"] =	"46c00006FG",
532  ["neg.ps_2"] =	"46c00007FG",
533  ["movf.ps_2"] =	"46c00011FG",
534  ["movf.ps_3"] =	"46c00011FGC",
535  ["movt.ps_2"] =	"46c10011FG",
536  ["movt.ps_3"] =	"46c10011FGC",
537  ["movz.ps_3"] =	"46c00012FGT",
538  ["movn.ps_3"] =	"46c00013FGT",
539  ["cvt.s.pu_2"] =	"46c00020FG",
540  ["cvt.s.pl_2"] =	"46c00028FG",
541  ["pll.ps_3"] =	"46c0002cFGH",
542  ["plu.ps_3"] =	"46c0002dFGH",
543  ["pul.ps_3"] =	"46c0002eFGH",
544  ["puu.ps_3"] =	"46c0002fFGH",
545  ["c.f.ps_2"] =	"46c00030GH",
546  ["c.f.ps_3"] =	"46c00030VGH",
547  ["c.un.ps_2"] =	"46c00031GH",
548  ["c.un.ps_3"] =	"46c00031VGH",
549  ["c.eq.ps_2"] =	"46c00032GH",
550  ["c.eq.ps_3"] =	"46c00032VGH",
551  ["c.ueq.ps_2"] =	"46c00033GH",
552  ["c.ueq.ps_3"] =	"46c00033VGH",
553  ["c.olt.ps_2"] =	"46c00034GH",
554  ["c.olt.ps_3"] =	"46c00034VGH",
555  ["c.ult.ps_2"] =	"46c00035GH",
556  ["c.ult.ps_3"] =	"46c00035VGH",
557  ["c.ole.ps_2"] =	"46c00036GH",
558  ["c.ole.ps_3"] =	"46c00036VGH",
559  ["c.ule.ps_2"] =	"46c00037GH",
560  ["c.ule.ps_3"] =	"46c00037VGH",
561  ["c.sf.ps_2"] =	"46c00038GH",
562  ["c.sf.ps_3"] =	"46c00038VGH",
563  ["c.ngle.ps_2"] =	"46c00039GH",
564  ["c.ngle.ps_3"] =	"46c00039VGH",
565  ["c.seq.ps_2"] =	"46c0003aGH",
566  ["c.seq.ps_3"] =	"46c0003aVGH",
567  ["c.ngl.ps_2"] =	"46c0003bGH",
568  ["c.ngl.ps_3"] =	"46c0003bVGH",
569  ["c.lt.ps_2"] =	"46c0003cGH",
570  ["c.lt.ps_3"] =	"46c0003cVGH",
571  ["c.nge.ps_2"] =	"46c0003dGH",
572  ["c.nge.ps_3"] =	"46c0003dVGH",
573  ["c.le.ps_2"] =	"46c0003eGH",
574  ["c.le.ps_3"] =	"46c0003eVGH",
575  ["c.ngt.ps_2"] =	"46c0003fGH",
576  ["c.ngt.ps_3"] =	"46c0003fVGH",
577
578  ["cvt.s.w_2"] =	"46800020FG",
579  ["cvt.d.w_2"] =	"46800021FG",
580
581  ["cvt.s.l_2"] =	"46a00020FG",
582  ["cvt.d.l_2"] =	"46a00021FG",
583
584  -- Opcode COP1X.
585  lwxc1_2 =		"4c000000FX",
586  ldxc1_2 =		"4c000001FX",
587  luxc1_2 =		"4c000005FX",
588  swxc1_2 =		"4c000008FX",
589  sdxc1_2 =		"4c000009FX",
590  suxc1_2 =		"4c00000dFX",
591  prefx_2 =		"4c00000fMX",
592  ["alnv.ps_4"] =	"4c00001eFGHS",
593  ["madd.s_4"] =	"4c000020FRGH",
594  ["madd.d_4"] =	"4c000021FRGH",
595  ["madd.ps_4"] =	"4c000026FRGH",
596  ["msub.s_4"] =	"4c000028FRGH",
597  ["msub.d_4"] =	"4c000029FRGH",
598  ["msub.ps_4"] =	"4c00002eFRGH",
599  ["nmadd.s_4"] =	"4c000030FRGH",
600  ["nmadd.d_4"] =	"4c000031FRGH",
601  ["nmadd.ps_4"] =	"4c000036FRGH",
602  ["nmsub.s_4"] =	"4c000038FRGH",
603  ["nmsub.d_4"] =	"4c000039FRGH",
604  ["nmsub.ps_4"] =	"4c00003eFRGH",
605}
606
607------------------------------------------------------------------------------
608
609local function parse_gpr(expr)
610  local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$")
611  local tp = map_type[tname or expr]
612  if tp then
613    local reg = ovreg or tp.reg
614    if not reg then
615      werror("type `"..(tname or expr).."' needs a register override")
616    end
617    expr = reg
618  end
619  local r = match(expr, "^r([1-3]?[0-9])$")
620  if r then
621    r = tonumber(r)
622    if r <= 31 then return r, tp end
623  end
624  werror("bad register name `"..expr.."'")
625end
626
627local function parse_fpr(expr)
628  local r = match(expr, "^f([1-3]?[0-9])$")
629  if r then
630    r = tonumber(r)
631    if r <= 31 then return r end
632  end
633  werror("bad register name `"..expr.."'")
634end
635
636local function parse_imm(imm, bits, shift, scale, signed)
637  local n = tonumber(imm)
638  if n then
639    local m = sar(n, scale)
640    if shl(m, scale) == n then
641      if signed then
642	local s = sar(m, bits-1)
643	if s == 0 then return shl(m, shift)
644	elseif s == -1 then return shl(m + shl(1, bits), shift) end
645      else
646	if sar(m, bits) == 0 then return shl(m, shift) end
647      end
648    end
649    werror("out of range immediate `"..imm.."'")
650  elseif match(imm, "^[rf]([1-3]?[0-9])$") or
651	 match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then
652    werror("expected immediate operand, got register")
653  else
654    waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
655    return 0
656  end
657end
658
659local function parse_disp(disp)
660  local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
661  if imm then
662    local r = shl(parse_gpr(reg), 21)
663    local extname = match(imm, "^extern%s+(%S+)$")
664    if extname then
665      waction("REL_EXT", map_extern[extname], nil, 1)
666      return r
667    else
668      return r + parse_imm(imm, 16, 0, 0, true)
669    end
670  end
671  local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
672  if reg and tailr ~= "" then
673    local r, tp = parse_gpr(reg)
674    if tp then
675      waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
676      return shl(r, 21)
677    end
678  end
679  werror("bad displacement `"..disp.."'")
680end
681
682local function parse_index(idx)
683  local rt, rs = match(idx, "^(.*)%(([%w_:]+)%)$")
684  if rt then
685    rt = parse_gpr(rt)
686    rs = parse_gpr(rs)
687    return shl(rt, 16) + shl(rs, 21)
688  end
689  werror("bad index `"..idx.."'")
690end
691
692local function parse_label(label, def)
693  local prefix = sub(label, 1, 2)
694  -- =>label (pc label reference)
695  if prefix == "=>" then
696    return "PC", 0, sub(label, 3)
697  end
698  -- ->name (global label reference)
699  if prefix == "->" then
700    return "LG", map_global[sub(label, 3)]
701  end
702  if def then
703    -- [1-9] (local label definition)
704    if match(label, "^[1-9]$") then
705      return "LG", 10+tonumber(label)
706    end
707  else
708    -- [<>][1-9] (local label reference)
709    local dir, lnum = match(label, "^([<>])([1-9])$")
710    if dir then -- Fwd: 1-9, Bkwd: 11-19.
711      return "LG", lnum + (dir == ">" and 0 or 10)
712    end
713    -- extern label (extern label reference)
714    local extname = match(label, "^extern%s+(%S+)$")
715    if extname then
716      return "EXT", map_extern[extname]
717    end
718  end
719  werror("bad label `"..label.."'")
720end
721
722------------------------------------------------------------------------------
723
724-- Handle opcodes defined with template strings.
725map_op[".template__"] = function(params, template, nparams)
726  if not params then return sub(template, 9) end
727  local op = tonumber(sub(template, 1, 8), 16)
728  local n = 1
729
730  -- Limit number of section buffer positions used by a single dasm_put().
731  -- A single opcode needs a maximum of 2 positions (ins/ext).
732  if secpos+2 > maxsecpos then wflush() end
733  local pos = wpos()
734
735  -- Process each character.
736  for p in gmatch(sub(template, 9), ".") do
737    if p == "D" then
738      op = op + shl(parse_gpr(params[n]), 11); n = n + 1
739    elseif p == "T" then
740      op = op + shl(parse_gpr(params[n]), 16); n = n + 1
741    elseif p == "S" then
742      op = op + shl(parse_gpr(params[n]), 21); n = n + 1
743    elseif p == "F" then
744      op = op + shl(parse_fpr(params[n]), 6); n = n + 1
745    elseif p == "G" then
746      op = op + shl(parse_fpr(params[n]), 11); n = n + 1
747    elseif p == "H" then
748      op = op + shl(parse_fpr(params[n]), 16); n = n + 1
749    elseif p == "R" then
750      op = op + shl(parse_fpr(params[n]), 21); n = n + 1
751    elseif p == "I" then
752      op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
753    elseif p == "U" then
754      op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1
755    elseif p == "O" then
756      op = op + parse_disp(params[n]); n = n + 1
757    elseif p == "X" then
758      op = op + parse_index(params[n]); n = n + 1
759    elseif p == "B" or p == "J" then
760      local mode, n, s = parse_label(params[n], false)
761      if p == "B" then n = n + 2048 end
762      waction("REL_"..mode, n, s, 1)
763      n = n + 1
764    elseif p == "A" then
765      op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1
766    elseif p == "M" then
767      op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1
768    elseif p == "N" then
769      op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1
770    elseif p == "C" then
771      op = op + parse_imm(params[n], 3, 18, 0, false); n = n + 1
772    elseif p == "V" then
773      op = op + parse_imm(params[n], 3, 8, 0, false); n = n + 1
774    elseif p == "W" then
775      op = op + parse_imm(params[n], 3, 0, 0, false); n = n + 1
776    elseif p == "Y" then
777      op = op + parse_imm(params[n], 20, 6, 0, false); n = n + 1
778    elseif p == "Z" then
779      op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
780    elseif p == "=" then
781      op = op + shl(band(op, 0xf800), 5) -- Copy D to T for clz, clo.
782    else
783      assert(false)
784    end
785  end
786  wputpos(pos, op)
787end
788
789------------------------------------------------------------------------------
790
791-- Pseudo-opcode to mark the position where the action list is to be emitted.
792map_op[".actionlist_1"] = function(params)
793  if not params then return "cvar" end
794  local name = params[1] -- No syntax check. You get to keep the pieces.
795  wline(function(out) writeactions(out, name) end)
796end
797
798-- Pseudo-opcode to mark the position where the global enum is to be emitted.
799map_op[".globals_1"] = function(params)
800  if not params then return "prefix" end
801  local prefix = params[1] -- No syntax check. You get to keep the pieces.
802  wline(function(out) writeglobals(out, prefix) end)
803end
804
805-- Pseudo-opcode to mark the position where the global names are to be emitted.
806map_op[".globalnames_1"] = function(params)
807  if not params then return "cvar" end
808  local name = params[1] -- No syntax check. You get to keep the pieces.
809  wline(function(out) writeglobalnames(out, name) end)
810end
811
812-- Pseudo-opcode to mark the position where the extern names are to be emitted.
813map_op[".externnames_1"] = function(params)
814  if not params then return "cvar" end
815  local name = params[1] -- No syntax check. You get to keep the pieces.
816  wline(function(out) writeexternnames(out, name) end)
817end
818
819------------------------------------------------------------------------------
820
821-- Label pseudo-opcode (converted from trailing colon form).
822map_op[".label_1"] = function(params)
823  if not params then return "[1-9] | ->global | =>pcexpr" end
824  if secpos+1 > maxsecpos then wflush() end
825  local mode, n, s = parse_label(params[1], true)
826  if mode == "EXT" then werror("bad label definition") end
827  waction("LABEL_"..mode, n, s, 1)
828end
829
830------------------------------------------------------------------------------
831
832-- Pseudo-opcodes for data storage.
833map_op[".long_*"] = function(params)
834  if not params then return "imm..." end
835  for _,p in ipairs(params) do
836    local n = tonumber(p)
837    if not n then werror("bad immediate `"..p.."'") end
838    if n < 0 then n = n + 2^32 end
839    wputw(n)
840    if secpos+2 > maxsecpos then wflush() end
841  end
842end
843
844-- Alignment pseudo-opcode.
845map_op[".align_1"] = function(params)
846  if not params then return "numpow2" end
847  if secpos+1 > maxsecpos then wflush() end
848  local align = tonumber(params[1])
849  if align then
850    local x = align
851    -- Must be a power of 2 in the range (2 ... 256).
852    for i=1,8 do
853      x = x / 2
854      if x == 1 then
855	waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
856	return
857      end
858    end
859  end
860  werror("bad alignment")
861end
862
863------------------------------------------------------------------------------
864
865-- Pseudo-opcode for (primitive) type definitions (map to C types).
866map_op[".type_3"] = function(params, nparams)
867  if not params then
868    return nparams == 2 and "name, ctype" or "name, ctype, reg"
869  end
870  local name, ctype, reg = params[1], params[2], params[3]
871  if not match(name, "^[%a_][%w_]*$") then
872    werror("bad type name `"..name.."'")
873  end
874  local tp = map_type[name]
875  if tp then
876    werror("duplicate type `"..name.."'")
877  end
878  -- Add #type to defines. A bit unclean to put it in map_archdef.
879  map_archdef["#"..name] = "sizeof("..ctype..")"
880  -- Add new type and emit shortcut define.
881  local num = ctypenum + 1
882  map_type[name] = {
883    ctype = ctype,
884    ctypefmt = format("Dt%X(%%s)", num),
885    reg = reg,
886  }
887  wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
888  ctypenum = num
889end
890map_op[".type_2"] = map_op[".type_3"]
891
892-- Dump type definitions.
893local function dumptypes(out, lvl)
894  local t = {}
895  for name in pairs(map_type) do t[#t+1] = name end
896  sort(t)
897  out:write("Type definitions:\n")
898  for _,name in ipairs(t) do
899    local tp = map_type[name]
900    local reg = tp.reg or ""
901    out:write(format("  %-20s %-20s %s\n", name, tp.ctype, reg))
902  end
903  out:write("\n")
904end
905
906------------------------------------------------------------------------------
907
908-- Set the current section.
909function _M.section(num)
910  waction("SECTION", num)
911  wflush(true) -- SECTION is a terminal action.
912end
913
914------------------------------------------------------------------------------
915
916-- Dump architecture description.
917function _M.dumparch(out)
918  out:write(format("DynASM %s version %s, released %s\n\n",
919    _info.arch, _info.version, _info.release))
920  dumpactions(out)
921end
922
923-- Dump all user defined elements.
924function _M.dumpdef(out, lvl)
925  dumptypes(out, lvl)
926  dumpglobals(out, lvl)
927  dumpexterns(out, lvl)
928end
929
930------------------------------------------------------------------------------
931
932-- Pass callbacks from/to the DynASM core.
933function _M.passcb(wl, we, wf, ww)
934  wline, werror, wfatal, wwarn = wl, we, wf, ww
935  return wflush
936end
937
938-- Setup the arch-specific module.
939function _M.setup(arch, opt)
940  g_arch, g_opt = arch, opt
941end
942
943-- Merge the core maps and the arch-specific maps.
944function _M.mergemaps(map_coreop, map_def)
945  setmetatable(map_op, { __index = map_coreop })
946  setmetatable(map_def, { __index = map_archdef })
947  return map_op, map_def
948end
949
950return _M
951
952------------------------------------------------------------------------------
953
954