mirror of
https://github.com/notwa/mm
synced 2024-11-05 05:39:02 -08:00
add basic fp arithmetic
This commit is contained in:
parent
301bfc99f8
commit
5822b592f1
1 changed files with 62 additions and 41 deletions
|
@ -215,11 +215,22 @@ local argtypes = {
|
||||||
|
|
||||||
movf= 'rd fs', -- starting with const, ending with 11 unset bits
|
movf= 'rd fs', -- starting with const, ending with 11 unset bits
|
||||||
bfo = 'base fs offset',
|
bfo = 'base fs offset',
|
||||||
}
|
|
||||||
|
|
||||||
|
tsdf= 'ft fs fd', -- starting with a const of 16, ending with a const
|
||||||
|
tsdd= 'ft fs fd', -- starting with a const of 17, ending with a const
|
||||||
|
}
|
||||||
|
|
||||||
local at = argtypes -- temporary shorthand
|
local at = argtypes -- temporary shorthand
|
||||||
local instruction_handlers = {
|
local instruction_handlers = {
|
||||||
|
ADD_D = {17, at.tsdd, 0},
|
||||||
|
ADD_S = {17, at.tsdf, 0},
|
||||||
|
DIV_D = {17, at.tsdd, 3},
|
||||||
|
DIV_S = {17, at.tsdf, 3},
|
||||||
|
MUL_D = {17, at.tsdd, 2},
|
||||||
|
MUL_S = {17, at.tsdf, 2},
|
||||||
|
SUB_D = {17, at.tsdd, 1},
|
||||||
|
SUB_S = {17, at.tsdf, 1},
|
||||||
|
|
||||||
CFC1 = {17, at.movf, 2},
|
CFC1 = {17, at.movf, 2},
|
||||||
CTC1 = {17, at.movf, 6},
|
CTC1 = {17, at.movf, 6},
|
||||||
DMFC1 = {17, at.movf, 1},
|
DMFC1 = {17, at.movf, 1},
|
||||||
|
@ -360,19 +371,6 @@ local instruction_handlers = {
|
||||||
}
|
}
|
||||||
at = nil
|
at = nil
|
||||||
|
|
||||||
local asm = ''
|
|
||||||
|
|
||||||
local f = io.open('Moonjump 2.asm', 'r')
|
|
||||||
if not f then
|
|
||||||
f = io.open('inject/Moonjump 2.asm', 'r')
|
|
||||||
if not f then
|
|
||||||
print('could not load assembly')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
asm = f:read('*a')
|
|
||||||
f:close()
|
|
||||||
|
|
||||||
Lexer = {}
|
Lexer = {}
|
||||||
function Lexer:setup(asm)
|
function Lexer:setup(asm)
|
||||||
self.asm = asm
|
self.asm = asm
|
||||||
|
@ -556,7 +554,7 @@ function Lexer:lex()
|
||||||
-- we can start matching numbers and dots too.
|
-- we can start matching numbers and dots too.
|
||||||
self:read_chars('[%w_.]')
|
self:read_chars('[%w_.]')
|
||||||
if self.chr == ':' then
|
if self.chr == ':' then
|
||||||
if self.buff:find('\\.') then
|
if self.buff:find('%.') then
|
||||||
self:error('labels cannot contain dots')
|
self:error('labels cannot contain dots')
|
||||||
end
|
end
|
||||||
self:nextc()
|
self:nextc()
|
||||||
|
@ -568,9 +566,10 @@ function Lexer:lex()
|
||||||
elseif all_registers[up] then
|
elseif all_registers[up] then
|
||||||
return 'REG', up
|
return 'REG', up
|
||||||
elseif all_instructions[up] then
|
elseif all_instructions[up] then
|
||||||
return 'INSTR', up
|
-- note: this allows instructions like "C_EQ.F" / "C.EQ_F"
|
||||||
|
return 'INSTR', up:gsub('%.', '_')
|
||||||
else
|
else
|
||||||
if self.buff:find('\\.') then
|
if self.buff:find('%.') then
|
||||||
self:error('labels cannot contain dots')
|
self:error('labels cannot contain dots')
|
||||||
end
|
end
|
||||||
return 'LABELSYM', self.buff
|
return 'LABELSYM', self.buff
|
||||||
|
@ -713,7 +712,7 @@ function Parser:instruction()
|
||||||
self:optional_comma()
|
self:optional_comma()
|
||||||
local offset = {'LOWER', self:const()}
|
local offset = {'LOWER', self:const()}
|
||||||
local base = self:deref()
|
local base = self:deref()
|
||||||
Dumper:add_instruction_5_5_16(h[1], base, rt, offset)
|
Dumper:add_instruction_5_5_16(h[1], base, ft, offset)
|
||||||
elseif h[2] == argtypes.sti then
|
elseif h[2] == argtypes.sti then
|
||||||
-- OP rt, rs, immediate
|
-- OP rt, rs, immediate
|
||||||
local rs = self:register()
|
local rs = self:register()
|
||||||
|
@ -818,7 +817,7 @@ function Parser:instruction()
|
||||||
elseif h[2] == argtypes.movf then
|
elseif h[2] == argtypes.movf then
|
||||||
local rt = self:register()
|
local rt = self:register()
|
||||||
self:optional_comma()
|
self:optional_comma()
|
||||||
local rd
|
local rd = nil
|
||||||
if name == 'MFC0' or name == 'MTC0' then
|
if name == 'MFC0' or name == 'MTC0' then
|
||||||
-- OP rt, rd
|
-- OP rt, rd
|
||||||
rd = self:register()
|
rd = self:register()
|
||||||
|
@ -828,6 +827,23 @@ function Parser:instruction()
|
||||||
end
|
end
|
||||||
local const = h[3] or self:error('internal error: expected const')
|
local const = h[3] or self:error('internal error: expected const')
|
||||||
Dumper:add_instruction_5_5_5_5_6(h[1], const, rt, rd, 0, 0)
|
Dumper:add_instruction_5_5_5_5_6(h[1], const, rt, rd, 0, 0)
|
||||||
|
elseif h[2] == argtypes.tsdf then
|
||||||
|
-- OP fd, fs, ft
|
||||||
|
local fd = self:register(fpu_registers)
|
||||||
|
self:optional_comma()
|
||||||
|
local fs = self:register(fpu_registers)
|
||||||
|
self:optional_comma()
|
||||||
|
local ft = self:register(fpu_registers)
|
||||||
|
local const = h[3] or self:error('internal error: expected const')
|
||||||
|
Dumper:add_instruction_5_5_5_5_6(h[1], 16, fd, fs, ft, const)
|
||||||
|
elseif h[2] == argtypes.tsdd then
|
||||||
|
local fd = self:register(fpu_registers)
|
||||||
|
self:optional_comma()
|
||||||
|
local fs = self:register(fpu_registers)
|
||||||
|
self:optional_comma()
|
||||||
|
local ft = self:register(fpu_registers)
|
||||||
|
local const = h[3] or self:error('internal error: expected const')
|
||||||
|
Dumper:add_instruction_5_5_5_5_6(h[1], 17, fd, fs, ft, const)
|
||||||
else
|
else
|
||||||
self:error('TODO')
|
self:error('TODO')
|
||||||
end
|
end
|
||||||
|
@ -874,48 +890,37 @@ function Dumper:error(msg)
|
||||||
error(string.format('Internal Error: %s', msg), 2)
|
error(string.format('Internal Error: %s', msg), 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Dumper:push(t)
|
||||||
|
--print(t.data)
|
||||||
|
table.insert(self.lines, t)
|
||||||
|
end
|
||||||
|
|
||||||
function Dumper:add_instruction_26(i, a)
|
function Dumper:add_instruction_26(i, a)
|
||||||
local t = {}
|
local t = {}
|
||||||
t.sizes = {26}
|
t.sizes = {26}
|
||||||
t.data = {i, a}
|
t.data = {i, a}
|
||||||
table.insert(self.lines, t)
|
self:push(t)
|
||||||
--print(('added {%s, %s}'):format(
|
|
||||||
-- tostring(i),
|
|
||||||
-- tostring(a)
|
|
||||||
--))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dumper:add_instruction_5_5_16(i, a, b, c)
|
function Dumper:add_instruction_5_5_16(i, a, b, c)
|
||||||
local t = {}
|
local t = {}
|
||||||
t.sizes = {5, 5, 16}
|
t.sizes = {5, 5, 16}
|
||||||
t.data = {i, a, b, c}
|
t.data = {i, a, b, c}
|
||||||
table.insert(self.lines, t)
|
self:push(t)
|
||||||
--print(('added {%s, %s, %s, %s}'):format(
|
|
||||||
-- tostring(i),
|
|
||||||
-- tostring(a), tostring(b), tostring(c)
|
|
||||||
--))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dumper:add_instruction_5_5_5_11(i, a, b, c, d)
|
function Dumper:add_instruction_5_5_5_11(i, a, b, c, d)
|
||||||
local t = {}
|
local t = {}
|
||||||
t.sizes = {5, 5, 5, 11}
|
t.sizes = {5, 5, 5, 11}
|
||||||
t.data = {i, a, b, c, d}
|
t.data = {i, a, b, c, d}
|
||||||
table.insert(self.lines, t)
|
self:push(t)
|
||||||
--print(('added {%s, %s, %s, %s, %s}'):format(
|
|
||||||
-- tostring(i),
|
|
||||||
-- tostring(a), tostring(b), tostring(c), tostring(d)
|
|
||||||
--))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dumper:add_instruction_5_5_5_5_6(i, a, b, c, d, e)
|
function Dumper:add_instruction_5_5_5_5_6(i, a, b, c, d, e)
|
||||||
local t = {}
|
local t = {}
|
||||||
t.sizes = {5, 5, 5, 5, 6}
|
t.sizes = {5, 5, 5, 5, 6}
|
||||||
t.data = {i, a, b, c, d, e}
|
t.data = {i, a, b, c, d, e}
|
||||||
table.insert(self.lines, t)
|
self:push(t)
|
||||||
--print(('added {%s, %s, %s, %s, %s, %s}'):format(
|
|
||||||
-- tostring(i),
|
|
||||||
-- tostring(a), tostring(b), tostring(c), tostring(d), tostring(e)
|
|
||||||
--))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Dumper:add_define(name, number)
|
function Dumper:add_define(name, number)
|
||||||
|
@ -938,7 +943,7 @@ function Dumper:desym(tok)
|
||||||
if type(tok[2]) == 'number' then
|
if type(tok[2]) == 'number' then
|
||||||
return tok[2]
|
return tok[2]
|
||||||
elseif all_registers[tok] then
|
elseif all_registers[tok] then
|
||||||
return registers[tok]
|
return registers[tok] or fpu_registers[tok]
|
||||||
elseif tok[1] == 'LABELSYM' then
|
elseif tok[1] == 'LABELSYM' then
|
||||||
print('(label)', tok[2])
|
print('(label)', tok[2])
|
||||||
return self.labels[tok[2]]*4
|
return self.labels[tok[2]]*4
|
||||||
|
@ -960,7 +965,7 @@ function Dumper:toval(tok)
|
||||||
elseif type(tok) == 'number' then
|
elseif type(tok) == 'number' then
|
||||||
return tok
|
return tok
|
||||||
elseif all_registers[tok] then
|
elseif all_registers[tok] then
|
||||||
return registers[tok]
|
return registers[tok] or fpu_registers[tok]
|
||||||
end
|
end
|
||||||
if type(tok) == 'table' then
|
if type(tok) == 'table' then
|
||||||
if #tok ~= 2 then
|
if #tok ~= 2 then
|
||||||
|
@ -996,6 +1001,9 @@ end
|
||||||
|
|
||||||
function Dumper:validate(n, bits)
|
function Dumper:validate(n, bits)
|
||||||
local max = 2^bits
|
local max = 2^bits
|
||||||
|
if n == nil then
|
||||||
|
self:error('value is nil')
|
||||||
|
end
|
||||||
if n > max or n < 0 then
|
if n > max or n < 0 then
|
||||||
print(("n %08X"):format(math.abs(n)))
|
print(("n %08X"):format(math.abs(n)))
|
||||||
self:error('value out of range')
|
self:error('value out of range')
|
||||||
|
@ -1080,6 +1088,19 @@ function Dumper:dump()
|
||||||
end
|
end
|
||||||
|
|
||||||
function main()
|
function main()
|
||||||
|
local asm = ''
|
||||||
|
|
||||||
|
local f = io.open('Moonjump 2.asm', 'r')
|
||||||
|
if not f then
|
||||||
|
f = io.open('inject/Moonjump 2.asm', 'r')
|
||||||
|
if not f then
|
||||||
|
error('could not load assembly', 1)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
asm = f:read('*a')
|
||||||
|
f:close()
|
||||||
|
|
||||||
Parser:parse(asm)
|
Parser:parse(asm)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue