.
This commit is contained in:
35
lib/code.c
35
lib/code.c
@@ -15,6 +15,10 @@
|
|||||||
#define N_CONST_ADDR 0x0c
|
#define N_CONST_ADDR 0x0c
|
||||||
#define CONST_START 0x10
|
#define CONST_START 0x10
|
||||||
|
|
||||||
|
#define OP_8BIT_OPERAND 0xa0
|
||||||
|
#define OP_16BIT_OPERAND 0xc0
|
||||||
|
#define OP_32BIT_OPERAND 0xe0
|
||||||
|
|
||||||
struct Code {
|
struct Code {
|
||||||
uint8_t const* bytecode;
|
uint8_t const* bytecode;
|
||||||
size_t bytecode_sz;
|
size_t bytecode_sz;
|
||||||
@@ -126,3 +130,34 @@ uint32_t code_n_functions(Code const* code)
|
|||||||
{
|
{
|
||||||
return code->fn_count;
|
return code->fn_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction code_next_instruction(Code const* code, uint32_t function_id, uint32_t pc)
|
||||||
|
{
|
||||||
|
uint32_t addr = code->fn_addr[function_id] + 4 + pc;
|
||||||
|
uint8_t opcode = code->bytecode[addr];
|
||||||
|
int32_t operand = 0;
|
||||||
|
uint8_t sz = 1;
|
||||||
|
|
||||||
|
if (opcode >= OP_8BIT_OPERAND && opcode < OP_16BIT_OPERAND) {
|
||||||
|
operand = code->bytecode[addr + 1];
|
||||||
|
sz = 2;
|
||||||
|
} else if (opcode >= OP_16BIT_OPERAND && opcode < OP_32BIT_OPERAND) {
|
||||||
|
opcode -= 0x20;
|
||||||
|
operand = (uint16_t) code->bytecode[addr + 1] |
|
||||||
|
(uint16_t) (code->bytecode[addr + 2] << 8);
|
||||||
|
sz = 3;
|
||||||
|
} else if (opcode >= OP_32BIT_OPERAND) {
|
||||||
|
opcode -= 0x40;
|
||||||
|
operand = (uint32_t) code->bytecode[addr + 1] |
|
||||||
|
(uint32_t) (code->bytecode[addr + 2] << 8) |
|
||||||
|
(uint32_t) (code->bytecode[addr + 3] << 16) |
|
||||||
|
(uint32_t) (code->bytecode[addr + 4] << 24);
|
||||||
|
sz = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Instruction) {
|
||||||
|
.operator = (TYC_INST) opcode,
|
||||||
|
.operand = operand,
|
||||||
|
.sz = sz,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -80,6 +80,81 @@ end
|
|||||||
-- --
|
-- --
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
local instructions = {
|
||||||
|
-- stack operations
|
||||||
|
pushi = 0xa0,
|
||||||
|
pushc = 0xa1,
|
||||||
|
pushf = 0xa2,
|
||||||
|
pushn = 0x00,
|
||||||
|
pushz = 0x01,
|
||||||
|
pusht = 0x02,
|
||||||
|
newa = 0x03,
|
||||||
|
newt = 0x04,
|
||||||
|
pop = 0x05,
|
||||||
|
dup = 0x06,
|
||||||
|
|
||||||
|
-- local variables
|
||||||
|
pushv = 0xa3,
|
||||||
|
set = 0xa4,
|
||||||
|
dupv = 0xa5,
|
||||||
|
setg = 0xa6,
|
||||||
|
getg = 0xa7,
|
||||||
|
|
||||||
|
-- function operations
|
||||||
|
call = 0xa7,
|
||||||
|
ret = 0x10,
|
||||||
|
reti = 0x11,
|
||||||
|
|
||||||
|
-- table and array operations
|
||||||
|
getkv = 0x16,
|
||||||
|
setkv = 0x17,
|
||||||
|
geti = 0xa8,
|
||||||
|
seti = 0xa9,
|
||||||
|
appnd = 0x18,
|
||||||
|
next = 0x19,
|
||||||
|
smt = 0x1a,
|
||||||
|
mt = 0x1b,
|
||||||
|
|
||||||
|
-- logical/arithmetic
|
||||||
|
sum = 0x20,
|
||||||
|
sub = 0x21,
|
||||||
|
mul = 0x22,
|
||||||
|
div = 0x23,
|
||||||
|
idiv = 0x24,
|
||||||
|
mod = 0x25,
|
||||||
|
eq = 0x26,
|
||||||
|
neq = 0x27,
|
||||||
|
lt = 0x28,
|
||||||
|
lte = 0x29,
|
||||||
|
gt = 0x2a,
|
||||||
|
gte = 0x2b,
|
||||||
|
['and'] = 0x2c,
|
||||||
|
['or'] = 0x2d,
|
||||||
|
xor = 0x2e,
|
||||||
|
pow = 0x2f,
|
||||||
|
shl = 0x30,
|
||||||
|
shr = 0x31,
|
||||||
|
|
||||||
|
-- other value operations
|
||||||
|
len = 0x40,
|
||||||
|
type = 0x41,
|
||||||
|
cast = 0xaa,
|
||||||
|
ver = 0x42,
|
||||||
|
|
||||||
|
-- external code
|
||||||
|
cmpl = 0x48,
|
||||||
|
asmbl = 0x49,
|
||||||
|
load = 0x4a,
|
||||||
|
|
||||||
|
-- control flow
|
||||||
|
bz = 0xca,
|
||||||
|
bnz = 0xcb,
|
||||||
|
jmp = 0xcc,
|
||||||
|
|
||||||
|
-- memory management
|
||||||
|
gc = 0x4b,
|
||||||
|
}
|
||||||
|
|
||||||
local MAGIC = 0xa7d6e9b1
|
local MAGIC = 0xa7d6e9b1
|
||||||
local VERSION = 1
|
local VERSION = 1
|
||||||
|
|
||||||
@@ -143,7 +218,27 @@ local function assemble(proto)
|
|||||||
local func = proto.functions[i]
|
local func = proto.functions[i]
|
||||||
local next_function_pos = #bin + 1
|
local next_function_pos = #bin + 1
|
||||||
push32(0) -- to be replaced with next function address
|
push32(0) -- to be replaced with next function address
|
||||||
-- TODO - add code
|
for _,inst in ipairs(func) do
|
||||||
|
local opcode, operand = instructions[inst[1]], inst[2]
|
||||||
|
if opcode == nil then error("Unknown instruction " .. inst[1]) end
|
||||||
|
if operand == nil then
|
||||||
|
table.insert(bin, opcode)
|
||||||
|
else
|
||||||
|
if opcode >= 0xc0 and opcode < 0xe0 then
|
||||||
|
table.insert(bin, opcode)
|
||||||
|
push16(operand)
|
||||||
|
elseif operand >= -128 and operand <= 127 then
|
||||||
|
table.insert(bin, opcode)
|
||||||
|
table.insert(bin, operand)
|
||||||
|
elseif operand >= -32768 and operand <= 32767 then
|
||||||
|
table.insert(bin, opcode + 0x20)
|
||||||
|
push16(operand)
|
||||||
|
else
|
||||||
|
table.insert(bin, opcode + 0x40)
|
||||||
|
push32(operand)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
replace32(next_function_pos, #bin)
|
replace32(next_function_pos, #bin)
|
||||||
end
|
end
|
||||||
return string.char(table.unpack(bin))
|
return string.char(table.unpack(bin))
|
||||||
|
|||||||
86
lib/priv.h
86
lib/priv.h
@@ -7,6 +7,85 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// INSTRUCTIONS
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
// STACK OPERATIONS
|
||||||
|
TO_PUSHI = 0XA0,
|
||||||
|
TO_PUSHC = 0XA1,
|
||||||
|
TO_PUSHF = 0XA2,
|
||||||
|
TO_PUSHN = 0X00,
|
||||||
|
TO_PUSHZ = 0X01,
|
||||||
|
TO_PUSHT = 0X02,
|
||||||
|
TO_NEWA = 0X03,
|
||||||
|
TO_NEWT = 0X04,
|
||||||
|
TO_POP = 0X05,
|
||||||
|
TO_DUP = 0X06,
|
||||||
|
|
||||||
|
// LOCAL VARIABLES
|
||||||
|
TO_PUSHV = 0XA3,
|
||||||
|
TO_SET = 0XA4,
|
||||||
|
TO_DUPV = 0XA5,
|
||||||
|
TO_SETG = 0XA6,
|
||||||
|
TO_GETG = 0XA7,
|
||||||
|
|
||||||
|
// FUNCTION OPERATIONS
|
||||||
|
TO_CALL = 0XA7,
|
||||||
|
TO_RET = 0X10,
|
||||||
|
TO_RETI = 0X11,
|
||||||
|
|
||||||
|
// TABLE AND ARRAY OPERATIONS
|
||||||
|
TO_GETKV = 0X16,
|
||||||
|
TO_SETKV = 0X17,
|
||||||
|
TO_GETI = 0XA8,
|
||||||
|
TO_SETI = 0XA9,
|
||||||
|
TO_APPND = 0X18,
|
||||||
|
TO_NEXT = 0X19,
|
||||||
|
TO_SMT = 0X1A,
|
||||||
|
TO_MT = 0X1B,
|
||||||
|
|
||||||
|
// LOGICAL/ARITHMETIC
|
||||||
|
TO_SUM = 0X20,
|
||||||
|
TO_SUB = 0X21,
|
||||||
|
TO_MUL = 0X22,
|
||||||
|
TO_DIV = 0X23,
|
||||||
|
TO_IDIV = 0X24,
|
||||||
|
TO_MOD = 0X25,
|
||||||
|
TO_EQ = 0X26,
|
||||||
|
TO_NEQ = 0X27,
|
||||||
|
TO_LT = 0X28,
|
||||||
|
TO_LTE = 0X29,
|
||||||
|
TO_GT = 0X2A,
|
||||||
|
TO_GTE = 0X2B,
|
||||||
|
TO_AND = 0X2C,
|
||||||
|
TO_OR = 0X2D,
|
||||||
|
TO_XOR = 0X2E,
|
||||||
|
TO_POW = 0X2F,
|
||||||
|
TO_SHL = 0X30,
|
||||||
|
TO_SHR = 0X31,
|
||||||
|
|
||||||
|
// OTHER VALUE OPERATIONS
|
||||||
|
TO_LEN = 0X40,
|
||||||
|
TO_TYPE = 0X41,
|
||||||
|
TO_CAST = 0XAA,
|
||||||
|
TO_VER = 0X42,
|
||||||
|
|
||||||
|
// EXTERNAL CODE
|
||||||
|
TO_CMPL = 0X48,
|
||||||
|
TO_ASMBL = 0X49,
|
||||||
|
TO_LOAD = 0X4A,
|
||||||
|
|
||||||
|
// CONTROL FLOW
|
||||||
|
TO_BZ = 0XCA,
|
||||||
|
TO_BNZ = 0XCB,
|
||||||
|
TO_JMP = 0XCC,
|
||||||
|
|
||||||
|
// MEMORY MANAGEMENT
|
||||||
|
TO_GC = 0X4B,
|
||||||
|
} TYC_INST;
|
||||||
|
|
||||||
//
|
//
|
||||||
// TYPE DECLARATION
|
// TYPE DECLARATION
|
||||||
//
|
//
|
||||||
@@ -33,6 +112,12 @@ typedef enum {
|
|||||||
TC_STRING, TC_REAL, TC_INVALID_TYPE
|
TC_STRING, TC_REAL, TC_INVALID_TYPE
|
||||||
} TYC_CONST_TYPE;
|
} TYC_CONST_TYPE;
|
||||||
|
|
||||||
|
typedef struct Instruction {
|
||||||
|
TYC_INST operator;
|
||||||
|
int32_t operand;
|
||||||
|
uint8_t sz;
|
||||||
|
} Instruction;
|
||||||
|
|
||||||
//
|
//
|
||||||
// UTILS
|
// UTILS
|
||||||
//
|
//
|
||||||
@@ -138,5 +223,6 @@ T_REAL code_const_real(Code const* code, size_t n);
|
|||||||
const char* code_const_string(Code const* code, size_t n);
|
const char* code_const_string(Code const* code, size_t n);
|
||||||
|
|
||||||
uint32_t code_n_functions(Code const* code);
|
uint32_t code_n_functions(Code const* code);
|
||||||
|
Instruction code_next_instruction(Code const* code, uint32_t function_id, uint32_t pc);
|
||||||
|
|
||||||
#endif //TYCHE_PRIV_H
|
#endif //TYCHE_PRIV_H
|
||||||
|
|||||||
26
test/tests.c
26
test/tests.c
@@ -223,7 +223,7 @@ int main()
|
|||||||
"\n"
|
"\n"
|
||||||
".func 0\n"
|
".func 0\n"
|
||||||
" pushi 2 ; this is a comment\n"
|
" pushi 2 ; this is a comment\n"
|
||||||
" pushi 3\n"
|
" pushi -3\n"
|
||||||
" sum\n"
|
" sum\n"
|
||||||
" ret\n"
|
" ret\n"
|
||||||
".func 1\n"
|
".func 1\n"
|
||||||
@@ -240,10 +240,32 @@ int main()
|
|||||||
assert(code_n_consts(code) == 2);
|
assert(code_n_consts(code) == 2);
|
||||||
assert(code_const_type(code, 0) == TC_REAL);
|
assert(code_const_type(code, 0) == TC_REAL);
|
||||||
assert(code_const_type(code, 1) == TC_STRING);
|
assert(code_const_type(code, 1) == TC_STRING);
|
||||||
assert(code_const_real(code, 0) >= 3.13 && code_const_real(code, 0) <= 3.15);
|
assert(code_const_real(code, 0) > 3.13f && code_const_real(code, 0) < 3.15f);
|
||||||
assert(strcmp(code_const_string(code, 1), "Hello world") == 0);
|
assert(strcmp(code_const_string(code, 1), "Hello world") == 0);
|
||||||
assert(code_n_functions(code) == 2);
|
assert(code_n_functions(code) == 2);
|
||||||
|
|
||||||
|
uint32_t addr = 0;
|
||||||
|
Instruction inst = code_next_instruction(code, 0, addr);
|
||||||
|
assert(inst.operator == TO_PUSHI);
|
||||||
|
assert(inst.operand == 2);
|
||||||
|
assert(inst.sz == 2);
|
||||||
|
addr += inst.sz;
|
||||||
|
|
||||||
|
inst = code_next_instruction(code, 0, addr);
|
||||||
|
assert(inst.operator == TO_PUSHI);
|
||||||
|
assert(inst.operand == -3);
|
||||||
|
addr += inst.sz;
|
||||||
|
|
||||||
|
inst = code_next_instruction(code, 0, addr);
|
||||||
|
assert(inst.operator == TO_SUM);
|
||||||
|
assert(inst.operand == 0);
|
||||||
|
addr += inst.sz;
|
||||||
|
|
||||||
|
inst = code_next_instruction(code, 1, 0);
|
||||||
|
assert(inst.operator == TO_PUSHI);
|
||||||
|
assert(inst.operand == 5000);
|
||||||
|
assert(inst.sz == 3);
|
||||||
|
|
||||||
code_destroy(code);
|
code_destroy(code);
|
||||||
free(bytecode);
|
free(bytecode);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user