diff --git a/asm/creole.py b/asm/creole.py index 1d98051..4cb4b8c 100644 --- a/asm/creole.py +++ b/asm/creole.py @@ -92,9 +92,14 @@ class Instruction(Enum): MUL = 4, ArgType.REG, ArgType.VAL, ArgType.VAL DIV = 5, ArgType.REG, ArgType.VAL, ArgType.VAL SDIV = 6, ArgType.REG, ArgType.VAL, ArgType.VAL - JL = 7, ArgType.LAB, ArgType.VAL, ArgType.VAL + SYS = 7, ArgType.VAL CLB = 8, ArgType.LAB - SYS = 9, ArgType.VAL + JL = 9, ArgType.LAB, ArgType.VAL, ArgType.VAL + JLE = 10, ArgType.LAB, ArgType.VAL, ArgType.VAL + JG = 11, ArgType.LAB, ArgType.VAL, ArgType.VAL + JGE = 12, ArgType.LAB, ArgType.VAL, ArgType.VAL + JE = 13, ArgType.LAB, ArgType.VAL, ArgType.VAL + JNE = 13, ArgType.LAB, ArgType.VAL, ArgType.VAL def __init__(self, opcode, *args): if opcode > 0x7F or opcode < 0: @@ -214,6 +219,10 @@ class Program: args_w_type = ins.typecheck(line[1:]) self.asm_push_line(ins.opcode, args_w_type) + def parse_lines(self, lines): + for l in lines: + self.parse_asm_line(l) + def __call__(self): b = bytes() for line in self.asm: diff --git a/asm/ffi.py b/asm/ffi.py index 4c1ca15..ba327bf 100644 --- a/asm/ffi.py +++ b/asm/ffi.py @@ -120,13 +120,15 @@ class Environment: def syscall(self, sc): raise InvalidSyscallError(sc) - def __call__(self): + def __call__(self, debug=False): sc = c_size_t() ret = RunRet.CONTINUE while not ret.is_halt(): ret = RunRet(dll.creole_step(byref(self.cenv), byref(sc))) if ret == RunRet.SYSCALL: self.syscall(sc) + if debug: + print(self.cenv.reg[0]) return ret class CParseLineException(Exception): diff --git a/asm/test.py b/asm/test.py index 4b6471c..00e9e5e 100644 --- a/asm/test.py +++ b/asm/test.py @@ -309,6 +309,22 @@ class DivTest(unittest.TestCase): self.assertEqual(cm.exception.i, 2) self.assertEqual(cm.exception.opcode, 5) +class LabelTest(unittest.TestCase): + def test_simple_loop(self): + p = Program() + p.parse_lines([ + "add r0 10 0", + "add r1 20 0", + "CLB l0", + "add r0 r0 -1", + "add r1 r1 1", + "jg l0 r0 0" + ]) + ex = ffi.Environment(p()) + self.assertEqual(ex(), ffi.RunRet.STOP) + self.assertEqual(ex.getreg(0), 0) + self.assertEqual(ex.getreg(1), 30) + class ProgramTest(unittest.TestCase): def test_exec_simple_reg(self): p = Program() diff --git a/creole.c b/creole.c index 135576f..6a1daa8 100644 --- a/creole.c +++ b/creole.c @@ -36,9 +36,14 @@ static const struct { 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(JL, 3, TYPE_LAB, TYPE_VAL, TYPE_VAL), + defop(SYS, 1, TYPE_VAL, TYPE_NONE, TYPE_NONE), defop(CLB, 1, TYPE_LAB, TYPE_NONE, TYPE_NONE), - defop(SYS, 1, TYPE_VAL, 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) }; /************************************************************************* @@ -518,6 +523,7 @@ 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; + int increase_pointer = 1; if (env->prgptr == env->prgend) return CREOLE_STEP_STOP; @@ -556,22 +562,70 @@ enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc) check(creole_reg_write(env, ins->w[0], (creole_signed)a1 / (creole_signed)a2)); break; + case CREOLE_SYS: + check(read_val(env, ins, 0, sc)); + rcode = CREOLE_STEP_SYSCALL; + break; case CREOLE_JL: check(read_val(env, ins, 1, &a1)); check(read_val(env, ins, 2, &a2)); check(check_label(env, ins->w[0])); - if (a1 < a2) + if (a1 < a2) { env->prgptr = env->lab[ins->w[0]]; + increase_pointer = 0; + } break; - case CREOLE_SYS: - check(read_val(env, ins, 0, sc)); - rcode = CREOLE_STEP_SYSCALL; + case CREOLE_JLE: + 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) { + env->prgptr = env->lab[ins->w[0]]; + increase_pointer = 0; + } + break; + case CREOLE_JE: + 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_JNE: + 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; default: rcode = CREOLE_STEP_UNKNOWN_OPCODE; } - env->prgptr++; + if (increase_pointer) + env->prgptr++; return rcode; } diff --git a/creole.h b/creole.h index 452bc91..f5b118f 100644 --- a/creole.h +++ b/creole.h @@ -24,9 +24,14 @@ enum creole_opcode { CREOLE_MUL = 4, CREOLE_DIV = 5, CREOLE_SDIV = 6, - CREOLE_JL = 7, + CREOLE_SYS = 7, CREOLE_CLB = 8, - CREOLE_SYS = 9, + CREOLE_JL = 9, + CREOLE_JLE = 10, + CREOLE_JG = 11, + CREOLE_JGE = 12, + CREOLE_JE = 13, + CREOLE_JNE = 14, CREOLE_OPCODE_LEN };