mirror of
https://github.com/notwa/mm
synced 2025-02-05 13:23:23 -08:00
various
fix jump and branch destinations. note: branching is no longer compatible with CajeASM. make LUI dumb: only use 'UPPER' with LI/LA. note: this is very incompatible with CajeASM. add LUUI pseudo-instruction to use 'UPPER' instead of 'LOWER'. fix SUBI/SUBIU parsing. fix LI for values under 0x10000. pass filename through main(). tell Lexer our filename. don't print filename in Dumper since it's irrelevant.
This commit is contained in:
parent
4a45b3c913
commit
f673308437
1 changed files with 22 additions and 18 deletions
|
@ -126,7 +126,7 @@ local instruction_handlers = {
|
||||||
SWL = {42, 'tob', 'bto'},
|
SWL = {42, 'tob', 'bto'},
|
||||||
SWR = {46, 'tob', 'bto'},
|
SWR = {46, 'tob', 'bto'},
|
||||||
|
|
||||||
LUI = {15, 'tJ', '0ti'},
|
LUI = {15, 'tj', '0ti'},
|
||||||
|
|
||||||
MFHI = {0, 'd', '00d0C', 16},
|
MFHI = {0, 'd', '00d0C', 16},
|
||||||
MFLO = {0, 'd', '00d0C', 18},
|
MFLO = {0, 'd', '00d0C', 18},
|
||||||
|
@ -336,6 +336,10 @@ local instruction_handlers = {
|
||||||
SUBI = {8, 'tsk', 'sti'},
|
SUBI = {8, 'tsk', 'sti'},
|
||||||
SUBIU = {9, 'tsk', 'sti'},
|
SUBIU = {9, 'tsk', 'sti'},
|
||||||
|
|
||||||
|
-- LUI only loads the lower 16 bits of its constant.
|
||||||
|
-- if you need the upper 16, use this instead.
|
||||||
|
LUUI = {15, 'tJ', '0ti'},
|
||||||
|
|
||||||
-- ...that expand to multiple instructions
|
-- ...that expand to multiple instructions
|
||||||
LI = 'LI', -- only one instruction for values < 0x10000
|
LI = 'LI', -- only one instruction for values < 0x10000
|
||||||
LA = 'LA',
|
LA = 'LA',
|
||||||
|
@ -767,7 +771,7 @@ function Parser:format_in(informat)
|
||||||
else
|
else
|
||||||
error('Internal Error: invalid input formatting string', 1)
|
error('Internal Error: invalid input formatting string', 1)
|
||||||
end
|
end
|
||||||
if c2:find('[dstDSToiIjJr]') then
|
if c2:find('[dstDSToiIjJkr]') then
|
||||||
self:optional_comma()
|
self:optional_comma()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -826,7 +830,9 @@ function Parser:instruction()
|
||||||
if h == nil then
|
if h == nil then
|
||||||
self:error('undefined instruction')
|
self:error('undefined instruction')
|
||||||
elseif h == 'LI' or h == 'LA' then
|
elseif h == 'LI' or h == 'LA' then
|
||||||
|
-- FIXME: this fails horribly with labels
|
||||||
local lui = instruction_handlers['LUI']
|
local lui = instruction_handlers['LUI']
|
||||||
|
local addi = instruction_handlers['ADDI']
|
||||||
local ori = instruction_handlers['ORI']
|
local ori = instruction_handlers['ORI']
|
||||||
local args = {}
|
local args = {}
|
||||||
args.rt = self:register()
|
args.rt = self:register()
|
||||||
|
@ -836,11 +842,13 @@ function Parser:instruction()
|
||||||
args.rs = args.rt
|
args.rs = args.rt
|
||||||
args.immediate = {'UPPER', im}
|
args.immediate = {'UPPER', im}
|
||||||
self:format_out(lui[3], lui[1], args, lui[4], lui[5])
|
self:format_out(lui[3], lui[1], args, lui[4], lui[5])
|
||||||
|
args.immediate = {'LOWER', im}
|
||||||
|
self:format_out(ori[3], ori[1], args, ori[4], ori[5])
|
||||||
else
|
else
|
||||||
args.rs = 'R0'
|
args.rs = 'R0'
|
||||||
|
args.immediate = {'LOWER', im}
|
||||||
|
self:format_out(addi[3], addi[1], args, addi[4], addi[5])
|
||||||
end
|
end
|
||||||
args.immediate = {'LOWER', im}
|
|
||||||
self:format_out(ori[3], ori[1], args, ori[4], ori[5])
|
|
||||||
elseif h[2] ~= nil then
|
elseif h[2] ~= nil then
|
||||||
args = self:format_in(h[2])
|
args = self:format_in(h[2])
|
||||||
self:format_out(h[3], h[1], args, h[4], h[5])
|
self:format_out(h[3], h[1], args, h[4], h[5])
|
||||||
|
@ -852,7 +860,7 @@ end
|
||||||
|
|
||||||
function Parser:parse(asm)
|
function Parser:parse(asm)
|
||||||
self.asm = asm
|
self.asm = asm
|
||||||
self.lexer = Lexer(asm)
|
self.lexer = Lexer(asm, self.fn)
|
||||||
|
|
||||||
self:advance()
|
self:advance()
|
||||||
while self.tt ~= 'EOF' do
|
while self.tt ~= 'EOF' do
|
||||||
|
@ -880,7 +888,7 @@ end
|
||||||
|
|
||||||
function Dumper:error(msg)
|
function Dumper:error(msg)
|
||||||
-- TOOD: we should pass line numbers down to add_instruction.
|
-- TOOD: we should pass line numbers down to add_instruction.
|
||||||
error(string.format('%s:%d: Dumper Error: %s', self.fn, self.pos, msg), 2)
|
error(string.format('%s:%d: Dumper Error: %s', '(code)', self.pos, msg), 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dumper:advance(by)
|
function Dumper:advance(by)
|
||||||
|
@ -985,7 +993,7 @@ function Dumper:desym(tok)
|
||||||
return self.labels[tok[2]]
|
return self.labels[tok[2]]
|
||||||
elseif tok[1] == 'LABELREL' then
|
elseif tok[1] == 'LABELREL' then
|
||||||
local rel = math.floor(self.labels[tok[2]]/4)
|
local rel = math.floor(self.labels[tok[2]]/4)
|
||||||
rel = rel - 2 - math.floor(self.pos/4)
|
rel = rel - 1 - math.floor(self.pos/4)
|
||||||
if rel > 0x8000 or rel <= -0x8000 then
|
if rel > 0x8000 or rel <= -0x8000 then
|
||||||
self:error('branch too far')
|
self:error('branch too far')
|
||||||
end
|
end
|
||||||
|
@ -1015,8 +1023,7 @@ function Dumper:toval(tok)
|
||||||
end
|
end
|
||||||
if tok[1] == 'UPPER' then
|
if tok[1] == 'UPPER' then
|
||||||
local val = self:desym(tok[2])
|
local val = self:desym(tok[2])
|
||||||
val = math.floor(val/0x10000)
|
return math.floor(val/0x10000)
|
||||||
return val
|
|
||||||
elseif tok[1] == 'LOWER' then
|
elseif tok[1] == 'LOWER' then
|
||||||
local val = self:desym(tok[2])
|
local val = self:desym(tok[2])
|
||||||
return val % 0x10000
|
return val % 0x10000
|
||||||
|
@ -1024,13 +1031,8 @@ function Dumper:toval(tok)
|
||||||
local val = -self:desym(tok[2])
|
local val = -self:desym(tok[2])
|
||||||
return val % 0x10000
|
return val % 0x10000
|
||||||
elseif tok[1] == 'INDEX' then
|
elseif tok[1] == 'INDEX' then
|
||||||
local val = self:desym(tok[2])
|
local val = self:desym(tok[2]) % 0x80000000
|
||||||
if type(tok[2]) == 'table' and tok[2][1] == 'LABELSYM' then
|
val = math.floor(val/4)
|
||||||
-- don't multiply by 4 twice
|
|
||||||
else
|
|
||||||
val = val*4
|
|
||||||
end
|
|
||||||
--print('(index)', val)
|
|
||||||
return val
|
return val
|
||||||
else
|
else
|
||||||
return self:desym(tok)
|
return self:desym(tok)
|
||||||
|
@ -1149,11 +1151,13 @@ local function assemble(fn_or_asm, writer)
|
||||||
writer = writer or io.write
|
writer = writer or io.write
|
||||||
|
|
||||||
function main()
|
function main()
|
||||||
|
local fn = nil
|
||||||
local asm = ''
|
local asm = ''
|
||||||
if fn_or_asm:find('[\r\n]') then
|
if fn_or_asm:find('[\r\n]') then
|
||||||
asm = fn_or_asm
|
asm = fn_or_asm
|
||||||
else
|
else
|
||||||
local f = io.open(fn_or_asm, 'r')
|
fn = fn_or_asm
|
||||||
|
local f = io.open(fn, 'r')
|
||||||
if not f then
|
if not f then
|
||||||
error('could not read assembly file', 1)
|
error('could not read assembly file', 1)
|
||||||
end
|
end
|
||||||
|
@ -1161,7 +1165,7 @@ local function assemble(fn_or_asm, writer)
|
||||||
f:close()
|
f:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
local parser = Parser(writer)
|
local parser = Parser(writer, fn)
|
||||||
return parser:parse(asm)
|
return parser:parse(asm)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue