microPython的源码解析之 asmxtensa.c

MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计.

#include <stdio.h>
#include <assert.h>

#include "py/runtime.h"

// 此文件中所有内容的包装器
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN

#include "py/asmxtensa.h"

#define WORD_SIZE (4) // 定义单词大小为4字节
#define SIGNED_FIT8(x) ((((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)) // 定义符号适合8位的宏
#define SIGNED_FIT12(x) ((((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)) // 定义符号适合12位的宏

// 汇编结束处理函数
void asm_xtensa_end_pass(asm_xtensa_t *as) {
   
    as->num_const = as->cur_const; // 将当前常量数量设置为总常量数量
    as->cur_const = 0; // 重置当前常量数量

    #if 0
    // 制作机器代码的十六进制转储
    if (as->base.pass == MP_ASM_PASS_EMIT) {
    // 如果是代码发射阶段
        uint8_t *d = as->base.code_base; // 获取代码基地址
        printf("XTENSA ASM:"); // 打印XTENSA汇编
        for (int i = 0; i < ((as->base.code_size + 15) & ~15); ++i) {
    // 遍历所有字节
            if (i % 16 == 0) {
    // 每16个字节换行
                printf("\n%08x:", (uint32_t)&d[i]);
            }
            if (i % 2 == 0) {
    // 每两个字节添加一个空格
                printf(" ");
            }
            printf("%02x", d[i]); // 打印字节值
        }
        printf("\n");
    }
    #endif
}

// 汇编入口函数
void asm_xtensa_entry(asm_xtensa_t *as, int num_locals) {
   
    // 跳过常量
    asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4);
    mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // 填充/对齐字节
    as->const_table = (uint32_t *)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4); // 获取常量表地址

    // 调整栈指针以存储a0, a12, a13, a14, a15和局部变量,16字节对齐
    as->stack_adjust = (((ASM_XTENSA_NUM_REGS_SAVED + num_locals) * WORD_SIZE) + 15) & ~15;
    if (SIGNED_FIT8(-as->stack_adjust)) {
    // 如果栈调整值适合8位有符号整数
        asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, -as->stack_adjust);
    } else {
    // 否则使用a9寄存器辅助
        asm_xtensa_op_movi(as, ASM_XTENSA_REG_A9, as->stack_adjust);
        asm_xtensa_op_sub(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A9);
    }

    // 保存返回值(a0)和调用保存寄存器(a12, a13, a14, a15)
    asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0);
    for (int i = 1; i < ASM_XTENSA_NUM_REGS_SAVED; ++i) {
   
        asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A11 + i, ASM_XTENSA_REG_A1, i);
    }
}

// 汇编退出函数
void asm_xtensa_exit(asm_xtensa_t *as) {
   
    // 恢复寄存器
    for (int i = ASM_XTENSA_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);

    // 恢复栈指针并返回
    if (SIGNED_FIT8(as->stack_adjust)) {
    // 如果栈调整值适合8位有符号整数
        asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, as->stack_adjust);
    } else {
    // 否则使用a9寄存器辅助
        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); // 从当前函数返回
}

// 汇编入口函数(Windows版本)
void asm_xtensa_entry_win(asm_xtensa_t *as, int num_locals) {
   
    // 跳过常量
    asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4);
    mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // 填充/对齐字节
    as->const_table = (uint32_t *)mp_asm_base_get_cur_to_write_bytes(
  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

openwin_top

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值