diff options
| author | 2023-02-11 14:28:43 +0000 | |
|---|---|---|
| committer | 2023-02-11 14:28:43 +0000 | |
| commit | 582a0a2c9a476abe9dec3410ff4f555433ed9e0f (patch) | |
| tree | 422878d94f091f440143348d7f52fcfa42b294dc /creole.c | |
| parent | test pop (diff) | |
enable compiling and add compile test
Diffstat (limited to 'creole.c')
| -rw-r--r-- | creole.c | 146 |
1 files changed, 109 insertions, 37 deletions
@@ -346,14 +346,27 @@ creole_parse_line(struct creole_ins *ins, struct creole_reader *r) * High level compiling interface *************************************************************************/ -static int typecheck(enum creole_word_flag fl, enum creole_arg_type typ) +static int valid_register(struct creole_env *env, int reg) +{ + return reg < env->reglen; +} + +static int valid_label(struct creole_env *env, int reg) +{ + 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; + 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; + case TYPE_LAB: return fl == CREOLE_IMMEDIATE + && valid_label(env, val); default: return 0; } } @@ -364,7 +377,7 @@ static enum creole_compiler_ret typecheck_ins(struct creole_env *env, unsigned i; for (i = 0; i < opcode_info[ins->opcode].arglen; i++) { - if (!typecheck(ins->w_flags[i], + if (!typecheck(env, ins->w[i], ins->w_flags[i], opcode_info[ins->opcode].argtype[i])) return CREOLE_TYPE_ERROR; } @@ -373,11 +386,13 @@ static enum creole_compiler_ret typecheck_ins(struct creole_env *env, static void clear_ins(struct creole_ins *i) { - i->opcode = 0; - i->w[0] = i->w[1] = i->w[2] = i->w_flags[0] = - i->w_flags[1] = i->w_flags[2] = 0; + 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) @@ -433,61 +448,118 @@ creole_compile(struct creole_env *env, struct creole_reader *r) return CREOLE_COMPILE_OK; } -#if 0 +enum creole_run_ret creole_reg_write(struct creole_env *env, + creole_word w, unsigned reg) +{ + if (!valid_register(env, reg)) + return CREOLE_REGISTER_OVERFLOW; + env->reg[reg] = w; + return CREOLE_STEP_CONTINUE; +} + +enum creole_run_ret creole_reg_read(struct creole_env *env, creole_word *w, + unsigned reg) +{ + if (!valid_register(env, reg)) + return CREOLE_REGISTER_OVERFLOW; + *w = env->reg[reg]; + return CREOLE_STEP_CONTINUE; +} + +static enum creole_run_ret read_val(struct creole_env *env, + struct creole_ins *ins, + unsigned arg, + creole_word *w) +{ + if (ins->w_flags[arg] == CREOLE_REGISTER) { + return creole_reg_read(env, w, ins->w[arg]); + } else { + *w = ins->w[arg]; + } + + return CREOLE_STEP_CONTINUE; +} + +enum creole_run_ret creole_push(struct creole_env *env, creole_word w) +{ + if (env->stkptr == env->stklen) + return CREOLE_STACK_OVERFLOW; + env->stk[env->stkptr++] = w; + return CREOLE_STEP_CONTINUE; +} + +enum creole_run_ret creole_pop(struct creole_env *env, creole_word *w) +{ + if (env->stkptr == 0) + return CREOLE_STACK_UNDERFLOW; + *w = env->stk[--env->stkptr]; + return CREOLE_STEP_CONTINUE; +} -static creole_word read_word(struct creole_ins *ins, int i) +static enum creole_run_ret +check_label(struct creole_env *env, creole_word label) { - if (env->w_flags[i] == CREOLE_REGISTER) - return env->reg[env->w[i]]; - else - return env->w[i]; + return label < env->lablen + ? CREOLE_STEP_CONTINUE + : CREOLE_RUN_LABEL_OVERFLOW; } -int creole_step(struct creole_env *env) +#define check(fun) do { \ + rcode = fun; \ + if (rcode != CREOLE_STEP_CONTINUE) \ + return rcode; \ +} while(0) + +enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc) { struct creole_ins *ins = env->prg + env->prgptr; creole_word a1, a2; + int rcode = CREOLE_STEP_CONTINUE; if (env->prgptr == env->prgend) return CREOLE_STEP_STOP; - env->prgptr++; switch (ins->opcode) { case CREOLE_PUSH: - if (env->stkptr == env->stklen) - return CREOLE_STACK_OVERFLOW; - env->stk[env->stkptr++] = env->reg[env->w[0]]; + check(read_val(env, ins, 0, &a1)); + check(creole_push(env, a1)); break; case CREOLE_POP: - if (env->stkptr == 0) - return CREOLE_STACK_OVERFLOW; - env->reg[env->w[0]] = env->stk[--env->stkptr]; + check(creole_pop(env, &a1)); + check(creole_reg_write(env, a1, ins->w[0])); break; case CREOLE_ADD: - a1 = read_word(ins, 1); - a2 = read_word(ins, 2); - env->reg[env->w[0]] = a1 + a2; + check(read_val(env, ins, 1, &a1)); + check(read_val(env, ins, 2, &a2)); + check(creole_reg_write(env, ins->w[0], a1 + a2)); break; case CREOLE_MUL: - a1 = read_word(ins, 1); - a2 = read_word(ins, 2); - env->reg[env->w[0]] = a1 * a2; + check(read_val(env, ins, 1, &a1)); + check(read_val(env, ins, 2, &a2)); + check(creole_reg_write(env, ins->w[0], a1 * a2)); break; case CREOLE_DIV: - a1 = read_word(ins, 1); - a2 = read_word(ins, 2); - env->reg[env->w[0]] = a1 / a2; + check(read_val(env, ins, 1, &a1)); + check(read_val(env, ins, 2, &a2)); + check(creole_reg_write(env, ins->w[0], a1 / a2)); break; case CREOLE_JL: - a1 = read_word(ins, 1); - a2 = read_word(ins, 2); + check(read_val(env, ins, 1, &a1)); + check(read_val(env, ins, 2, &a2)); + check(check_label(env, ins->w[0])); if (a1 < a2) - env->prgptr = env->lab[env->w[0]]; + env->prgptr = env->lab[ins->w[0]]; break; - case SYS: - a1 = read_word(ins, 1); - /* do syscall */ + case CREOLE_SYS: + check(read_val(env, ins, 0, sc)); + rcode = CREOLE_STEP_SYSCALL; break; + default: + rcode = CREOLE_STEP_UNKNOWN_OPCODE; } + + env->prgptr++; + return rcode; } -#endif + +#undef check |
