aboutsummaryrefslogtreecommitdiffstats
path: root/creole.c
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2023-02-12 18:06:08 +0000
committerGravatar Peter McGoron 2023-02-12 18:06:08 +0000
commit7b3eaf9b4f9aaec02ce63be638de373397fa9460 (patch)
tree8231125e0b6d1dad534fae72fe9880ba1bda33cb /creole.c
parentjump tests (diff)
add pseudoinstructions that compile to regular instructions
Diffstat (limited to 'creole.c')
-rw-r--r--creole.c86
1 files changed, 51 insertions, 35 deletions
diff --git a/creole.c b/creole.c
index 6a1daa8..fbde87e 100644
--- a/creole.c
+++ b/creole.c
@@ -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;
}