add data, remove labels and make jumps absolute
This commit is contained in:
parent
d14c655f6a
commit
83c568c8dd
310
creole.c
310
creole.c
|
@ -30,7 +30,6 @@ enum creole_arg_type {
|
||||||
TYPE_IMM,
|
TYPE_IMM,
|
||||||
TYPE_REG,
|
TYPE_REG,
|
||||||
TYPE_VAL,
|
TYPE_VAL,
|
||||||
TYPE_LAB,
|
|
||||||
CREOLE_ARG_TYPE_LEN
|
CREOLE_ARG_TYPE_LEN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ enum creole_arg_type {
|
||||||
*/
|
*/
|
||||||
#define defop(s, n, a1, a2, a3) {n, {a1, a2, a3}}
|
#define defop(s, n, a1, a2, a3) {n, {a1, a2, a3}}
|
||||||
static const struct {
|
static const struct {
|
||||||
unsigned arglen;
|
int arglen;
|
||||||
enum creole_arg_type argtype[CREOLE_MAX_ARG];
|
enum creole_arg_type argtype[CREOLE_MAX_ARG];
|
||||||
} opcode_info[CREOLE_OPCODE_LEN] = {
|
} opcode_info[CREOLE_OPCODE_LEN] = {
|
||||||
defop(NOOP, 0, TYPE_NONE, TYPE_NONE, TYPE_NONE),
|
defop(NOOP, 0, TYPE_NONE, TYPE_NONE, TYPE_NONE),
|
||||||
|
@ -50,11 +49,11 @@ static const struct {
|
||||||
defop(MUL, 3, TYPE_REG, TYPE_VAL, TYPE_VAL),
|
defop(MUL, 3, TYPE_REG, TYPE_VAL, TYPE_VAL),
|
||||||
defop(DIV, 3, TYPE_REG, TYPE_VAL, TYPE_VAL),
|
defop(DIV, 3, TYPE_REG, TYPE_VAL, TYPE_VAL),
|
||||||
defop(SYS, 1, TYPE_VAL, TYPE_NONE, TYPE_NONE),
|
defop(SYS, 1, TYPE_VAL, TYPE_NONE, TYPE_NONE),
|
||||||
defop(CLB, 1, TYPE_LAB, TYPE_NONE, TYPE_NONE),
|
defop(JL, 3, TYPE_IMM, TYPE_VAL, TYPE_VAL),
|
||||||
defop(JL, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL),
|
defop(JLE, 3, TYPE_IMM, TYPE_VAL, TYPE_VAL),
|
||||||
defop(JLE, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL),
|
defop(JE, 3, TYPE_IMM, TYPE_VAL, TYPE_VAL),
|
||||||
defop(JE, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL),
|
defop(JNE, 3, TYPE_IMM, TYPE_VAL, TYPE_VAL),
|
||||||
defop(JNE, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL)
|
defop(DB, 1, TYPE_IMM, TYPE_NONE, TYPE_NONE)
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
@ -330,12 +329,49 @@ int creole_encode(creole_word i, unsigned encode_to, unsigned high_bits,
|
||||||
* one single byte of all zeros.
|
* one single byte of all zeros.
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
enum creole_compiler_ret
|
struct ins {
|
||||||
creole_parse_line(struct creole_ins *ins, struct creole_reader *r)
|
unsigned char *start;
|
||||||
|
unsigned char *datapt;
|
||||||
|
enum creole_opcode opcode;
|
||||||
|
creole_word w[CREOLE_MAX_ARG];
|
||||||
|
creole_word w_flags[CREOLE_MAX_ARG];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int valid_register(struct creole_env *env, int reg)
|
||||||
|
{
|
||||||
|
return reg < env->reglen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int typecheck_arg(struct creole_env *env, int val,
|
||||||
|
enum creole_word_flag fl,
|
||||||
|
enum creole_arg_type typ)
|
||||||
|
{
|
||||||
|
switch (typ) {
|
||||||
|
case TYPE_IMM: return fl == CREOLE_IMMEDIATE;
|
||||||
|
case TYPE_REG: return fl == CREOLE_REGISTER
|
||||||
|
&& valid_register(env, val);
|
||||||
|
case TYPE_VAL: return fl == CREOLE_IMMEDIATE
|
||||||
|
|| fl == CREOLE_REGISTER;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum creole_word_flag arg_get_type(unsigned high_bits)
|
||||||
|
{
|
||||||
|
if (high_bits & 1) {
|
||||||
|
return CREOLE_REGISTER;
|
||||||
|
} else {
|
||||||
|
return CREOLE_IMMEDIATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum creole_compiler_ret
|
||||||
|
parse_line(struct creole_env *env, struct ins *ins, struct creole_reader *r)
|
||||||
{
|
{
|
||||||
struct word w = {0};
|
struct word w = {0};
|
||||||
unsigned arg = 0;
|
int i;
|
||||||
|
|
||||||
|
ins->start = r->p;
|
||||||
if (!decode_seq(r, &w))
|
if (!decode_seq(r, &w))
|
||||||
return CREOLE_OPCODE_READ_ERROR;
|
return CREOLE_OPCODE_READ_ERROR;
|
||||||
|
|
||||||
|
@ -344,15 +380,34 @@ creole_parse_line(struct creole_ins *ins, struct creole_reader *r)
|
||||||
return CREOLE_OPCODE_MALFORMED;
|
return CREOLE_OPCODE_MALFORMED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (arg = 0; arg < opcode_info[ins->opcode].arglen; arg++) {
|
if (opcode_info[ins->opcode].arglen >= CREOLE_MAX_ARG)
|
||||||
|
return CREOLE_OPCODE_MALFORMED;
|
||||||
|
for (i = 0; i < opcode_info[ins->opcode].arglen; i++) {
|
||||||
if (!decode_seq(r, &w))
|
if (!decode_seq(r, &w))
|
||||||
return CREOLE_ARG_READ_ERROR;
|
return CREOLE_ARG_READ_ERROR;
|
||||||
if (w.len == 1)
|
if (w.len == 1)
|
||||||
return CREOLE_ARG_MALFORMED;
|
return CREOLE_ARG_MALFORMED;
|
||||||
ins->w[arg] = w.word;
|
ins->w[i] = w.word;
|
||||||
ins->w_flags[arg] = w.high_bits;
|
ins->w_flags[i] = w.high_bits;
|
||||||
|
|
||||||
|
if (!typecheck_arg(env, ins->w[i],
|
||||||
|
arg_get_type(ins->w_flags[i]),
|
||||||
|
opcode_info[ins->opcode].argtype[i]))
|
||||||
|
return CREOLE_TYPE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ins->opcode == CREOLE_DB) {
|
||||||
|
ins->datapt = r->p;
|
||||||
|
do {
|
||||||
|
if (!decode_seq(r, &w))
|
||||||
|
return CREOLE_ARG_READ_ERROR;
|
||||||
|
} while (w.len != 1);
|
||||||
|
if (w.word != 0)
|
||||||
|
return CREOLE_LAST_READ_ERROR;
|
||||||
|
return CREOLE_COMPILE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ins->datapt = NULL;
|
||||||
if (!decode_seq(r, &w))
|
if (!decode_seq(r, &w))
|
||||||
return CREOLE_LAST_READ_ERROR;
|
return CREOLE_LAST_READ_ERROR;
|
||||||
if (w.word != 0 || w.len != 1)
|
if (w.word != 0 || w.len != 1)
|
||||||
|
@ -364,123 +419,40 @@ creole_parse_line(struct creole_ins *ins, struct creole_reader *r)
|
||||||
* High level compiling interface
|
* High level compiling interface
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
static int valid_register(struct creole_env *env, int reg)
|
static void
|
||||||
|
add_to_env(struct creole_env *env, struct ins *ins)
|
||||||
{
|
{
|
||||||
return reg < env->reglen;
|
switch (ins->opcode) {
|
||||||
}
|
case CREOLE_DB:
|
||||||
|
env->dats[ins->w[0]] = ins->datapt;
|
||||||
static int valid_label(struct creole_env *env, int reg)
|
break;
|
||||||
{
|
|
||||||
return reg < env->lablen;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int typecheck(struct creole_env *env, int val,
|
|
||||||
enum creole_word_flag fl, enum creole_arg_type typ)
|
|
||||||
{
|
|
||||||
switch (typ) {
|
|
||||||
case TYPE_IMM: return fl == CREOLE_IMMEDIATE;
|
|
||||||
case TYPE_REG: return fl == CREOLE_REGISTER
|
|
||||||
&& valid_register(env, val);
|
|
||||||
case TYPE_VAL: return fl == CREOLE_IMMEDIATE
|
|
||||||
|| fl == CREOLE_REGISTER;
|
|
||||||
case TYPE_LAB: return fl == CREOLE_IMMEDIATE
|
|
||||||
&& valid_label(env, val);
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum creole_word_flag get_type_from_high_bit(unsigned high_bits)
|
|
||||||
{
|
|
||||||
if (high_bits & 1) {
|
|
||||||
return CREOLE_REGISTER;
|
|
||||||
} else {
|
|
||||||
return CREOLE_IMMEDIATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum creole_compiler_ret typecheck_ins(struct creole_env *env,
|
|
||||||
struct creole_ins *ins)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
for (i = 0; i < opcode_info[ins->opcode].arglen; i++) {
|
|
||||||
if (!typecheck(env, ins->w[i],
|
|
||||||
get_type_from_high_bit(ins->w_flags[i]),
|
|
||||||
opcode_info[ins->opcode].argtype[i]))
|
|
||||||
return CREOLE_TYPE_ERROR;
|
|
||||||
}
|
|
||||||
return CREOLE_COMPILE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_ins(struct creole_ins *i)
|
|
||||||
{
|
|
||||||
const struct creole_ins blank = {0};
|
|
||||||
*i = blank;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****
|
|
||||||
* Get rid of instructions that can be written out at compile time.
|
|
||||||
***/
|
|
||||||
static enum creole_compiler_ret
|
|
||||||
handle_compiletime_immediate(struct creole_env *env,
|
|
||||||
struct creole_ins *cur_ins)
|
|
||||||
{
|
|
||||||
switch (cur_ins->opcode) {
|
|
||||||
case CREOLE_CLB:
|
|
||||||
if (cur_ins->w[0] >= env->lablen)
|
|
||||||
return CREOLE_LABEL_OVERFLOW;
|
|
||||||
env->lab[cur_ins->w[0]] = env->prgptr;
|
|
||||||
/* Delete instruction because it is a compile time
|
|
||||||
* instruction. Place next instruction in its place. */
|
|
||||||
clear_ins(cur_ins);
|
|
||||||
return CREOLE_COMPILE_CLEARED_INSTRUCTION;
|
|
||||||
case CREOLE_NOOP:
|
|
||||||
clear_ins(cur_ins);
|
|
||||||
return CREOLE_COMPILE_CLEARED_INSTRUCTION;
|
|
||||||
default:
|
default:
|
||||||
return typecheck_ins(env, cur_ins);
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: The compile step can be completely removed in favor of directly
|
|
||||||
* executing the bytecode, disassembling it with creole_parse_line()
|
|
||||||
* at every instance. This will also make the implementation simpler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum creole_compiler_ret
|
enum creole_compiler_ret
|
||||||
creole_compile(struct creole_env *env, struct creole_reader *r)
|
creole_compile(struct creole_env *env)
|
||||||
{
|
{
|
||||||
struct creole_ins *cur_ins = env->prg;
|
struct ins ins = {0};
|
||||||
int rcode;
|
int rcode;
|
||||||
|
|
||||||
while (env->prgptr < env->prglen) {
|
env->r_current = env->r_start;
|
||||||
rcode = creole_parse_line(cur_ins, r);
|
|
||||||
|
while (!read_eof(&env->r_current)) {
|
||||||
|
rcode = parse_line(env, &ins, &env->r_current);
|
||||||
if (rcode != CREOLE_COMPILE_OK)
|
if (rcode != CREOLE_COMPILE_OK)
|
||||||
return rcode;
|
return rcode;
|
||||||
|
add_to_env(env, &ins);
|
||||||
rcode = handle_compiletime_immediate(env, cur_ins);
|
|
||||||
switch (rcode) {
|
|
||||||
case CREOLE_COMPILE_CLEARED_INSTRUCTION:
|
|
||||||
break;
|
|
||||||
case CREOLE_COMPILE_OK:
|
|
||||||
cur_ins++;
|
|
||||||
env->prgptr++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return rcode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_eof(r))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env->prgptr == env->prglen && !read_eof(r))
|
|
||||||
return CREOLE_PROGRAM_OVERFLOW;
|
|
||||||
env->prgend = env->prgptr;
|
|
||||||
env->prgptr = 0;
|
|
||||||
return CREOLE_COMPILE_OK;
|
return CREOLE_COMPILE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Running and interaction interface
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
enum creole_run_ret creole_reg_write(struct creole_env *env, unsigned reg,
|
enum creole_run_ret creole_reg_write(struct creole_env *env, unsigned reg,
|
||||||
creole_word w)
|
creole_word w)
|
||||||
{
|
{
|
||||||
|
@ -501,11 +473,11 @@ enum creole_run_ret creole_reg_read(struct creole_env *env, unsigned reg,
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum creole_run_ret read_val(struct creole_env *env,
|
static enum creole_run_ret read_val(struct creole_env *env,
|
||||||
struct creole_ins *ins,
|
struct ins *ins,
|
||||||
unsigned arg,
|
unsigned arg,
|
||||||
creole_word *w)
|
creole_word *w)
|
||||||
{
|
{
|
||||||
if (get_type_from_high_bit(ins->w_flags[arg]) == CREOLE_REGISTER) {
|
if (arg_get_type(ins->w_flags[arg]) == CREOLE_REGISTER) {
|
||||||
return creole_reg_read(env, ins->w[arg], w);
|
return creole_reg_read(env, ins->w[arg], w);
|
||||||
} else {
|
} else {
|
||||||
*w = ins->w[arg];
|
*w = ins->w[arg];
|
||||||
|
@ -530,14 +502,6 @@ enum creole_run_ret creole_pop(struct creole_env *env, creole_word *w)
|
||||||
return CREOLE_STEP_CONTINUE;
|
return CREOLE_STEP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum creole_run_ret
|
|
||||||
check_label(struct creole_env *env, creole_word label)
|
|
||||||
{
|
|
||||||
return label < env->lablen
|
|
||||||
? CREOLE_STEP_CONTINUE
|
|
||||||
: CREOLE_RUN_LABEL_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum argument_signed {
|
enum argument_signed {
|
||||||
ALL_UNSIGNED = 0, /* 0b00 */
|
ALL_UNSIGNED = 0, /* 0b00 */
|
||||||
FIRST_SIGNED = 2, /* 0b10 */
|
FIRST_SIGNED = 2, /* 0b10 */
|
||||||
|
@ -556,8 +520,18 @@ static enum argument_signed check_sign_bits(unsigned flags1, unsigned flags2)
|
||||||
return rcode; \
|
return rcode; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
int creole_jump(struct creole_env *env, creole_word off)
|
||||||
|
{
|
||||||
|
/* When env->r_start.left == off, this is the end of the program. */
|
||||||
|
if (env->r_start.left < off)
|
||||||
|
return 0;
|
||||||
|
env->r_current.p = env->r_start.p + off;
|
||||||
|
env->r_current.left = env->r_start.left - off;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define chk_sign_op(OPER) do { \
|
#define chk_sign_op(OPER) do { \
|
||||||
switch (check_sign_bits(ins->w_flags[1], ins->w_flags[2])) { \
|
switch (check_sign_bits(ins.w_flags[1], ins.w_flags[2])) { \
|
||||||
case ALL_UNSIGNED: \
|
case ALL_UNSIGNED: \
|
||||||
a1 = a1 OPER a2; \
|
a1 = a1 OPER a2; \
|
||||||
break; \
|
break; \
|
||||||
|
@ -577,90 +551,82 @@ static enum argument_signed check_sign_bits(unsigned flags1, unsigned flags2)
|
||||||
|
|
||||||
enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc)
|
enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc)
|
||||||
{
|
{
|
||||||
struct creole_ins *ins = env->prg + env->prgptr;
|
struct ins ins = {0};
|
||||||
creole_word a1, a2;
|
creole_word a0, a1, a2;
|
||||||
int rcode = CREOLE_STEP_CONTINUE;
|
int rcode = CREOLE_STEP_CONTINUE;
|
||||||
int increase_pointer = 1;
|
|
||||||
|
|
||||||
if (env->prgptr == env->prgend)
|
if (env->r_current.left == 0)
|
||||||
return CREOLE_STEP_STOP;
|
return CREOLE_STEP_STOP;
|
||||||
|
|
||||||
switch (ins->opcode) {
|
if (parse_line(env, &ins, &env->r_current) != CREOLE_COMPILE_OK)
|
||||||
|
return CREOLE_RUN_DECODE_ERROR;
|
||||||
|
|
||||||
|
switch (ins.opcode) {
|
||||||
case CREOLE_PUSH:
|
case CREOLE_PUSH:
|
||||||
check(read_val(env, ins, 0, &a1));
|
check(read_val(env, &ins, 0, &a1));
|
||||||
check(creole_push(env, a1));
|
check(creole_push(env, a1));
|
||||||
break;
|
break;
|
||||||
case CREOLE_POP:
|
case CREOLE_POP:
|
||||||
check(creole_pop(env, &a1));
|
check(creole_pop(env, &a1));
|
||||||
check(creole_reg_write(env, ins->w[0], a1));
|
check(creole_reg_write(env, ins.w[0], a1));
|
||||||
break;
|
break;
|
||||||
case CREOLE_ADD:
|
case CREOLE_ADD:
|
||||||
check(read_val(env, ins, 1, &a1));
|
check(read_val(env, &ins, 1, &a1));
|
||||||
check(read_val(env, ins, 2, &a2));
|
check(read_val(env, &ins, 2, &a2));
|
||||||
check(creole_reg_write(env, ins->w[0], a1 + a2));
|
check(creole_reg_write(env, ins.w[0], a1 + a2));
|
||||||
break;
|
break;
|
||||||
case CREOLE_MUL:
|
case CREOLE_MUL:
|
||||||
check(read_val(env, ins, 1, &a1));
|
check(read_val(env, &ins, 1, &a1));
|
||||||
check(read_val(env, ins, 2, &a2));
|
check(read_val(env, &ins, 2, &a2));
|
||||||
check(creole_reg_write(env, ins->w[0], a1 * a2));
|
check(creole_reg_write(env, ins.w[0], a1 * a2));
|
||||||
break;
|
break;
|
||||||
case CREOLE_DIV:
|
case CREOLE_DIV:
|
||||||
check(read_val(env, ins, 1, &a1));
|
check(read_val(env, &ins, 1, &a1));
|
||||||
check(read_val(env, ins, 2, &a2));
|
check(read_val(env, &ins, 2, &a2));
|
||||||
if (a2 == 0) {
|
if (a2 == 0) {
|
||||||
return CREOLE_DIV_BY_ZERO;
|
return CREOLE_DIV_BY_ZERO;
|
||||||
}
|
}
|
||||||
chk_sign_op(/);
|
chk_sign_op(/);
|
||||||
check(creole_reg_write(env, ins->w[0], a1));
|
check(creole_reg_write(env, ins.w[0], a1));
|
||||||
break;
|
break;
|
||||||
case CREOLE_SYS:
|
case CREOLE_SYS:
|
||||||
check(read_val(env, ins, 0, sc));
|
check(read_val(env, &ins, 0, sc));
|
||||||
rcode = CREOLE_STEP_SYSCALL;
|
rcode = CREOLE_STEP_SYSCALL;
|
||||||
break;
|
break;
|
||||||
case CREOLE_JL:
|
case CREOLE_JL:
|
||||||
check(read_val(env, ins, 1, &a1));
|
check(read_val(env, &ins, 0, &a0));
|
||||||
check(read_val(env, ins, 2, &a2));
|
check(read_val(env, &ins, 1, &a1));
|
||||||
check(check_label(env, ins->w[0]));
|
check(read_val(env, &ins, 2, &a2));
|
||||||
chk_sign_op(<);
|
chk_sign_op(<);
|
||||||
if (a1) {
|
if (a1 && !creole_jump(env, a0))
|
||||||
env->prgptr = env->lab[ins->w[0]];
|
return CREOLE_JUMP_OVERFLOW;
|
||||||
increase_pointer = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CREOLE_JLE:
|
case CREOLE_JLE:
|
||||||
check(read_val(env, ins, 1, &a1));
|
check(read_val(env, &ins, 0, &a0));
|
||||||
check(read_val(env, ins, 2, &a2));
|
check(read_val(env, &ins, 1, &a1));
|
||||||
check(check_label(env, ins->w[0]));
|
check(read_val(env, &ins, 2, &a2));
|
||||||
chk_sign_op(<=);
|
chk_sign_op(<=);
|
||||||
if (a1) {
|
if (a1 && !creole_jump(env, a0))
|
||||||
env->prgptr = env->lab[ins->w[0]];
|
return CREOLE_JUMP_OVERFLOW;
|
||||||
increase_pointer = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CREOLE_JE:
|
case CREOLE_JE:
|
||||||
check(read_val(env, ins, 1, &a1));
|
check(read_val(env, &ins, 0, &a0));
|
||||||
check(read_val(env, ins, 2, &a2));
|
check(read_val(env, &ins, 1, &a1));
|
||||||
check(check_label(env, ins->w[0]));
|
check(read_val(env, &ins, 2, &a2));
|
||||||
if (a1 == a2) {
|
if (a1 == a2 && !creole_jump(env, a0))
|
||||||
env->prgptr = env->lab[ins->w[0]];
|
return CREOLE_JUMP_OVERFLOW;
|
||||||
increase_pointer = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CREOLE_JNE:
|
case CREOLE_JNE:
|
||||||
check(read_val(env, ins, 1, &a1));
|
check(read_val(env, &ins, 0, &a0));
|
||||||
check(read_val(env, ins, 2, &a2));
|
check(read_val(env, &ins, 1, &a1));
|
||||||
check(check_label(env, ins->w[0]));
|
check(read_val(env, &ins, 2, &a2));
|
||||||
if (a1 != a2) {
|
if (a1 != a2 && !creole_jump(env, a0))
|
||||||
env->prgptr = env->lab[ins->w[0]];
|
return CREOLE_JUMP_OVERFLOW;
|
||||||
increase_pointer = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rcode = CREOLE_STEP_UNKNOWN_OPCODE;
|
rcode = CREOLE_STEP_UNKNOWN_OPCODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (increase_pointer)
|
|
||||||
env->prgptr++;
|
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
46
creole.h
46
creole.h
|
@ -41,11 +41,11 @@ enum creole_opcode {
|
||||||
CREOLE_MUL,
|
CREOLE_MUL,
|
||||||
CREOLE_DIV,
|
CREOLE_DIV,
|
||||||
CREOLE_SYS,
|
CREOLE_SYS,
|
||||||
CREOLE_CLB,
|
|
||||||
CREOLE_JL,
|
CREOLE_JL,
|
||||||
CREOLE_JLE,
|
CREOLE_JLE,
|
||||||
CREOLE_JE,
|
CREOLE_JE,
|
||||||
CREOLE_JNE,
|
CREOLE_JNE,
|
||||||
|
CREOLE_DB,
|
||||||
CREOLE_OPCODE_LEN
|
CREOLE_OPCODE_LEN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ enum creole_compiler_ret {
|
||||||
CREOLE_ARG_MALFORMED,
|
CREOLE_ARG_MALFORMED,
|
||||||
CREOLE_LAST_READ_ERROR,
|
CREOLE_LAST_READ_ERROR,
|
||||||
CREOLE_LAST_MALFORMED,
|
CREOLE_LAST_MALFORMED,
|
||||||
CREOLE_LABEL_OVERFLOW,
|
CREOLE_DATA_OVERFLOW,
|
||||||
CREOLE_TYPE_ERROR,
|
CREOLE_TYPE_ERROR,
|
||||||
CREOLE_COMPILE_CLEARED_INSTRUCTION,
|
CREOLE_COMPILE_CLEARED_INSTRUCTION,
|
||||||
CREOLE_PROGRAM_OVERFLOW,
|
CREOLE_PROGRAM_OVERFLOW,
|
||||||
|
@ -76,45 +76,37 @@ enum creole_run_ret {
|
||||||
CREOLE_STEP_STOP,
|
CREOLE_STEP_STOP,
|
||||||
CREOLE_STACK_OVERFLOW,
|
CREOLE_STACK_OVERFLOW,
|
||||||
CREOLE_STACK_UNDERFLOW,
|
CREOLE_STACK_UNDERFLOW,
|
||||||
CREOLE_RUN_LABEL_OVERFLOW,
|
CREOLE_RUN_DECODE_ERROR,
|
||||||
CREOLE_REGISTER_OVERFLOW,
|
CREOLE_REGISTER_OVERFLOW,
|
||||||
CREOLE_STEP_UNKNOWN_OPCODE,
|
CREOLE_STEP_UNKNOWN_OPCODE,
|
||||||
CREOLE_DIV_BY_ZERO,
|
CREOLE_DIV_BY_ZERO,
|
||||||
CREOLE_STEP_HIGH_BIT_MALFORMED,
|
CREOLE_STEP_HIGH_BIT_MALFORMED,
|
||||||
|
CREOLE_JUMP_OVERFLOW,
|
||||||
CREOLE_RUN_RET_LEN
|
CREOLE_RUN_RET_LEN
|
||||||
};
|
};
|
||||||
|
|
||||||
struct creole_ins {
|
|
||||||
enum creole_opcode opcode;
|
|
||||||
unsigned char w_flags[3];
|
|
||||||
creole_word w[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct creole_env {
|
|
||||||
creole_word *reg;
|
|
||||||
size_t reglen;
|
|
||||||
|
|
||||||
size_t *lab;
|
|
||||||
size_t lablen;
|
|
||||||
|
|
||||||
creole_word *stk;
|
|
||||||
size_t stkptr, stklen;
|
|
||||||
|
|
||||||
struct creole_ins *prg;
|
|
||||||
size_t prgptr, prgend, prglen;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct creole_reader {
|
struct creole_reader {
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
size_t left;
|
size_t left;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct creole_env {
|
||||||
|
unsigned char **dats;
|
||||||
|
size_t datlen;
|
||||||
|
|
||||||
|
creole_word *reg;
|
||||||
|
size_t reglen;
|
||||||
|
|
||||||
|
creole_word *stk;
|
||||||
|
size_t stkptr, stklen;
|
||||||
|
|
||||||
|
struct creole_reader r_current;
|
||||||
|
struct creole_reader r_start;
|
||||||
|
};
|
||||||
|
|
||||||
int creole_encode(creole_word i, unsigned encode_to, unsigned high_bits,
|
int creole_encode(creole_word i, unsigned encode_to, unsigned high_bits,
|
||||||
unsigned char buf[7]);
|
unsigned char buf[7]);
|
||||||
enum creole_compiler_ret
|
enum creole_compiler_ret creole_compile(struct creole_env *env);
|
||||||
creole_parse_line(struct creole_ins *ins, struct creole_reader *r);
|
|
||||||
enum creole_compiler_ret
|
|
||||||
creole_compile(struct creole_env *env, struct creole_reader *r);
|
|
||||||
|
|
||||||
enum creole_run_ret creole_reg_write(struct creole_env *env, unsigned reg,
|
enum creole_run_ret creole_reg_write(struct creole_env *env, unsigned reg,
|
||||||
creole_word w);
|
creole_word w);
|
||||||
|
|
Loading…
Reference in New Issue