diff options
| author | 2023-02-12 18:06:08 +0000 | |
|---|---|---|
| committer | 2023-02-12 18:06:08 +0000 | |
| commit | 7b3eaf9b4f9aaec02ce63be638de373397fa9460 (patch) | |
| tree | 8231125e0b6d1dad534fae72fe9880ba1bda33cb /creole.c | |
| parent | jump tests (diff) | |
add pseudoinstructions that compile to regular instructions
Diffstat (limited to 'creole.c')
| -rw-r--r-- | creole.c | 86 |
1 files changed, 51 insertions, 35 deletions
@@ -35,13 +35,10 @@ static const struct { defop(ADD, 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(SDIV, 3, TYPE_REG, TYPE_VAL, TYPE_VAL), defop(SYS, 1, TYPE_VAL, TYPE_NONE, TYPE_NONE), defop(CLB, 1, TYPE_LAB, TYPE_NONE, TYPE_NONE), defop(JL, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL), defop(JLE, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL), - defop(JG, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL), - defop(JGE, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL), defop(JE, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL), defop(JNE, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL) }; @@ -378,13 +375,23 @@ static int typecheck(struct creole_env *env, int val, } } +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], ins->w_flags[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; } @@ -479,7 +486,7 @@ static enum creole_run_ret read_val(struct creole_env *env, unsigned arg, creole_word *w) { - if (ins->w_flags[arg] == CREOLE_REGISTER) { + if (get_type_from_high_bit(ins->w_flags[arg]) == CREOLE_REGISTER) { return creole_reg_read(env, ins->w[arg], w); } else { *w = ins->w[arg]; @@ -512,12 +519,43 @@ check_label(struct creole_env *env, creole_word label) : CREOLE_RUN_LABEL_OVERFLOW; } +enum argument_signed { + ALL_UNSIGNED = 0, // 0b00 + FIRST_SIGNED = 2, // 0b10 + SECOND_SIGNED = 1, // 0b01 + ALL_SIGNED = 3 // 0b11 +}; + +static enum argument_signed check_sign_bits(unsigned flags1, unsigned flags2) +{ + return (flags1 & 0x2) | ((flags2 & 0x2) >> 1); +} + #define check(fun) do { \ rcode = fun; \ if (rcode != CREOLE_STEP_CONTINUE) \ return rcode; \ } while(0) +#define chk_sign_op(OPER) do { \ + switch (check_sign_bits(ins->w_flags[1], ins->w_flags[2])) { \ + case ALL_UNSIGNED: \ + a1 = a1 OPER a2; \ + break; \ + case FIRST_SIGNED: \ + a1 = (creole_signed)a1 OPER a2; \ + break; \ + case SECOND_SIGNED: \ + a1 = a1 OPER (creole_signed)a2; \ + break; \ + case ALL_SIGNED: \ + a1 = (creole_signed) a1 OPER (creole_signed) a2; \ + break; \ + default: \ + return CREOLE_STEP_HIGH_BIT_MALFORMED; \ + } \ +} while(0) + enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc) { struct creole_ins *ins = env->prg + env->prgptr; @@ -550,17 +588,11 @@ enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc) case CREOLE_DIV: check(read_val(env, ins, 1, &a1)); check(read_val(env, ins, 2, &a2)); - if (a2 == 0) - return CREOLE_DIV_BY_ZERO; - check(creole_reg_write(env, ins->w[0], a1 / a2)); - break; - case CREOLE_SDIV: - check(read_val(env, ins, 1, &a1)); - check(read_val(env, ins, 2, &a2)); - if (a2 == 0) + if (a2 == 0) { return CREOLE_DIV_BY_ZERO; - check(creole_reg_write(env, ins->w[0], - (creole_signed)a1 / (creole_signed)a2)); + } + chk_sign_op(/); + check(creole_reg_write(env, ins->w[0], a1)); break; case CREOLE_SYS: check(read_val(env, ins, 0, sc)); @@ -570,7 +602,8 @@ enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc) check(read_val(env, ins, 1, &a1)); check(read_val(env, ins, 2, &a2)); check(check_label(env, ins->w[0])); - if (a1 < a2) { + chk_sign_op(<); + if (a1) { env->prgptr = env->lab[ins->w[0]]; increase_pointer = 0; } @@ -579,25 +612,8 @@ enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc) 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[ins->w[0]]; - increase_pointer = 0; - } - break; - case CREOLE_JG: - 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[ins->w[0]]; - increase_pointer = 0; - } - break; - case CREOLE_JGE: - check(read_val(env, ins, 1, &a1)); - check(read_val(env, ins, 2, &a2)); - check(check_label(env, ins->w[0])); - if (a1 >= a2) { + chk_sign_op(<=); + if (a1) { env->prgptr = env->lab[ins->w[0]]; increase_pointer = 0; } |
