Exemple #1
0
void asm_xtensa_exit(asm_xtensa_t *as) {
    // restore registers
    for (int i = NUM_REGS_SAVED - 1; i >= 1; --i) {
        asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A11 + i, ASM_XTENSA_REG_A1, i);
    }
    asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0);

    // restore stack-pointer and return
    if (SIGNED_FIT8(as->stack_adjust)) {
        asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, as->stack_adjust);
    } else {
        asm_xtensa_op_movi(as, ASM_XTENSA_REG_A9, as->stack_adjust);
        asm_xtensa_op_add_n(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A9);
    }

    asm_xtensa_op_ret_n(as);
}
STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) {
    size_t op_len;
    const char *op_str = (const char*)qstr_data(op, &op_len);

    if (n_args == 0) {
        if (op == MP_QSTR_ret_n) {
            asm_xtensa_op_ret_n(&emit->as);
        } else {
            goto unknown_op;
        }

    } else if (n_args == 1) {
        if (op == MP_QSTR_callx0) {
            uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
            asm_xtensa_op_callx0(&emit->as, r0);
        } else if (op == MP_QSTR_j) {
            int label = get_arg_label(emit, op_str, pn_args[0]);
            asm_xtensa_j_label(&emit->as, label);
        } else if (op == MP_QSTR_jx) {
            uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
            asm_xtensa_op_jx(&emit->as, r0);
        } else {
            goto unknown_op;
        }

    } else if (n_args == 2) {
        uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
        if (op == MP_QSTR_beqz) {
            int label = get_arg_label(emit, op_str, pn_args[1]);
            asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_EQ, r0, label);
        } else if (op == MP_QSTR_bnez) {
            int label = get_arg_label(emit, op_str, pn_args[1]);
            asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_NE, r0, label);
        } else if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) {
            // we emit mov.n for both "mov" and "mov_n" opcodes
            uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
            asm_xtensa_op_mov_n(&emit->as, r0, r1);
        } else if (op == MP_QSTR_movi) {
            // for convenience we emit l32r if the integer doesn't fit in movi
            uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0);
            asm_xtensa_mov_reg_i32(&emit->as, r0, imm);
        } else {
            goto unknown_op;
        }

    } else if (n_args == 3) {
        // search table for 3 arg instructions
        for (uint i = 0; i < MP_ARRAY_SIZE(opcode_table_3arg); i++) {
            const opcode_table_3arg_t *o = &opcode_table_3arg[i];
            if (op == o->name) {
                uint r0 = get_arg_reg(emit, op_str, pn_args[0]);
                uint r1 = get_arg_reg(emit, op_str, pn_args[1]);
                if (o->type == RRR) {
                    uint r2 = get_arg_reg(emit, op_str, pn_args[2]);
                    asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, o->a0, o->a1, r0, r1, r2));
                } else if (o->type == RRI8_B) {
                    int label = get_arg_label(emit, op_str, pn_args[2]);
                    asm_xtensa_bcc_reg_reg_label(&emit->as, o->a0, r0, r1, label);
                } else {
                    int shift, min, max;
                    if ((o->type & 0xf0) == 0) {
                        shift = 0;
                        min = -128;
                        max = 127;
                    } else {
                        shift = (o->type & 0xf0) >> 5;
                        min = 0;
                        max = 0xff << shift;
                    }
                    uint32_t imm = get_arg_i(emit, op_str, pn_args[2], min, max);
                    asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRI8(o->a0, o->a1, r1, r0, (imm >> shift) & 0xff));
                }
                return;
            }
        }
        goto unknown_op;

    } else {