34
34
#include "py/emit.h"
35
35
#include "py/compile.h"
36
36
#include "py/runtime.h"
37
+ #include "py/asmbase.h"
37
38
38
39
#if MICROPY_ENABLE_COMPILER && MICROPY_USE_SMALL_HEAP_COMPILER
39
40
@@ -81,6 +82,19 @@ typedef enum {
81
82
82
83
#endif
83
84
85
+ #if MICROPY_EMIT_INLINE_ASM
86
+ // define macros for inline assembler
87
+ #if MICROPY_EMIT_INLINE_THUMB
88
+ #define ASM_DECORATOR_QSTR MP_QSTR_asm_thumb
89
+ #define ASM_EMITTER (f ) emit_inline_thumb_##f
90
+ #elif MICROPY_EMIT_INLINE_XTENSA
91
+ #define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa
92
+ #define ASM_EMITTER (f ) emit_inline_xtensa_##f
93
+ #else
94
+ #error "unknown asm emitter"
95
+ #endif
96
+ #endif
97
+
84
98
#define EMIT_INLINE_ASM (fun ) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
85
99
#define EMIT_INLINE_ASM_ARG (fun , ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
86
100
@@ -117,7 +131,7 @@ typedef struct _compiler_t {
117
131
const emit_method_table_t * emit_method_table ; // current emit method table
118
132
#endif
119
133
120
- #if MICROPY_EMIT_INLINE_THUMB
134
+ #if MICROPY_EMIT_INLINE_ASM
121
135
emit_inline_asm_t * emit_inline_asm ; // current emitter for inline asm
122
136
const emit_inline_asm_method_table_t * emit_inline_asm_method_table ; // current emit method table for inline asm
123
137
#endif
@@ -790,10 +804,10 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, const byte *p, const by
790
804
} else if (attr == MP_QSTR_viper ) {
791
805
* emit_options = MP_EMIT_OPT_VIPER ;
792
806
#endif
793
- #if MICROPY_EMIT_INLINE_THUMB
794
- } else if (attr == MP_QSTR_asm_thumb ) {
795
- * emit_options = MP_EMIT_OPT_ASM_THUMB ;
796
- #endif
807
+ #if MICROPY_EMIT_INLINE_ASM
808
+ } else if (attr == ASM_DECORATOR_QSTR ) {
809
+ * emit_options = MP_EMIT_OPT_ASM ;
810
+ #endif
797
811
} else {
798
812
compile_syntax_error (comp , NULL , "invalid micropython decorator" );
799
813
}
@@ -3016,7 +3030,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
3016
3030
assert (comp -> cur_except_level == 0 );
3017
3031
}
3018
3032
3019
- #if MICROPY_EMIT_INLINE_THUMB
3033
+ #if MICROPY_EMIT_INLINE_ASM
3020
3034
// requires 3 passes: SCOPE, CODE_SIZE, EMIT
3021
3035
STATIC void compile_scope_inline_asm (compiler_t * comp , scope_t * scope , pass_kind_t pass ) {
3022
3036
comp -> pass = pass ;
@@ -3029,7 +3043,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
3029
3043
}
3030
3044
3031
3045
if (comp -> pass > MP_PASS_SCOPE ) {
3032
- EMIT_INLINE_ASM_ARG (start_pass , comp -> pass , comp -> scope_cur , & comp -> compile_error );
3046
+ EMIT_INLINE_ASM_ARG (start_pass , comp -> pass , & comp -> compile_error );
3033
3047
}
3034
3048
3035
3049
// get the function definition parse node
@@ -3134,7 +3148,8 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
3134
3148
return ;
3135
3149
}
3136
3150
if (pass > MP_PASS_SCOPE ) {
3137
- EMIT_INLINE_ASM_ARG (align , pt_small_int_value (p_args ));
3151
+ mp_asm_base_align ((mp_asm_base_t * )comp -> emit_inline_asm ,
3152
+ pt_small_int_value (p_args ));
3138
3153
}
3139
3154
} else if (op == MP_QSTR_data ) {
3140
3155
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
3151
3166
}
3152
3167
mp_int_t val ;
3153
3168
p_args = pt_get_small_int (p_args , & val );
3154
- EMIT_INLINE_ASM_ARG (data , bytesize , val );
3169
+ mp_asm_base_data ((mp_asm_base_t * )comp -> emit_inline_asm ,
3170
+ bytesize , val );
3155
3171
}
3156
3172
}
3157
3173
} else {
@@ -3174,6 +3190,13 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
3174
3190
3175
3191
if (comp -> pass > MP_PASS_SCOPE ) {
3176
3192
EMIT_INLINE_ASM_ARG (end_pass , type_sig );
3193
+
3194
+ if (comp -> pass == MP_PASS_EMIT ) {
3195
+ void * f = mp_asm_base_get_code ((mp_asm_base_t * )comp -> emit_inline_asm );
3196
+ mp_emit_glue_assign_native (comp -> scope_cur -> raw_code , MP_CODE_NATIVE_ASM ,
3197
+ f , mp_asm_base_get_code_size ((mp_asm_base_t * )comp -> emit_inline_asm ),
3198
+ NULL , comp -> scope_cur -> num_pos_args , 0 , type_sig );
3199
+ }
3177
3200
}
3178
3201
3179
3202
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
3309
3332
keep_going = true;
3310
3333
s -> raw_code = mp_emit_glue_new_raw_code ();
3311
3334
if (false) {
3312
- #if MICROPY_EMIT_INLINE_THUMB
3313
- } else if (s -> emit_options == MP_EMIT_OPT_ASM_THUMB ) {
3335
+ #if MICROPY_EMIT_INLINE_ASM
3336
+ } else if (s -> emit_options == MP_EMIT_OPT_ASM ) {
3314
3337
compile_scope_inline_asm (comp , s , MP_PASS_SCOPE );
3315
- #endif
3338
+ #endif
3316
3339
} else {
3317
3340
compile_scope (comp , s , MP_PASS_SCOPE );
3318
3341
}
@@ -3337,30 +3360,32 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
3337
3360
// compile pass 2 and 3
3338
3361
#if MICROPY_EMIT_NATIVE
3339
3362
emit_t * emit_native = NULL ;
3340
- #endif
3341
- #if MICROPY_EMIT_INLINE_THUMB
3342
- emit_inline_asm_t * emit_inline_thumb = NULL ;
3343
3363
#endif
3344
3364
for (uint i = 0 ; i < comp -> num_scopes && comp -> compile_error == MP_OBJ_NULL ; ++ i ) {
3345
3365
scope_t * s = comp -> scopes [i ];
3346
3366
if (s == NULL ) { continue ; }
3347
3367
if (false) {
3348
3368
// dummy
3349
3369
3350
- #if MICROPY_EMIT_INLINE_THUMB
3351
- } else if (s -> emit_options == MP_EMIT_OPT_ASM_THUMB ) {
3352
- // inline assembly for thumb
3353
- if (emit_inline_thumb == NULL ) {
3354
- emit_inline_thumb = emit_inline_thumb_new ( max_num_labels );
3370
+ #if MICROPY_EMIT_INLINE_ASM
3371
+ } else if (s -> emit_options == MP_EMIT_OPT_ASM ) {
3372
+ // inline assembly
3373
+ if (comp -> emit_inline_asm == NULL ) {
3374
+ comp -> emit_inline_asm = ASM_EMITTER ( new )( comp -> co_data , max_num_labels );
3355
3375
}
3356
3376
comp -> emit = NULL ;
3357
- comp -> emit_inline_asm = emit_inline_thumb ;
3358
- comp -> emit_inline_asm_method_table = & emit_inline_thumb_method_table ;
3377
+ comp -> emit_inline_asm_method_table = & ASM_EMITTER (method_table );
3378
+ compile_scope_inline_asm (comp , s , MP_PASS_CODE_SIZE );
3379
+ #if MICROPY_EMIT_INLINE_XTENSA
3380
+ // Xtensa requires an extra pass to compute size of l32r const table
3381
+ // TODO this can be improved by calculating it during SCOPE pass
3382
+ // but that requires some other structural changes to the asm emitters
3359
3383
compile_scope_inline_asm (comp , s , MP_PASS_CODE_SIZE );
3384
+ #endif
3360
3385
if (comp -> compile_error == MP_OBJ_NULL ) {
3361
3386
compile_scope_inline_asm (comp , s , MP_PASS_EMIT );
3362
3387
}
3363
- #endif
3388
+ #endif
3364
3389
3365
3390
} else {
3366
3391
@@ -3445,11 +3470,11 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f
3445
3470
#endif
3446
3471
}
3447
3472
#endif
3448
- #if MICROPY_EMIT_INLINE_THUMB
3449
- if (emit_inline_thumb != NULL ) {
3450
- emit_inline_thumb_free ( emit_inline_thumb );
3473
+ #if MICROPY_EMIT_INLINE_ASM
3474
+ if (comp -> emit_inline_asm != NULL ) {
3475
+ ASM_EMITTER ( free )( comp -> emit_inline_asm );
3451
3476
}
3452
- #endif
3477
+ #endif
3453
3478
3454
3479
// free the parse tree
3455
3480
mp_parse_tree_clear (parse_tree );
0 commit comments