--
-- Usage: require('thisfile');
--
-- Match operand to be r0..r3 (or R0..R3), and return the number;
function isReg(op)
local nr = op:match( '%s*[rR]([0-3])' );
if( nr ) then
return tonumber(nr) ;
else
Error("Operand must be R0..R3");
end
end
-- Match 2 operands to be r0..r3 (or R0..R3), and return
-- a value between 0x00 and 0x0f corresponding with { R0,R0 } .. {R3,R3}
function isReg2(op1, op2)
local n1, n2 = isReg(op1), isReg(op2);
return( n2*4 + n1 );
end
--
-- Match a possible operand for the ADDQ instruction, and return
-- the corresponding instruction-offset.
--
function isQuickOp(op1)
local opVal = { ['#2']=0, ['#1']=1, ['#-2']=2, ['#-1']=3 };
local result = opVal[op1];
if( result == nil ) then
Error("ADDQ value must be #2, #1, #-1 or #-2");
end
return result ;
end
--------------------------------------------------------------------------------
-- Chapter: Evaluate symbol:
--------------------------------------------------------------------------------
require( './lib' );
require( 'symtab' );
--
-- Take a value in range 0..2^32-1 and return a table of byte-values
-- in little-endian order
--
function As_table(val)
local r = {};
while( val > 0 ) do
local b = math.fmod(val,256);
table.insert(r,b);
val = math.floor(val / 256);
end
return r ;
end
--
-- Evaluate a constant expression in any of the formats below
-- Decimal, just digits
-- Hex, prefix 0x or 0X
-- Binary, prefix 0b or '%'
-- String, enclosed in single or double quotes.
-- Symbol, start with underscore or letter, followed by one or more letters/digits/underscores
--
-- Return a table with the bytes that compose the value described object.
-- [==[
function Eval(exp)
local capture, idx;
if( exp == '' ) then return nil end;
-- Decimal, just digits.
capture = exp:match("^(%d+)")
if( capture and not exp:match("%D+") ) then return( As_table(tonumber(capture)) ); end;
-- Hex, prefix 0x or 0X
capture = exp:match("^(0[xX]%x+)")
if( capture and not exp:match("%X+",3) ) then return( As_table(tonumber(capture)) ); end;
-- Binary, prefix 0b, 0B, or '%'
idx,capture = exp:match("^0[bB]()([01]+)")
if( not idx ) then idx,capture = exp:match("^%%()([01]+)") end;
if( not exp:match("[^01]+",idx) ) then
local result = 0;
for i = 1,capture:len() do
result = result * 2;
if( capture:sub(i,i) == '1' ) then result = result + 1; end;
end--for
return( As_table(result) );
end
-- String, enclosed in single or double-quotes.
capture = exp:match("'(.+)'") or exp:match('"(.+)"') ;
if( capture ) then
local result = {};
for i = 1,capture:len() do
table.insert( result, capture:byte(i) );
end--for
return result ;
end--if
capture = exp:match("^([_%a]+[_%w]*)");
if( capture ) then
local result = symtab_lookup(capture);
if( not result ) then
print("Undefined symbol");
return( nil );
end
return( As_table( result ) );
end
end--Eval()
function Eval_as_word(exp)
local t = Eval(exp);
if( #t == 1 ) then table.insert(t,0x00); end--if : append zero as most-significant byte.
return t ;
end
function Eval_as_byte(exp)
local t = Eval(exp);
if( #t > 1 ) then Error("Byte operand expected"); end--if
return t ;
end
--EOF--