diff options
| author | Mike Pall <mike> | 2010-08-26 02:09:15 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2010-08-26 02:09:15 +0200 |
| commit | 4f47d31fefbe8a690fbf85e8bf2b74598e72a183 (patch) | |
| tree | 3c06e40b536f7a94370c75cfc9fb9e3e513935e0 /dynasm | |
| parent | 5526fa23122a0192c4315a1955a44bbaa2607d43 (diff) | |
| download | luajit-4f47d31fefbe8a690fbf85e8bf2b74598e72a183.tar.gz luajit-4f47d31fefbe8a690fbf85e8bf2b74598e72a183.tar.bz2 luajit-4f47d31fefbe8a690fbf85e8bf2b74598e72a183.zip | |
PPC: Add DynASM PowerPC module. Standard instructions only.
Diffstat (limited to 'dynasm')
| -rw-r--r-- | dynasm/dasm_ppc.lua | 926 |
1 files changed, 926 insertions, 0 deletions
diff --git a/dynasm/dasm_ppc.lua b/dynasm/dasm_ppc.lua new file mode 100644 index 00000000..acea7cc1 --- /dev/null +++ b/dynasm/dasm_ppc.lua | |||
| @@ -0,0 +1,926 @@ | |||
| 1 | ------------------------------------------------------------------------------ | ||
| 2 | -- DynASM PPC module. | ||
| 3 | -- | ||
| 4 | -- Copyright (C) 2005-2010 Mike Pall. All rights reserved. | ||
| 5 | -- See dynasm.lua for full copyright notice. | ||
| 6 | ------------------------------------------------------------------------------ | ||
| 7 | |||
| 8 | -- Module information: | ||
| 9 | local _info = { | ||
| 10 | arch = "ppc", | ||
| 11 | description = "DynASM PPC module", | ||
| 12 | version = "1.2.1", | ||
| 13 | vernum = 10201, | ||
| 14 | release = "2010-XX-XX", | ||
| 15 | author = "Mike Pall", | ||
| 16 | license = "MIT", | ||
| 17 | } | ||
| 18 | |||
| 19 | -- Exported glue functions for the arch-specific module. | ||
| 20 | local _M = { _info = _info } | ||
| 21 | |||
| 22 | -- Cache library functions. | ||
| 23 | local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs | ||
| 24 | local assert, setmetatable = assert, setmetatable | ||
| 25 | local _s = string | ||
| 26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | ||
| 27 | local match, gmatch = _s.match, _s.gmatch | ||
| 28 | local concat, sort = table.concat, table.sort | ||
| 29 | |||
| 30 | -- Inherited tables and callbacks. | ||
| 31 | local g_opt, g_arch | ||
| 32 | local wline, werror, wfatal, wwarn | ||
| 33 | |||
| 34 | -- Action name list. | ||
| 35 | -- CHECK: Keep this in sync with the C code! | ||
| 36 | local action_names = { | ||
| 37 | "STOP", "SECTION", "ESC", "REL_EXT", | ||
| 38 | "ALIGN", "REL_LG", "LABEL_LG", | ||
| 39 | "REL_PC", "LABEL_PC", "IMM", | ||
| 40 | } | ||
| 41 | |||
| 42 | -- Maximum number of section buffer positions for dasm_put(). | ||
| 43 | -- CHECK: Keep this in sync with the C code! | ||
| 44 | local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. | ||
| 45 | |||
| 46 | -- Action name -> action number. | ||
| 47 | local map_action = {} | ||
| 48 | for n,name in ipairs(action_names) do | ||
| 49 | map_action[name] = n-1 | ||
| 50 | end | ||
| 51 | |||
| 52 | -- Action list buffer. | ||
| 53 | local actlist = {} | ||
| 54 | |||
| 55 | -- Argument list for next dasm_put(). Start with offset 0 into action list. | ||
| 56 | local actargs = { 0 } | ||
| 57 | |||
| 58 | -- Current number of section buffer positions for dasm_put(). | ||
| 59 | local secpos = 1 | ||
| 60 | |||
| 61 | ------------------------------------------------------------------------------ | ||
| 62 | |||
| 63 | -- Return 8 digit hex number. | ||
| 64 | local function tohex(x) | ||
| 65 | return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua. | ||
| 66 | end | ||
| 67 | |||
| 68 | -- Dump action names and numbers. | ||
| 69 | local function dumpactions(out) | ||
| 70 | out:write("DynASM encoding engine action codes:\n") | ||
| 71 | for n,name in ipairs(action_names) do | ||
| 72 | local num = map_action[name] | ||
| 73 | out:write(format(" %-10s %02X %d\n", name, num, num)) | ||
| 74 | end | ||
| 75 | out:write("\n") | ||
| 76 | end | ||
| 77 | |||
| 78 | -- Write action list buffer as a huge static C array. | ||
| 79 | local function writeactions(out, name) | ||
| 80 | local nn = #actlist | ||
| 81 | if nn == 0 then nn = 1; actlist[0] = map_action.STOP end | ||
| 82 | out:write("static const unsigned int ", name, "[", nn, "] = {\n") | ||
| 83 | for i = 1,nn-1 do | ||
| 84 | assert(out:write("0x", tohex(actlist[i]), ",\n")) | ||
| 85 | end | ||
| 86 | assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) | ||
| 87 | end | ||
| 88 | |||
| 89 | ------------------------------------------------------------------------------ | ||
| 90 | |||
| 91 | -- Add word to action list. | ||
| 92 | local function wputxw(n) | ||
| 93 | assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | ||
| 94 | actlist[#actlist+1] = n | ||
| 95 | end | ||
| 96 | |||
| 97 | -- Add action to list with optional arg. Advance buffer pos, too. | ||
| 98 | local function waction(action, val, a, num) | ||
| 99 | local w = assert(map_action[action], "bad action name `"..action.."'") | ||
| 100 | wputxw(w * 0x10000 + (val or 0)) | ||
| 101 | if a then actargs[#actargs+1] = a end | ||
| 102 | if a or num then secpos = secpos + (num or 1) end | ||
| 103 | end | ||
| 104 | |||
| 105 | -- Flush action list (intervening C code or buffer pos overflow). | ||
| 106 | local function wflush(term) | ||
| 107 | if #actlist == actargs[1] then return end -- Nothing to flush. | ||
| 108 | if not term then waction("STOP") end -- Terminate action list. | ||
| 109 | wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) | ||
| 110 | actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). | ||
| 111 | secpos = 1 -- The actionlist offset occupies a buffer position, too. | ||
| 112 | end | ||
| 113 | |||
| 114 | -- Put escaped word. | ||
| 115 | local function wputw(n) | ||
| 116 | if n <= 0xffffff then waction("ESC") end | ||
| 117 | wputxw(n) | ||
| 118 | end | ||
| 119 | |||
| 120 | -- Reserve position for word. | ||
| 121 | local function wpos() | ||
| 122 | local pos = #actlist+1 | ||
| 123 | actlist[pos] = "" | ||
| 124 | return pos | ||
| 125 | end | ||
| 126 | |||
| 127 | -- Store word to reserved position. | ||
| 128 | local function wputpos(pos, n) | ||
| 129 | assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") | ||
| 130 | actlist[pos] = n | ||
| 131 | end | ||
| 132 | |||
| 133 | ------------------------------------------------------------------------------ | ||
| 134 | |||
| 135 | -- Global label name -> global label number. With auto assignment on 1st use. | ||
| 136 | local next_global = 20 | ||
| 137 | local map_global = setmetatable({}, { __index = function(t, name) | ||
| 138 | if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end | ||
| 139 | local n = next_global | ||
| 140 | if n > 2047 then werror("too many global labels") end | ||
| 141 | next_global = n + 1 | ||
| 142 | t[name] = n | ||
| 143 | return n | ||
| 144 | end}) | ||
| 145 | |||
| 146 | -- Dump global labels. | ||
| 147 | local function dumpglobals(out, lvl) | ||
| 148 | local t = {} | ||
| 149 | for name, n in pairs(map_global) do t[n] = name end | ||
| 150 | out:write("Global labels:\n") | ||
| 151 | for i=20,next_global-1 do | ||
| 152 | out:write(format(" %s\n", t[i])) | ||
| 153 | end | ||
| 154 | out:write("\n") | ||
| 155 | end | ||
| 156 | |||
| 157 | -- Write global label enum. | ||
| 158 | local function writeglobals(out, prefix) | ||
| 159 | local t = {} | ||
| 160 | for name, n in pairs(map_global) do t[n] = name end | ||
| 161 | out:write("enum {\n") | ||
| 162 | for i=20,next_global-1 do | ||
| 163 | out:write(" ", prefix, t[i], ",\n") | ||
| 164 | end | ||
| 165 | out:write(" ", prefix, "_MAX\n};\n") | ||
| 166 | end | ||
| 167 | |||
| 168 | -- Write global label names. | ||
| 169 | local function writeglobalnames(out, name) | ||
| 170 | local t = {} | ||
| 171 | for name, n in pairs(map_global) do t[n] = name end | ||
| 172 | out:write("static const char *const ", name, "[] = {\n") | ||
| 173 | for i=20,next_global-1 do | ||
| 174 | out:write(" \"", t[i], "\",\n") | ||
| 175 | end | ||
| 176 | out:write(" (const char *)0\n};\n") | ||
| 177 | end | ||
| 178 | |||
| 179 | ------------------------------------------------------------------------------ | ||
| 180 | |||
| 181 | -- Extern label name -> extern label number. With auto assignment on 1st use. | ||
| 182 | local next_extern = 0 | ||
| 183 | local map_extern_ = {} | ||
| 184 | local map_extern = setmetatable({}, { __index = function(t, name) | ||
| 185 | -- No restrictions on the name for now. | ||
| 186 | local n = next_extern | ||
| 187 | if n > 2047 then werror("too many extern labels") end | ||
| 188 | next_extern = n + 1 | ||
| 189 | t[name] = n | ||
| 190 | map_extern_[n] = name | ||
| 191 | return n | ||
| 192 | end}) | ||
| 193 | |||
| 194 | -- Dump extern labels. | ||
| 195 | local function dumpexterns(out, lvl) | ||
| 196 | out:write("Extern labels:\n") | ||
| 197 | for i=0,next_extern-1 do | ||
| 198 | out:write(format(" %s\n", map_extern_[i])) | ||
| 199 | end | ||
| 200 | out:write("\n") | ||
| 201 | end | ||
| 202 | |||
| 203 | -- Write extern label names. | ||
| 204 | local function writeexternnames(out, name) | ||
| 205 | out:write("static const char *const ", name, "[] = {\n") | ||
| 206 | for i=0,next_extern-1 do | ||
| 207 | out:write(" \"", map_extern_[i], "\",\n") | ||
| 208 | end | ||
| 209 | out:write(" (const char *)0\n};\n") | ||
| 210 | end | ||
| 211 | |||
| 212 | ------------------------------------------------------------------------------ | ||
| 213 | |||
| 214 | -- Arch-specific maps. | ||
| 215 | local map_archdef = { sp = "r1" } -- Ext. register name -> int. name. | ||
| 216 | |||
| 217 | local map_type = {} -- Type name -> { ctype, reg } | ||
| 218 | local ctypenum = 0 -- Type number (for Dt... macros). | ||
| 219 | |||
| 220 | -- Reverse defines for registers. | ||
| 221 | function _M.revdef(s) | ||
| 222 | if s == "r1" then return "sp" end | ||
| 223 | return s | ||
| 224 | end | ||
| 225 | |||
| 226 | local map_cond = { | ||
| 227 | lt = 0, gt = 1, eq = 2, so = 3, | ||
| 228 | ge = 4, le = 5, ne = 6, ns = 7, | ||
| 229 | } | ||
| 230 | |||
| 231 | ------------------------------------------------------------------------------ | ||
| 232 | |||
| 233 | -- Template strings for PPC instructions. | ||
| 234 | local map_op = { | ||
| 235 | tdi_3 = "08000000ARI", | ||
| 236 | twi_3 = "0c000000ARI", | ||
| 237 | mulli_3 = "1c000000RRI", | ||
| 238 | subfic_3 = "20000000RRI", | ||
| 239 | cmplwi_3 = "28000000XRU", | ||
| 240 | cmplwi_2 = "28000000-RU", | ||
| 241 | cmpldi_3 = "28200000XRU", | ||
| 242 | cmpldi_2 = "28200000-RU", | ||
| 243 | cmpwi_3 = "2c000000XRI", | ||
| 244 | cmpwi_2 = "2c000000-RI", | ||
| 245 | cmpdi_3 = "2c200000XRI", | ||
| 246 | cmpdi_2 = "2c200000-RI", | ||
| 247 | addic_3 = "30000000RRI", | ||
| 248 | ["addic._3"] = "34000000RRI", | ||
| 249 | addi_3 = "38000000RRI", | ||
| 250 | li_2 = "38000000RI", | ||
| 251 | addis_3 = "3c000000RRI", | ||
| 252 | lis_2 = "3c000000RI", | ||
| 253 | lus_2 = "3c000000RU", | ||
| 254 | la_2 = "3c000000RD", | ||
| 255 | bc_3 = "40000000AAK", | ||
| 256 | bcl_3 = "40000001AAK", | ||
| 257 | bdnz_1 = "42000000K", | ||
| 258 | bdz_1 = "42400000K", | ||
| 259 | sc_0 = "44000000", | ||
| 260 | b_1 = "48000000J", | ||
| 261 | bl_1 = "48000001J", | ||
| 262 | rlwimi_5 = "50000000RR~AAA.", | ||
| 263 | rlwinm_5 = "54000000RR~AAA.", | ||
| 264 | rlwnm_5 = "5c000000RR~RAA.", | ||
| 265 | ori_3 = "60000000RR~U", | ||
| 266 | nop_0 = "60000000", | ||
| 267 | oris_3 = "64000000RR~U", | ||
| 268 | xori_3 = "68000000RR~U", | ||
| 269 | xoris_3 = "6c000000RR~U", | ||
| 270 | ["andi._3"] = "70000000RR~U", | ||
| 271 | ["andis._3"] = "74000000RR~U", | ||
| 272 | lwz_2 = "80000000RD", | ||
| 273 | lwzu_2 = "84000000RD", | ||
| 274 | lbz_2 = "88000000RD", | ||
| 275 | lbzu_2 = "8c000000RD", | ||
| 276 | stw_2 = "90000000RD", | ||
| 277 | stwu_2 = "94000000RD", | ||
| 278 | stb_2 = "98000000RD", | ||
| 279 | stbu_2 = "9c000000RD", | ||
| 280 | lhz_2 = "a0000000RD", | ||
| 281 | lhzu_2 = "a4000000RD", | ||
| 282 | lha_2 = "a8000000RD", | ||
| 283 | lhau_2 = "ac000000RD", | ||
| 284 | sth_2 = "b0000000RD", | ||
| 285 | sthu_2 = "b4000000RD", | ||
| 286 | lmw_2 = "b8000000RD", | ||
| 287 | stmw_2 = "bc000000RD", | ||
| 288 | lfs_2 = "c0000000FD", | ||
| 289 | lfsu_2 = "c4000000FD", | ||
| 290 | lfd_2 = "c8000000FD", | ||
| 291 | lfdu_2 = "cc000000FD", | ||
| 292 | stfs_2 = "d0000000FD", | ||
| 293 | stfsu_2 = "d4000000FD", | ||
| 294 | stfd_2 = "d8000000FD", | ||
| 295 | stfdu_2 = "dc000000FD", | ||
| 296 | ld_2 = "e8000000RD", -- NYI: displacement must be divisible by 4. | ||
| 297 | ldu_2 = "e8000001RD", | ||
| 298 | lwa_2 = "e8000002RD", | ||
| 299 | std_2 = "f8000000RD", | ||
| 300 | stdu_2 = "f8000001RD", | ||
| 301 | |||
| 302 | -- Primary opcode 19: | ||
| 303 | mcrf_2 = "4c000000XX", | ||
| 304 | isync_0 = "4c00012c", | ||
| 305 | crnor_3 = "4c000042CCC", | ||
| 306 | crnot_2 = "4c000042CC=", | ||
| 307 | crandc_3 = "4c000102CCC", | ||
| 308 | crxor_3 = "4c000182CCC", | ||
| 309 | crclr_1 = "4c000182C==", | ||
| 310 | crnand_3 = "4c0001c2CCC", | ||
| 311 | crand_3 = "4c000202CCC", | ||
| 312 | creqv_3 = "4c000242CCC", | ||
| 313 | crset_1 = "4c000242C==", | ||
| 314 | crorc_3 = "4c000342CCC", | ||
| 315 | cror_3 = "4c000382CCC", | ||
| 316 | crmove_2 = "4c000382CC=", | ||
| 317 | bclr_2 = "4c000020AA", | ||
| 318 | bclrl_2 = "4c000021AA", | ||
| 319 | bcctr_2 = "4c000420AA", | ||
| 320 | bcctrl_2 = "4c000421AA", | ||
| 321 | blr_0 = "4e800020", | ||
| 322 | blrl_0 = "4e800021", | ||
| 323 | bctr_0 = "4e800420", | ||
| 324 | bctrl_0 = "4e800421", | ||
| 325 | |||
| 326 | -- Primary opcode 31: | ||
| 327 | cmpw_3 = "7c000000XRR", | ||
| 328 | cmpw_2 = "7c000000-RR", | ||
| 329 | cmpd_3 = "7c200000XRR", | ||
| 330 | cmpd_2 = "7c200000-RR", | ||
| 331 | tw_3 = "7c000008ARR", | ||
| 332 | subfc_3 = "7c000010RRR.", | ||
| 333 | subc_3 = "7c000010RRR~.", | ||
| 334 | mulhdu_3 = "7c000012RRR.", | ||
| 335 | addc_3 = "7c000014RRR.", | ||
| 336 | mulhwu_3 = "7c000016RRR.", | ||
| 337 | isel_4 = "7c00001eRRRC", | ||
| 338 | isellt_3 = "7c00001eRRR", | ||
| 339 | iselgt_3 = "7c00005eRRR", | ||
| 340 | iseleq_3 = "7c00009eRRR", | ||
| 341 | mfcr_1 = "7c000026R", | ||
| 342 | -- NYI: mtcrf, mtocrf, mfocrf | ||
| 343 | lwarx_3 = "7c000028RRR", | ||
| 344 | ldx_3 = "7c00002aRRR", | ||
| 345 | lwzx_3 = "7c00002eRRR", | ||
| 346 | slw_3 = "7c000030RR~R.", | ||
| 347 | cntlzw_2 = "7c000034RR~", | ||
| 348 | sld_3 = "7c000036RR~R.", | ||
| 349 | and_3 = "7c000038RR~R.", | ||
| 350 | cmplw_3 = "7c000040XRR", | ||
| 351 | cmplw_2 = "7c000040-RR", | ||
| 352 | cmpld_3 = "7c200040XRR", | ||
| 353 | cmpld_2 = "7c200040-RR", | ||
| 354 | subf_3 = "7c000050RRR.", | ||
| 355 | sub_3 = "7c000050RRR~.", | ||
| 356 | ldux_3 = "7c00006aRRR", | ||
| 357 | dcbst_2 = "7c00006c-RR", | ||
| 358 | lwzux_3 = "7c00006eRRR", | ||
| 359 | cntlzd_2 = "7c000074RR~", | ||
| 360 | andc_3 = "7c000078RR~R.", | ||
| 361 | td_3 = "7c000088ARR", | ||
| 362 | mulhd_3 = "7c000092RRR.", | ||
| 363 | mulhw_3 = "7c000096RRR.", | ||
| 364 | ldarx_3 = "7c0000a8RRR", | ||
| 365 | dcbf_2 = "7c0000ac-RR", | ||
| 366 | lbzx_3 = "7c0000aeRRR", | ||
| 367 | neg_2 = "7c0000d0RR.", | ||
| 368 | lbzux_3 = "7c0000eeRRR", | ||
| 369 | popcntb_2 = "7c0000f4RR~", | ||
| 370 | not_2 = "7c0000f8RR~%.", | ||
| 371 | nor_3 = "7c0000f8RR~R.", | ||
| 372 | subfe_3 = "7c000110RRR.", | ||
| 373 | adde_3 = "7c000114RRR.", | ||
| 374 | stdx_3 = "7c00012aRRR", | ||
| 375 | stwcx_3 = "7c00012cRRR.", | ||
| 376 | stwx_3 = "7c00012eRRR", | ||
| 377 | prtyw_2 = "7c000134RR~", | ||
| 378 | stdux_3 = "7c00016aRRR", | ||
| 379 | stwux_3 = "7c00016eRRR", | ||
| 380 | prtyd_2 = "7c000174RR~", | ||
| 381 | subfze_2 = "7c000190RR.", | ||
| 382 | addze_2 = "7c000194RR.", | ||
| 383 | stdcx_3 = "7c0001acRRR.", | ||
| 384 | stbx_3 = "7c0001aeRRR", | ||
| 385 | subfme_2 = "7c0001d0RR.", | ||
| 386 | mulld_3 = "7c0001d2RRR.", | ||
| 387 | addme_2 = "7c0001d4RR.", | ||
| 388 | mullw_3 = "7c0001d6RRR.", | ||
| 389 | dcbtst_2 = "7c0001ec-RR", | ||
| 390 | stbux_3 = "7c0001eeRRR", | ||
| 391 | add_3 = "7c000214RRR.", | ||
| 392 | dcbt_2 = "7c00022c-RR", | ||
| 393 | lhzx_3 = "7c00022eRRR", | ||
| 394 | eqv_3 = "7c000238RR~R.", | ||
| 395 | eciwx_3 = "7c00026cRRR", | ||
| 396 | lhzux_3 = "7c00026eRRR", | ||
| 397 | xor_3 = "7c000278RR~R.", | ||
| 398 | mfspefscr_1 = "7c0082a6R", | ||
| 399 | mfxer_1 = "7c0102a6R", | ||
| 400 | mflr_1 = "7c0802a6R", | ||
| 401 | mfctr_1 = "7c0902a6R", | ||
| 402 | lwax_3 = "7c0002aaRRR", | ||
| 403 | lhax_3 = "7c0002aeRRR", | ||
| 404 | mftb_1 = "7c0c42e6R", | ||
| 405 | mftbu_1 = "7c0d42e6R", | ||
| 406 | lwaux_3 = "7c0002eaRRR", | ||
| 407 | lhaux_3 = "7c0002eeRRR", | ||
| 408 | sthx_3 = "7c00032eRRR", | ||
| 409 | orc_3 = "7c000338RR~R.", | ||
| 410 | ecowx_3 = "7c00036cRRR", | ||
| 411 | sthux_3 = "7c00036eRRR", | ||
| 412 | or_3 = "7c000378RR~R.", | ||
| 413 | mr_2 = "7c000378RR~%.", | ||
| 414 | divdu_3 = "7c000392RRR.", | ||
| 415 | divwu_3 = "7c000396RRR.", | ||
| 416 | mtspefscr_1 = "7c0083a6R", | ||
| 417 | mtxer_1 = "7c0103a6R", | ||
| 418 | mtlr_1 = "7c0803a6R", | ||
| 419 | mtctr_1 = "7c0903a6R", | ||
| 420 | dcbi_2 = "7c0003ac-RR", | ||
| 421 | nand_3 = "7c0003b8RR~R.", | ||
| 422 | divd_3 = "7c0003d2RRR.", | ||
| 423 | divw_3 = "7c0003d6RRR.", | ||
| 424 | cmpb_3 = "7c0003f8RR~R.", | ||
| 425 | mcrxr_1 = "7c000400X", | ||
| 426 | subfco_3 = "7c000410RRR.", | ||
| 427 | addco_3 = "7c000414RRR.", | ||
| 428 | ldbrx_3 = "7c000428RRR", | ||
| 429 | lswx_3 = "7c00042aRRR", | ||
| 430 | lwbrx_3 = "7c00042cRRR", | ||
| 431 | lfsx_3 = "7c00042eFRR", | ||
| 432 | srw_3 = "7c000430RR~R.", | ||
| 433 | srd_3 = "7c000436RR~R.", | ||
| 434 | subfo_3 = "7c000450RRR.", | ||
| 435 | lfsux_3 = "7c00046eFRR", | ||
| 436 | lswi_3 = "7c0004aaRRA", | ||
| 437 | sync_0 = "7c0004ac", | ||
| 438 | lwsync_0 = "7c2004ac", | ||
| 439 | ptesync_0 = "7c4004ac", | ||
| 440 | lfdx_3 = "7c0004aeFRR", | ||
| 441 | nego_2 = "7c0004d0RR.", | ||
| 442 | lfdux_3 = "7c0004eeFRR", | ||
| 443 | subfeo_3 = "7c000510RRR.", | ||
| 444 | addeo_3 = "7c000514RRR.", | ||
| 445 | stdbrx_3 = "7c000528RRR", | ||
| 446 | stswx_3 = "7c00052aRRR", | ||
| 447 | stwbrx_3 = "7c00052cRRR", | ||
| 448 | stfsx_3 = "7c00052eFRR", | ||
| 449 | stfsux_3 = "7c00056eFRR", | ||
| 450 | subfzeo_2 = "7c000590RR.", | ||
| 451 | addzeo_2 = "7c000594RR.", | ||
| 452 | stswi_3 = "7c0005aaRRA", | ||
| 453 | stfdx_3 = "7c0005aeFRR", | ||
| 454 | subfmeo_2 = "7c0005d0RR.", | ||
| 455 | mulldo_3 = "7c0005d2RRR.", | ||
| 456 | addmeo_2 = "7c0005d4RR.", | ||
| 457 | mullwo_3 = "7c0005d6RRR.", | ||
| 458 | dcba_2 = "7c0005ec-RR", | ||
| 459 | stfdux_3 = "7c0005eeFRR", | ||
| 460 | addo_3 = "7c000614RRR.", | ||
| 461 | lhbrx_3 = "7c00062cRRR", | ||
| 462 | sraw_3 = "7c000630RR~R.", | ||
| 463 | srad_3 = "7c000634RR~R.", | ||
| 464 | srawi_3 = "7c000670RR~A.", | ||
| 465 | eieio_0 = "7c0006ac", | ||
| 466 | lfiwax_3 = "7c0006aeFRR", | ||
| 467 | sthbrx_3 = "7c00072cRRR", | ||
| 468 | extsh_2 = "7c000734RR~.", | ||
| 469 | extsb_2 = "7c000774RR~.", | ||
| 470 | divduo_3 = "7c000792RRR.", | ||
| 471 | divwou_3 = "7c000796RRR.", | ||
| 472 | icbi_2 = "7c0007ac-RR", | ||
| 473 | stfiwx_3 = "7c0007aeFRR", | ||
| 474 | extsw_2 = "7c0007b4RR~.", | ||
| 475 | divdo_3 = "7c0007d2RRR.", | ||
| 476 | divwo_3 = "7c0007d6RRR.", | ||
| 477 | dcbz_2 = "7c0007ec-RR", | ||
| 478 | |||
| 479 | -- Primary opcode 59: | ||
| 480 | fdivs_3 = "ec000024FFF.", | ||
| 481 | fsubs_3 = "ec000028FFF.", | ||
| 482 | fadds_3 = "ec00002aFFF.", | ||
| 483 | fsqrts_2 = "ec00002cF-F.", | ||
| 484 | fres_2 = "ec000030F-F.", | ||
| 485 | fmuls_3 = "ec000032FF-F.", | ||
| 486 | frsqrtes_2 = "ec000034F-F.", | ||
| 487 | fmsubs_4 = "ec000038FFFF~.", | ||
| 488 | fmadds_4 = "ec00003aFFFF~.", | ||
| 489 | fnmsubs_4 = "ec00003cFFFF~.", | ||
| 490 | fnmadds_4 = "ec00003eFFFF~.", | ||
| 491 | |||
| 492 | -- Primary opcode 63: | ||
| 493 | fdiv_3 = "fc000024FFF.", | ||
| 494 | fsub_3 = "fc000028FFF.", | ||
| 495 | fadd_3 = "fc00002aFFF.", | ||
| 496 | fsqrt_2 = "fc00002cF-F.", | ||
| 497 | fsel_4 = "fc00002eFFFF~.", | ||
| 498 | fre_2 = "fc000030F-F.", | ||
| 499 | fmul_3 = "fc000032FF-F.", | ||
| 500 | frsqrte_2 = "fc000034F-F.", | ||
| 501 | fmsub_4 = "fc000038FFFF~.", | ||
| 502 | fmadd_4 = "fc00003aFFFF~.", | ||
| 503 | fnmsub_4 = "fc00003cFFFF~.", | ||
| 504 | fnmadd_4 = "fc00003eFFFF~.", | ||
| 505 | fcmpu_3 = "fc000000XFF", | ||
| 506 | fcpsgn_3 = "fc000010FFF.", | ||
| 507 | fcmpo_3 = "fc000040XFF", | ||
| 508 | mtfsb1_1 = "fc00004cA", | ||
| 509 | fneg_2 = "fc000050F-F.", | ||
| 510 | mcrfs_2 = "fc000080XX", | ||
| 511 | mtfsb0_1 = "fc00008cA", | ||
| 512 | fmr_2 = "fc000090F-F.", | ||
| 513 | frsp_2 = "fc000018F-F.", | ||
| 514 | fctiw_2 = "fc00001cF-F.", | ||
| 515 | fctiwz_2 = "fc00001eF-F.", | ||
| 516 | mtfsfi_2 = "fc00010cAA", -- NYI: upshift. | ||
| 517 | fnabs_2 = "fc000110F-F.", | ||
| 518 | fabs_2 = "fc000210F-F.", | ||
| 519 | frin_2 = "fc000310F-F.", | ||
| 520 | friz_2 = "fc000350F-F.", | ||
| 521 | frip_2 = "fc000390F-F.", | ||
| 522 | frim_2 = "fc0003d0F-F.", | ||
| 523 | mffs_1 = "fc00048eF.", | ||
| 524 | mtfsf_1 = "fc00058eF.", | ||
| 525 | fctid_2 = "fc00065cF-F.", | ||
| 526 | fctidz_2 = "fc00065eF-F.", | ||
| 527 | fcfid_2 = "fc00069cF-F.", | ||
| 528 | |||
| 529 | -- NYI: some 64 bit PowerPC and Book E instructions: | ||
| 530 | -- rldicl, rldicr, rldic, rldimi, rldcl, rldcr, sradi, 64 bit ext. add/sub, | ||
| 531 | -- extended addressing branches, cache management, loads and stores | ||
| 532 | } | ||
| 533 | |||
| 534 | -- Add mnemonics for "." variants. | ||
| 535 | do | ||
| 536 | local t = {} | ||
| 537 | for k,v in pairs(map_op) do | ||
| 538 | if sub(v, -1) == "." then | ||
| 539 | local v2 = sub(v, 1, 7)..char(byte(v, 8)+1)..sub(v, 9, -2) | ||
| 540 | t[sub(k, 1, -3).."."..sub(k, -2)] = v2 | ||
| 541 | end | ||
| 542 | end | ||
| 543 | for k,v in pairs(t) do | ||
| 544 | map_op[k] = v | ||
| 545 | end | ||
| 546 | end | ||
| 547 | |||
| 548 | -- Add more branch mnemonics. | ||
| 549 | for cond,c in pairs(map_cond) do | ||
| 550 | local b1 = "b"..cond | ||
| 551 | local c1 = (c%4)*0x00010000 + (c < 4 and 0x01000000 or 0) | ||
| 552 | -- bX | ||
| 553 | map_op[b1.."_1"] = tohex(0x40800000 + c1).."K" | ||
| 554 | map_op[b1.."_2"] = tohex(0x40800000 + c1).."-XK" | ||
| 555 | -- bXlr[l] | ||
| 556 | map_op[b1.."lr".."_0"] = tohex(0x4c800020 + c1) | ||
| 557 | map_op[b1.."lrl".."_0"] = tohex(0x4c800021 + c1) | ||
| 558 | map_op[b1.."ctr".."_0"] = tohex(0x4c800420 + c1) | ||
| 559 | map_op[b1.."ctrl".."_0"] = tohex(0x4c800421 + c1) | ||
| 560 | -- bXctr[l] | ||
| 561 | map_op[b1.."lr".."_1"] = tohex(0x4c800020 + c1).."-X" | ||
| 562 | map_op[b1.."lrl".."_1"] = tohex(0x4c800021 + c1).."-X" | ||
| 563 | map_op[b1.."ctr".."_1"] = tohex(0x4c800420 + c1).."-X" | ||
| 564 | map_op[b1.."ctrl".."_1"] = tohex(0x4c800421 + c1).."-X" | ||
| 565 | end | ||
| 566 | |||
| 567 | ------------------------------------------------------------------------------ | ||
| 568 | |||
| 569 | local function parse_gpr(expr) | ||
| 570 | local tname, ovreg = match(expr, "^([%w_]+):(r[0-9][0-9]?)$") | ||
| 571 | local tp = map_type[tname or expr] | ||
| 572 | if tp then | ||
| 573 | local reg = ovreg or tp.reg | ||
| 574 | if not reg then | ||
| 575 | werror("type `"..(tname or expr).."' needs a register override") | ||
| 576 | end | ||
| 577 | expr = reg | ||
| 578 | end | ||
| 579 | local r = match(expr, "^r([1-3]?[0-9])$") | ||
| 580 | if r then | ||
| 581 | r = tonumber(r) | ||
| 582 | if r <= 31 then return r, tp end | ||
| 583 | end | ||
| 584 | werror("bad register name `"..expr.."'") | ||
| 585 | end | ||
| 586 | |||
| 587 | local function parse_fpr(expr) | ||
| 588 | local r = match(expr, "^f([1-3]?[0-9])$") | ||
| 589 | if r then | ||
| 590 | r = tonumber(r) | ||
| 591 | if r <= 31 then return r end | ||
| 592 | end | ||
| 593 | werror("bad register name `"..expr.."'") | ||
| 594 | end | ||
| 595 | |||
| 596 | local function parse_cr(expr) | ||
| 597 | local r = match(expr, "^cr([0-7])$") | ||
| 598 | if r then return tonumber(r) end | ||
| 599 | werror("bad condition register name `"..expr.."'") | ||
| 600 | end | ||
| 601 | |||
| 602 | local function parse_cond(expr) | ||
| 603 | local r, cond = match(expr, "^4%*cr([0-7])%+(%w%w)$") | ||
| 604 | if r then | ||
| 605 | r = tonumber(r) | ||
| 606 | local c = map_cond[cond] | ||
| 607 | if c and c < 4 then return r*4+c end | ||
| 608 | end | ||
| 609 | werror("bad condition bit name `"..expr.."'") | ||
| 610 | end | ||
| 611 | |||
| 612 | local function parse_imm(imm, bits, shift, scale, signed) | ||
| 613 | local n = tonumber(imm) | ||
| 614 | if n then | ||
| 615 | if n % 2^scale == 0 then | ||
| 616 | n = n / 2^scale | ||
| 617 | if signed then | ||
| 618 | if n >= 0 then | ||
| 619 | if n < 2^(bits-1) then return n*2^shift end | ||
| 620 | else | ||
| 621 | if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end | ||
| 622 | end | ||
| 623 | else | ||
| 624 | if n >= 0 and n <= 2^bits-1 then return n*2^shift end | ||
| 625 | end | ||
| 626 | end | ||
| 627 | werror("out of range immediate `"..imm.."'") | ||
| 628 | else | ||
| 629 | waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm) | ||
| 630 | return 0 | ||
| 631 | end | ||
| 632 | end | ||
| 633 | |||
| 634 | local function parse_disp(disp) | ||
| 635 | local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") | ||
| 636 | if imm then | ||
| 637 | local r = parse_gpr(reg) | ||
| 638 | if r == 0 then werror("cannot use r0 in displacement") end | ||
| 639 | return r*65536 + parse_imm(imm, 16, 0, 0, true) | ||
| 640 | end | ||
| 641 | local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") | ||
| 642 | if reg and tailr ~= "" then | ||
| 643 | local r, tp = parse_gpr(reg) | ||
| 644 | if r == 0 then werror("cannot use r0 in displacement") end | ||
| 645 | if tp then | ||
| 646 | waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) | ||
| 647 | return r*65536 | ||
| 648 | end | ||
| 649 | end | ||
| 650 | werror("bad displacement `"..disp.."'") | ||
| 651 | end | ||
| 652 | |||
| 653 | local function parse_u5disp(disp, scale) | ||
| 654 | local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") | ||
| 655 | if imm then | ||
| 656 | local r = parse_gpr(reg) | ||
| 657 | if r == 0 then werror("cannot use r0 in displacement") end | ||
| 658 | return r*65536 + parse_imm(imm, 5, 11, scale, false) | ||
| 659 | end | ||
| 660 | local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") | ||
| 661 | if reg and tailr ~= "" then | ||
| 662 | local r, tp = parse_gpr(reg) | ||
| 663 | if r == 0 then werror("cannot use r0 in displacement") end | ||
| 664 | if tp then | ||
| 665 | waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr)) | ||
| 666 | return r*65536 | ||
| 667 | end | ||
| 668 | end | ||
| 669 | werror("bad displacement `"..disp.."'") | ||
| 670 | end | ||
| 671 | |||
| 672 | local function parse_label(label, def) | ||
| 673 | local prefix = sub(label, 1, 2) | ||
| 674 | -- =>label (pc label reference) | ||
| 675 | if prefix == "=>" then | ||
| 676 | return "PC", 0, sub(label, 3) | ||
| 677 | end | ||
| 678 | -- ->name (global label reference) | ||
| 679 | if prefix == "->" then | ||
| 680 | return "LG", map_global[sub(label, 3)] | ||
| 681 | end | ||
| 682 | if def then | ||
| 683 | -- [1-9] (local label definition) | ||
| 684 | if match(label, "^[1-9]$") then | ||
| 685 | return "LG", 10+tonumber(label) | ||
| 686 | end | ||
| 687 | else | ||
| 688 | -- [<>][1-9] (local label reference) | ||
| 689 | local dir, lnum = match(label, "^([<>])([1-9])$") | ||
| 690 | if dir then -- Fwd: 1-9, Bkwd: 11-19. | ||
| 691 | return "LG", lnum + (dir == ">" and 0 or 10) | ||
| 692 | end | ||
| 693 | -- extern label (extern label reference) | ||
| 694 | local extname = match(label, "^extern%s+(%S+)$") | ||
| 695 | if extname then | ||
| 696 | return "EXT", map_extern[extname] | ||
| 697 | end | ||
| 698 | end | ||
| 699 | werror("bad label `"..label.."'") | ||
| 700 | end | ||
| 701 | |||
| 702 | ------------------------------------------------------------------------------ | ||
| 703 | |||
| 704 | -- Handle opcodes defined with template strings. | ||
| 705 | map_op[".template__"] = function(params, template, nparams) | ||
| 706 | if not params then return sub(template, 9) end | ||
| 707 | local op = tonumber(sub(template, 1, 8), 16) | ||
| 708 | local n, rs = 1, 26 | ||
| 709 | |||
| 710 | -- Limit number of section buffer positions used by a single dasm_put(). | ||
| 711 | -- A single opcode needs a maximum of 3 positions (rlwinm). | ||
| 712 | if secpos+3 > maxsecpos then wflush() end | ||
| 713 | local pos = wpos() | ||
| 714 | |||
| 715 | -- Process each character. | ||
| 716 | for p in gmatch(sub(template, 9), ".") do | ||
| 717 | if p == "R" then | ||
| 718 | rs = rs - 5; op = op + parse_gpr(params[n]) * 2^rs; n = n + 1 | ||
| 719 | elseif p == "F" then | ||
| 720 | rs = rs - 5; op = op + parse_fpr(params[n]) * 2^rs; n = n + 1 | ||
| 721 | elseif p == "A" then | ||
| 722 | rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1 | ||
| 723 | elseif p == "I" then | ||
| 724 | op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1 | ||
| 725 | elseif p == "U" then | ||
| 726 | op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1 | ||
| 727 | elseif p == "D" then | ||
| 728 | op = op + parse_disp(params[n]); n = n + 1 | ||
| 729 | elseif p == "C" then | ||
| 730 | rs = rs - 5; op = op + parse_cond(params[n]) * 2^rs; n = n + 1 | ||
| 731 | elseif p == "X" then | ||
| 732 | rs = rs - 5; op = op + parse_cr(params[n]) * 2^(rs+2); n = n + 1 | ||
| 733 | elseif p == "J" or p == "K" then | ||
| 734 | local mode, n, s = parse_label(params[n], false) | ||
| 735 | if p == "K" then n = n + 2048 end | ||
| 736 | waction("REL_"..mode, n, s, 1) | ||
| 737 | n = n + 1 | ||
| 738 | elseif p == "=" or p == "%" then | ||
| 739 | local mm = 2^(rs + (p == "%" and 5 or 0)) | ||
| 740 | local t = ((op - op % mm) / mm) % 32 | ||
| 741 | rs = rs - 5 | ||
| 742 | op = op + t * 2^rs | ||
| 743 | elseif p == "~" then | ||
| 744 | local mm = 2^rs | ||
| 745 | local t1l = op % mm | ||
| 746 | local t1h = (op - t1l) / mm | ||
| 747 | local t2l = t1h % 32 | ||
| 748 | local t2h = (t1h - t2l) / 32 | ||
| 749 | local t3l = t2h % 32 | ||
| 750 | op = ((t2h - t3l + t2l)*32 + t3l)*mm + t1l | ||
| 751 | elseif p == "-" then | ||
| 752 | rs = rs - 5 | ||
| 753 | elseif p == "." then | ||
| 754 | -- Ignored. | ||
| 755 | else | ||
| 756 | assert(false) | ||
| 757 | end | ||
| 758 | end | ||
| 759 | wputpos(pos, op) | ||
| 760 | end | ||
| 761 | |||
| 762 | ------------------------------------------------------------------------------ | ||
| 763 | |||
| 764 | -- Pseudo-opcode to mark the position where the action list is to be emitted. | ||
| 765 | map_op[".actionlist_1"] = function(params) | ||
| 766 | if not params then return "cvar" end | ||
| 767 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
| 768 | wline(function(out) writeactions(out, name) end) | ||
| 769 | end | ||
| 770 | |||
| 771 | -- Pseudo-opcode to mark the position where the global enum is to be emitted. | ||
| 772 | map_op[".globals_1"] = function(params) | ||
| 773 | if not params then return "prefix" end | ||
| 774 | local prefix = params[1] -- No syntax check. You get to keep the pieces. | ||
| 775 | wline(function(out) writeglobals(out, prefix) end) | ||
| 776 | end | ||
| 777 | |||
| 778 | -- Pseudo-opcode to mark the position where the global names are to be emitted. | ||
| 779 | map_op[".globalnames_1"] = function(params) | ||
| 780 | if not params then return "cvar" end | ||
| 781 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
| 782 | wline(function(out) writeglobalnames(out, name) end) | ||
| 783 | end | ||
| 784 | |||
| 785 | -- Pseudo-opcode to mark the position where the extern names are to be emitted. | ||
| 786 | map_op[".externnames_1"] = function(params) | ||
| 787 | if not params then return "cvar" end | ||
| 788 | local name = params[1] -- No syntax check. You get to keep the pieces. | ||
| 789 | wline(function(out) writeexternnames(out, name) end) | ||
| 790 | end | ||
| 791 | |||
| 792 | ------------------------------------------------------------------------------ | ||
| 793 | |||
| 794 | -- Label pseudo-opcode (converted from trailing colon form). | ||
| 795 | map_op[".label_1"] = function(params) | ||
| 796 | if not params then return "[1-9] | ->global | =>pcexpr" end | ||
| 797 | if secpos+1 > maxsecpos then wflush() end | ||
| 798 | local mode, n, s = parse_label(params[1], true) | ||
| 799 | if mode == "EXT" then werror("bad label definition") end | ||
| 800 | waction("LABEL_"..mode, n, s, 1) | ||
| 801 | end | ||
| 802 | |||
| 803 | ------------------------------------------------------------------------------ | ||
| 804 | |||
| 805 | -- Pseudo-opcodes for data storage. | ||
| 806 | map_op[".long_*"] = function(params) | ||
| 807 | if not params then return "imm..." end | ||
| 808 | for _,p in ipairs(params) do | ||
| 809 | local n = tonumber(p) | ||
| 810 | if not n then werror("bad immediate `"..p.."'") end | ||
| 811 | if n < 0 then n = n + 2^32 end | ||
| 812 | wputw(n) | ||
| 813 | if secpos+2 > maxsecpos then wflush() end | ||
| 814 | end | ||
| 815 | end | ||
| 816 | |||
| 817 | -- Alignment pseudo-opcode. | ||
| 818 | map_op[".align_1"] = function(params) | ||
| 819 | if not params then return "numpow2" end | ||
| 820 | if secpos+1 > maxsecpos then wflush() end | ||
| 821 | local align = tonumber(params[1]) | ||
| 822 | if align then | ||
| 823 | local x = align | ||
| 824 | -- Must be a power of 2 in the range (2 ... 256). | ||
| 825 | for i=1,8 do | ||
| 826 | x = x / 2 | ||
| 827 | if x == 1 then | ||
| 828 | waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. | ||
| 829 | return | ||
| 830 | end | ||
| 831 | end | ||
| 832 | end | ||
| 833 | werror("bad alignment") | ||
| 834 | end | ||
| 835 | |||
| 836 | ------------------------------------------------------------------------------ | ||
| 837 | |||
| 838 | -- Pseudo-opcode for (primitive) type definitions (map to C types). | ||
| 839 | map_op[".type_3"] = function(params, nparams) | ||
| 840 | if not params then | ||
| 841 | return nparams == 2 and "name, ctype" or "name, ctype, reg" | ||
| 842 | end | ||
| 843 | local name, ctype, reg = params[1], params[2], params[3] | ||
| 844 | if not match(name, "^[%a_][%w_]*$") then | ||
| 845 | werror("bad type name `"..name.."'") | ||
| 846 | end | ||
| 847 | local tp = map_type[name] | ||
| 848 | if tp then | ||
| 849 | werror("duplicate type `"..name.."'") | ||
| 850 | end | ||
| 851 | -- Add #type to defines. A bit unclean to put it in map_archdef. | ||
| 852 | map_archdef["#"..name] = "sizeof("..ctype..")" | ||
| 853 | -- Add new type and emit shortcut define. | ||
| 854 | local num = ctypenum + 1 | ||
| 855 | map_type[name] = { | ||
| 856 | ctype = ctype, | ||
| 857 | ctypefmt = format("Dt%X(%%s)", num), | ||
| 858 | reg = reg, | ||
| 859 | } | ||
| 860 | wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) | ||
| 861 | ctypenum = num | ||
| 862 | end | ||
| 863 | map_op[".type_2"] = map_op[".type_3"] | ||
| 864 | |||
| 865 | -- Dump type definitions. | ||
| 866 | local function dumptypes(out, lvl) | ||
| 867 | local t = {} | ||
| 868 | for name in pairs(map_type) do t[#t+1] = name end | ||
| 869 | sort(t) | ||
| 870 | out:write("Type definitions:\n") | ||
| 871 | for _,name in ipairs(t) do | ||
| 872 | local tp = map_type[name] | ||
| 873 | local reg = tp.reg or "" | ||
| 874 | out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) | ||
| 875 | end | ||
| 876 | out:write("\n") | ||
| 877 | end | ||
| 878 | |||
| 879 | ------------------------------------------------------------------------------ | ||
| 880 | |||
| 881 | -- Set the current section. | ||
| 882 | function _M.section(num) | ||
| 883 | waction("SECTION", num) | ||
| 884 | wflush(true) -- SECTION is a terminal action. | ||
| 885 | end | ||
| 886 | |||
| 887 | ------------------------------------------------------------------------------ | ||
| 888 | |||
| 889 | -- Dump architecture description. | ||
| 890 | function _M.dumparch(out) | ||
| 891 | out:write(format("DynASM %s version %s, released %s\n\n", | ||
| 892 | _info.arch, _info.version, _info.release)) | ||
| 893 | dumpactions(out) | ||
| 894 | end | ||
| 895 | |||
| 896 | -- Dump all user defined elements. | ||
| 897 | function _M.dumpdef(out, lvl) | ||
| 898 | dumptypes(out, lvl) | ||
| 899 | dumpglobals(out, lvl) | ||
| 900 | dumpexterns(out, lvl) | ||
| 901 | end | ||
| 902 | |||
| 903 | ------------------------------------------------------------------------------ | ||
| 904 | |||
| 905 | -- Pass callbacks from/to the DynASM core. | ||
| 906 | function _M.passcb(wl, we, wf, ww) | ||
| 907 | wline, werror, wfatal, wwarn = wl, we, wf, ww | ||
| 908 | return wflush | ||
| 909 | end | ||
| 910 | |||
| 911 | -- Setup the arch-specific module. | ||
| 912 | function _M.setup(arch, opt) | ||
| 913 | g_arch, g_opt = arch, opt | ||
| 914 | end | ||
| 915 | |||
| 916 | -- Merge the core maps and the arch-specific maps. | ||
| 917 | function _M.mergemaps(map_coreop, map_def) | ||
| 918 | setmetatable(map_op, { __index = map_coreop }) | ||
| 919 | setmetatable(map_def, { __index = map_archdef }) | ||
| 920 | return map_op, map_def | ||
| 921 | end | ||
| 922 | |||
| 923 | return _M | ||
| 924 | |||
| 925 | ------------------------------------------------------------------------------ | ||
| 926 | |||
