From bd0c5f4b347860a55977c60071d2b4f930c95650 Mon Sep 17 00:00:00 2001 From: Connor Olding Date: Tue, 24 Nov 2015 13:23:22 -0800 Subject: [PATCH] implement align and skip directives --- README.md | 29 +++++++++++++++++++---------- lips.lua | 42 +++++++++++++++++++++++------------------- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 0bf3be7..8dffbbb 100644 --- a/README.md +++ b/README.md @@ -108,25 +108,34 @@ TagLo, TagHi, ErrorEPC, RESERVED ## Directives -* BYTE: writes a list of 8-bit numbers until end-of-line. +* `.byte {numbers...}` +writes a series of 8-bit numbers until end-of-line. be wary of potential alignment issues. -* HALFWORD: writes a list of 16-bit numbers until end-of-line. +* `.halfword {numbers...}` +writes a series of 16-bit numbers until end-of-line. be wary of potential alignment issues. -* WORD: writes a list of 32-bit numbers until end-of-line. +* `.word {numbers...}` +writes a series of 32-bit numbers until end-of-line. -* SKIP: takes one or two arguments. +* `.align [n] [fill]` +aligns the next datum to a `n*2` boundary using `fill` for spacing. +if `n` is not given, 2 is implied. +if `fill` is not given, 0 is implied. -* ORG: change the current address for writing to; seeking. -for now, this is untested and likely to cause performance issues. +* `.skip {n} [fill]` +skips the next `n` bytes using `fill` for spacing. +if `fill` is not given, no bytes are overwritten, +and only the position is changed. + +* `.org {address}` +set the current address for writing to; seek. +until lips is a little more optimized, +be cautious of seeking to large addresses. ### Unimplemented -* ALIGN: takes one or two arguments. -unlike some other assemblers, -ALIGN only affects the first immediately following datum. - * FLOAT: writes a list of 32-bit floating point numbers until end-of-line. this may not get implemented due to a lack of aliasing in vanilla Lua, and thus accuracy issues. diff --git a/lips.lua b/lips.lua index 52b3d2a..9a19e3b 100644 --- a/lips.lua +++ b/lips.lua @@ -1,8 +1,5 @@ -- lips.lua --- instructions: https://github.com/mikeryan/n64dev/tree/master/docs/n64ops --- lexer and parser are somewhat based on http://chunkbake.luaforge.net/ - local assembler = { _DESCRIPTION = 'Assembles MIPS assembly files for the R4300i CPU.', _URL = 'https://github.com/notwa/lips/', @@ -132,6 +129,7 @@ local instructions = { o: offset b: base i: immediate (infmt 'i', 'j', 'J', and 'k' all write to here) + I: index C: constant (given in argument immediately after) F: format constant (given in argument after constant) --]] @@ -751,14 +749,18 @@ function Parser:directive() if name == 'ORG' then self.dumper:add_directive(name, self:number()) elseif name == 'ALIGN' or name == 'SKIP' then - local size = self:number() - if self:is_EOL() then - self.dumper:add_directive(name, size) + if self:is_EOL() and name == 'ALIGN' then + self.dumper:add_directive(name, 0) else - self:optional_comma() - self.dumper:add_directive(name, size, self:number()) + local size = self:number() + if self:is_EOL() then + self.dumper:add_directive(name, size) + else + self:optional_comma() + self.dumper:add_directive(name, size, self:number()) + end + self:expect_EOL() end - self:expect_EOL() elseif name == 'BYTE' or name == 'HALFWORD' or name == 'WORD' then self.dumper:add_directive(name, self:number()) while not self:is_EOL() do @@ -1128,12 +1130,18 @@ function Dumper:add_directive(name, a, b) self.pos = a % 0x80000000 self:advance(0) elseif name == 'ALIGN' then - t.kind = 'align' - t.align = a - t.fill = b + t.kind = 'ahead' + local align = a*2 + if align == 0 then + align = 4 + elseif align < 0 then + self:error('negative alignment') + end + local temp = self.pos + align - 1 + t.skip = temp - (temp % align) - self.pos + t.fill = t.fill or 0 table.insert(self.commands, t) - --self.size = size.size + ??? - self:error('align directive is unimplemented') + self:advance(t.skip) elseif name == 'SKIP' then t.kind = 'ahead' t.skip = a @@ -1273,14 +1281,10 @@ function Dumper:dump() self:write(t) elseif t.kind == 'goto' then self.pos = t.addr - elseif t.kind == 'align' then - -- TODO: align next instruction to 2*n boundary - -- note: traditionally, alignment keeps until .align 0 is given - self:error('align directive is unimplemented') elseif t.kind == 'ahead' then if t.fill then for i=1, t.skip do - self:write{self.fill} + self:write{t.fill} end else self.pos = self.pos + t.skip