mirror of
https://github.com/notwa/mm
synced 2025-02-05 05:23:22 -08:00
use relative labels
This commit is contained in:
parent
9a808fdb80
commit
e4ff34e0c0
2 changed files with 77 additions and 26 deletions
|
@ -805,13 +805,20 @@ function Lexer:lex(_yield)
|
||||||
self:error('unmatched closing bracket')
|
self:error('unmatched closing bracket')
|
||||||
elseif self.chr == ')' then
|
elseif self.chr == ')' then
|
||||||
self:error('unmatched closing parenthesis')
|
self:error('unmatched closing parenthesis')
|
||||||
elseif self.chr == '-' then
|
elseif self.chr == '+' or self.chr == '-' then
|
||||||
self:nextc()
|
local sign_chr = self.chr
|
||||||
local n = self:read_number()
|
local sign = sign_chr == '+' and 1 or -1
|
||||||
if n then
|
local buff = self:read_chars('%'..self.chr)
|
||||||
yield('NUM', -n)
|
if #buff == 1 and self.chr == ':' then
|
||||||
|
self:nextc()
|
||||||
|
yield('RELLABEL', sign_chr)
|
||||||
else
|
else
|
||||||
self:error('expected number after minus sign')
|
local n = self:read_number()
|
||||||
|
if n then
|
||||||
|
yield('NUM', sign*n)
|
||||||
|
else
|
||||||
|
yield('RELLABELSYM', sign*#buff)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local n = self:read_number()
|
local n = self:read_number()
|
||||||
|
@ -1323,12 +1330,14 @@ function Parser:tokenize(asm)
|
||||||
return t.tt, t.tok, t.fn, t.line
|
return t.tt, t.tok, t.fn, t.line
|
||||||
end
|
end
|
||||||
|
|
||||||
-- first pass: collect tokens and constants.
|
-- first pass: collect tokens, constants, and relative labels.
|
||||||
-- can't do more because instruction size can depend on a constant's size
|
-- can't do more because instruction size can depend on a constant's size
|
||||||
-- and labels depend on instruction size.
|
-- and labels depend on instruction size.
|
||||||
-- note however, instruction size does not depend on label size.
|
-- note however, instruction size does not depend on label size.
|
||||||
-- this would cause a recursive problem to solve,
|
-- this would cause a recursive problem to solve,
|
||||||
-- which is too much for our simple assembler.
|
-- which is too much for our simple assembler.
|
||||||
|
local plus_labels = {} -- constructed forwards
|
||||||
|
local minus_labels = {} -- constructed backwards
|
||||||
while true do
|
while true do
|
||||||
local tt, tok, fn, line = lex()
|
local tt, tok, fn, line = lex()
|
||||||
self.fn = fn
|
self.fn = fn
|
||||||
|
@ -1339,6 +1348,14 @@ function Parser:tokenize(asm)
|
||||||
self:error('expected number for define')
|
self:error('expected number for define')
|
||||||
end
|
end
|
||||||
self.defines[tok] = tok2
|
self.defines[tok] = tok2
|
||||||
|
elseif tt == 'RELLABEL' then
|
||||||
|
if tok == '+' then
|
||||||
|
insert(plus_labels, line)
|
||||||
|
elseif tok == '-' then
|
||||||
|
insert(minus_labels, 1, line)
|
||||||
|
else
|
||||||
|
error('Internal Error: unexpected token for relative label', 1)
|
||||||
|
end
|
||||||
elseif tt == 'EOL' then
|
elseif tt == 'EOL' then
|
||||||
-- noop
|
-- noop
|
||||||
elseif tt == 'EOF' then
|
elseif tt == 'EOF' then
|
||||||
|
@ -1350,7 +1367,7 @@ function Parser:tokenize(asm)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- resolve defines
|
-- resolve defines and relative labels
|
||||||
for i, t in ipairs(self.tokens) do
|
for i, t in ipairs(self.tokens) do
|
||||||
self.fn = t.fn
|
self.fn = t.fn
|
||||||
self.line = t.line
|
self.line = t.line
|
||||||
|
@ -1360,6 +1377,40 @@ function Parser:tokenize(asm)
|
||||||
if t.tok == nil then
|
if t.tok == nil then
|
||||||
self:error('undefined define') -- uhhh nice wording
|
self:error('undefined define') -- uhhh nice wording
|
||||||
end
|
end
|
||||||
|
elseif t.tt == 'RELLABEL' then
|
||||||
|
t.tt = 'LABEL'
|
||||||
|
-- exploits the fact that user labels can't begin with a number
|
||||||
|
-- FIXME: can produce bad results with includes, etc
|
||||||
|
t.tok = tostring(t.line)
|
||||||
|
elseif t.tt == 'RELLABELSYM' then
|
||||||
|
t.tt = 'LABELSYM'
|
||||||
|
local rel = t.tok
|
||||||
|
local seen = 0
|
||||||
|
-- TODO: don't iterate over *every* label, just the ones nearby
|
||||||
|
if rel > 0 then
|
||||||
|
for i, line in ipairs(plus_labels) do
|
||||||
|
if line > t.line then
|
||||||
|
seen = seen + 1
|
||||||
|
if seen == rel then
|
||||||
|
t.tok = tostring(line)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for i, line in ipairs(minus_labels) do
|
||||||
|
if line < t.line then
|
||||||
|
seen = seen - 1
|
||||||
|
if seen == rel then
|
||||||
|
t.tok = tostring(line)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if seen ~= rel then
|
||||||
|
self:error('could not find appropriate relative label')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,47 +20,47 @@
|
||||||
lhu t9, @rupees_offset(t0)
|
lhu t9, @rupees_offset(t0)
|
||||||
lw s1, hold_delay
|
lw s1, hold_delay
|
||||||
andi t4, t2, @button_any
|
andi t4, t2, @button_any
|
||||||
bne t4, r0, no_reset
|
bne t4, r0, +
|
||||||
addi s1, s1, 1
|
addi s1, s1, 1
|
||||||
li s1, 0
|
li s1, 0
|
||||||
no_reset:
|
+:
|
||||||
subi t4, s1, 1
|
subi t4, s1, 1
|
||||||
beq t4, r0, first_time
|
beq t4, r0, +
|
||||||
nop
|
nop
|
||||||
subi t4, s1, @hold_delay_amount
|
subi t4, s1, @hold_delay_amount
|
||||||
bltz t4, return
|
bltz t4, return
|
||||||
nop
|
nop
|
||||||
first_time:
|
+:
|
||||||
andi t3, t2, @button_D_up
|
andi t3, t2, @button_D_up
|
||||||
beq t3, r0, no_D_up
|
beq t3, r0, +
|
||||||
nop
|
nop
|
||||||
addi t9, t9, 1
|
addi t9, t9, 1
|
||||||
no_D_up:
|
+:
|
||||||
andi t3, t2, @button_D_down
|
andi t3, t2, @button_D_down
|
||||||
beq t3, r0, no_D_down
|
beq t3, r0, +
|
||||||
nop
|
nop
|
||||||
subi t9, t9, 1
|
subi t9, t9, 1
|
||||||
no_D_down:
|
+:
|
||||||
andi t3, t2, @button_D_right
|
andi t3, t2, @button_D_right
|
||||||
beq t3, r0, no_D_right
|
beq t3, r0, +
|
||||||
nop
|
nop
|
||||||
addi t9, t9, 10
|
addi t9, t9, 10
|
||||||
no_D_right:
|
+:
|
||||||
andi t3, t2, @button_D_left
|
andi t3, t2, @button_D_left
|
||||||
beq t3, r0, no_D_left
|
beq t3, r0, +
|
||||||
nop
|
nop
|
||||||
subi t9, t9, 10
|
subi t9, t9, 10
|
||||||
no_D_left:
|
+:
|
||||||
subi t4, t9, 1
|
subi t4, t9, 1
|
||||||
bgez t4, no_min
|
bgez t4, +
|
||||||
nop
|
nop
|
||||||
li t9, @max_actor_no
|
li t9, @max_actor_no
|
||||||
no_min:
|
+:
|
||||||
subi t4, t9, @max_actor_no
|
subi t4, t9, @max_actor_no
|
||||||
blez t4, no_max
|
blez t4, +
|
||||||
nop
|
nop
|
||||||
li t9, 1
|
li t9, 1
|
||||||
no_max:
|
+:
|
||||||
sh t9, @rupees_offset(t0)
|
sh t9, @rupees_offset(t0)
|
||||||
andi t3, t2, @button_L
|
andi t3, t2, @button_L
|
||||||
beq t3, r0, return
|
beq t3, r0, return
|
||||||
|
@ -162,12 +162,12 @@ is_object_loaded:
|
||||||
add t0, t8, t9 // current item
|
add t0, t8, t9 // current item
|
||||||
lb t1, 8(t0) // remaining items
|
lb t1, 8(t0) // remaining items
|
||||||
li v0, 1
|
li v0, 1
|
||||||
is_object_loaded_loop:
|
-:
|
||||||
lh t2, 12(t0) // item's object number
|
lh t2, 12(t0) // item's object number
|
||||||
beq a0, t2, is_object_loaded_return
|
beq a0, t2, is_object_loaded_return
|
||||||
subi t1, t1, 1 // TODO: double check there's no off-by-one error
|
subi t1, t1, 1 // TODO: double check there's no off-by-one error
|
||||||
addi t0, t0, 68
|
addi t0, t0, 68
|
||||||
bne t1, r0, is_object_loaded_loop
|
bne t1, r0, -
|
||||||
nop
|
nop
|
||||||
cl v0
|
cl v0
|
||||||
is_object_loaded_return:
|
is_object_loaded_return:
|
||||||
|
|
Loading…
Add table
Reference in a new issue