From 8e5aced1fd4845b23b203d8d15f9b34b6b022ceb Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 9 Dec 2016 16:39:39 +1100 Subject: [PATCH] py: Integrate Xtensa assembler into native emitter. The config option MICROPY_EMIT_XTENSA can now be enabled to target the Xtensa architecture with @micropython.native and @micropython.viper decorators. --- py/compile.c | 2 ++ py/emit.h | 3 +++ py/emitnative.c | 24 +++++++++++++++++++++++- py/mkrules.mk | 2 +- py/mpconfig.h | 7 ++++++- py/py.mk | 8 +++++++- 6 files changed, 42 insertions(+), 4 deletions(-) diff --git a/py/compile.c b/py/compile.c index 418c1100bf..7c2c89fb52 100644 --- a/py/compile.c +++ b/py/compile.c @@ -79,6 +79,8 @@ typedef enum { #define NATIVE_EMITTER(f) emit_native_thumb_##f #elif MICROPY_EMIT_ARM #define NATIVE_EMITTER(f) emit_native_arm_##f +#elif MICROPY_EMIT_XTENSA +#define NATIVE_EMITTER(f) emit_native_xtensa_##f #else #error "unknown native emitter" #endif diff --git a/py/emit.h b/py/emit.h index 885033e3d0..122df8e7d2 100644 --- a/py/emit.h +++ b/py/emit.h @@ -154,6 +154,7 @@ extern const emit_method_table_t emit_native_x64_method_table; extern const emit_method_table_t emit_native_x86_method_table; extern const emit_method_table_t emit_native_thumb_method_table; extern const emit_method_table_t emit_native_arm_method_table; +extern const emit_method_table_t emit_native_xtensa_method_table; extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops; extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops; @@ -164,6 +165,7 @@ emit_t *emit_native_x64_new(mp_obj_t *error_slot, mp_uint_t max_num_labels); emit_t *emit_native_x86_new(mp_obj_t *error_slot, mp_uint_t max_num_labels); emit_t *emit_native_thumb_new(mp_obj_t *error_slot, mp_uint_t max_num_labels); emit_t *emit_native_arm_new(mp_obj_t *error_slot, mp_uint_t max_num_labels); +emit_t *emit_native_xtensa_new(mp_obj_t *error_slot, mp_uint_t max_num_labels); void emit_bc_set_max_num_labels(emit_t* emit, mp_uint_t max_num_labels); @@ -172,6 +174,7 @@ void emit_native_x64_free(emit_t *emit); void emit_native_x86_free(emit_t *emit); void emit_native_thumb_free(emit_t *emit); void emit_native_arm_free(emit_t *emit); +void emit_native_xtensa_free(emit_t *emit); void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope); void mp_emit_bc_end_pass(emit_t *emit); diff --git a/py/emitnative.c b/py/emitnative.c index 5a7e0ea341..2e18d26b4a 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -61,7 +61,8 @@ #if (MICROPY_EMIT_X64 && N_X64) \ || (MICROPY_EMIT_X86 && N_X86) \ || (MICROPY_EMIT_THUMB && N_THUMB) \ - || (MICROPY_EMIT_ARM && N_ARM) + || (MICROPY_EMIT_ARM && N_ARM) \ + || (MICROPY_EMIT_XTENSA && N_XTENSA) \ // this is defined so that the assembler exports generic assembler API macros #define GENERIC_ASM_API (1) @@ -139,6 +140,12 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { #include "py/asmarm.h" #define EXPORT_FUN(name) emit_native_arm_##name +#elif N_XTENSA + +// Xtensa specific stuff +#include "py/asmxtensa.h" +#define EXPORT_FUN(name) emit_native_xtensa_##name + #else #error unknown native emitter @@ -1965,6 +1972,21 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { ASM_ARM_CC_NE, }; asm_arm_setcc_reg(emit->as, REG_RET, ccs[op - MP_BINARY_OP_LESS]); + #elif N_XTENSA + static uint8_t ccs[6] = { + ASM_XTENSA_CC_LT, + 0x80 | ASM_XTENSA_CC_LT, // for GT we'll swap args + ASM_XTENSA_CC_EQ, + 0x80 | ASM_XTENSA_CC_GE, // for LE we'll swap args + ASM_XTENSA_CC_GE, + ASM_XTENSA_CC_NE, + }; + uint8_t cc = ccs[op - MP_BINARY_OP_LESS]; + if ((cc & 0x80) == 0) { + asm_xtensa_setcc_reg_reg_reg(emit->as, cc, REG_RET, REG_ARG_2, reg_rhs); + } else { + asm_xtensa_setcc_reg_reg_reg(emit->as, cc & ~0x80, REG_RET, reg_rhs, REG_ARG_2); + } #else #error not implemented #endif diff --git a/py/mkrules.mk b/py/mkrules.mk index d509f7b481..f4a2363a7a 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -49,7 +49,7 @@ $(BUILD)/%.o: %.c # List all native flags since the current build system doesn't have # the micropython configuration available. However, these flags are # needed to extract all qstrings -QSTR_GEN_EXTRA_CFLAGS += -DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB -DN_ARM +QSTR_GEN_EXTRA_CFLAGS += -DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB -DN_ARM -DN_XTENSA QSTR_GEN_EXTRA_CFLAGS += -I$(BUILD)/tmp vpath %.c . $(TOP) diff --git a/py/mpconfig.h b/py/mpconfig.h index 4572fc4cc9..15f770573b 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -288,8 +288,13 @@ #define MICROPY_EMIT_ARM (0) #endif +// Whether to emit Xtensa native code +#ifndef MICROPY_EMIT_XTENSA +#define MICROPY_EMIT_XTENSA (0) +#endif + // Convenience definition for whether any native emitter is enabled -#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM) +#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA) /*****************************************************************************/ /* Compiler configuration */ diff --git a/py/py.mk b/py/py.mk index 87a860f755..9d2a188f1a 100644 --- a/py/py.mk +++ b/py/py.mk @@ -130,6 +130,8 @@ PY_O_BASENAME = \ emitinlinethumb.o \ asmarm.o \ emitnarm.o \ + asmxtensa.o \ + emitnxtensa.o \ formatfloat.o \ parsenumbase.o \ parsenum.o \ @@ -250,7 +252,7 @@ PY_O += $(BUILD)/$(BUILD)/frozen_mpy.o endif # Sources that may contain qstrings -SRC_QSTR_IGNORE = nlr% emitnx% emitnthumb% emitnarm% +SRC_QSTR_IGNORE = nlr% emitnx86% emitnx64% emitnthumb% emitnarm% emitnxtensa% SRC_QSTR = $(SRC_MOD) $(addprefix py/,$(filter-out $(SRC_QSTR_IGNORE),$(PY_O_BASENAME:.o=.c)) emitnative.c) # Anything that depends on FORCE will be considered out-of-date @@ -292,6 +294,10 @@ $(PY_BUILD)/emitnarm.o: CFLAGS += -DN_ARM $(PY_BUILD)/emitnarm.o: py/emitnative.c $(call compile_c) +$(PY_BUILD)/emitnxtensa.o: CFLAGS += -DN_XTENSA +$(PY_BUILD)/emitnxtensa.o: py/emitnative.c + $(call compile_c) + # optimising gc for speed; 5ms down to 4ms on pybv2 $(PY_BUILD)/gc.o: CFLAGS += $(CSUPEROPT)