From 311b1e362fc5aa92d7a3d0dc19a782f226e2b64f Mon Sep 17 00:00:00 2001 From: Connor Olding Date: Sun, 10 Apr 2016 02:59:39 -0700 Subject: [PATCH] implement offsets for constants --- README.md | 2 -- lips/Dumper.lua | 16 ++++++++++------ lips/Lexer.lua | 4 ++++ lips/Parser.lua | 4 ++++ lips/Preproc.lua | 17 +++++++++++++++-- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index fc222ae..c30ea6b 100644 --- a/README.md +++ b/README.md @@ -91,8 +91,6 @@ my_label: lw s1, (s0) lw s2, 256(s0) lw s3, label(s0) - -; this is currently unsupported however sw s2, label+4 sw s3, label+4(s0) diff --git a/lips/Dumper.lua b/lips/Dumper.lua index d908b95..9273103 100644 --- a/lips/Dumper.lua +++ b/lips/Dumper.lua @@ -138,21 +138,25 @@ function Dumper:desym(t) end return rel % 0x10000 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') return data.registers[t.tok] or data.fpu_registers[t.tok] or data.sys_registers[t.tok] - elseif t.tt == 'LABELSYM' then + elseif t.tt == 'LABELSYM' or t.tt == 'LABELREL' then local label = self.labels[t.tok] if label == nil then self:error('undefined label') end - return label - elseif t.tt == 'LABELREL' then - local label = self.labels[t.tok] - if label == nil then - self:error('undefined label') + if t.offset then + label = label + t.offset end + if t.tt == 'LABELSYM' then + return label + end + label = label % 0x80000000 local pos = self.pos % 0x80000000 local rel = floor(label/4) - 1 - floor(pos/4) diff --git a/lips/Lexer.lua b/lips/Lexer.lua index d97883f..ff4184a 100644 --- a/lips/Lexer.lua +++ b/lips/Lexer.lua @@ -379,6 +379,10 @@ function Lexer:lex(_yield) local n = self:read_number() if n then yield('NUM', sign*n) + elseif #buff == 1 then + -- this could be a RELLABELSYM + -- we'll have to let the preproc figure it out + yield('UNARY', sign) else yield('RELLABELSYM', sign*#buff) end diff --git a/lips/Parser.lua b/lips/Parser.lua index eaf1f92..3559b49 100644 --- a/lips/Parser.lua +++ b/lips/Parser.lua @@ -179,6 +179,7 @@ function Parser:instruction() elseif overrides[name] then overrides[name](self, name) elseif h[2] == 'tob' then -- TODO: or h[2] == 'Tob' then + -- handle all the addressing modes for lw/sw-like instructions local lui = data.instructions['LUI'] local addu = data.instructions['ADDU'] local args = {} @@ -191,6 +192,9 @@ function Parser:instruction() local lui_args = {} local addu_args = {} local o = self:const() + if self.tt == 'NUM' then + o:set('offset', self:const().tok) + end args.offset = self:token(o) if not o.portion then args.offset:set('portion', 'lower') diff --git a/lips/Preproc.lua b/lips/Preproc.lua index 07f0e72..568426a 100644 --- a/lips/Preproc.lua +++ b/lips/Preproc.lua @@ -17,11 +17,24 @@ function Preproc:process(tokens) local plus_labels = {} -- constructed forwards local minus_labels = {} -- constructed backwards - -- first pass: resolve defines, collect relative labels + -- first pass: resolve unary ops, defines, and collect relative labels local new_tokens = {} self.i = 0 while self.i < #self.tokens do local t = self:advance() + local sign = 1 + if t.tt == 'UNARY' then + local peek = self.tokens[self.i + 1] + if peek.tt == 'UNARY' then + self:error('unary operators cannot be chained') + elseif peek.tt == 'EOL' or peek.tt == 'SEP' then + t.tt = 'RELLABEL' + elseif peek.tt == 'DEFSYM' then + sign = t.tok + else + self:error('expected a symbolic constant after unary operator') + end + end if t.tt == nil then error('Internal Error: missing token') elseif t.tt == 'DEF' then @@ -36,7 +49,7 @@ function Preproc:process(tokens) if tok == nil then self:error('undefined define') -- uhhh nice wording end - insert(new_tokens, self:token(tt, tok)) + insert(new_tokens, self:token(tt, tok * sign)) elseif t.tt == 'RELLABEL' then if t.tok == '+' then insert(plus_labels, #new_tokens + 1)