mirror of
https://github.com/notwa/lips
synced 2024-11-14 18:19:03 -08:00
properly compute offsets
This commit is contained in:
parent
694f09c9e0
commit
6eac36584f
4 changed files with 57 additions and 44 deletions
|
@ -160,8 +160,9 @@ function Collector:instruction()
|
||||||
elseif self.tt == 'UNARY' then
|
elseif self.tt == 'UNARY' then
|
||||||
local peek = self.tokens[self.i + 1]
|
local peek = self.tokens[self.i + 1]
|
||||||
if peek.tt == 'VARSYM' then
|
if peek.tt == 'VARSYM' then
|
||||||
|
local negate = t.tok == -1
|
||||||
t = self:advance()
|
t = self:advance()
|
||||||
t = Token(t):set('negate')
|
t = Token(t):set('negate', negate)
|
||||||
insert(s, t)
|
insert(s, t)
|
||||||
self:advance()
|
self:advance()
|
||||||
elseif peek.tt == 'EOL' or peek.tt == 'SEP' then
|
elseif peek.tt == 'EOL' or peek.tt == 'SEP' then
|
||||||
|
|
|
@ -73,47 +73,6 @@ function Dumper:desym(t)
|
||||||
error('Internal Error: failed to desym')
|
error('Internal Error: failed to desym')
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dumper:toval(t)
|
|
||||||
if type(t) == 'number' then
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
assert(type(t) == 'table', 'Internal Error: invalid value')
|
|
||||||
|
|
||||||
local val = self:desym(t)
|
|
||||||
|
|
||||||
if t.index then
|
|
||||||
val = val % 0x80000000
|
|
||||||
val = floor(val/4)
|
|
||||||
end
|
|
||||||
if t.negate then
|
|
||||||
val = -val
|
|
||||||
end
|
|
||||||
|
|
||||||
if t.portion == 'upper' then
|
|
||||||
val = bitrange(val, 16, 31)
|
|
||||||
elseif t.portion == 'lower' then
|
|
||||||
val = bitrange(val, 0, 15)
|
|
||||||
elseif t.portion == 'upperoff' then
|
|
||||||
local upper = bitrange(val, 16, 31)
|
|
||||||
local lower = bitrange(val, 0, 15)
|
|
||||||
if lower >= 0x8000 then
|
|
||||||
-- accommodate for offsets being signed
|
|
||||||
upper = (upper + 1) % 0x10000
|
|
||||||
end
|
|
||||||
val = upper
|
|
||||||
end
|
|
||||||
|
|
||||||
if t.negate or t.signed then
|
|
||||||
if val >= 0x10000 or val < -0x8000 then
|
|
||||||
self:error('value out of range', val)
|
|
||||||
end
|
|
||||||
val = val % 0x10000
|
|
||||||
end
|
|
||||||
|
|
||||||
return val
|
|
||||||
end
|
|
||||||
|
|
||||||
function Dumper:validate(n, bits)
|
function Dumper:validate(n, bits)
|
||||||
local max = 2^bits
|
local max = 2^bits
|
||||||
if n == nil then
|
if n == nil then
|
||||||
|
@ -126,7 +85,16 @@ function Dumper:validate(n, bits)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dumper:valvar(t, bits)
|
function Dumper:valvar(t, bits)
|
||||||
local val = self:toval(t)
|
local val = t
|
||||||
|
local err
|
||||||
|
if type(val) ~= 'number' then
|
||||||
|
t.tok = self:desym(t)
|
||||||
|
t.tt = 'NUM'
|
||||||
|
val, err = t:compute()
|
||||||
|
if err then
|
||||||
|
self:error(err, val)
|
||||||
|
end
|
||||||
|
end
|
||||||
return self:validate(val, bits)
|
return self:validate(val, bits)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
|
local floor = math.floor
|
||||||
|
|
||||||
local path = string.gsub(..., "[^.]+$", "")
|
local path = string.gsub(..., "[^.]+$", "")
|
||||||
local Base = require(path.."Base")
|
local Base = require(path.."Base")
|
||||||
|
local util = require(path.."util")
|
||||||
|
|
||||||
|
local bitrange = util.bitrange
|
||||||
|
|
||||||
local Token = Base:extend()
|
local Token = Base:extend()
|
||||||
function Token:init(...)
|
function Token:init(...)
|
||||||
|
@ -63,4 +68,39 @@ function Token:set(key, value)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Token:compute()
|
||||||
|
assert(self.tt == 'NUM', 'Internal Error: cannot compute a non-number token')
|
||||||
|
local n = self.tok
|
||||||
|
if self.index then
|
||||||
|
n = n % 0x80000000
|
||||||
|
n = floor(n/4)
|
||||||
|
end
|
||||||
|
if self.negate then
|
||||||
|
n = -n
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.portion == 'upper' then
|
||||||
|
n = bitrange(n, 16, 31)
|
||||||
|
elseif self.portion == 'lower' then
|
||||||
|
n = bitrange(n, 0, 15)
|
||||||
|
elseif self.portion == 'upperoff' then
|
||||||
|
local upper = bitrange(n, 16, 31)
|
||||||
|
local lower = bitrange(n, 0, 15)
|
||||||
|
if lower >= 0x8000 then
|
||||||
|
-- accommodate for offsets being signed
|
||||||
|
upper = (upper + 1) % 0x10000
|
||||||
|
end
|
||||||
|
n = upper
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.negate or self.signed then
|
||||||
|
if n >= 0x10000 or n < -0x8000 then
|
||||||
|
return n, 'value out of range'
|
||||||
|
end
|
||||||
|
n = n % 0x10000
|
||||||
|
end
|
||||||
|
|
||||||
|
return n
|
||||||
|
end
|
||||||
|
|
||||||
return Token
|
return Token
|
||||||
|
|
|
@ -16,7 +16,11 @@ local function tob_override(self, name)
|
||||||
else -- NUM or LABELSYM
|
else -- NUM or LABELSYM
|
||||||
local o = self:pop('CONST')
|
local o = self:pop('CONST')
|
||||||
if self:peek('NUM') then
|
if self:peek('NUM') then
|
||||||
o:set('offset', self:pop('CONST').tok)
|
local temp, err = self:pop('CONST'):compute()
|
||||||
|
if err then
|
||||||
|
self:error(err, temp)
|
||||||
|
end
|
||||||
|
o:set('offset', temp)
|
||||||
end
|
end
|
||||||
offset = self:token(o)
|
offset = self:token(o)
|
||||||
if not o.portion then
|
if not o.portion then
|
||||||
|
|
Loading…
Reference in a new issue