mirror of
https://github.com/notwa/mm
synced 2024-11-05 06:39:02 -08:00
95 lines
2.3 KiB
Lua
95 lines
2.3 KiB
Lua
local floor = math.floor
|
|
local open = io.open
|
|
|
|
local function readfile(fn, binary)
|
|
local mode = binary and 'rb' or 'r'
|
|
local f = open(fn, mode)
|
|
if not f then
|
|
local kind = binary and 'binary' or 'assembly'
|
|
error('could not open '..kind..' file for reading: '..tostring(fn), 2)
|
|
end
|
|
local data = f:read('*a')
|
|
f:close()
|
|
return data
|
|
end
|
|
|
|
local function bitrange(x, lower, upper)
|
|
return floor(x / 2^lower) % 2^(upper - lower + 1)
|
|
end
|
|
|
|
local function parent(t)
|
|
local mt = getmetatable(t)
|
|
if mt == nil then
|
|
return nil
|
|
end
|
|
return mt.__index
|
|
end
|
|
|
|
local function signs(s)
|
|
local start, end_ = s:find('[+-]+')
|
|
if start ~= 1 then
|
|
return 0
|
|
end
|
|
if s:sub(1, 1) == '+' then
|
|
return end_
|
|
elseif s:sub(1, 1) == '-' then
|
|
return -end_
|
|
end
|
|
end
|
|
|
|
-- http://stackoverflow.com/a/9279009
|
|
local loadcode
|
|
if setfenv and loadstring then -- 5.1, JIT
|
|
loadcode = function(code, environment)
|
|
local f = assert(loadstring(code))
|
|
setfenv(f, environment)
|
|
return f
|
|
end
|
|
else -- 5.2, 5.3
|
|
loadcode = function(code, environment)
|
|
return assert(load(code, nil, 't', environment))
|
|
end
|
|
end
|
|
|
|
local data_sizes = {
|
|
BYTE = 1,
|
|
HALFWORD = 2,
|
|
WORD = 4,
|
|
}
|
|
|
|
local function measure_data(s)
|
|
assert(s and s.type == '!DATA', 'Internal Error: expected !DATA statement')
|
|
local n = 0
|
|
for i, t in ipairs(s) do
|
|
if t.tt == 'LABELSYM' then
|
|
n = n + 4
|
|
elseif t.tt == 'NUM' then
|
|
if t.size == nil then
|
|
error('Internal Error: unspecified data size in NUM')
|
|
end
|
|
local size = data_sizes[t.size]
|
|
if size == nil then
|
|
error('Internal Error: unknown data size in NUM, got '..tostring(t.size))
|
|
end
|
|
n = n + size
|
|
elseif t.tt == 'WORDS' then
|
|
n = n + #t.tok * 4
|
|
elseif t.tt == 'HALFWORDS' then
|
|
n = n + #t.tok * 2
|
|
elseif t.tt == 'BYTES' then
|
|
n = n + #t.tok * 1
|
|
else
|
|
error('Internal Error: unknown data type in !DATA, got '..tostring(t.tt))
|
|
end
|
|
end
|
|
return n
|
|
end
|
|
|
|
return {
|
|
readfile = readfile,
|
|
bitrange = bitrange,
|
|
parent = parent,
|
|
signs = signs,
|
|
loadcode = loadcode,
|
|
measure_data = measure_data,
|
|
}
|