dynasm.lua 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070
  1. ------------------------------------------------------------------------------
  2. -- DynASM. A dynamic assembler for code generation engines.
  3. -- Originally designed and implemented for LuaJIT.
  4. --
  5. -- Copyright (C) 2005-2009 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 = "2009-04-16",
  15. author = "Mike Pall",
  16. url = "http://luajit.org/dynasm.html",
  17. license = "MIT",
  18. copyright = [[
  19. Copyright (C) 2005-2009 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 initially available, too.
  324. map_op[".include_1"] = map_coreop[".include_1"]
  325. ------------------------------------------------------------------------------
  326. -- Support variables for macros.
  327. local mac_capture, mac_lineno, mac_name
  328. local mac_active = {}
  329. local mac_list = {}
  330. -- Pseudo-opcode to define a macro.
  331. map_coreop[".macro_*"] = function(mparams)
  332. if not mparams then return "name [, params...]" end
  333. -- Split off and validate macro name.
  334. local name = remove(mparams, 1)
  335. if not name then werror("missing macro name") end
  336. if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]+$")) then
  337. wfatal("bad macro name `"..name.."'")
  338. end
  339. -- Validate macro parameter names.
  340. local mdup = {}
  341. for _,mp in ipairs(mparams) do
  342. if not match(mp, "^[%a_][%w_]*$") then
  343. wfatal("bad macro parameter name `"..mp.."'")
  344. end
  345. if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end
  346. mdup[mp] = true
  347. end
  348. -- Check for duplicate or recursive macro definitions.
  349. local opname = name.."_"..#mparams
  350. if map_op[opname] or map_op[name.."_*"] then
  351. wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)")
  352. end
  353. if mac_capture then wfatal("recursive macro definition") end
  354. -- Enable statement capture.
  355. local lines = {}
  356. mac_lineno = g_lineno
  357. mac_name = name
  358. mac_capture = function(stmt) -- Statement capture function.
  359. -- Stop macro definition with .endmacro pseudo-opcode.
  360. if not match(stmt, "^%s*.endmacro%s*$") then
  361. lines[#lines+1] = stmt
  362. return
  363. end
  364. mac_capture = nil
  365. mac_lineno = nil
  366. mac_name = nil
  367. mac_list[#mac_list+1] = opname
  368. -- Add macro-op definition.
  369. map_op[opname] = function(params)
  370. if not params then return mparams, lines end
  371. -- Protect against recursive macro invocation.
  372. if mac_active[opname] then wfatal("recursive macro invocation") end
  373. mac_active[opname] = true
  374. -- Setup substitution map.
  375. local subst = {}
  376. for i,mp in ipairs(mparams) do subst[mp] = params[i] end
  377. local mcom
  378. if g_opt.maccomment and g_opt.comment then
  379. mcom = " MACRO "..name.." ("..#mparams..")"
  380. wcomment("{"..mcom)
  381. end
  382. -- Loop through all captured statements
  383. for _,stmt in ipairs(lines) do
  384. -- Substitute macro parameters.
  385. local st = gsub(stmt, "[%w_]+", subst)
  386. st = definesubst(st)
  387. st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b.
  388. if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end
  389. -- Emit statement. Use a protected call for better diagnostics.
  390. local ok, err = pcall(dostmt, st)
  391. if not ok then
  392. -- Add the captured statement to the error.
  393. wprinterr(err, "\n", g_indent, "| ", stmt,
  394. "\t[MACRO ", name, " (", #mparams, ")]\n")
  395. end
  396. end
  397. if mcom then wcomment("}"..mcom) end
  398. mac_active[opname] = nil
  399. end
  400. end
  401. end
  402. -- An .endmacro pseudo-opcode outside of a macro definition is an error.
  403. map_coreop[".endmacro_0"] = function(params)
  404. wfatal(".endmacro without .macro")
  405. end
  406. -- Dump all macros and their contents (with -PP only).
  407. local function dumpmacros(out, lvl)
  408. sort(mac_list)
  409. out:write("Macros:\n")
  410. for _,opname in ipairs(mac_list) do
  411. local name = sub(opname, 1, -3)
  412. local params, lines = map_op[opname]()
  413. out:write(format(" %-20s %s\n", name, concat(params, ", ")))
  414. if lvl > 1 then
  415. for _,line in ipairs(lines) do
  416. out:write(" |", line, "\n")
  417. end
  418. out:write("\n")
  419. end
  420. end
  421. out:write("\n")
  422. end
  423. -- Check for unfinished macro definitions.
  424. local function checkmacros()
  425. if mac_capture then
  426. wprinterr(g_fname, ":", mac_lineno,
  427. ": error: unfinished .macro `", mac_name ,"'\n")
  428. end
  429. end
  430. ------------------------------------------------------------------------------
  431. -- Support variables for captures.
  432. local cap_lineno, cap_name
  433. local cap_buffers = {}
  434. local cap_used = {}
  435. -- Start a capture.
  436. map_coreop[".capture_1"] = function(params)
  437. if not params then return "name" end
  438. wflush()
  439. local name = params[1]
  440. if not match(name, "^[%a_][%w_]*$") then
  441. wfatal("bad capture name `"..name.."'")
  442. end
  443. if cap_name then
  444. wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno)
  445. end
  446. cap_name = name
  447. cap_lineno = g_lineno
  448. -- Create or continue a capture buffer and start the output line capture.
  449. local buf = cap_buffers[name]
  450. if not buf then buf = {}; cap_buffers[name] = buf end
  451. g_capbuffer = buf
  452. g_synclineno = 0
  453. end
  454. -- Stop a capture.
  455. map_coreop[".endcapture_0"] = function(params)
  456. wflush()
  457. if not cap_name then wfatal(".endcapture without a valid .capture") end
  458. cap_name = nil
  459. cap_lineno = nil
  460. g_capbuffer = nil
  461. g_synclineno = 0
  462. end
  463. -- Dump a capture buffer.
  464. map_coreop[".dumpcapture_1"] = function(params)
  465. if not params then return "name" end
  466. wflush()
  467. local name = params[1]
  468. if not match(name, "^[%a_][%w_]*$") then
  469. wfatal("bad capture name `"..name.."'")
  470. end
  471. cap_used[name] = true
  472. wline(function(out)
  473. local buf = cap_buffers[name]
  474. if buf then wdumplines(out, buf) end
  475. end)
  476. g_synclineno = 0
  477. end
  478. -- Dump all captures and their buffers (with -PP only).
  479. local function dumpcaptures(out, lvl)
  480. out:write("Captures:\n")
  481. for name,buf in pairs(cap_buffers) do
  482. out:write(format(" %-20s %4s)\n", name, "("..#buf))
  483. if lvl > 1 then
  484. local bar = rep("=", 76)
  485. out:write(" ", bar, "\n")
  486. for _,line in ipairs(buf) do
  487. out:write(" ", line, "\n")
  488. end
  489. out:write(" ", bar, "\n\n")
  490. end
  491. end
  492. out:write("\n")
  493. end
  494. -- Check for unfinished or unused captures.
  495. local function checkcaptures()
  496. if cap_name then
  497. wprinterr(g_fname, ":", cap_lineno,
  498. ": error: unfinished .capture `", cap_name,"'\n")
  499. return
  500. end
  501. for name in pairs(cap_buffers) do
  502. if not cap_used[name] then
  503. wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n")
  504. end
  505. end
  506. end
  507. ------------------------------------------------------------------------------
  508. -- Sections names.
  509. local map_sections = {}
  510. -- Pseudo-opcode to define code sections.
  511. -- TODO: Data sections, BSS sections. Needs extra C code and API.
  512. map_coreop[".section_*"] = function(params)
  513. if not params then return "name..." end
  514. if #map_sections > 0 then werror("duplicate section definition") end
  515. wflush()
  516. for sn,name in ipairs(params) do
  517. local opname = "."..name.."_0"
  518. if not match(name, "^[%a][%w_]*$") or
  519. map_op[opname] or map_op["."..name.."_*"] then
  520. werror("bad section name `"..name.."'")
  521. end
  522. map_sections[#map_sections+1] = name
  523. wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1))
  524. map_op[opname] = function(params) g_arch.section(sn-1) end
  525. end
  526. wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections))
  527. end
  528. -- Dump all sections.
  529. local function dumpsections(out, lvl)
  530. out:write("Sections:\n")
  531. for _,name in ipairs(map_sections) do
  532. out:write(format(" %s\n", name))
  533. end
  534. out:write("\n")
  535. end
  536. ------------------------------------------------------------------------------
  537. -- Load architecture-specific module.
  538. local function loadarch(arch)
  539. if not match(arch, "^[%w_]+$") then return "bad arch name" end
  540. local ok, m_arch = pcall(require, "dasm_"..arch)
  541. if not ok then return "cannot load module: "..m_arch end
  542. g_arch = m_arch
  543. wflush = m_arch.passcb(wline, werror, wfatal, wwarn)
  544. m_arch.setup(arch, g_opt)
  545. map_op, map_def = m_arch.mergemaps(map_coreop, map_def)
  546. end
  547. -- Dump architecture description.
  548. function opt_map.dumparch(args)
  549. local name = optparam(args)
  550. if not g_arch then
  551. local err = loadarch(name)
  552. if err then opterror(err) end
  553. end
  554. local t = {}
  555. for name in pairs(map_coreop) do t[#t+1] = name end
  556. for name in pairs(map_op) do t[#t+1] = name end
  557. sort(t)
  558. local out = stdout
  559. local _arch = g_arch._info
  560. out:write(format("%s version %s, released %s, %s\n",
  561. _info.name, _info.version, _info.release, _info.url))
  562. g_arch.dumparch(out)
  563. local pseudo = true
  564. out:write("Pseudo-Opcodes:\n")
  565. for _,sname in ipairs(t) do
  566. local name, nparam = match(sname, "^(.+)_([0-9%*])$")
  567. if name then
  568. if pseudo and sub(name, 1, 1) ~= "." then
  569. out:write("\nOpcodes:\n")
  570. pseudo = false
  571. end
  572. local f = map_op[sname]
  573. local s
  574. if nparam ~= "*" then nparam = nparam + 0 end
  575. if nparam == 0 then
  576. s = ""
  577. elseif type(f) == "string" then
  578. s = map_op[".template__"](nil, f, nparam)
  579. else
  580. s = f(nil, nparam)
  581. end
  582. if type(s) == "table" then
  583. for _,s2 in ipairs(s) do
  584. out:write(format(" %-12s %s\n", name, s2))
  585. end
  586. else
  587. out:write(format(" %-12s %s\n", name, s))
  588. end
  589. end
  590. end
  591. out:write("\n")
  592. exit(0)
  593. end
  594. -- Pseudo-opcode to set the architecture.
  595. -- Only initially available (map_op is replaced when called).
  596. map_op[".arch_1"] = function(params)
  597. if not params then return "name" end
  598. local err = loadarch(params[1])
  599. if err then wfatal(err) end
  600. end
  601. -- Dummy .arch pseudo-opcode to improve the error report.
  602. map_coreop[".arch_1"] = function(params)
  603. if not params then return "name" end
  604. wfatal("duplicate .arch statement")
  605. end
  606. ------------------------------------------------------------------------------
  607. -- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'.
  608. map_coreop[".nop_*"] = function(params)
  609. if not params then return "[ignored...]" end
  610. end
  611. -- Pseudo-opcodes to raise errors.
  612. map_coreop[".error_1"] = function(params)
  613. if not params then return "message" end
  614. werror(params[1])
  615. end
  616. map_coreop[".fatal_1"] = function(params)
  617. if not params then return "message" end
  618. wfatal(params[1])
  619. end
  620. -- Dump all user defined elements.
  621. local function dumpdef(out)
  622. local lvl = g_opt.dumpdef
  623. if lvl == 0 then return end
  624. dumpsections(out, lvl)
  625. dumpdefines(out, lvl)
  626. if g_arch then g_arch.dumpdef(out, lvl) end
  627. dumpmacros(out, lvl)
  628. dumpcaptures(out, lvl)
  629. end
  630. ------------------------------------------------------------------------------
  631. -- Helper for splitstmt.
  632. local splitlvl
  633. local function splitstmt_one(c)
  634. if c == "(" then
  635. splitlvl = ")"..splitlvl
  636. elseif c == "[" then
  637. splitlvl = "]"..splitlvl
  638. elseif c == ")" or c == "]" then
  639. if sub(splitlvl, 1, 1) ~= c then werror("unbalanced () or []") end
  640. splitlvl = sub(splitlvl, 2)
  641. elseif splitlvl == "" then
  642. return " \0 "
  643. end
  644. return c
  645. end
  646. -- Split statement into (pseudo-)opcode and params.
  647. local function splitstmt(stmt)
  648. -- Convert label with trailing-colon into .label statement.
  649. local label = match(stmt, "^%s*(.+):%s*$")
  650. if label then return ".label", {label} end
  651. -- Split at commas and equal signs, but obey parentheses and brackets.
  652. splitlvl = ""
  653. stmt = gsub(stmt, "[,%(%)%[%]]", splitstmt_one)
  654. if splitlvl ~= "" then werror("unbalanced () or []") end
  655. -- Split off opcode.
  656. local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$")
  657. if not op then werror("bad statement syntax") end
  658. -- Split parameters.
  659. local params = {}
  660. for p in gmatch(other, "%s*(%Z+)%z?") do
  661. params[#params+1] = gsub(p, "%s+$", "")
  662. end
  663. if #params > 16 then werror("too many parameters") end
  664. params.op = op
  665. return op, params
  666. end
  667. -- Process a single statement.
  668. dostmt = function(stmt)
  669. -- Ignore empty statements.
  670. if match(stmt, "^%s*$") then return end
  671. -- Capture macro defs before substitution.
  672. if mac_capture then return mac_capture(stmt) end
  673. stmt = definesubst(stmt)
  674. -- Emit C code without parsing the line.
  675. if sub(stmt, 1, 1) == "|" then
  676. local tail = sub(stmt, 2)
  677. wflush()
  678. if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end
  679. return
  680. end
  681. -- Split into (pseudo-)opcode and params.
  682. local op, params = splitstmt(stmt)
  683. -- Get opcode handler (matching # of parameters or generic handler).
  684. local f = map_op[op.."_"..#params] or map_op[op.."_*"]
  685. if not f then
  686. if not g_arch then wfatal("first statement must be .arch") end
  687. -- Improve error report.
  688. for i=0,16 do
  689. if map_op[op.."_"..i] then
  690. werror("wrong number of parameters for `"..op.."'")
  691. end
  692. end
  693. werror("unknown statement `"..op.."'")
  694. end
  695. -- Call opcode handler or special handler for template strings.
  696. if type(f) == "string" then
  697. map_op[".template__"](params, f)
  698. else
  699. f(params)
  700. end
  701. end
  702. -- Process a single line.
  703. local function doline(line)
  704. if g_opt.flushline then wflush() end
  705. -- Assembler line?
  706. local indent, aline = match(line, "^(%s*)%|(.*)$")
  707. if not aline then
  708. -- No, plain C code line, need to flush first.
  709. wflush()
  710. wsync()
  711. wline(line, false)
  712. return
  713. end
  714. g_indent = indent -- Remember current line indentation.
  715. -- Emit C code (even from macros). Avoids echo and line parsing.
  716. if sub(aline, 1, 1) == "|" then
  717. if not mac_capture then
  718. wsync()
  719. elseif g_opt.comment then
  720. wsync()
  721. wcomment(aline)
  722. end
  723. dostmt(aline)
  724. return
  725. end
  726. -- Echo assembler line as a comment.
  727. if g_opt.comment then
  728. wsync()
  729. wcomment(aline)
  730. end
  731. -- Strip assembler comments.
  732. aline = gsub(aline, "//.*$", "")
  733. -- Split line into statements at semicolons.
  734. if match(aline, ";") then
  735. for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end
  736. else
  737. dostmt(aline)
  738. end
  739. end
  740. ------------------------------------------------------------------------------
  741. -- Write DynASM header.
  742. local function dasmhead(out)
  743. out:write(format([[
  744. /*
  745. ** This file has been pre-processed with DynASM.
  746. ** %s
  747. ** DynASM version %s, DynASM %s version %s
  748. ** DO NOT EDIT! The original file is in "%s".
  749. */
  750. #if DASM_VERSION != %d
  751. #error "Version mismatch between DynASM and included encoding engine"
  752. #endif
  753. ]], _info.url,
  754. _info.version, g_arch._info.arch, g_arch._info.version,
  755. g_fname, _info.vernum))
  756. end
  757. -- Read input file.
  758. readfile = function(fin)
  759. g_indent = ""
  760. g_lineno = 0
  761. g_synclineno = -1
  762. -- Process all lines.
  763. for line in fin:lines() do
  764. g_lineno = g_lineno + 1
  765. g_curline = line
  766. local ok, err = pcall(doline, line)
  767. if not ok and wprinterr(err, "\n") then return true end
  768. end
  769. wflush()
  770. -- Close input file.
  771. assert(fin == stdin or fin:close())
  772. end
  773. -- Write output file.
  774. local function writefile(outfile)
  775. local fout
  776. -- Open output file.
  777. if outfile == nil or outfile == "-" then
  778. fout = stdout
  779. else
  780. fout = assert(io.open(outfile, "w"))
  781. end
  782. -- Write all buffered lines
  783. wdumplines(fout, g_wbuffer)
  784. -- Close output file.
  785. assert(fout == stdout or fout:close())
  786. -- Optionally dump definitions.
  787. dumpdef(fout == stdout and stderr or stdout)
  788. end
  789. -- Translate an input file to an output file.
  790. local function translate(infile, outfile)
  791. g_wbuffer = {}
  792. g_indent = ""
  793. g_lineno = 0
  794. g_synclineno = -1
  795. -- Put header.
  796. wline(dasmhead)
  797. -- Read input file.
  798. local fin
  799. if infile == "-" then
  800. g_fname = "(stdin)"
  801. fin = stdin
  802. else
  803. g_fname = infile
  804. fin = assert(io.open(infile, "r"))
  805. end
  806. readfile(fin)
  807. -- Check for errors.
  808. if not g_arch then
  809. wprinterr(g_fname, ":*: error: missing .arch directive\n")
  810. end
  811. checkconds()
  812. checkmacros()
  813. checkcaptures()
  814. if g_errcount ~= 0 then
  815. stderr:write(g_fname, ":*: info: ", g_errcount, " error",
  816. (type(g_errcount) == "number" and g_errcount > 1) and "s" or "",
  817. " in input file -- no output file generated.\n")
  818. dumpdef(stderr)
  819. exit(1)
  820. end
  821. -- Write output file.
  822. writefile(outfile)
  823. end
  824. ------------------------------------------------------------------------------
  825. -- Print help text.
  826. function opt_map.help()
  827. stdout:write("DynASM -- ", _info.description, ".\n")
  828. stdout:write("DynASM ", _info.version, " ", _info.release, " ", _info.url, "\n")
  829. stdout:write[[
  830. Usage: dynasm [OPTION]... INFILE.dasc|-
  831. -h, --help Display this help text.
  832. -V, --version Display version and copyright information.
  833. -o, --outfile FILE Output file name (default is stdout).
  834. -I, --include DIR Add directory to the include search path.
  835. -c, --ccomment Use /* */ comments for assembler lines.
  836. -C, --cppcomment Use // comments for assembler lines (default).
  837. -N, --nocomment Suppress assembler lines in output.
  838. -M, --maccomment Show macro expansions as comments (default off).
  839. -L, --nolineno Suppress CPP line number information in output.
  840. -F, --flushline Flush action list for every line.
  841. -D NAME[=SUBST] Define a substitution.
  842. -U NAME Undefine a substitution.
  843. -P, --dumpdef Dump defines, macros, etc. Repeat for more output.
  844. -A, --dumparch ARCH Load architecture ARCH and dump description.
  845. ]]
  846. exit(0)
  847. end
  848. -- Print version information.
  849. function opt_map.version()
  850. stdout:write(format("%s version %s, released %s\n%s\n\n%s",
  851. _info.name, _info.version, _info.release, _info.url, _info.copyright))
  852. exit(0)
  853. end
  854. -- Misc. options.
  855. function opt_map.outfile(args) g_opt.outfile = optparam(args) end
  856. function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end
  857. function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end
  858. function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end
  859. function opt_map.nocomment() g_opt.comment = false end
  860. function opt_map.maccomment() g_opt.maccomment = true end
  861. function opt_map.nolineno() g_opt.cpp = false end
  862. function opt_map.flushline() g_opt.flushline = true end
  863. function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end
  864. ------------------------------------------------------------------------------
  865. -- Short aliases for long options.
  866. local opt_alias = {
  867. h = "help", ["?"] = "help", V = "version",
  868. o = "outfile", I = "include",
  869. c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment",
  870. L = "nolineno", F = "flushline",
  871. P = "dumpdef", A = "dumparch",
  872. }
  873. -- Parse single option.
  874. local function parseopt(opt, args)
  875. opt_current = #opt == 1 and "-"..opt or "--"..opt
  876. local f = opt_map[opt] or opt_map[opt_alias[opt]]
  877. if not f then
  878. opterror("unrecognized option `", opt_current, "'. Try `--help'.\n")
  879. end
  880. f(args)
  881. end
  882. -- Parse arguments.
  883. local function parseargs(args)
  884. -- Default options.
  885. g_opt.comment = "//|"
  886. g_opt.endcomment = ""
  887. g_opt.cpp = true
  888. g_opt.dumpdef = 0
  889. g_opt.include = { "" }
  890. -- Process all option arguments.
  891. args.argn = 1
  892. repeat
  893. local a = args[args.argn]
  894. if not a then break end
  895. local lopt, opt = match(a, "^%-(%-?)(.+)")
  896. if not opt then break end
  897. args.argn = args.argn + 1
  898. if lopt == "" then
  899. -- Loop through short options.
  900. for o in gmatch(opt, ".") do parseopt(o, args) end
  901. else
  902. -- Long option.
  903. parseopt(opt, args)
  904. end
  905. until false
  906. -- Check for proper number of arguments.
  907. local nargs = #args - args.argn + 1
  908. if nargs ~= 1 then
  909. if nargs == 0 then
  910. if g_opt.dumpdef > 0 then return dumpdef(stdout) end
  911. end
  912. opt_map.help()
  913. end
  914. -- Translate a single input file to a single output file
  915. -- TODO: Handle multiple files?
  916. translate(args[args.argn], g_opt.outfile)
  917. end
  918. ------------------------------------------------------------------------------
  919. -- Add the directory dynasm.lua resides in to the Lua module search path.
  920. local arg = arg
  921. if arg and arg[0] then
  922. local prefix = match(arg[0], "^(.*[/\\])")
  923. if prefix then package.path = prefix.."?.lua;"..package.path end
  924. end
  925. -- Start DynASM.
  926. parseargs{...}
  927. ------------------------------------------------------------------------------