36 #if MICROPY_EMIT_INLINE_XTENSA 38 struct _emit_inline_asm_t {
51 *emit->error_slot = exc;
56 memset(&emit->as, 0,
sizeof(emit->as));
58 emit->max_num_labels = max_num_labels;
59 emit->label_lookup =
m_new(
qstr, max_num_labels);
64 m_del(
qstr, emit->label_lookup, emit->max_num_labels);
71 emit->error_slot = error_slot;
73 memset(emit->label_lookup, 0, emit->max_num_labels *
sizeof(
qstr));
86 emit_inline_xtensa_error_msg(emit,
"can only have up to 4 parameters to Xtensa assembly");
89 for (
mp_uint_t i = 0; i < n_params; i++) {
91 emit_inline_xtensa_error_msg(emit,
"parameters must be registers in sequence a2 to a5");
95 if (!(
strlen(p) == 2 && p[0] ==
'a' && p[1] ==
'2' + i)) {
96 emit_inline_xtensa_error_msg(emit,
"parameters must be registers in sequence a2 to a5");
104 assert(label_num < emit->max_num_labels);
107 for (
uint i = 0; i < emit->max_num_labels; i++) {
108 if (emit->label_lookup[i] == label_id) {
113 emit->label_lookup[label_num] = label_id;
118 typedef struct _reg_name_t {
byte reg;
byte name[3]; } reg_name_t;
119 STATIC const reg_name_t reg_name_table[] = {
150 const char *reg_str = get_arg_str(pn);
152 const reg_name_t *r = ®_name_table[i];
153 if (reg_str[0] == r->name[0]
154 && reg_str[1] == r->name[1]
155 && reg_str[2] == r->name[2]
156 && (reg_str[2] ==
'\0' || reg_str[3] ==
'\0')) {
160 emit_inline_xtensa_error_exc(emit,
162 "'%s' expects a register", op));
173 if (min != max && ((
int)i < min || (
int)i > max)) {
186 for (
uint i = 0; i < emit->max_num_labels; i++) {
187 if (emit->label_lookup[i] == label_qstr) {
202 typedef struct _opcode_table_3arg_t {
207 } opcode_table_3arg_t;
209 STATIC const opcode_table_3arg_t opcode_table_3arg[] = {
211 {MP_QSTR_and_, RRR, 0, 1},
212 {MP_QSTR_or_, RRR, 0, 2},
213 {MP_QSTR_xor, RRR, 0, 3},
214 {MP_QSTR_add, RRR, 0, 8},
215 {MP_QSTR_sub, RRR, 0, 12},
216 {MP_QSTR_mull, RRR, 2, 8},
220 {MP_QSTR_l8ui, RRI8 | 0x10, 2, 0},
221 {MP_QSTR_l16ui, RRI8 | 0x30, 2, 1},
222 {MP_QSTR_l32i, RRI8 | 0x50, 2, 2},
223 {MP_QSTR_s8i, RRI8 | 0x10, 2, 4},
224 {MP_QSTR_s16i, RRI8 | 0x30, 2, 5},
225 {MP_QSTR_s32i, RRI8 | 0x50, 2, 6},
226 {MP_QSTR_l16si, RRI8 | 0x30, 2, 9},
227 {MP_QSTR_addi, RRI8 | 0x00, 2, 12},
245 const char *op_str = (
const char*)
qstr_data(op, &op_len);
248 if (op == MP_QSTR_ret_n) {
249 asm_xtensa_op_ret_n(&emit->as);
254 }
else if (n_args == 1) {
255 if (op == MP_QSTR_callx0) {
256 uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
257 asm_xtensa_op_callx0(&emit->as, r0);
258 }
else if (op == MP_QSTR_j) {
259 int label = get_arg_label(emit, op_str, pn_args[0]);
261 }
else if (op == MP_QSTR_jx) {
262 uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
263 asm_xtensa_op_jx(&emit->as, r0);
268 }
else if (n_args == 2) {
269 uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
270 if (op == MP_QSTR_beqz) {
271 int label = get_arg_label(emit, op_str, pn_args[1]);
273 }
else if (op == MP_QSTR_bnez) {
274 int label = get_arg_label(emit, op_str, pn_args[1]);
276 }
else if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) {
278 uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
279 asm_xtensa_op_mov_n(&emit->as, r0, r1);
280 }
else if (op == MP_QSTR_movi) {
282 uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0);
288 }
else if (n_args == 3) {
291 const opcode_table_3arg_t *o = &opcode_table_3arg[i];
293 uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
294 uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
295 if (o->type == RRR) {
296 uint r2 = get_arg_reg(emit, op_str, pn_args[2]);
298 }
else if (o->type == RRI8_B) {
299 int label = get_arg_label(emit, op_str, pn_args[2]);
303 if ((o->type & 0xf0) == 0) {
308 shift = (o->type & 0xf0) >> 5;
312 uint32_t imm = get_arg_i(emit, op_str, pn_args[2], min, max);
338 emit_inline_xtensa_start_pass,
339 emit_inline_xtensa_end_pass,
340 emit_inline_xtensa_count_params,
341 emit_inline_xtensa_label,
342 emit_inline_xtensa_op,
345 #endif // MICROPY_EMIT_INLINE_XTENSA #define MP_ASM_PASS_COMPUTE
void asm_xtensa_end_pass(asm_xtensa_t *as)
void * memset(void *b, int c, size_t len)
const char * qstr_str(qstr q)
void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label)
void asm_xtensa_j_label(asm_xtensa_t *as, uint label)
#define m_del(type, ptr, num)
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt,...)
void asm_xtensa_bccz_reg_label(asm_xtensa_t *as, uint cond, uint reg, uint label)
void mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels)
uintptr_t mp_parse_node_t
const mp_obj_type_t mp_type_SyntaxError
void asm_xtensa_op24(asm_xtensa_t *as, uint32_t op)
bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o)
mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg)
void asm_xtensa_entry(asm_xtensa_t *as, int num_locals)
#define MP_PARSE_NODE_IS_ID(pn)
#define m_del_obj(type, ptr)
void mp_asm_base_start_pass(mp_asm_base_t *as, int pass)
size_t strlen(const char *s)
#define ASM_XTENSA_CC_GEU
void emit_inline_xtensa_free(emit_inline_asm_t *emit)
#define ASM_XTENSA_CCZ_NE
#define ASM_XTENSA_CC_ALL
const byte * qstr_data(qstr q, size_t *len)
void asm_xtensa_exit(asm_xtensa_t *as)
#define ASM_XTENSA_ENCODE_RRR(op0, op1, op2, r, s, t)
#define MP_PARSE_NODE_LEAF_ARG(pn)
emit_inline_asm_t * emit_inline_xtensa_new(mp_uint_t max_num_labels)
#define ASM_XTENSA_ENCODE_RRI8(op0, r, s, t, imm8)
#define ASM_XTENSA_CC_NALL
#define ASM_XTENSA_CC_ANY
#define ASM_XTENSA_CCZ_EQ
void asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32)
const emit_inline_asm_method_table_t emit_inline_xtensa_method_table
void mp_asm_base_deinit(mp_asm_base_t *as, bool free_code)
mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg)
#define ASM_XTENSA_CC_NONE
void asm_xtensa_bcc_reg_reg_label(asm_xtensa_t *as, uint cond, uint reg1, uint reg2, uint label)
struct _emit_inline_asm_t emit_inline_asm_t