Functions to convert values to/from inline asm.

This commit is contained in:
Damien 2013-10-06 12:04:13 +01:00
parent dc83382903
commit e4af64f307

View File

@ -71,7 +71,7 @@ typedef struct _py_obj_base_t {
const char *id; const char *id;
qstr u_str; qstr u_str;
#ifdef PY_FLOAT #ifdef PY_FLOAT
float_t flt; float_t u_flt;
#endif #endif
struct { // for O_FUN_[012N] struct { // for O_FUN_[012N]
int n_args; int n_args;
@ -258,7 +258,7 @@ py_obj_t py_obj_new_str(qstr qstr) {
py_obj_t py_obj_new_float(float_t val) { py_obj_t py_obj_new_float(float_t val) {
py_obj_base_t *o = m_new(py_obj_base_t, 1); py_obj_base_t *o = m_new(py_obj_base_t, 1);
o->kind = O_FLOAT; o->kind = O_FLOAT;
o->flt = val; o->u_flt = val;
return (py_obj_t)o; return (py_obj_t)o;
} }
#endif #endif
@ -298,7 +298,7 @@ typedef struct _py_code_t {
py_fun_t fun; py_fun_t fun;
} u_native; } u_native;
struct { struct {
py_fun_t fun; void *fun;
} u_inline_asm; } u_inline_asm;
}; };
} py_code_t; } py_code_t;
@ -497,7 +497,7 @@ void py_obj_print(py_obj_t o_in) {
break; break;
#ifdef PY_FLOAT #ifdef PY_FLOAT
case O_FLOAT: case O_FLOAT:
printf("%f", o->flt); printf("%f", o->u_flt);
break; break;
#endif #endif
case O_LIST: case O_LIST:
@ -745,16 +745,63 @@ py_obj_t rt_make_function(int n_args, py_fun_t code) {
return o; return o;
} }
// convert a Python object to a sensible value for inline asm
machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) {
// TODO for byte_array, pass pointer to the array
if (IS_SMALL_INT(obj)) {
return FROM_SMALL_INT(obj);
} else if (obj == py_const_none) {
return 0;
} else if (obj == py_const_false) {
return 0;
} else if (obj == py_const_true) {
return 1;
} else {
py_obj_base_t *o = obj;
switch (o->kind) {
case O_STR:
// pointer to the string (it's probably constant though!)
return (machine_uint_t)qstr_str(o->u_str);
case O_FLOAT:
// convert float to int (could also pass in float registers)
return (machine_int_t)o->u_flt;
case O_LIST:
// pointer to start of list (could pass length, but then could use len(x) for that)
return (machine_uint_t)o->u_list.items;
default:
// just pass along a pointer to the object
return (machine_uint_t)obj;
}
}
}
// convert a return value from inline asm to a sensible Python object
py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) {
return TO_SMALL_INT(val);
}
typedef machine_uint_t (*inline_asm_fun_0_t)();
typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
py_obj_t rt_call_function_0(py_obj_t fun) { py_obj_t rt_call_function_0(py_obj_t fun) {
if (IS_O(fun, O_FUN_0)) { if (IS_O(fun, O_FUN_0)) {
py_obj_base_t *o = fun; py_obj_base_t *o = fun;
DEBUG_OP_printf("calling native %p...\n", o->u_fun.fun); DEBUG_OP_printf("calling native %p with no args\n", o->u_fun.fun);
return ((py_fun_0_t)o->u_fun.fun)(); return ((py_fun_0_t)o->u_fun.fun)();
} else if (IS_O(fun, O_FUN_BC)) { } else if (IS_O(fun, O_FUN_BC)) {
py_obj_base_t *o = fun; py_obj_base_t *o = fun;
assert(o->u_fun_bc.n_args == 0); assert(o->u_fun_bc.n_args == 0);
DEBUG_OP_printf("calling byte code %p...\n", o->u_fun_bc.code); DEBUG_OP_printf("calling byte code %p with no args\n", o->u_fun_bc.code);
return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, NULL, 0); return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, NULL, 0);
} else if (IS_O(fun, O_FUN_ASM)) {
py_obj_base_t *o = fun;
assert(o->u_fun_asm.n_args == 0);
DEBUG_OP_printf("calling inline asm %p with no args\n", o->u_fun_asm.fun);
return rt_convert_val_from_inline_asm(((inline_asm_fun_0_t)o->u_fun_asm.fun)());
} else { } else {
printf("fun0:%p\n", fun); printf("fun0:%p\n", fun);
assert(0); assert(0);
@ -776,13 +823,7 @@ py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
py_obj_base_t *o = fun; py_obj_base_t *o = fun;
assert(o->u_fun_asm.n_args == 1); assert(o->u_fun_asm.n_args == 1);
DEBUG_OP_printf("calling inline asm %p with 1 arg\n", o->u_fun_asm.fun); DEBUG_OP_printf("calling inline asm %p with 1 arg\n", o->u_fun_asm.fun);
machine_int_t arg_val; return rt_convert_val_from_inline_asm(((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(arg)));
if (IS_SMALL_INT(arg)) {
arg_val = FROM_SMALL_INT(arg);
} else {
arg_val = arg;
}
return ((py_fun_1_t)o->u_fun_asm.fun)(arg_val);
} else if (IS_O(fun, O_BOUND_METH)) { } else if (IS_O(fun, O_BOUND_METH)) {
py_obj_base_t *o = fun; py_obj_base_t *o = fun;
return rt_call_function_2(o->u_bound_meth.meth, o->u_bound_meth.self, arg); return rt_call_function_2(o->u_bound_meth.meth, o->u_bound_meth.self, arg);
@ -796,16 +837,21 @@ py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) { py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
if (IS_O(fun, O_FUN_2)) { if (IS_O(fun, O_FUN_2)) {
py_obj_base_t *o = fun; py_obj_base_t *o = fun;
DEBUG_OP_printf("calling native %p...\n", o->u_fun.fun); DEBUG_OP_printf("calling native %p with 2 args\n", o->u_fun.fun);
return ((py_fun_2_t)o->u_fun.fun)(arg1, arg2); return ((py_fun_2_t)o->u_fun.fun)(arg1, arg2);
} else if (IS_O(fun, O_FUN_BC)) { } else if (IS_O(fun, O_FUN_BC)) {
py_obj_base_t *o = fun; py_obj_base_t *o = fun;
assert(o->u_fun_bc.n_args == 2); assert(o->u_fun_bc.n_args == 2);
DEBUG_OP_printf("calling byte code %p...\n", o->u_fun_bc.code); DEBUG_OP_printf("calling byte code %p with 2 args\n", o->u_fun_bc.code);
py_obj_t args[2]; py_obj_t args[2];
args[0] = arg1; args[0] = arg1;
args[1] = arg2; args[1] = arg2;
return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, &args[0], 2); return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, &args[0], 2);
} else if (IS_O(fun, O_FUN_ASM)) {
py_obj_base_t *o = fun;
assert(o->u_fun_asm.n_args == 2);
DEBUG_OP_printf("calling inline asm %p with 2 args\n", o->u_fun_asm.fun);
return rt_convert_val_from_inline_asm(((inline_asm_fun_2_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(arg1), rt_convert_obj_for_inline_asm(arg2)));
} else { } else {
assert(0); assert(0);
return py_const_none; return py_const_none;