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(