diff --git a/Lua/lib/lips/Expander.lua b/Lua/lib/lips/Expander.lua index 08e885f..95d9efe 100644 --- a/Lua/lib/lips/Expander.lua +++ b/Lua/lib/lips/Expander.lua @@ -31,6 +31,8 @@ function Expander:pop(kind) ret = self.s[self.i] elseif kind == 'CPU' then ret = self:register(data.registers) + elseif kind == 'FPU' then + ret = self:register(data.fpu_registers) elseif kind == 'DEREF' then ret = self:deref() elseif kind == 'CONST' then diff --git a/Lua/lib/lips/Expression.lua b/Lua/lib/lips/Expression.lua index 022c765..5634c3a 100644 --- a/Lua/lib/lips/Expression.lua +++ b/Lua/lib/lips/Expression.lua @@ -144,22 +144,39 @@ function Expression:lex1(str, tokens) local here = " (#"..tostring(pos)..")" if consider(' +') then consume(#considered) - elseif consider('[0-9.]') then + elseif consider('[0-9.]') or consider('[%%$#]') then local num if consider('((0|[1-9][0-9]*)%.[0-9]*|%.[0-9]+)(e0|e[1-9][0-9]*)?') then num = tonumber(considered) elseif consider('(0|[1-9][0-9]*)e(0|[1-9][0-9]*)') then num = tonumber(considered) - elseif consider('[0-1]+b') then - num = tonumber(considered, 2) + elseif consider('%%[0-9]+') then + if considered:match('[2-9]') then + return "bad binary number: "..considered..here + end + num = tonumber(considered:sub(2), 2) + elseif consider('$[0-9A-Fa-f]+') then + num = tonumber(considered:sub(2), 16) elseif consider('0x[0-9A-Fa-f]+') then - num = tonumber(considered, 16) + num = tonumber(considered:sub(3), 16) + elseif consider('0o[0-9]+') then + if considered:match('[89]') then + return "bad octal number: "..considered..here + end + num = tonumber(considered:sub(3), 8) + elseif consider('0b[0-9]+') then + if considered:match('[2-9]') then + return "bad binary number: "..considered..here + end + num = tonumber(considered:sub(3), 2) elseif consider('0[0-9]+') then if considered:match('[89]') then return "bad octal number: "..considered..here end - num = tonumber(considered, 8) - elseif consider('[0-9]*') then + num = tonumber(considered:sub(2), 8) + elseif consider('#[0-9]+') then + num = tonumber(considered:sub(2)) + elseif consider('[0-9]+') then num = tonumber(considered) end if num == nil then @@ -176,7 +193,7 @@ function Expression:lex1(str, tokens) elseif consider_operator() then insert(tokens, {type='operator', value=considered}) consume(#considered) - elseif consider('%w+') then + elseif consider('[%w_]+') then local num = self.variables[considered] if num == nil then return 'undefined variable "'..considered..'"' diff --git a/Lua/lib/lips/Lexer.lua b/Lua/lib/lips/Lexer.lua index ff7318c..a8617a6 100644 --- a/Lua/lib/lips/Lexer.lua +++ b/Lua/lib/lips/Lexer.lua @@ -3,6 +3,7 @@ local char = string.char local find = string.find local format = string.format local insert = table.insert +local unpack = rawget(_G, 'unpack') or table.unpack local path = string.gsub(..., "[^.]+$", "") local data = require(path.."data") @@ -15,6 +16,7 @@ local simple_escapes = { ['"'] = 0x22, ['a'] = 0x07, ['b'] = 0x08, + ['e'] = 0x1B, ['f'] = 0x0C, ['n'] = 0x0A, ['r'] = 0x0D, @@ -263,6 +265,18 @@ function Lexer:lex_string(yield) local simple = simple_escapes[self.chr] if simple then insert(bytes, simple) + elseif self.chr == 'x' then + self:nextc() + local hex = self.chrchr + if not self.chr:find('[0-9a-fA-F]') then + self:error('invalid hex escape sequence: \\x'..hex) + end + self:nextc() + if not self.chr:find('[0-9a-fA-F]') then + self:error('invalid hex escape sequence: \\x'..hex) + end + local byte = tonumber(hex, 16) + insert(bytes, byte) else self:error('unknown escape sequence') end @@ -276,32 +290,27 @@ function Lexer:lex_string(yield) yield('STRING', bytes) end -function Lexer:lex_string_naive(yield) -- no escape sequences - if self.chr ~= '"' then - self:error('expected opening double quote') - end - self:nextc() - local buff = self:read_chars('[^"\n]') - if self.chr ~= '"' then - self:error('expected closing double quote') - end - self:nextc() - yield('STRING', buff) -end - function Lexer:lex_filename(_yield) self:read_spaces() - local fn - self:lex_string_naive(function(tt, tok) - fn = tok + local fn = '' + self:lex_string(function(tt, tok) + fn = char(unpack(tok)) end) _yield('STRING', fn, self.fn, self.line) - if self.chr ~= '\n' then + self:read_spaces() + if self.chr == ';' or self.chrchr == '//' then + self:skip_to_EOL() + end + if self.chr == '\n' then + _yield('EOL', '\n', self.fn, self.line) + self:nextc() + elseif self.ord == self.EOF then + _yield('EOL', '\n', self.fn, self.line) + self.was_EOL = true + else self:error('expected EOL after filename') end - _yield('EOL', '\n', self.fn, self.line) - self:nextc() return fn end diff --git a/Lua/lib/lips/TokenIter.lua b/Lua/lib/lips/TokenIter.lua index a63032f..70dca0e 100644 --- a/Lua/lib/lips/TokenIter.lua +++ b/Lua/lib/lips/TokenIter.lua @@ -184,7 +184,8 @@ function TokenIter:special() local args = {} while true do - local arg = self:advance() + self:advance() + local arg = self.t if not self.arg_types[arg.tt] then self:error('invalid argument type', arg.tt) else diff --git a/Lua/lib/lips/overrides.lua b/Lua/lib/lips/overrides.lua index b4b4f01..8470847 100644 --- a/Lua/lib/lips/overrides.lua +++ b/Lua/lib/lips/overrides.lua @@ -49,9 +49,10 @@ end local overrides = {} -- note: "self" is an instance of Expander +local fpu_tob = {} local function tob_override(self, name) -- handle all the addressing modes for lw/sw-like instructions - local dest = self:pop('CPU') + local dest = fpu_tob[name] and self:pop('FPU') or self:pop('CPU') local offset, base if self:peek('DEREF') then offset = 0 @@ -96,6 +97,9 @@ end for k, v in pairs(data.instructions) do if v[2] == 'tob' then overrides[k] = tob_override + elseif v[2] == 'Tob' then + fpu_tob[k] = true + overrides[k] = tob_override end end diff --git a/Lua/lib/lips/writers.lua b/Lua/lib/lips/writers.lua index 45bf6d8..63e9a52 100644 --- a/Lua/lib/lips/writers.lua +++ b/Lua/lib/lips/writers.lua @@ -82,4 +82,32 @@ function writers.make_tester() end end +function writers.make_gameshark() + local buff = {} + local max = -1 + return function(pos, b) + if pos then + pos = pos % 0x80000000 + buff[pos] = b + if pos > max then + max = pos + end + elseif max >= 0 then + for i=0, max, 2 do + local a = buff[i+0] + local b = buff[i+1] + a = a and ("%02X"):format(a) + b = b and ("%02X"):format(b) + if a and b then + print(('81%06X %s'):format(i, a..b)) + elseif a then + print(('80%06X 00%s'):format(i, a)) + elseif b then + print(('80%06X 00%s'):format(i + 1, b)) + end + end + end + end +end + return writers