summaryrefslogtreecommitdiffstatshomepage
path: root/py/runtime.c
diff options
context:
space:
mode:
authorDamien <damien.p.george@gmail.com>2013-10-05 23:17:28 +0100
committerDamien <damien.p.george@gmail.com>2013-10-05 23:17:28 +0100
commit826005c60b3c22c468ec21e995844037aafd6f99 (patch)
tree291ba04ec4ab625316babc91bcdeebf5634150a3 /py/runtime.c
parent5bfb759980c3891a9401d877fb225770146c79df (diff)
downloadmicropython-826005c60b3c22c468ec21e995844037aafd6f99.tar.gz
micropython-826005c60b3c22c468ec21e995844037aafd6f99.zip
Add support for inline thumb assembly.
Diffstat (limited to 'py/runtime.c')
-rw-r--r--py/runtime.c89
1 files changed, 67 insertions, 22 deletions
diff --git a/py/runtime.c b/py/runtime.c
index 26ecdc14fe..4ac680562c 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -40,6 +40,7 @@ typedef enum {
O_FUN_2,
O_FUN_N,
O_FUN_BC,
+ O_FUN_ASM,
O_BOUND_METH,
O_LIST,
O_SET,
@@ -73,14 +74,18 @@ typedef struct _py_obj_base_t {
float_t flt;
#endif
struct { // for O_FUN_[012N]
- void *fun;
int n_args;
+ void *fun;
} u_fun;
struct { // for O_FUN_BC
+ int n_args;
byte *code;
uint len;
- int n_args;
} u_fun_bc;
+ struct { // for O_FUN_ASM
+ int n_args;
+ void *fun;
+ } u_fun_asm;
struct { // for O_BOUND_METH
py_obj_t meth;
py_obj_t self;
@@ -275,8 +280,10 @@ static qstr q_len;
static qstr q___build_class__;
typedef enum {
- PY_CODE_NATIVE,
+ PY_CODE_NONE,
PY_CODE_BYTE,
+ PY_CODE_NATIVE,
+ PY_CODE_INLINE_ASM,
} py_code_kind_t;
typedef struct _py_code_t {
@@ -284,12 +291,15 @@ typedef struct _py_code_t {
int n_args;
union {
struct {
- py_fun_t fun;
- } u_native;
- struct {
byte *code;
uint len;
} u_byte;
+ struct {
+ py_fun_t fun;
+ } u_native;
+ struct {
+ py_fun_t fun;
+ } u_inline_asm;
};
} py_code_t;
@@ -368,10 +378,30 @@ int rt_get_new_unique_code_id() {
return next_unique_code_id++;
}
-void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
+static void alloc_unique_codes() {
if (unique_codes == NULL) {
unique_codes = m_new(py_code_t, next_unique_code_id);
+ for (int i = 0; i < next_unique_code_id; i++) {
+ unique_codes[i].kind = PY_CODE_NONE;
+ }
}
+}
+
+void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args) {
+ alloc_unique_codes();
+
+ assert(unique_code_id < next_unique_code_id);
+ unique_codes[unique_code_id].kind = PY_CODE_BYTE;
+ unique_codes[unique_code_id].n_args = n_args;
+ unique_codes[unique_code_id].u_byte.code = code;
+ unique_codes[unique_code_id].u_byte.len = len;
+
+ DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
+}
+
+void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
+ alloc_unique_codes();
+
assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
unique_codes[unique_code_id].kind = PY_CODE_NATIVE;
unique_codes[unique_code_id].n_args = n_args;
@@ -392,17 +422,27 @@ void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_arg
}
}
-void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args) {
- if (unique_codes == NULL) {
- unique_codes = m_new(py_code_t, next_unique_code_id);
- }
- assert(unique_code_id < next_unique_code_id);
- unique_codes[unique_code_id].kind = PY_CODE_BYTE;
+void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
+ alloc_unique_codes();
+
+ assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
+ unique_codes[unique_code_id].kind = PY_CODE_INLINE_ASM;
unique_codes[unique_code_id].n_args = n_args;
- unique_codes[unique_code_id].u_byte.code = code;
- unique_codes[unique_code_id].u_byte.len = len;
+ unique_codes[unique_code_id].u_inline_asm.fun = fun;
- DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
+ DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
+ byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
+ for (int i = 0; i < 128 && i < len; i++) {
+ if (i > 0 && i % 16 == 0) {
+ DEBUG_printf("\n");
+ }
+ DEBUG_printf(" %02x", fun_data[i]);
+ }
+ DEBUG_printf("\n");
+
+ if (fp_native != NULL) {
+ fwrite(fun_data, len, 1, fp_native);
+ }
}
const char *py_obj_get_type_str(py_obj_t o_in) {
@@ -649,6 +689,12 @@ py_obj_t rt_make_function_from_id(int unique_code_id) {
py_code_t *c = &unique_codes[unique_code_id];
py_obj_base_t *o = m_new(py_obj_base_t, 1);
switch (c->kind) {
+ case PY_CODE_BYTE:
+ o->kind = O_FUN_BC;
+ o->u_fun_bc.n_args = c->n_args;
+ o->u_fun_bc.code = c->u_byte.code;
+ o->u_fun_bc.len = c->u_byte.len;
+ break;
case PY_CODE_NATIVE:
switch (c->n_args) {
case 0: o->kind = O_FUN_0; break;
@@ -658,11 +704,10 @@ py_obj_t rt_make_function_from_id(int unique_code_id) {
}
o->u_fun.fun = c->u_native.fun;
break;
- case PY_CODE_BYTE:
- o->kind = O_FUN_BC;
- o->u_fun_bc.code = c->u_byte.code;
- o->u_fun_bc.len = c->u_byte.len;
- o->u_fun_bc.n_args = c->n_args;
+ case PY_CODE_INLINE_ASM:
+ o->kind = O_FUN_ASM;
+ o->u_fun_asm.n_args = c->n_args;
+ o->u_fun_asm.fun = c->u_inline_asm.fun;
break;
default:
assert(0);
@@ -695,8 +740,8 @@ py_obj_t rt_make_function(int n_args, py_fun_t code) {
// assumes code is a pointer to a py_fun_t (i think this is safe...)
py_obj_base_t *o = m_new(py_obj_base_t, 1);
o->kind = O_FUN_N;
- o->u_fun.fun = code;
o->u_fun.n_args = n_args;
+ o->u_fun.fun = code;
return o;
}