mirror of
https://github.com/notwa/lips
synced 2024-11-14 09:19:02 -08:00
allow 1 register in place of 2, pseudo stuff…
allow CL to take more than one argument. implement pseudo-instructions NEGU, SGT, and SGTU.
This commit is contained in:
parent
f3765a0300
commit
6b0d27ba6d
3 changed files with 120 additions and 22 deletions
|
@ -211,7 +211,7 @@ function Preproc:pop(kind)
|
|||
end
|
||||
|
||||
function Preproc:expand(statements)
|
||||
-- third pass: expand pseudo-instructions
|
||||
-- third pass: expand pseudo-instructions and register arguments
|
||||
self.statements = {}
|
||||
for i=1, #statements do
|
||||
local s = statements[i]
|
||||
|
@ -227,6 +227,23 @@ function Preproc:expand(statements)
|
|||
error('Internal Error: unknown instruction')
|
||||
end
|
||||
|
||||
if data.one_register_variants[name] then
|
||||
self.i = 1
|
||||
local a = self:register(data.all_registers)
|
||||
local b = s[2]
|
||||
if b == nil or b.tt ~= 'REG' then
|
||||
insert(s, 2, self:token(a))
|
||||
end
|
||||
elseif data.two_register_variants[name] then
|
||||
self.i = 1
|
||||
local a = self:register(data.all_registers)
|
||||
local b = self:register(data.all_registers)
|
||||
local c = s[3]
|
||||
if c == nil or c.tt ~= 'REG' then
|
||||
insert(s, 2, self:token(a))
|
||||
end
|
||||
end
|
||||
|
||||
if overrides[name] then
|
||||
self.i = 1
|
||||
overrides[name](self, name)
|
||||
|
|
107
lips/data.lua
107
lips/data.lua
|
@ -86,7 +86,13 @@ data.fmt_double = 17
|
|||
data.fmt_word = 20
|
||||
data.fmt_long = 21
|
||||
|
||||
-- set up dummy values for pseudo-instructions later
|
||||
local __ = {}
|
||||
-- instructions with the first two arguments as registers, but not the third
|
||||
local o1 = {}
|
||||
-- instructions with all three arguments as registers
|
||||
local o2 = {}
|
||||
|
||||
data.instructions = {
|
||||
--[[
|
||||
data guide:
|
||||
|
@ -248,6 +254,7 @@ data.instructions = {
|
|||
|
||||
-- coprocessor-related instructions
|
||||
|
||||
-- TODO: these can take a code value
|
||||
TEQ = {0, 'st', 'st00C', 52},
|
||||
TGE = {0, 'st', 'st00C', 48},
|
||||
TGEU = {0, 'st', 'st00C', 49},
|
||||
|
@ -280,6 +287,7 @@ data.instructions = {
|
|||
CACHE = {47, 'iob', 'bio'},
|
||||
|
||||
-- misuses 'F' to write the initial bit
|
||||
-- RFE = {16, '', 'F000C', 16, 16},
|
||||
ERET = {16, '', 'F000C', 24, 16},
|
||||
TLBP = {16, '', 'F000C', 8, 16},
|
||||
TLBR = {16, '', 'F000C', 1, 16},
|
||||
|
@ -381,8 +389,11 @@ data.instructions = {
|
|||
CL = { 0, 'd', '00d0C', 37}, -- OR RD, R0, R0
|
||||
MOV = { 0, 'ds', 's0d0C', 37}, -- OR RD, RS, R0
|
||||
NEG = { 0, 'dt', '0td0C', 34}, -- SUB RD, R0, RT
|
||||
NEGU = { 0, 'dt', '0td0C', 35}, -- SUBU RD, R0, RT
|
||||
NOP = { 0, '', '0'}, -- SLL R0, R0, 0
|
||||
NOT = { 0, 'ds', 's0d0C', 39}, -- NOR RD, RS, R0
|
||||
SGT = { 0, 'dst', 'tsd0C', 42}, -- SLT RD, RT, RS
|
||||
SGTU = { 0, 'dst', 'tsd0C', 43}, -- SLTU RD, RT, RS
|
||||
SUBI = { 8, 'tsk', 'sti'}, -- ADDI RT, RS, -immediate
|
||||
SUBIU = { 9, 'tsk', 'sti'}, -- ADDIU RT, RS, -immediate
|
||||
|
||||
|
@ -394,41 +405,95 @@ data.instructions = {
|
|||
PUSH = __,
|
||||
POP = __,
|
||||
JPOP = __,
|
||||
-- CL = __, overridden to take varargs
|
||||
|
||||
ABS = __, -- BGEZ NOP SUBU?
|
||||
MUL = __, -- MULT MFLO
|
||||
--DIV = __, -- 3 arguments
|
||||
REM = __, -- 3 arguments
|
||||
ABS = o1, -- SRA XOR SUBU
|
||||
MUL = o2, -- MULT MFLO
|
||||
-- DIV = o2, -- 3 arguments
|
||||
REM = o2, -- 3 arguments
|
||||
|
||||
NAND = __, -- AND, NOT
|
||||
NANDI = __, -- ANDI, NOT
|
||||
NORI = __, -- ORI, NOT
|
||||
ROL = __, -- SLL, SRL, OR
|
||||
ROR = __, -- SRL, SLL, OR
|
||||
NAND = o2, -- AND, NOT
|
||||
NANDI = o1, -- ANDI, NOT
|
||||
NORI = o1, -- ORI, NOT
|
||||
ROL = o1, -- SLL, SRL, OR
|
||||
ROR = o1, -- SRL, SLL, OR
|
||||
|
||||
SEQ = __, SEQI = __, SEQIU = __, SEQU = __,
|
||||
SGE = __, SGEI = __, SGEIU = __, SGEU = __,
|
||||
SGT = __, SGTI = __, SGTIU = __, SGTU = __,
|
||||
SLE = __, SLEI = __, SLEIU = __, SLEU = __,
|
||||
SNE = __, SNEI = __, SNEIU = __, SNEU = __,
|
||||
SEQ = o2,
|
||||
SGE = o2, SGEU = o2,
|
||||
SLE = o2, SLEU = o2,
|
||||
SNE = o2,
|
||||
|
||||
BGE = __,
|
||||
BLE = __,
|
||||
BLT = __,
|
||||
BGT = __,
|
||||
SEQI = o1, SEQIU = o1,
|
||||
SGEI = o1, SGEIU = o1,
|
||||
SGTI = o1, SGTIU = o1,
|
||||
SLEI = o1, SLEIU = o1,
|
||||
SNEI = o1, SNEIU = o1,
|
||||
|
||||
BGE = o1, BGEU = o1,
|
||||
BLE = o1, BLEU = o1,
|
||||
BLT = o1, BLTU = o1,
|
||||
BGT = o1, BGTU = o1,
|
||||
|
||||
BEQI = __, BEQIL = __,
|
||||
BNEI = __, BNEIL = __,
|
||||
BGEI = __, BGEIL = __,
|
||||
BGTI = __, BGTIL = __,
|
||||
BLEI = __, BLEIL = __,
|
||||
BLTI = __, BLTIL = __,
|
||||
BGTI = __, BGTIL = __,
|
||||
BNEI = __, BNEIL = __,
|
||||
|
||||
BGEL = o1, BGEUL = o1,
|
||||
BGTL = o1, BGTUL = o1,
|
||||
BLEL = o1, BLEUL = o1,
|
||||
BLTL = o1, BLTUL = o1,
|
||||
|
||||
}
|
||||
|
||||
local register_types = {
|
||||
d = 0,
|
||||
s = 0,
|
||||
t = 0,
|
||||
D = 1,
|
||||
S = 1,
|
||||
T = 1,
|
||||
X = 2,
|
||||
Y = 2,
|
||||
Z = 2,
|
||||
}
|
||||
|
||||
data.one_register_variants = {}
|
||||
data.two_register_variants = {}
|
||||
|
||||
data.all_instructions = {}
|
||||
local i = 1
|
||||
for k, v in pairs(data.instructions) do
|
||||
data.all_instructions[k:gsub('_', '.')] = i
|
||||
local name = k:gsub('_', '.')
|
||||
|
||||
-- if the first two args of an instructions are the same register type,
|
||||
-- allow it to be used with just one argument to cover both.
|
||||
-- likewise, if all three arguments are registers of the same type,
|
||||
-- allow just two to be used.
|
||||
local fmt = v[2]
|
||||
if fmt then
|
||||
local a = fmt:sub(1, 1)
|
||||
local b = fmt:sub(2, 2)
|
||||
local c = fmt:sub(3, 3)
|
||||
a = register_types[a]
|
||||
b = register_types[b]
|
||||
c = register_types[c]
|
||||
if a ~= nil and b ~= nil and a == b then
|
||||
if c == nil then
|
||||
data.one_register_variants[name] = true
|
||||
elseif c == a then
|
||||
data.two_register_variants[name] = true
|
||||
end
|
||||
end
|
||||
elseif v == o1 then
|
||||
data.one_register_variants[name] = true
|
||||
elseif v == o2 then
|
||||
data.two_register_variants[name] = true
|
||||
end
|
||||
|
||||
data.all_instructions[name] = i
|
||||
i = i + 1
|
||||
end
|
||||
revtable(data.all_instructions)
|
||||
|
|
|
@ -177,6 +177,22 @@ function overrides:ROL(name)
|
|||
end
|
||||
overrides.ROR = overrides.ROL
|
||||
|
||||
function overrides:ABS(name)
|
||||
local dest = self:pop('CPU')
|
||||
local src = self:pop('CPU')
|
||||
self:push_new('SRA', 'AT', src, 31)
|
||||
self:push_new('XOR', dest, src, 'AT')
|
||||
self:push_new('SUBU', dest, dest, 'AT')
|
||||
end
|
||||
|
||||
function overrides:CL(name)
|
||||
self:expect{'REG'} -- assert there's at least one argument
|
||||
for i=1, #self.s do
|
||||
local reg = self:pop('CPU')
|
||||
self:push_new('CL', reg)
|
||||
end
|
||||
end
|
||||
|
||||
function overrides:JR(name)
|
||||
local src = self:peek() and self:pop('CPU') or 'RA'
|
||||
self:push_new('JR', src)
|
||||
|
|
Loading…
Reference in a new issue