aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2023-02-11 14:28:43 +0000
committerGravatar Peter McGoron 2023-02-11 14:28:43 +0000
commit582a0a2c9a476abe9dec3410ff4f555433ed9e0f (patch)
tree422878d94f091f440143348d7f52fcfa42b294dc
parenttest pop (diff)
enable compiling and add compile test
-rw-r--r--asm/ffi.py25
-rw-r--r--asm/test.py43
-rw-r--r--creole.c146
-rw-r--r--creole.h20
4 files changed, 163 insertions, 71 deletions
diff --git a/asm/ffi.py b/asm/ffi.py
index 39d9800..a1907c6 100644
--- a/asm/ffi.py
+++ b/asm/ffi.py
@@ -13,6 +13,20 @@ class CompileRet(Enum):
LABEL_OVERFLOW = 7
TYPE_ERROR = 8
CLEARED_INSTRUCTION = 9
+ PROGRAM_OVERFLOW = 10
+
+class RunRet(Enum):
+ CONTINUE = 0
+ SYSCALL = 1
+ STOP = 2
+ STACK_OVERFLOW = 3
+ STACK_UNDERFLOW = 4
+ RUN_LABEL_OVERFLOW = 5
+ REGISTER_OVERFLOW = 6
+ UNKNOWN_OPCODE = 7
+
+ def is_halt(self):
+ return not (self == RunRet.CONTINUE or self == RunRet.SYSCALL)
class CIns(Structure):
_fields_ = [("opcode", c_int),
@@ -76,6 +90,17 @@ class Environment:
ret = dll.creole_compile(byref(self.cenv), byref(rd))
return CompileRet(ret)
+ def syscall(self, sc):
+ pass
+ def __call__(self):
+ 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)
+ return ret
+
class CParseLineException(Exception):
pass
def parse_line(line):
diff --git a/asm/test.py b/asm/test.py
index ba6d125..ca54f59 100644
--- a/asm/test.py
+++ b/asm/test.py
@@ -98,7 +98,6 @@ class PopTest(unittest.TestCase):
def test_compile_throw_pop_literal(self):
p = Program()
- ex = ffi.Environment()
with self.assertRaises(TypecheckException) as cm:
p.parse_asm_line("pop 6")
self.assertEqual(cm.exception.argtype, ArgType.REG)
@@ -108,7 +107,6 @@ class PopTest(unittest.TestCase):
def test_compile_throw_pop_label(self):
p = Program()
- ex = ffi.Environment()
with self.assertRaises(TypecheckException) as cm:
p.parse_asm_line("pop l9")
self.assertEqual(cm.exception.argtype, ArgType.REG)
@@ -128,45 +126,22 @@ class PopTest(unittest.TestCase):
p = Program()
with self.assertRaises(TypecheckLenException) as cm:
p.parse_asm_line("push")
- self.assertEqual(cm.exception.opcode, 2)
+ self.assertEqual(cm.exception.opcode, 1)
self.assertEqual(cm.exception.insargs, [])
self.assertEqual(cm.exception.argtypelen, 1)
class ProgramTest(unittest.TestCase):
- def test_two(self):
- p = Program()
- p.parse_asm_line("PUSH r1")
- p.parse_asm_line("ADD r1 5 6")
- b = p()
- self.assertEqual(b, b'\x01\xC2\x81\x00\x03\xC2\x81\xC0\x85\xC0\x86\x00')
- def test_label(self):
+ def test_exec_simple_reg(self):
p = Program()
- b_ex = bytes()
- p.parse_asm_line("CLB l0")
- b_ex = b_ex + b'\x07\xC0\x80\x00'
+ p.parse_asm_line("push 5")
+ p.parse_asm_line("push 6")
p.parse_asm_line("pop r0")
- b_ex = b_ex + b'\x02\xC2\x80\x00'
p.parse_asm_line("pop r1")
- b_ex = b_ex + b'\x02\xC2\x81\x00'
- p.parse_asm_line("mul r2 r0 r1")
- b_ex = b_ex + b'\x04\xC2\x82\xC2\x80\xC2\x81\x00'
- p.parse_asm_line("push r2")
- b_ex = b_ex + b'\x01\xC2\x82\x00'
- p.parse_asm_line("push r2")
- b_ex = b_ex + b'\x01\xC2\x82\x00'
- p.parse_asm_line("jl l0 r2 10")
- b_ex = b_ex + b'\x06\xC0\x80\xC2\x82\xC0\x8A\x00'
- b = p()
- self.assertEqual(b, b_ex)
-
- def test_parse_imm(self):
- p = Program()
- p.parse_asm_line("add r1 23 3648")
- ins = ffi.parse_line(p())
- self.assertEqual(ins[0], Instruction.ADD.opcode)
- self.assertEqual(ins[1][0], (1,1))
- self.assertEqual(ins[1][1], (0,23))
- self.assertEqual(ins[1][2], (0,3648))
+ ex = ffi.Environment()
+ self.assertEqual(ex.load(p()), ffi.CompileRet.OK)
+ self.assertEqual(ex(), ffi.RunRet.STOP)
+ self.assertEqual(ex.cenv.reg[0], 6)
+ self.assertEqual(ex.cenv.reg[1], 5)
if __name__ == "__main__":
unittest.main()
diff --git a/creole.c b/creole.c
index 78beaa0..b482d1e 100644
--- a/creole.c
+++ b/creole.c
@@ -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
diff --git a/creole.h b/creole.h
index 827fe82..cb43e8b 100644
--- a/creole.h
+++ b/creole.h
@@ -47,6 +47,18 @@ enum creole_compiler_ret {
CREOLE_COMPILE_RET_LEN
};
+enum creole_run_ret {
+ CREOLE_STEP_CONTINUE,
+ CREOLE_STEP_SYSCALL,
+ CREOLE_STEP_STOP,
+ CREOLE_STACK_OVERFLOW,
+ CREOLE_STACK_UNDERFLOW,
+ CREOLE_RUN_LABEL_OVERFLOW,
+ CREOLE_REGISTER_OVERFLOW,
+ CREOLE_STEP_UNKNOWN_OPCODE,
+ CREOLE_RUN_RET_LEN
+};
+
struct creole_ins {
enum creole_opcode opcode;
unsigned char w_flags[3];
@@ -79,4 +91,12 @@ 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, creole_word w,
+ unsigned reg);
+enum creole_run_ret creole_reg_read(struct creole_env *env, creole_word *w,
+ unsigned reg);
+enum creole_run_ret creole_push(struct creole_env *env, creole_word w);
+enum creole_run_ret creole_pop(struct creole_env *env, creole_word *w);
+enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc);
+
#endif /* CREOLE_H */
'>-173/+130 git-svn-id: svn://svn.linux1394.org/libraw1394/trunk@100 53a565d1-3bb7-0310-b661-cf11e63c67ab 2003-01-05emulate legacy ISO reception API on top of new rawiso APIGravatar dmaas 7-131/+174 git-svn-id: svn://svn.linux1394.org/libraw1394/trunk@99 53a565d1-3bb7-0310-b661-cf11e63c67ab 2002-12-24update iso API for multi-channel reception and new packet buffer layoutGravatar dmaas 4-123/+236 git-svn-id: svn://svn.linux1394.org/libraw1394/trunk@98 53a565d1-3bb7-0310-b661-cf11e63c67ab 2002-12-20oops, irq_interval needs to be signedGravatar anonymous 1-1/+1 git-svn-id: svn://svn.linux1394.org/libraw1394/trunk@97 53a565d1-3bb7-0310-b661-cf11e63c67ab 2002-12-20dmaas - renamed exported arm definitions into the raw1394_ namespace; ↵Gravatar anonymous 3-124/+48 brought kernel-raw1394.h back in sync with the kernel version git-svn-id: svn://svn.linux1394.org/libraw1394/trunk@96 53a565d1-3bb7-0310-b661-cf11e63c67ab 2002-12-16rawiso updates:Gravatar dmaas 3-18/+25 - changed return type of rawiso xmit/recv handlers from int to enum raw1394_iso_disposition - added an ioctl (RAW1394_ISO_QUEUE_ACTIVITY) to force an ISO_ACTIVITY event into the queue. This is needed for handling RAW1394_ISO_DEFER, to kick us out of the next read() instead of sleeping forever. - removed references to "8-byte" isochronous header - this is an OHCI-specific implementation detail git-svn-id: svn://svn.linux1394.org/libraw1394/trunk@95 53a565d1-3bb7-0310-b661-cf11e63c67ab 2002-11-18fix cplusplus extern C blockGravatar ddennedy 1-4/+4 git-svn-id: svn://svn.linux1394.org/libraw1394/trunk@94 53a565d1-3bb7-0310-b661-cf11e63c67ab 2002-11-18merged rawiso branchGravatar ddennedy 7-6/+488 git-svn-id: svn://svn.linux1394.org/libraw1394/trunk@93 53a565d1-3bb7-0310-b661-cf11e63c67ab