dynasm.lua 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  1. ------------------------------------------------------------------------------
  2. -- DynASM. A dynamic assembler for code generation engines.
  3. -- Originally designed and implemented for LuaJIT.
  4. --
  5. -- Copyright (C) 2005-2010 Mike Pall. All rights reserved.
  6. -- See below for full copyright notice.
  7. ------------------------------------------------------------------------------
  8. -- Application information.
  9. local _info = {
  10. name = "DynASM",
  11. description = "A dynamic assembler for code generation engines",
  12. version = "1.2.1",
  13. vernum = 10201,
  14. release = "2010-01-09",
  15. author = "Mike Pall",
  16. url = "http://luajit.org/dynasm.html",
  17. license = "MIT",
  18. copyright = [[
  19. Copyright (C) 2005-2010 Mike Pall. All rights reserved.
  20. Permission is hereby granted, free of charge, to any person obtaining
  21. a copy of this software and associated documentation files (the
  22. "Software"), to deal in the Software without restriction, including
  23. without limitation the rights to use, copy, modify, merge, publish,
  24. distribute, sublicense, and/or sell copies of the Software, and to
  25. permit persons to whom the Software is furnished to do so, subject to
  26. the following conditions:
  27. The above copyright notice and this permission notice shall be
  28. included in all copies or substantial portions of the Software.
  29. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  30. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  31. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  32. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  33. CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  34. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  35. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  36. [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
  37. ]],
  38. }
  39. -- Cache library functions.
  40. local type, pairs, ipairs = type, pairs, ipairs
  41. local pcall, error, assert = pcall, error, assert
  42. local _s = string
  43. local sub, match, gmatch, gsub = _s.sub, _s.match, _s.gmatch, _s.gsub
  44. local format, rep, upper = _s.format, _s.rep, _s.upper
  45. local _t = table
  46. local insert, remove, concat, sort = _t.insert, _t.remove, _t.concat, _t.sort
  47. local exit = os.exit
  48. local io = io
  49. local stdin, stdout, stderr = io.stdin, io.stdout, io.stderr
  50. ------------------------------------------------------------------------------
  51. -- Program options.
  52. local g_opt = {}
  53. -- Global state for current file.
  54. local g_fname, g_curline, g_indent, g_lineno, g_synclineno, g_arch
  55. local g_errcount = 0
  56. -- Write buffer for output file.
  57. local g_wbuffer, g_capbuffer
  58. ------------------------------------------------------------------------------
  59. -- Write an output line (or callback function) to the buffer.
  60. local function wline(line, needindent)
  61. local buf = g_capbuffer or g_wbuffer
  62. buf[#buf+1] = needindent and g_indent..line or line
  63. g_synclineno = g_synclineno + 1
  64. end
  65. -- Write assembler line as a comment, if requestd.
  66. local function wcomment(aline)
  67. if g_opt.comment then
  68. wline(g_opt.comment..aline..g_opt.endcomment, true)
  69. end
  70. end
  71. -- Resync CPP line numbers.
  72. local function wsync()
  73. if g_synclineno ~= g_lineno and g_opt.cpp then
  74. wline("# "..g_lineno..' "'..g_fname..'"')
  75. g_synclineno = g_lineno
  76. end
  77. end
  78. -- Dummy action flush function. Replaced with arch-specific function later.
  79. local function wflush(term)
  80. end
  81. -- Dump all buffered output lines.
  82. local function wdumplines(out, buf)
  83. for _,line in ipairs(buf) do
  84. if type(line) == "string" then
  85. assert(out:write(line, "\n"))
  86. else
  87. -- Special callback to dynamically insert lines after end of processing.
  88. line(out)
  89. end
  90. end
  91. end
  92. ------------------------------------------------------------------------------
  93. -- Emit an error. Processing continues with next statement.
  94. local function werror(msg)
  95. error(format("%s:%s: error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0)
  96. end
  97. -- Emit a fatal error. Processing stops.
  98. local function wfatal(msg)
  99. g_errcount = "fatal"
  100. werror(msg)
  101. end
  102. -- Print a warning. Processing continues.
  103. local function wwarn(msg)
  104. stderr:write(format("%s:%s: warning: %s:\n%s\n",
  105. g_fname, g_lineno, msg, g_curline))
  106. end
  107. -- Print caught error message. But suppress excessive errors.
  108. local function wprinterr(...)
  109. if type(g_errcount) == "number" then
  110. -- Regular error.
  111. g_errcount = g_errcount + 1
  112. if g_errcount < 21 then -- Seems to be a reasonable limit.
  113. stderr:write(...)
  114. elseif g_errcount == 21 then
  115. stderr:write(g_fname,
  116. ":*: warning: too many errors (suppressed further messages).\n")
  117. end
  118. else
  119. -- Fatal error.
  120. stderr:write(...)
  121. return true -- Stop processing.
  122. end
  123. end
  124. ------------------------------------------------------------------------------
  125. -- Map holding all option handlers.
  126. local opt_map = {}
  127. local opt_current
  128. -- Print error and exit with error status.
  129. local function opterror(...)
  130. stderr:write("dynasm.lua: ERROR: ", ...)
  131. stderr:write("\n")
  132. exit(1)
  133. end
  134. -- Get option parameter.
  135. local function optparam(args)
  136. local argn = args.argn
  137. local p = args[argn]
  138. if not p then
  139. opterror("missing parameter for option `", opt_current, "'.")
  140. end
  141. args.argn = argn + 1
  142. return p
  143. end
  144. ------------------------------------------------------------------------------
  145. -- Core pseudo-opcodes.
  146. local map_coreop = {}
  147. -- Dummy opcode map. Replaced by arch-specific map.
  148. local map_op = {}
  149. -- Forward declarations.
  150. local dostmt
  151. local readfile
  152. ------------------------------------------------------------------------------
  153. -- Map for defines (initially empty, chains to arch-specific map).
  154. local map_def = {}
  155. -- Pseudo-opcode to define a substitution.
  156. map_coreop[".define_2"] = function(params, nparams)
  157. if not params then return nparams == 1 and "name" or "name, subst" end
  158. local name, def = params[1], params[2] or "1"
  159. if not match(name, "^[%a_][%w_]*$") then werror("bad or duplicate define") end
  160. map_def[name] = def
  161. end
  162. map_coreop[".define_1"] = map_coreop[".define_2"]
  163. -- Define a substitution on the command line.
  164. function opt_map.D(args)
  165. local namesubst = optparam(args)
  166. local name, subst = match(namesubst, "^([%a_][%w_]*)=(.*)$")
  167. if name then
  168. map_def[name] = subst
  169. elseif match(namesubst, "^[%a_][%w_]*$") then
  170. map_def[namesubst] = "1"
  171. else
  172. opterror("bad define")
  173. end
  174. end
  175. -- Undefine a substitution on the command line.
  176. function opt_map.U(args)
  177. local name = optparam(args)
  178. if match(name, "^[%a_][%w_]*$") then
  179. map_def[name] = nil
  180. else
  181. opterror("bad define")
  182. end
  183. end
  184. -- Helper for definesubst.
  185. local gotsubst
  186. local function definesubst_one(word)
  187. local subst = map_def[word]
  188. if subst then gotsubst = word; return subst else return word end
  189. end
  190. -- Iteratively substitute defines.
  191. local function definesubst(stmt)
  192. -- Limit number of iterations.
  193. for i=1,100 do
  194. gotsubst = false
  195. stmt = gsub(stmt, "#?[%w_]+", definesubst_one)
  196. if not gotsubst then break end
  197. end
  198. if gotsubst then wfatal("recursive define involving `"..gotsubst.."'") end
  199. return stmt
  200. end
  201. -- Dump all defines.
  202. local function dumpdefines(out, lvl)
  203. local t = {}
  204. for name in pairs(map_def) do
  205. t[#t+1] = name
  206. end
  207. sort(t)
  208. out:write("Defines:\n")
  209. for _,name in ipairs(t) do
  210. local subst = map_def[name]
  211. if g_arch then subst = g_arch.revdef(subst) end
  212. out:write(format(" %-20s %s\n", name, subst))
  213. end
  214. out:write("\n")
  215. end
  216. ------------------------------------------------------------------------------
  217. -- Support variables for conditional assembly.
  218. local condlevel = 0
  219. local condstack = {}
  220. -- Evaluate condition with a Lua expression. Substitutions already performed.
  221. local function cond_eval(cond)
  222. local func, err = loadstring("return "..cond)
  223. if func then
  224. setfenv(func, {}) -- No globals. All unknown identifiers evaluate to nil.
  225. local ok, res = pcall(func)
  226. if ok then
  227. if res == 0 then return false end -- Oh well.
  228. return not not res
  229. end
  230. err = res
  231. end
  232. wfatal("bad condition: "..err)
  233. end
  234. -- Skip statements until next conditional pseudo-opcode at the same level.
  235. local function stmtskip()
  236. local dostmt_save = dostmt
  237. local lvl = 0
  238. dostmt = function(stmt)
  239. local op = match(stmt, "^%s*(%S+)")
  240. if op == ".if" then
  241. lvl = lvl + 1
  242. elseif lvl ~= 0 then
  243. if op == ".endif" then lvl = lvl - 1 end
  244. elseif op == ".elif" or op == ".else" or op == ".endif" then
  245. dostmt = dostmt_save
  246. dostmt(stmt)
  247. end
  248. end
  249. end
  250. -- Pseudo-opcodes for conditional assembly.
  251. map_coreop[".if_1"] = function(params)
  252. if not params then return "condition" end
  253. local lvl = condlevel + 1
  254. local res = cond_eval(params[1])
  255. condlevel = lvl
  256. condstack[lvl] = res
  257. if not res then stmtskip() end
  258. end
  259. map_coreop[".elif_1"] = function(params)
  260. if not params then return "condition" end
  261. if condlevel == 0 then wfatal(".elif without .if") end
  262. local lvl = condlevel
  263. local res = condstack[lvl]
  264. if res then
  265. if res == "else" then wfatal(".elif after .else") end
  266. else
  267. res = cond_eval(params[1])
  268. if res then
  269. condstack[lvl] = res
  270. return
  271. end
  272. end
  273. stmtskip()
  274. end
  275. map_coreop[".else_0"] = function(params)
  276. if condlevel == 0 then wfatal(".else without .if") end
  277. local lvl = condlevel
  278. local res = condstack[lvl]
  279. condstack[lvl] = "else"
  280. if res then
  281. if res == "else" then wfatal(".else after .else") end
  282. stmtskip()
  283. end
  284. end
  285. map_coreop[".endif_0"] = function(params)
  286. local lvl = condlevel
  287. if lvl == 0 then wfatal(".endif without .if") end
  288. condlevel = lvl - 1
  289. end
  290. -- Check for unfinished conditionals.
  291. local function checkconds()
  292. if g_errcount ~= "fatal" and condlevel ~= 0 then
  293. wprinterr(g_fname, ":*: error: unbalanced conditional\n")
  294. end
  295. end
  296. ------------------------------------------------------------------------------
  297. -- Search for a file in the given path and open it for reading.
  298. local function pathopen(path, name)
  299. local dirsep = match(package.path, "\\") and "\\" or "/"
  300. for _,p in ipairs(path) do
  301. local fullname = p == "" and name or p..dirsep..name
  302. local fin = io.open(fullname, "r")
  303. if fin then
  304. g_fname = fullname
  305. return fin
  306. end
  307. end
  308. end
  309. -- Include a file.
  310. map_coreop[".include_1"] = function(params)
  311. if not params then return "filename" end
  312. local name = params[1]
  313. -- Save state. Ugly, I know. but upvalues are fast.
  314. local gf, gl, gcl, gi = g_fname, g_lineno, g_curline, g_indent
  315. -- Read the included file.
  316. local fatal = readfile(pathopen(g_opt.include, name) or
  317. wfatal("include file `"..name.."' not found"))
  318. -- Restore state.
  319. g_synclineno = -1
  320. g_fname, g_lineno, g_curline, g_indent = gf, gl, gcl, gi
  321. if fatal then wfatal("in include file") end
  322. end
  323. -- Make .include and conditionals initially available, too.
  324. map_op[".include_1"] = map_coreop[".include_1"]
  325. map_op[".if_1"] = map_coreop[".if_1"]
  326. map_op[".elif_1"] = map_coreop[".elif_1"]
  327. map_op[".else_0"] = map_coreop[".else_0"]
  328. map_op[".endif_0"] = map_coreop[".endif_0"]
  329. ------------------------------------------------------------------------------
  330. -- Support variables for macros.
  331. local mac_capture, mac_lineno, mac_name
  332. local mac_active = {}
  333. local mac_list = {}
  334. -- Pseudo-opcode to define a macro.
  335. map_coreop[".macro_*"] = function(mparams)
  336. if not mparams then return "name [, params...]" end
  337. -- Split off and validate macro name.
  338. local name = remove(mparams, 1)
  339. if not name then werror("missing macro name") end
  340. if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]+$")) then
  341. wfatal("bad macro name `"..name.."'")
  342. end
  343. -- Validate macro parameter names.
  344. local mdup = {}
  345. for _,mp in ipairs(mparams) do
  346. if not match(mp, "^[%a_][%w_]*$") then
  347. wfatal("bad macro parameter name `"..mp.."'")
  348. end
  349. if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end
  350. mdup[mp] = true
  351. end
  352. -- Check for duplicate or recursive macro definitions.
  353. local opname = name.."_"..#mparams
  354. if map_op[opname] or map_op[name.."_*"] then
  355. wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)")
  356. end
  357. if mac_capture then wfatal("recursive macro definition") end
  358. -- Enable statement capture.
  359. local lines = {}
  360. mac_lineno = g_lineno
  361. mac_name = name
  362. mac_capture = function(stmt) -- Statement capture function.
  363. -- Stop macro definition with .endmacro pseudo-opcode.
  364. if not match(stmt, "^%s*.endmacro%s*$") then
  365. lines[#lines+1] = stmt
  366. return
  367. end
  368. mac_capture = nil
  369. mac_lineno = nil
  370. mac_name = nil
  371. mac_list[#mac_list+1] = opname
  372. -- Add macro-op definition.
  373. map_op[opname] = function(params)
  374. if not params then return mparams, lines end
  375. -- Protect against recursive macro invocation.
  376. if mac_active[opname] then wfatal("recursive macro invocation") end
  377. mac_active[opname] = true
  378. -- Setup substitution map.
  379. local subst = {}
  380. for i,mp in ipairs(mparams) do subst[mp] = params[i] end
  381. local mcom
  382. if g_opt.maccomment and g_opt.comment then
  383. mcom = " MACRO "..name.." ("..#mparams..")"
  384. wcomment("{"..mcom)
  385. end
  386. -- Loop through all captured statements
  387. for _,stmt in ipairs(lines) do
  388. -- Substitute macro parameters.
  389. local st = gsub(stmt, "[%w_]+", subst)
  390. st = definesubst(st)
  391. st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b.
  392. if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end
  393. -- Emit statement. Use a protected call for better diagnostics.
  394. local ok, err = pcall(dostmt, st)
  395. if not ok then
  396. -- Add the captured statement to the error.
  397. wprinterr(err, "\n", g_indent, "| ", stmt,
  398. "\t[MACRO ", name, " (", #mparams, ")]\n")
  399. end
  400. end
  401. if mcom then wcomment("}"..mcom) end
  402. mac_active[opname] = nil
  403. end
  404. end
  405. end
  406. -- An .endmacro pseudo-opcode outside of a macro definition is an error.
  407. map_coreop[".endmacro_0"] = function(params)
  408. wfatal(".endmacro without .macro")
  409. end
  410. -- Dump all macros and their contents (with -PP only).
  411. local function dumpmacros(out, lvl)
  412. sort(mac_list)
  413. out:write("Macros:\n")
  414. for _,opname in ipairs(mac_list) do
  415. local name = sub(opname, 1, -3)
  416. local params, lines = map_op[opname]()
  417. out:write(format(" %-20s %s\n", name, concat(params, ", ")))
  418. if lvl > 1 then
  419. for _,line in ipairs(lines) do
  420. out:write(" |", line, "\n")
  421. end
  422. out:write("\n")
  423. end
  424. end
  425. out:write("\n")
  426. end
  427. -- Check for unfinished macro definitions.
  428. local function checkmacros()
  429. if mac_capture then
  430. wprinterr(g_fname, ":", mac_lineno,
  431. ": error: unfinished .macro `", mac_name ,"'\n")
  432. end
  433. end
  434. ------------------------------------------------------------------------------
  435. -- Support variables for captures.
  436. local cap_lineno, cap_name
  437. local cap_buffers = {}
  438. local cap_used = {}
  439. -- Start a capture.
  440. map_coreop[".capture_1"] = function(params)
  441. if not params then return "name" end
  442. wflush()
  443. local name = params[1]
  444. if not match(name, "^[%a_][%w_]*$") then
  445. wfatal("bad capture name `"..name.."'")
  446. end
  447. if cap_name then
  448. wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno)
  449. end
  450. cap_name = name
  451. cap_lineno = g_lineno
  452. -- Create or continue a capture buffer and start the output line capture.
  453. local buf = cap_buffers[name]
  454. if not buf then buf = {}; cap_buffers[name] = buf end
  455. g_capbuffer = buf
  456. g_synclineno = 0
  457. end
  458. -- Stop a capture.
  459. map_coreop[".endcapture_0"] = function(params)
  460. wflush()
  461. if not cap_name then wfatal(".endcapture without a valid .capture") end
  462. cap_name = nil
  463. cap_lineno = nil
  464. g_capbuffer = nil
  465. g_synclineno = 0
  466. end
  467. -- Dump a capture buffer.
  468. map_coreop[".dumpcapture_1"] = function(params)
  469. if not params then return "name" end
  470. wflush()
  471. local name = params[1]
  472. if not match(name, "^[%a_][%w_]*$") then
  473. wfatal("bad capture name `"..name.."'")
  474. end
  475. cap_used[name] = true
  476. wline(function(out)
  477. local buf = cap_buffers[name]
  478. if buf then wdumplines(out, buf) end
  479. end)
  480. g_synclineno = 0
  481. end
  482. -- Dump all captures and their buffers (with -PP only).
  483. local function dumpcaptures(out, lvl)
  484. out:write("Captures:\n")
  485. for name,buf in pairs(cap_buffers) do
  486. out:write(format(" %-20s %4s)\n", name, "("..#buf))
  487. if lvl > 1 then
  488. local bar = rep("=", 76)
  489. out:write(" ", bar, "\n")
  490. for _,line in ipairs(buf) do
  491. out:write(" ", line, "\n")
  492. end
  493. out:write(" ", bar, "\n\n")
  494. end
  495. end
  496. out:write("\n")
  497. end
  498. -- Check for unfinished or unused captures.
  499. local function checkcaptures()
  500. if cap_name then
  501. wprinterr(g_fname, ":", cap_lineno,
  502. ": error: unfinished .capture `", cap_name,"'\n")
  503. return
  504. end
  505. for name in pairs(cap_buffers) do
  506. if not cap_used[name] then
  507. wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n")
  508. end
  509. end
  510. end
  511. ------------------------------------------------------------------------------
  512. -- Sections names.
  513. local map_sections = {}
  514. -- Pseudo-opcode to define code sections.
  515. -- TODO: Data sections, BSS sections. Needs extra C code and API.
  516. map_coreop[".section_*"] = function(params)
  517. if not params then return "name..." end
  518. if #map_sections > 0 then werror("duplicate section definition") end
  519. wflush()
  520. for sn,name in ipairs(params) do
  521. local opname = "."..name.."_0"
  522. if not match(name, "^[%a][%w_]*$") or
  523. map_op[opname] or map_op["."..name.."_*"] then
  524. werror("bad section name `"..name.."'")
  525. end
  526. map_sections[#map_sections+1] = name
  527. wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1))
  528. map_op[opname] = function(params) g_arch.section(sn-1) end
  529. end
  530. wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections))
  531. end
  532. -- Dump all sections.
  533. local function dumpsections(out, lvl)
  534. out:write("Sections:\n")
  535. for _,name in ipairs(map_sections) do
  536. out:write(format(" %s\n", name))
  537. end
  538. out:write("\n")
  539. end
  540. ------------------------------------------------------------------------------
  541. -- Load architecture-specific module.
  542. local function loadarch(arch)
  543. if not match(arch, "^[%w_]+$") then return "bad arch name" end
  544. local ok, m_arch = pcall(require, "dasm_"..arch)
  545. if not ok then return "cannot load module: "..m_arch end
  546. g_arch = m_arch
  547. wflush = m_arch.passcb(wline, werror, wfatal, wwarn)
  548. m_arch.setup(arch, g_opt)
  549. map_op, map_def = m_arch.mergemaps(map_coreop, map_def)
  550. end
  551. -- Dump architecture description.
  552. function opt_map.dumparch(args)
  553. local name = optparam(args)
  554. if not g_arch then
  555. local err = loadarch(name)
  556. if err then opterror(err) end
  557. end
  558. local t = {}
  559. for name in pairs(map_coreop) do t[#t+1] = name end
  560. for name in pairs(map_op) do t[#t+1] = name end
  561. sort(t)
  562. local out = stdout
  563. local _arch = g_arch._info
  564. out:write(format("%s version %s, released %s, %s\n",
  565. _info.name, _info.version, _info.release, _info.url))
  566. g_arch.dumparch(out)
  567. local pseudo = true
  568. out:write("Pseudo-Opcodes:\n")
  569. for _,sname in ipairs(t) do
  570. local name, nparam = match(sname, "^(.+)_([0-9%*])$")
  571. if name then
  572. if pseudo and sub(name, 1, 1) ~= "." then
  573. out:write("\nOpcodes:\n")
  574. pseudo = false
  575. end
  576. local f = map_op[sname]
  577. local s
  578. if nparam ~= "*" then nparam = nparam + 0 end
  579. if nparam == 0 then
  580. s = ""
  581. elseif type(f) == "string" then
  582. s = map_op[".template__"](nil, f, nparam)
  583. else
  584. s = f(nil, nparam)
  585. end
  586. if type(s) == "table" then
  587. for _,s2 in ipairs(s) do
  588. out:write(format(" %-12s %s\n", name, s2))
  589. end
  590. else
  591. out:write(format(" %-12s %s\n", name, s))
  592. end
  593. end
  594. end
  595. out:write("\n")
  596. exit(0)
  597. end
  598. -- Pseudo-opcode to set the architecture.
  599. -- Only initially available (map_op is replaced when called).
  600. map_op[".arch_1"] = function(params)
  601. if not params then return "name" end
  602. local err = loadarch(params[1])
  603. if err then wfatal(err) end
  604. end
  605. -- Dummy .arch pseudo-opcode to improve the error report.
  606. map_coreop[".arch_1"] = function(params)
  607. if not params then return "name" end
  608. wfatal("duplicate .arch statement")
  609. end
  610. ------------------------------------------------------------------------------
  611. -- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'.
  612. map_coreop[".nop_*"] = function(params)
  613. if not params then return "[ignored...]" end
  614. end
  615. -- Pseudo-opcodes to raise errors.
  616. map_coreop[".error_1"] = function(params)
  617. if not params then return "message" end
  618. werror(params[1])
  619. end
  620. map_coreop[".fatal_1"] = function(params)
  621. if not params then return "message" end
  622. wfatal(params[1])
  623. end
  624. -- Dump all user defined elements.
  625. local function dumpdef(out)
  626. local lvl = g_opt.dumpdef
  627. if lvl == 0 then return end
  628. dumpsections(out, lvl)
  629. dumpdefines(out, lvl)
  630. if g_arch then g_arch.dumpdef(out, lvl) end
  631. dumpmacros(out, lvl)
  632. dumpcaptures(out, lvl)
  633. end
  634. ------------------------------------------------------------------------------
  635. -- Helper for splitstmt.
  636. local splitlvl
  637. local function splitstmt_one(c)
  638. if c == "(" then
  639. splitlvl = ")"..splitlvl
  640. elseif c == "[" then
  641. splitlvl = "]"..splitlvl
  642. elseif c == ")" or c == "]" then
  643. if sub(splitlvl, 1, 1) ~= c then werror("unbalanced () or []") end
  644. splitlvl = sub(splitlvl, 2)
  645. elseif splitlvl == "" then
  646. return " \0 "
  647. end
  648. return c
  649. end
  650. -- Split statement into (pseudo-)opcode and params.
  651. local function splitstmt(stmt)
  652. -- Convert label with trailing-colon into .label statement.
  653. local label = match(stmt, "^%s*(.+):%s*$")
  654. if label then return ".label", {label} end
  655. -- Split at commas and equal signs, but obey parentheses and brackets.
  656. splitlvl = ""
  657. stmt = gsub(stmt, "[,%(%)%[%]]", splitstmt_one)
  658. if splitlvl ~= "" then werror("unbalanced () or []") end
  659. -- Split off opcode.
  660. local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$")
  661. if not op then werror("bad statement syntax") end
  662. -- Split parameters.
  663. local params = {}
  664. for p in gmatch(other, "%s*(%Z+)%z?") do
  665. params[#params+1] = gsub(p, "%s+$", "")
  666. end
  667. if #params > 16 then werror("too many parameters") end
  668. params.op = op
  669. return op, params
  670. end
  671. -- Process a single statement.
  672. dostmt = function(stmt)
  673. -- Ignore empty statements.
  674. if match(stmt, "^%s*$") then return end
  675. -- Capture macro defs before substitution.
  676. if mac_capture then return mac_capture(stmt) end
  677. stmt = definesubst(stmt)
  678. -- Emit C code without parsing the line.
  679. if sub(stmt, 1, 1) == "|" then
  680. local tail = sub(stmt, 2)
  681. wflush()
  682. if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end
  683. return
  684. end
  685. -- Split into (pseudo-)opcode and params.
  686. local op, params = splitstmt(stmt)
  687. -- Get opcode handler (matching # of parameters or generic handler).
  688. local f = map_op[op.."_"..#params] or map_op[op.."_*"]
  689. if not f then
  690. if not g_arch then wfatal("first statement must be .arch") end
  691. -- Improve error report.
  692. for i=0,16 do
  693. if map_op[op.."_"..i] then
  694. werror("wrong number of parameters for `"..op.."'")
  695. end
  696. end
  697. werror("unknown statement `"..op.."'")
  698. end
  699. -- Call opcode handler or special handler for template strings.
  700. if type(f) == "string" then
  701. map_op[".template__"](params, f)
  702. else
  703. f(params)
  704. end
  705. end
  706. -- Process a single line.
  707. local function doline(line)
  708. if g_opt.flushline then wflush() end
  709. -- Assembler line?
  710. local indent, aline = match(line, "^(%s*)%|(.*)$")
  711. if not aline then
  712. -- No, plain C code line, need to flush first.
  713. wflush()
  714. wsync()
  715. wline(line, false)
  716. return
  717. end
  718. g_indent = indent -- Remember current line indentation.
  719. -- Emit C code (even from macros). Avoids echo and line parsing.
  720. if sub(aline, 1, 1) == "|" then
  721. if not mac_capture then
  722. wsync()
  723. elseif g_opt.comment then
  724. wsync()
  725. wcomment(aline)
  726. end
  727. dostmt(aline)
  728. return
  729. end
  730. -- Echo assembler line as a comment.
  731. if g_opt.comment then
  732. wsync()
  733. wcomment(aline)
  734. end
  735. -- Strip assembler comments.
  736. aline = gsub(aline, "//.*$", "")
  737. -- Split line into statements at semicolons.
  738. if match(aline, ";") then
  739. for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end
  740. else
  741. dostmt(aline)
  742. end
  743. end
  744. ------------------------------------------------------------------------------
  745. -- Write DynASM header.
  746. local function dasmhead(out)
  747. out:write(format([[
  748. /*
  749. ** This file has been pre-processed with DynASM.
  750. ** %s
  751. ** DynASM version %s, DynASM %s version %s
  752. ** DO NOT EDIT! The original file is in "%s".
  753. */
  754. #if DASM_VERSION != %d
  755. #error "Version mismatch between DynASM and included encoding engine"
  756. #endif
  757. ]], _info.url,
  758. _info.version, g_arch._info.arch, g_arch._info.version,
  759. g_fname, _info.vernum))
  760. end
  761. -- Read input file.
  762. readfile = function(fin)
  763. g_indent = ""
  764. g_lineno = 0
  765. g_synclineno = -1
  766. -- Process all lines.
  767. for line in fin:lines() do
  768. g_lineno = g_lineno + 1
  769. g_curline = line
  770. local ok, err = pcall(doline, line)
  771. if not ok and wprinterr(err, "\n") then return true end
  772. end
  773. wflush()
  774. -- Close input file.
  775. assert(fin == stdin or fin:close())
  776. end
  777. -- Write output file.
  778. local function writefile(outfile)
  779. local fout
  780. -- Open output file.
  781. if outfile == nil or outfile == "-" then
  782. fout = stdout
  783. else
  784. fout = assert(io.open(outfile, "w"))
  785. end
  786. -- Write all buffered lines
  787. wdumplines(fout, g_wbuffer)
  788. -- Close output file.
  789. assert(fout == stdout or fout:close())
  790. -- Optionally dump definitions.
  791. dumpdef(fout == stdout and stderr or stdout)
  792. end
  793. -- Translate an input file to an output file.
  794. local function translate(infile, outfile)
  795. g_wbuffer = {}
  796. g_indent = ""
  797. g_lineno = 0
  798. g_synclineno = -1
  799. -- Put header.
  800. wline(dasmhead)
  801. -- Read input file.
  802. local fin
  803. if infile == "-" then
  804. g_fname = "(stdin)"
  805. fin = stdin
  806. else
  807. g_fname = infile
  808. fin = assert(io.open(infile, "r"))
  809. end
  810. readfile(fin)
  811. -- Check for errors.
  812. if not g_arch then
  813. wprinterr(g_fname, ":*: error: missing .arch directive\n")
  814. end
  815. checkconds()
  816. checkmacros()
  817. checkcaptures()
  818. if g_errcount ~= 0 then
  819. stderr:write(g_fname, ":*: info: ", g_errcount, " error",
  820. (type(g_errcount) == "number" and g_errcount > 1) and "s" or "",
  821. " in input file -- no output file generated.\n")
  822. dumpdef(stderr)
  823. exit(1)
  824. end
  825. -- Write output file.
  826. writefile(outfile)
  827. end
  828. ------------------------------------------------------------------------------
  829. -- Print help text.
  830. function opt_map.help()
  831. stdout:write("DynASM -- ", _info.description, ".\n")
  832. stdout:write("DynASM ", _info.version, " ", _info.release, " ", _info.url, "\n")
  833. stdout:write[[
  834. Usage: dynasm [OPTION]... INFILE.dasc|-
  835. -h, --help Display this help text.
  836. -V, --version Display version and copyright information.
  837. -o, --outfile FILE Output file name (default is stdout).
  838. -I, --include DIR Add directory to the include search path.
  839. -c, --ccomment Use /* */ comments for assembler lines.
  840. -C, --cppcomment Use // comments for assembler lines (default).
  841. -N, --nocomment Suppress assembler lines in output.
  842. -M, --maccomment Show macro expansions as comments (default off).
  843. -L, --nolineno Suppress CPP line number information in output.
  844. -F, --flushline Flush action list for every line.
  845. -D NAME[=SUBST] Define a substitution.
  846. -U NAME Undefine a substitution.
  847. -P, --dumpdef Dump defines, macros, etc. Repeat for more output.
  848. -A, --dumparch ARCH Load architecture ARCH and dump description.
  849. ]]
  850. exit(0)
  851. end
  852. -- Print version information.
  853. function opt_map.version()
  854. stdout:write(format("%s version %s, released %s\n%s\n\n%s",
  855. _info.name, _info.version, _info.release, _info.url, _info.copyright))
  856. exit(0)
  857. end
  858. -- Misc. options.
  859. function opt_map.outfile(args) g_opt.outfile = optparam(args) end
  860. function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end
  861. function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end
  862. function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end
  863. function opt_map.nocomment() g_opt.comment = false end
  864. function opt_map.maccomment() g_opt.maccomment = true end
  865. function opt_map.nolineno() g_opt.cpp = false end
  866. function opt_map.flushline() g_opt.flushline = true end
  867. function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end
  868. ------------------------------------------------------------------------------
  869. -- Short aliases for long options.
  870. local opt_alias = {
  871. h = "help", ["?"] = "help", V = "version",
  872. o = "outfile", I = "include",
  873. c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment",
  874. L = "nolineno", F = "flushline",
  875. P = "dumpdef", A = "dumparch",
  876. }
  877. -- Parse single option.
  878. local function parseopt(opt, args)
  879. opt_current = #opt == 1 and "-"..opt or "--"..opt
  880. local f = opt_map[opt] or opt_map[opt_alias[opt]]
  881. if not f then
  882. opterror("unrecognized option `", opt_current, "'. Try `--help'.\n")
  883. end
  884. f(args)
  885. end
  886. -- Parse arguments.
  887. local function parseargs(args)
  888. -- Default options.
  889. g_opt.comment = "//|"
  890. g_opt.endcomment = ""
  891. g_opt.cpp = true
  892. g_opt.dumpdef = 0
  893. g_opt.include = { "" }
  894. -- Process all option arguments.
  895. args.argn = 1
  896. repeat
  897. local a = args[args.argn]
  898. if not a then break end
  899. local lopt, opt = match(a, "^%-(%-?)(.+)")
  900. if not opt then break end
  901. args.argn = args.argn + 1
  902. if lopt == "" then
  903. -- Loop through short options.
  904. for o in gmatch(opt, ".") do parseopt(o, args) end
  905. else
  906. -- Long option.
  907. parseopt(opt, args)
  908. end
  909. until false
  910. -- Check for proper number of arguments.
  911. local nargs = #args - args.argn + 1
  912. if nargs ~= 1 then
  913. if nargs == 0 then
  914. if g_opt.dumpdef > 0 then return dumpdef(stdout) end
  915. end
  916. opt_map.help()
  917. end
  918. -- Translate a single input file to a single output file
  919. -- TODO: Handle multiple files?
  920. translate(args[args.argn], g_opt.outfile)
  921. end
  922. ------------------------------------------------------------------------------
  923. -- Add the directory dynasm.lua resides in to the Lua module search path.
  924. local arg = arg
  925. if arg and arg[0] then
  926. local prefix = match(arg[0], "^(.*[/\\])")
  927. if prefix then package.path = prefix.."?.lua;"..package.path end
  928. end
  929. -- Start DynASM.
  930. parseargs{...}
  931. ------------------------------------------------------------------------------