From f851540b24919b0d15357b83e571823abb9a8fcf Mon Sep 17 00:00:00 2001 From: Connor Olding Date: Sun, 24 Apr 2016 03:55:12 -0700 Subject: [PATCH] various fixes, mostly for labels reimplement modulo by 0x80000000 for labels. allow numeric label values ("REL") to be "fixed" to bypass label calculation. add offsets after label calculation instead of before. properly check for EOL after all expected arguments have been exhausted. finally, add token properties to debug dumps. --- lips/Dumper.lua | 19 ++++++++++--------- lips/Muncher.lua | 7 ------- lips/Parser.lua | 24 +++++++++++++++++++----- lips/Preproc.lua | 6 ++---- lips/Reader.lua | 2 +- lips/Token.lua | 14 +++++++++----- lips/overrides.lua | 9 +++++---- 7 files changed, 46 insertions(+), 35 deletions(-) diff --git a/lips/Dumper.lua b/lips/Dumper.lua index bdae542..3563eaf 100644 --- a/lips/Dumper.lua +++ b/lips/Dumper.lua @@ -36,6 +36,8 @@ function Dumper:export_labels(t) end function Dumper:label_delta(from, to) + from = from % 0x80000000 + to = to % 0x80000000 local rel = floor(to/4) - 1 - floor(from/4) if rel > 0x8000 or rel <= -0x8000 then self:error('branch too far', rel) @@ -44,12 +46,10 @@ function Dumper:label_delta(from, to) end function Dumper:desym(t) - if t.tt == 'REL' then - return t.tok + -- note: don't run t:compute() here; let valvar handle that + if t.tt == 'REL' and not t.fixed then + return self:label_delta(self:pc(), t.tok) elseif type(t.tok) == 'number' then - if t.offset then - return t.tok + t.offset - end return t.tok elseif t.tt == 'REG' then assert(data.all_registers[t.tok], 'Internal Error: unknown register') @@ -59,9 +59,6 @@ function Dumper:desym(t) if label == nil then self:error('undefined label', t.tok) end - if t.offset then - label = label + t.offset - end if t.tt == 'LABELSYM' then return label end @@ -138,6 +135,7 @@ function Dumper:format_in(informat) -- see data.lua for a guide on what all these mean local args = {} --if #informat ~= #s then error('mismatch') end + self.i = 0 for i=1, #informat do self.i = i local c = informat:sub(i, i) @@ -168,7 +166,7 @@ function Dumper:format_in(informat) elseif c == 'I' and not args.index then args.index = self:const():set('index') elseif c == 'k' and not args.immediate then - args.immediate = self:const(nil, 'no label'):set('negate') + args.immediate = self:const(nil, 'no label'):set('signed'):set('negate') elseif c == 'K' and not args.immediate then args.immediate = self:const(nil, 'no label'):set('signed') elseif c == 'b' and not args.base then @@ -220,6 +218,9 @@ function Dumper:assemble(s) self.s = s if h[2] ~= nil then local args = self:format_in(h[2]) + if self.i ~= #s then + self:error('expected EOL; too many arguments') + end return self:format_out(h, args) else self:error('unimplemented instruction', name) diff --git a/lips/Muncher.lua b/lips/Muncher.lua index 355ee6c..a9794ed 100644 --- a/lips/Muncher.lua +++ b/lips/Muncher.lua @@ -122,13 +122,6 @@ function Muncher:const(relative, no_label) self:error('labels are not allowed here', self.tt) end local t = self:token(self.t) - if relative then - if self.tt == 'LABELSYM' then - t.tt = 'LABELREL' - else - t.tt = 'REL' - end - end self:advance() return t end diff --git a/lips/Parser.lua b/lips/Parser.lua index 78c66f6..66d2766 100644 --- a/lips/Parser.lua +++ b/lips/Parser.lua @@ -41,14 +41,25 @@ function Parser:tokenize(asm) end function Parser:debug_dump() + local boring = { + tt = true, + tok = true, + fn = true, + line = true, + } for i, s in ipairs(self.statements) do local values = '' - for j, v in ipairs(s) do - local tok = v.tok + for j, t in ipairs(s) do + local tok = t.tok if type(tok) == 'number' then tok = ("$%X"):format(tok) end - values = values..'\t'..v.tt..'('..tostring(tok)..')' + values = values..'\t'..t.tt..'('..tostring(tok)..')' + for k, v in pairs(t) do + if not boring[k] then + values = values..'['..k..'='..tostring(v)..']' + end + end end values = values:sub(2) print(s.line, s.type, values) @@ -62,14 +73,17 @@ function Parser:parse(asm) local preproc = Preproc(self.options) self.statements = preproc:process(self.statements) - self.statements = preproc:expand(self.statements) if self.options.debug_pre then self:debug_dump() end + self.statements = preproc:expand(self.statements) + + if self.options.debug_post then self:debug_dump() end + local dumper = Dumper(self.writer, self.options) self.statements = dumper:load(self.statements) - if self.options.debug_dump then self:debug_dump() end + if self.options.debug_asm then self:debug_dump() end if self.options.labels then dumper:export_labels(self.options.labels) diff --git a/lips/Preproc.lua b/lips/Preproc.lua index 60ba783..06778c7 100644 --- a/lips/Preproc.lua +++ b/lips/Preproc.lua @@ -198,11 +198,9 @@ function Preproc:pop(kind) ret = self:deref() elseif kind == 'CONST' then ret = self:const() - elseif kind == 'REL' then - ret = self:const('REL') elseif kind == 'END' then - if self.s[self.i + 1] ~= nil then - self:error('too many arguments') + if self.s[self.i] ~= nil then + self:error('expected EOL; too many arguments') end return -- don't increment self.i past end of arguments else diff --git a/lips/Reader.lua b/lips/Reader.lua index f405edb..ca1468a 100644 --- a/lips/Reader.lua +++ b/lips/Reader.lua @@ -68,7 +68,7 @@ function Reader:const(relative, no_label) self:expect{'NUM', 'LABELREL'} end local new = Token(t) - if relative then + if relative then -- you probably shouldn't use this in Preproc if t.tt == 'LABELSYM' then new.tt = 'LABELREL' elseif t.tt == 'NUM' then diff --git a/lips/Token.lua b/lips/Token.lua index 482b9f8..1911034 100644 --- a/lips/Token.lua +++ b/lips/Token.lua @@ -68,11 +68,15 @@ function Token:set(key, value) return self end -function Token:compute() - assert(self.tt == 'NUM', 'Internal Error: cannot compute a non-number token') - local n = self.tok +function Token:compute(n) + local n = n or self.tok + assert(n or self.tt == 'NUM', 'Internal Error: cannot compute a non-number token') + + if self.offset then + n = n + self.offset + end + if self.index then - -- TODO: should this still be here now that we have .base? n = n % 0x80000000 n = floor(n/4) end @@ -94,7 +98,7 @@ function Token:compute() n = upper end - if self.negate or self.signed then + if self.signed then if n >= 0x10000 or n < -0x8000 then return n, 'value out of range' end diff --git a/lips/overrides.lua b/lips/overrides.lua index 1850183..137bd47 100644 --- a/lips/overrides.lua +++ b/lips/overrides.lua @@ -201,7 +201,7 @@ function overrides:BEQI(name) local branch = branch_basics[name] local reg = self:pop('CPU') local im = self:pop('CONST') - local offset = self:pop('REL'):set('signed') + local offset = self:pop('CONST') if reg == 'AT' then self:error('register cannot be AT in this pseudo-instruction') @@ -219,7 +219,7 @@ function overrides:BLTI(name) local branch = branch_basics[name] local reg = self:pop('CPU') local im = self:pop('CONST') - local offset = self:pop('REL'):set('signed') + local offset = self:pop('CONST') if reg == 'AT' then self:error('register cannot be AT in this pseudo-instruction') @@ -241,7 +241,7 @@ function overrides:BLEI(name) local branch = branch_basics[name] local reg = self:pop('CPU') local im = self:pop('CONST') - local offset = self:pop('REL'):set('signed') + local offset = self:pop('CONST') if reg == 'AT' then self:error('register cannot be AT in this pseudo-instruction') @@ -253,7 +253,8 @@ function overrides:BLEI(name) if name == 'BLEI' or name =='BLEIL' then beq_offset = offset else - beq_offset = 2 -- branch to delay slot of the next branch + -- branch to delay slot of the next branch + beq_offset = self:token('NUM', 2):set('fixed') end self:push_new('BEQ', reg, 'AT', beq_offset)