kopia lustrzana https://github.com/micropython/micropython
py/emitinlinethumb: Update to work with new small-heap compiler.
Note that the inline assembler only works with the small-heap compiler enabled.pull/9172/head
rodzic
414537711d
commit
d64154c730
|
@ -34,6 +34,7 @@
|
|||
#include "py/emit.h"
|
||||
#include "py/compile.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/asmbase.h"
|
||||
|
||||
#if MICROPY_ENABLE_COMPILER && MICROPY_USE_SMALL_HEAP_COMPILER
|
||||
|
||||
|
@ -81,6 +82,19 @@ typedef enum {
|
|||
|
||||
#endif
|
||||
|
||||
#if MICROPY_EMIT_INLINE_ASM
|
||||
// define macros for inline assembler
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
#define ASM_DECORATOR_QSTR MP_QSTR_asm_thumb
|
||||
#define ASM_EMITTER(f) emit_inline_thumb_##f
|
||||
#elif MICROPY_EMIT_INLINE_XTENSA
|
||||
#define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa
|
||||
#define ASM_EMITTER(f) emit_inline_xtensa_##f
|
||||
#else
|
||||
#error "unknown asm emitter"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
|
||||
#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
|
||||
|
||||
|
@ -117,7 +131,7 @@ typedef struct _compiler_t {
|
|||
const emit_method_table_t *emit_method_table; // current emit method table
|
||||
#endif
|
||||
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
#if MICROPY_EMIT_INLINE_ASM
|
||||
emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
|
||||
const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm
|
||||
#endif
|
||||
|
@ -790,10 +804,10 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, const byte *p, const by
|
|||
} else if (attr == MP_QSTR_viper) {
|
||||
*emit_options = MP_EMIT_OPT_VIPER;
|
||||
#endif
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
} else if (attr == MP_QSTR_asm_thumb) {
|
||||
*emit_options = MP_EMIT_OPT_ASM_THUMB;
|
||||
#endif
|
||||
#if MICROPY_EMIT_INLINE_ASM
|
||||
} else if (attr == ASM_DECORATOR_QSTR) {
|
||||
*emit_options = MP_EMIT_OPT_ASM;
|
||||
#endif
|
||||
} else {
|
||||
compile_syntax_error(comp, NULL, "invalid micropython decorator");
|
||||
}
|
||||
|
@ -3016,7 +3030,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
|||
assert(comp->cur_except_level == 0);
|
||||
}
|
||||
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
#if MICROPY_EMIT_INLINE_ASM
|
||||
// requires 3 passes: SCOPE, CODE_SIZE, EMIT
|
||||
STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
||||
comp->pass = pass;
|
||||
|
@ -3029,7 +3043,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
|
|||
}
|
||||
|
||||
if (comp->pass > MP_PASS_SCOPE) {
|
||||
EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur, &comp->compile_error);
|
||||
EMIT_INLINE_ASM_ARG(start_pass, comp->pass, &comp->compile_error);
|
||||
}
|
||||
|
||||
// get the function definition parse node
|
||||
|
@ -3134,7 +3148,8 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
|
|||
return;
|
||||
}
|
||||
if (pass > MP_PASS_SCOPE) {
|
||||
EMIT_INLINE_ASM_ARG(align, pt_small_int_value(p_args));
|
||||
mp_asm_base_align((mp_asm_base_t*)comp->emit_inline_asm,
|
||||
pt_small_int_value(p_args));
|
||||
}
|
||||
} else if (op == MP_QSTR_data) {
|
||||
if (!(n_args >= 2 && pt_is_small_int(p_args))) {
|
||||
|
@ -3151,7 +3166,8 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
|
|||
}
|
||||
mp_int_t val;
|
||||
p_args = pt_get_small_int(p_args, &val);
|
||||
EMIT_INLINE_ASM_ARG(data, bytesize, val);
|
||||
mp_asm_base_data((mp_asm_base_t*)comp->emit_inline_asm,
|
||||
bytesize, val);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -3174,6 +3190,13 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
|
|||
|
||||
if (comp->pass > MP_PASS_SCOPE) {
|
||||
EMIT_INLINE_ASM_ARG(end_pass, type_sig);
|
||||
|
||||
if (comp->pass == MP_PASS_EMIT) {
|
||||
void *f = mp_asm_base_get_code((mp_asm_base_t*)comp->emit_inline_asm);
|
||||
mp_emit_glue_assign_native(comp->scope_cur->raw_code, MP_CODE_NATIVE_ASM,
|
||||
f, mp_asm_base_get_code_size((mp_asm_base_t*)comp->emit_inline_asm),
|
||||
NULL, comp->scope_cur->num_pos_args, 0, type_sig);
|
||||
}
|
||||
}
|
||||
|
||||
if (comp->compile_error != MP_OBJ_NULL) {
|
||||
|
@ -3309,10 +3332,10 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
|
|||
keep_going = true;
|
||||
s->raw_code = mp_emit_glue_new_raw_code();
|
||||
if (false) {
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
} else if (s->emit_options == MP_EMIT_OPT_ASM_THUMB) {
|
||||
#if MICROPY_EMIT_INLINE_ASM
|
||||
} else if (s->emit_options == MP_EMIT_OPT_ASM) {
|
||||
compile_scope_inline_asm(comp, s, MP_PASS_SCOPE);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
compile_scope(comp, s, MP_PASS_SCOPE);
|
||||
}
|
||||
|
@ -3337,9 +3360,6 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
|
|||
// compile pass 2 and 3
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
emit_t *emit_native = NULL;
|
||||
#endif
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
emit_inline_asm_t *emit_inline_thumb = NULL;
|
||||
#endif
|
||||
for (uint i = 0; i < comp->num_scopes && comp->compile_error == MP_OBJ_NULL; ++i) {
|
||||
scope_t *s = comp->scopes[i];
|
||||
|
@ -3347,20 +3367,25 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
|
|||
if (false) {
|
||||
// dummy
|
||||
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
} else if (s->emit_options == MP_EMIT_OPT_ASM_THUMB) {
|
||||
// inline assembly for thumb
|
||||
if (emit_inline_thumb == NULL) {
|
||||
emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
|
||||
#if MICROPY_EMIT_INLINE_ASM
|
||||
} else if (s->emit_options == MP_EMIT_OPT_ASM) {
|
||||
// inline assembly
|
||||
if (comp->emit_inline_asm == NULL) {
|
||||
comp->emit_inline_asm = ASM_EMITTER(new)(comp->co_data, max_num_labels);
|
||||
}
|
||||
comp->emit = NULL;
|
||||
comp->emit_inline_asm = emit_inline_thumb;
|
||||
comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
|
||||
comp->emit_inline_asm_method_table = &ASM_EMITTER(method_table);
|
||||
compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
|
||||
#if MICROPY_EMIT_INLINE_XTENSA
|
||||
// Xtensa requires an extra pass to compute size of l32r const table
|
||||
// TODO this can be improved by calculating it during SCOPE pass
|
||||
// but that requires some other structural changes to the asm emitters
|
||||
compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
|
||||
#endif
|
||||
if (comp->compile_error == MP_OBJ_NULL) {
|
||||
compile_scope_inline_asm(comp, s, MP_PASS_EMIT);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -3445,11 +3470,11 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
|
|||
#endif
|
||||
}
|
||||
#endif
|
||||
#if MICROPY_EMIT_INLINE_THUMB
|
||||
if (emit_inline_thumb != NULL) {
|
||||
emit_inline_thumb_free(emit_inline_thumb);
|
||||
#if MICROPY_EMIT_INLINE_ASM
|
||||
if (comp->emit_inline_asm != NULL) {
|
||||
ASM_EMITTER(free)(comp->emit_inline_asm);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// free the parse tree
|
||||
mp_parse_tree_clear(parse_tree);
|
||||
|
|
|
@ -271,7 +271,7 @@ typedef struct _emit_inline_asm_method_table_t {
|
|||
extern const emit_inline_asm_method_table_t emit_inline_thumb_method_table;
|
||||
extern const emit_inline_asm_method_table_t emit_inline_xtensa_method_table;
|
||||
|
||||
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels);
|
||||
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t *co_data, mp_uint_t max_num_labels);
|
||||
emit_inline_asm_t *emit_inline_xtensa_new(mp_uint_t max_num_labels);
|
||||
|
||||
void emit_inline_thumb_free(emit_inline_asm_t *emit);
|
||||
|
|
|
@ -55,6 +55,7 @@ struct _emit_inline_asm_t {
|
|||
asm_thumb_t as;
|
||||
uint16_t pass;
|
||||
mp_obj_t *error_slot;
|
||||
mp_uint_t *co_data;
|
||||
mp_uint_t max_num_labels;
|
||||
qstr *label_lookup;
|
||||
};
|
||||
|
@ -67,10 +68,11 @@ STATIC void emit_inline_thumb_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) {
|
|||
*emit->error_slot = exc;
|
||||
}
|
||||
|
||||
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels) {
|
||||
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t *co_data, mp_uint_t max_num_labels) {
|
||||
emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);
|
||||
memset(&emit->as, 0, sizeof(emit->as));
|
||||
mp_asm_base_init(&emit->as.base, max_num_labels);
|
||||
emit->co_data = co_data;
|
||||
emit->max_num_labels = max_num_labels;
|
||||
emit->label_lookup = m_new(qstr, max_num_labels);
|
||||
return emit;
|
||||
|
@ -97,21 +99,21 @@ STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_s
|
|||
asm_thumb_end_pass(&emit->as);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, const byte *p, const byte *ptop) {
|
||||
mp_uint_t n_params = 0;
|
||||
while (p != ptop) {
|
||||
if (++n_params > 4) {
|
||||
emit_inline_thumb_error_msg(emit, "can only have up to 4 parameters to Thumb assembly");
|
||||
return 0;
|
||||
}
|
||||
if (!pt_is_any_id(p)) {
|
||||
STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, const byte *pn, const byte *ptop) {
|
||||
mp_uint_t n_params = pt_num_nodes(pn, ptop);
|
||||
if (n_params > 4) {
|
||||
emit_inline_thumb_error_msg(emit, "can only have up to 4 parameters to Thumb assembly");
|
||||
return 0;
|
||||
}
|
||||
for (mp_uint_t i = 0; i < n_params; i++) {
|
||||
if (!MP_PARSE_NODE_IS_ID(pn)) {
|
||||
emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3");
|
||||
return 0;
|
||||
}
|
||||
qstr qst;
|
||||
p = pt_extract_id(p, &qst);
|
||||
const char *param = qstr_str(qst);
|
||||
if (!(strlen(param) == 2 && param[0] == 'r' && param[1] == '0' + n_params - 1)) {
|
||||
pn = pt_extract_id(pn, &qst);
|
||||
const char *p = qstr_str(qst);
|
||||
if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) {
|
||||
emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3");
|
||||
return 0;
|
||||
}
|
||||
|
@ -168,8 +170,8 @@ STATIC const special_reg_name_t special_reg_name_table[] = {
|
|||
|
||||
// return empty string in case of error, so we can attempt to parse the string
|
||||
// without a special check if it was in fact a string
|
||||
STATIC const char *get_arg_str(const byte *pn) {
|
||||
if (pt_is_any_id(pn)) {
|
||||
STATIC const char *get_arg_str(mp_parse_node_t pn) {
|
||||
if (MP_PARSE_NODE_IS_ID(pn)) {
|
||||
qstr qst;
|
||||
pt_extract_id(pn, &qst);
|
||||
return qstr_str(qst);
|
||||
|
@ -178,7 +180,7 @@ STATIC const char *get_arg_str(const byte *pn) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, const byte *pn, mp_uint_t max_reg) {
|
||||
STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_uint_t max_reg) {
|
||||
const char *reg_str = get_arg_str(pn);
|
||||
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) {
|
||||
const reg_name_t *r = ®_name_table[i];
|
||||
|
@ -202,7 +204,7 @@ STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, const byte
|
|||
return 0;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, const byte *pn) {
|
||||
STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
|
||||
const char *reg_str = get_arg_str(pn);
|
||||
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(special_reg_name_table); i++) {
|
||||
const special_reg_name_t *r = &special_reg_name_table[i];
|
||||
|
@ -217,7 +219,7 @@ STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, co
|
|||
}
|
||||
|
||||
#if MICROPY_EMIT_INLINE_THUMB_FLOAT
|
||||
STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, const byte *pn) {
|
||||
STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
|
||||
const char *reg_str = get_arg_str(pn);
|
||||
if (reg_str[0] == 's' && reg_str[1] != '\0') {
|
||||
mp_uint_t regno = 0;
|
||||
|
@ -245,31 +247,32 @@ malformed:
|
|||
}
|
||||
#endif
|
||||
|
||||
STATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, const byte *p) {
|
||||
STATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
|
||||
// a register list looks like {r0, r1, r2} and is parsed as a Python set
|
||||
|
||||
if (!pt_is_rule(p, PN_atom_brace)) {
|
||||
if (!pt_is_rule(pn, PN_atom_brace)) {
|
||||
goto bad_arg;
|
||||
}
|
||||
|
||||
const byte *ptop;
|
||||
p = pt_rule_extract_top(p, &ptop);
|
||||
pn = pt_rule_extract_top(pn, &ptop);
|
||||
|
||||
mp_uint_t reglist = 0;
|
||||
|
||||
if (p == ptop) {
|
||||
if (pn == ptop) {
|
||||
goto bad_arg;
|
||||
} else if (pt_is_any_id(p)) {
|
||||
}
|
||||
if (MP_PARSE_NODE_IS_ID(pn)) {
|
||||
// set with one element
|
||||
reglist |= 1 << get_arg_reg(emit, op, p, 15);
|
||||
} else if (pt_is_rule(p, PN_dictorsetmaker)) {
|
||||
p = pt_rule_first(p);
|
||||
const byte *p1 = pt_next(p);
|
||||
reglist |= 1 << get_arg_reg(emit, op, pn, 15);
|
||||
} else if (pt_is_rule(pn, PN_dictorsetmaker)) {
|
||||
pn = pt_rule_first(pn);
|
||||
const byte *p1 = pt_next(pn);
|
||||
if (pt_is_rule(p1, PN_dictorsetmaker_list)) {
|
||||
// set with multiple elements
|
||||
|
||||
// get first element of set (we rely on get_arg_reg to catch syntax errors)
|
||||
reglist |= 1 << get_arg_reg(emit, op, p, 15);
|
||||
reglist |= 1 << get_arg_reg(emit, op, pn, 15);
|
||||
|
||||
// get tail elements (2nd, 3rd, ...)
|
||||
const byte *p1_top;
|
||||
|
@ -296,9 +299,9 @@ bad_arg:
|
|||
return 0;
|
||||
}
|
||||
|
||||
STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, const byte *pn, uint32_t fit_mask) {
|
||||
STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint32_t fit_mask) {
|
||||
mp_obj_t o;
|
||||
if (!mp_parse_node_get_int_maybe(pn, &o)) {
|
||||
if (!mp_parse_node_get_int_maybe(pn, &o, emit->co_data)) {
|
||||
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an integer", op));
|
||||
return 0;
|
||||
}
|
||||
|
@ -310,25 +313,25 @@ STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, const byte *p
|
|||
return i;
|
||||
}
|
||||
|
||||
STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, const byte *p, const byte **p_base, const byte **p_offset) {
|
||||
if (!pt_is_rule(p, PN_atom_bracket)) {
|
||||
STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_parse_node_t *pn_base, mp_parse_node_t *pn_offset) {
|
||||
if (!pt_is_rule(pn, PN_atom_bracket)) {
|
||||
goto bad_arg;
|
||||
}
|
||||
if (pt_is_rule_empty(p)) {
|
||||
if (pt_is_rule_empty(pn)) {
|
||||
goto bad_arg;
|
||||
}
|
||||
p = pt_rule_first(p);
|
||||
if (!pt_is_rule(p, PN_testlist_comp)) {
|
||||
pn = pt_rule_first(pn);
|
||||
if (!pt_is_rule(pn, PN_testlist_comp)) {
|
||||
goto bad_arg;
|
||||
}
|
||||
const byte *ptop;
|
||||
p = pt_rule_extract_top(p, &ptop);
|
||||
if (pt_num_nodes(p, ptop) != 2) {
|
||||
pn = pt_rule_extract_top(pn, &ptop);
|
||||
if (pt_num_nodes(pn, ptop) != 2) {
|
||||
goto bad_arg;
|
||||
}
|
||||
|
||||
*p_base = p;
|
||||
*p_offset = pt_next(p);
|
||||
*pn_base = pn;
|
||||
*pn_offset = pt_next(pn);
|
||||
return true;
|
||||
|
||||
bad_arg:
|
||||
|
@ -336,13 +339,13 @@ bad_arg:
|
|||
return false;
|
||||
}
|
||||
|
||||
STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, const byte *p) {
|
||||
if (!pt_is_any_id(p)) {
|
||||
STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
|
||||
if (!MP_PARSE_NODE_IS_ID(pn)) {
|
||||
emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a label", op));
|
||||
return 0;
|
||||
}
|
||||
qstr label_qstr;
|
||||
pt_extract_id(p, &label_qstr);
|
||||
pt_extract_id(pn, &label_qstr);
|
||||
for (uint i = 0; i < emit->max_num_labels; i++) {
|
||||
if (emit->label_lookup[i] == label_qstr) {
|
||||
return i;
|
||||
|
@ -421,7 +424,7 @@ STATIC const format_vfp_op_t format_vfp_op_table[] = {
|
|||
// shorthand alias for whether we allow ARMv7-M instructions
|
||||
#define ARMV7M MICROPY_EMIT_INLINE_THUMB_ARMV7M
|
||||
|
||||
STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, const byte **pn_args) {
|
||||
STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) {
|
||||
// TODO perhaps make two tables:
|
||||
// one_args =
|
||||
// "b", LAB, asm_thumb_b_n,
|
||||
|
@ -495,7 +498,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
op_code_hi = 0xed90;
|
||||
op_vldr_vstr:;
|
||||
mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
|
||||
const byte *pn_base, *pn_offset;
|
||||
mp_parse_node_t pn_base, pn_offset;
|
||||
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
|
||||
mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
|
||||
mp_uint_t i8;
|
||||
|
@ -634,7 +637,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
}
|
||||
|
||||
} else if (n_args == 2) {
|
||||
if (pt_is_any_id(pn_args[1])) {
|
||||
if (MP_PARSE_NODE_IS_ID(pn_args[1])) {
|
||||
// second arg is a register (or should be)
|
||||
mp_uint_t op_code, op_code_hi;
|
||||
if (op == MP_QSTR_mov) {
|
||||
|
@ -713,7 +716,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
asm_thumb_mov_reg_i16(&emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);
|
||||
} else if (ARMV7M && op == MP_QSTR_ldrex) {
|
||||
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||
const byte *pn_base, *pn_offset;
|
||||
mp_parse_node_t pn_base, pn_offset;
|
||||
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
|
||||
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
|
||||
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
|
||||
|
@ -724,7 +727,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_9_10_op_table); i++) {
|
||||
if (op == format_9_10_op_table[i].name) {
|
||||
op_code = format_9_10_op_table[i].op;
|
||||
const byte *pn_base, *pn_offset;
|
||||
mp_parse_node_t pn_base, pn_offset;
|
||||
mp_uint_t rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
||||
if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
|
||||
mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
|
||||
|
@ -769,7 +772,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
|
||||
rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
|
||||
int src_b;
|
||||
if (pt_is_any_id(pn_args[2])) {
|
||||
if (MP_PARSE_NODE_IS_ID(pn_args[2])) {
|
||||
op_code |= ASM_THUMB_FORMAT_2_REG_OPERAND;
|
||||
src_b = get_arg_reg(emit, op_str, pn_args[2], 7);
|
||||
} else {
|
||||
|
@ -794,7 +797,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a
|
|||
} else if (ARMV7M && op == MP_QSTR_strex) {
|
||||
mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
|
||||
mp_uint_t r_src = get_arg_reg(emit, op_str, pn_args[1], 15);
|
||||
const byte *pn_base, *pn_offset;
|
||||
mp_parse_node_t pn_base, pn_offset;
|
||||
if (get_arg_addr(emit, op_str, pn_args[2], &pn_base, &pn_offset)) {
|
||||
mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
|
||||
mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
|
||||
|
|
22
py/parse2.c
22
py/parse2.c
|
@ -294,21 +294,15 @@ STATIC byte *pt_advance(const byte *p, bool full_rule) {
|
|||
return (byte*)p;
|
||||
}
|
||||
|
||||
bool mp_parse_node_get_int_maybe(const byte *p, mp_obj_t *o) {
|
||||
bool mp_parse_node_get_int_maybe(const byte *p, mp_obj_t *o, mp_uint_t *co_data) {
|
||||
if (pt_is_small_int(p)) {
|
||||
*o = MP_OBJ_NEW_SMALL_INT(pt_small_int_value(p));
|
||||
return true;
|
||||
#if 0 // TODO
|
||||
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_const_object)) {
|
||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
|
||||
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||
// nodes are 32-bit pointers, but need to extract 64-bit object
|
||||
*o = (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32);
|
||||
#else
|
||||
*o = (mp_obj_t)pns->nodes[0];
|
||||
#endif
|
||||
return MP_OBJ_IS_INT(*o);
|
||||
#endif
|
||||
} else if (*p == MP_PT_CONST_OBJECT) {
|
||||
size_t idx;
|
||||
p = pt_extract_const_obj(p, &idx);
|
||||
*o = (mp_obj_t)co_data[idx];
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -481,9 +475,9 @@ STATIC const byte *pt_del_byte(pt_t *pt, const byte *p) {
|
|||
|
||||
#if MICROPY_COMP_MODULE_CONST
|
||||
#include "py/builtin.h"
|
||||
STATIC const mp_map_elem_t mp_constants_table[] = {
|
||||
STATIC const mp_rom_map_elem_t mp_constants_table[] = {
|
||||
#if MICROPY_PY_UCTYPES
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uctypes), (mp_obj_t)&mp_module_uctypes },
|
||||
{ MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
|
||||
#endif
|
||||
// Extra constants as defined by a port
|
||||
MICROPY_PORT_CONSTANTS
|
||||
|
|
|
@ -44,6 +44,9 @@ struct _mp_lexer_t;
|
|||
#define MP_PT_ID_BASE (10) // +16
|
||||
#define MP_PT_RULE_BASE (26) // +173-ish
|
||||
|
||||
// macro to eliminate differences between original parser and this one
|
||||
#define MP_PARSE_NODE_IS_ID(pn) pt_is_any_id(pn)
|
||||
|
||||
typedef const byte *mp_parse_node_t;
|
||||
|
||||
extern const byte pt_const_int0[];
|
||||
|
@ -114,7 +117,7 @@ const byte *pt_rule_extract_top(const byte *p, const byte **ptop);
|
|||
const byte *pt_rule_extract(const byte *p, mp_uint_t *rule_id, size_t *src_line, const byte **ptop);
|
||||
bool pt_is_rule_empty(const byte *p);
|
||||
|
||||
bool mp_parse_node_get_int_maybe(const byte *p, mp_obj_t *o);
|
||||
bool mp_parse_node_get_int_maybe(const byte *p, mp_obj_t *o, mp_uint_t *co_data);
|
||||
const byte *mp_parse_node_extract_list(const byte **p, mp_uint_t pn_kind);
|
||||
|
||||
typedef enum {
|
||||
|
|
Ładowanie…
Reference in New Issue