PORT按CPU型号更简单

This commit is contained in:
2026-05-27 23:30:31 +08:00
parent 21b3c925c2
commit dc144a5cf4
24 changed files with 2519 additions and 953 deletions
+1
View File
@@ -0,0 +1 @@
#include <cpu.h>
+47
View File
@@ -0,0 +1,47 @@
#ifndef INCLUDED_CPU_H
#define INCLUDED_CPU_H
#ifndef INCLUDED_CH32V10X_H
#define INCLUDED_CH32V10X_H
#include <ch32v10x.h>
#endif /*INCLUDED_CH32V10X_H*/
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#ifndef INCLUDED_OS_COMPILER_H
#include <os_compiler.h>
#endif /*INCLUDED_OS_COMPILER_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#define CPU_KEY1 0xFA05
#define CPU_KEY2 0xBCAF
#define CPU_KEY3 0xBEEF
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
OS_STATIC_FORCE_INLINE
os_uint_t cpu_save_disable_irq_in_isr(void){
os_uint_t result;
__asm volatile ("csrrw %0, mstatus, %1":"=r"(result):"r"(0x1800):"memory");
return result;
}
OS_STATIC_FORCE_INLINE
void cpu_restore_irq_in_isr(os_uint_t value){
__set_MSTATUS(value);
}
#define os_port_disable_irq __disable_irq
#define os_port_enable_irq __enable_irq
#define os_port_save_disable_irq_in_isr cpu_save_disable_irq_in_isr
#define os_port_restore_irq_in_isr cpu_restore_irq_in_isr
#define os_port_save_disable_irq cpu_save_disable_irq_in_isr
#define os_port_restore_irq cpu_restore_irq_in_isr
#endif /*INCLUDED_CPU_H*/
+10
View File
@@ -0,0 +1,10 @@
#include <os_loopdelay.h>
#if defined (__GNUC__) /*!< GNU Compiler */
__attribute__((naked))
void os_loop_delay(unsigned long ulCount){
__asm(" add a0, a0, -1 \n"
" bne x0, a0, os_loop_delay \n"
" ret ");
}
#endif /* __CC_ARM */
+34
View File
@@ -0,0 +1,34 @@
#ifndef INCLUDED_OS_LOOPDELAY_H
#define INCLUDED_OS_LOOPDELAY_H
#ifndef INCLUDED_OS_TYPES_H
#include <os_types.h>
#endif /*INCLUDED_OS_TYPES_H*/
#define OS_LOOP_DELAY_US(n) (n * SystemCoreClock/3000000)
#define OS_LOOP_DELAY_MS(n) (n * SystemCoreClock/3000)
#define OS_LOOP_DELAY_S(n) (n * SystemCoreClock/3)
/*
72Mhz时钟时,当ulCount为1时,函数耗时3个时钟,延时=3*1/72us=1/24us
SystemCoreClock=72000000
us级延时,延时n微秒
LoopDelay(n*(SystemCoreClock/3000000));
ms级延时,延时n毫秒
LoopDelay(n*(SystemCoreClock/3000));
m级延时,延时n秒
LoopDelay(n*(SystemCoreClock/3));
*/
void os_loop_delay(unsigned long ulCount);
#define OS_LoopDelayUS(n) os_loop_delay(OS_LOOP_DELAY_US(n))
#define OS_LoopDelayMS(n) os_loop_delay(OS_LOOP_DELAY_MS(n))
#define OS_LoopDelayS(n) os_loop_delay(OS_LOOP_DELAY_S(n))
#endif /*INCLUDED_OS_LOOPDELAY_H*/
+226
View File
@@ -0,0 +1,226 @@
#include "os_port.h"
#include "os_stack.h"
#include "os_macros.h"
#include "os_align.h"
#include "os_compiler.h"
#include "os_systick.h"
#include "os_sched.h"
#include "os_isr.h"
#include "cpu.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
OS_STATIC_FORCE_INLINE
uint32_t _SysTick_Config(os_tick_t ticks)
{
NVIC->CFGR = (CPU_KEY1<<16) | (1<<1/*NESTCTRL*/) | (1<<0/*HWSTKCTRL*/); /* 关闭硬件压栈和嵌套 */
NVIC_SetPriority(SysTick_IRQn,0xf0);
NVIC_SetPriority(Software_IRQn,0xf0);
SysTick->CTLR=0;
SysTick->CNTL0=0;SysTick->CNTL1=0;SysTick->CNTL2=0;SysTick->CNTL3=0;
SysTick->CNTH0=0;SysTick->CNTH1=0;SysTick->CNTH2=0;SysTick->CNTH3=0;
SysTick->CMPLR0=(uint8_t)(ticks-1);
SysTick->CMPLR1=(uint8_t)((ticks-1)>>8);
SysTick->CMPLR2=(uint8_t)((ticks-1)>>16);
SysTick->CMPLR3=(uint8_t)((ticks-1)>>24);
SysTick->CMPHR0=0;SysTick->CMPHR1=0;SysTick->CMPHR2=0;SysTick->CMPHR3=0;
SysTick->CTLR=0x1;
NVIC_EnableIRQ(SysTick_IRQn);
NVIC_EnableIRQ(Software_IRQn);
return 0;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
typedef struct {
#if (OS_CFG_CPU_FPU_PRESENT)
os_uintptr_t f0;
os_uintptr_t f1;
os_uintptr_t f2;
os_uintptr_t f3;
os_uintptr_t f4;
os_uintptr_t f5;
os_uintptr_t f6;
os_uintptr_t f7;
os_uintptr_t f8;
os_uintptr_t f9;
os_uintptr_t f10;
os_uintptr_t f11;
os_uintptr_t f12;
os_uintptr_t f13;
os_uintptr_t f14;
os_uintptr_t f15;
os_uintptr_t f16;
os_uintptr_t f17;
os_uintptr_t f18;
os_uintptr_t f19;
os_uintptr_t f20;
os_uintptr_t f21;
os_uintptr_t f22;
os_uintptr_t f23;
os_uintptr_t f24;
os_uintptr_t f25;
os_uintptr_t f26;
os_uintptr_t f27;
os_uintptr_t f28;
os_uintptr_t f29;
os_uintptr_t f30;
os_uintptr_t f31;
#endif
os_uintptr_t mstatus; /* zero, 用于 mstatus 保存 */
os_uintptr_t ra; /* 返回地址 */
os_uintptr_t mepc; /* 栈指针, mepc */
os_uintptr_t x3; /* 全局指针 */
os_uintptr_t x4; /* 线程指针 */
os_uintptr_t x5; /* 临时寄存器0 */
os_uintptr_t x6; /* 临时寄存器1 */
os_uintptr_t x7; /* 临时寄存器2 */
os_uintptr_t x8; /* s0/fp */
os_uintptr_t x9; /* 保存寄存器1 */
os_uintptr_t a0; /* 函数参数/返回值 */
os_uintptr_t x11; /* 函数参数 */
os_uintptr_t x12; /* 函数参数 */
os_uintptr_t x13; /* 函数参数 */
os_uintptr_t x14; /* 函数参数 */
os_uintptr_t x15; /* 函数参数 */
os_uintptr_t x16; /* 函数参数 */
os_uintptr_t x17; /* 函数参数 */
os_uintptr_t x18; /* 保存寄存器 */
os_uintptr_t x19; /* 保存寄存器 */
os_uintptr_t x20; /* 保存寄存器 */
os_uintptr_t x21; /* 保存寄存器 */
os_uintptr_t x22; /* 保存寄存器 */
os_uintptr_t x23; /* 保存寄存器 */
os_uintptr_t x24; /* 保存寄存器 */
os_uintptr_t x25; /* 保存寄存器 */
os_uintptr_t x26; /* 保存寄存器 */
os_uintptr_t x27; /* 保存寄存器 */
os_uintptr_t x28; /* 临时寄存器 */
os_uintptr_t x29; /* 临时寄存器 */
os_uintptr_t x30; /* 临时寄存器 */
os_uintptr_t x31; /* 临时寄存器 */
}os_stack_frame_t;
#define STACK_FRAME_SIZE sizeof(os_stack_frame_t)
#define MSTATUS_MPIE (1<<7)
os_stack_t os_port_cpu_stack_init(os_task_entry_t entry, void* param
, void* stack_base, os_size_t stack_size, void(*exit_entry)(void)){
os_uintptr_t stack_max = (os_uintptr_t)((uint8_t *) stack_base + stack_size);
os_uintptr_t real_max = OS_ALIGN_DOWN(stack_max, OS_ALIGN_SIZE); /* 实际栈顶的位置,对齐后的位置 */
stack_size -= (stack_max - real_max); /* 实际栈大小 */
os_stack_frame_t* p_frame = (os_stack_frame_t*)(real_max - STACK_FRAME_SIZE);
for(os_size_t i=0; i<STACK_FRAME_SIZE/sizeof(os_uintptr_t); i++){
((os_uintptr_t*)(p_frame))[i] = 0x5ac0ffee;
}
p_frame->mstatus = MSTATUS_MPIE;
p_frame->mepc = (os_uintptr_t)entry;
p_frame->a0 = (os_uintptr_t)param;
p_frame->ra = (os_uintptr_t)exit_entry;
os_stack_t stack;
stack.min = (os_uintptr_t)stack_base;
stack.max = (os_uintptr_t)real_max;
stack.type = kOsStackType_MaxToMin;
stack.sp = p_frame;
return stack;
}
//void os_port_disable_irq(void){
// RISCV_disable_irq();
//}
//
//void os_port_enable_irq(void){
// RISCV_enable_irq();
//}
//
//os_uint_t os_port_save_disable_irq(void){
// return os_port_save_disable_irq_in_isr();
//}
//
//void os_port_restore_irq(os_uint_t level){
// os_port_restore_irq_in_isr(level);
//}
//os_uint_t os_port_save_disable_irq_in_isr(void){
// return RISCV_get_set_MSTATUS(0x1800);
//}
//void os_port_restore_irq_in_isr(os_uint_t level){
// RISCV_set_MSTATUS(level);
//}
void os_sched(void){
os_sched_in_isr();
}
OS_WEAK
void os_port_init(void){
}
OS_WEAK
void os_port_startup(void){
_SysTick_Config(SystemCoreClock/8/OS_CFG_TICKS_PER_SECOND);
}
/*
* 发出上下文切换的请求
*/
void os_port_send_context_switch_request(void){
NVIC_SetPendingIRQ(Software_IRQn);
}
/*
* 清除上下文切换的请求
*/
void os_port_clear_context_switch_request(void){
NVIC_ClearPendingIRQ(Software_IRQn);
}
extern void os_port_context_switch_to(os_uintptr_t to);
OS_USED
void os_port_context_switch(void* from_sp, void* to_sp){
os_critical_enter_in_isr();
if(g_os_port_context_switch_flag==OS_TRUE){
os_critical_leave_in_isr();
return;
}
g_os_port_switch_from_sp = from_sp;
g_os_port_switch_to_sp = to_sp;
g_os_port_context_switch_flag = OS_TRUE;
os_critical_leave_in_isr();
if(from_sp==0){
os_port_context_switch_to((os_uintptr_t)to_sp);
}else{
os_port_send_context_switch_request();
}
}
void SysTick_Handler(void) __attribute__((interrupt()));
void SysTick_Handler(void){
SysTick->CTLR=0;
SysTick->CNTL0=0;SysTick->CNTL1=0;SysTick->CNTL2=0;SysTick->CNTL3=0;
SysTick->CNTH0=0;SysTick->CNTH1=0;SysTick->CNTH2=0;SysTick->CNTH3=0;
SysTick->CTLR=0x1;
// 调用系统心跳处理
os_systick_tick();
}
+321
View File
@@ -0,0 +1,321 @@
#include "os_config.h"
#if __riscv_xlen == 64
#define REG_BYTES 8
#define STORE sd
#define LOAD ld
#define FSTORE fsd
#define FLOAD fld
#elif __riscv_xlen == 32
#define REG_BYTES 4
#define STORE sw
#define LOAD lw
#define FSTORE fsw
#define FLOAD flw
#else
#error Assembler did not define __riscv_xlen
#endif
#define CONTEXT_SIZE (32 * REG_BYTES)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// CODE
#ifdef OS_CFG_CPU_CLZ_ASM_PRESENT
.section .text.cpu_clz,"ax",%progbits
.align 8
.func
.global cpu_clz
cpu_clz:
clz a0, a0
ret
.endfunc
#endif
.section .text.os_port_context_switch_to,"ax",%progbits
.align 8
.func
.global os_port_context_switch_to
.extern os_port_on_switch_success
os_port_context_switch_to:
/* machine mode, disable ISR */
li t0, 0x1800
csrw mstatus, t0
/* first save interrupt stack */
la t0, _eusrstack
addi t0, t0, -512
csrw mscratch,t0
/* restore sp */
LOAD sp, (a0)
csrrw sp, mscratch, sp
jal os_port_on_switch_success
csrrw sp, mscratch, sp
/* restore mstatus.MPIE */
LOAD a0, 0*REG_BYTES(sp)
csrs mstatus, a0
/* restore mepc */
LOAD a0, 2 * REG_BYTES(sp)
csrw mepc, a0
/* return address */
LOAD x1, 1 * REG_BYTES(sp)
LOAD x4, 4 * REG_BYTES(sp)
LOAD x5, 5 * REG_BYTES(sp)
LOAD x6, 6 * REG_BYTES(sp)
LOAD x7, 7 * REG_BYTES(sp)
LOAD x8, 8 * REG_BYTES(sp)
LOAD x9, 9 * REG_BYTES(sp)
LOAD x10, 10 * REG_BYTES(sp)
LOAD x11, 11 * REG_BYTES(sp)
LOAD x12, 12 * REG_BYTES(sp)
LOAD x13, 13 * REG_BYTES(sp)
LOAD x14, 14 * REG_BYTES(sp)
LOAD x15, 15 * REG_BYTES(sp)
LOAD x16, 16 * REG_BYTES(sp)
LOAD x17, 17 * REG_BYTES(sp)
LOAD x18, 18 * REG_BYTES(sp)
LOAD x19, 19 * REG_BYTES(sp)
LOAD x20, 20 * REG_BYTES(sp)
LOAD x21, 21 * REG_BYTES(sp)
LOAD x22, 22 * REG_BYTES(sp)
LOAD x23, 23 * REG_BYTES(sp)
LOAD x24, 24 * REG_BYTES(sp)
LOAD x25, 25 * REG_BYTES(sp)
LOAD x26, 26 * REG_BYTES(sp)
LOAD x27, 27 * REG_BYTES(sp)
LOAD x28, 28 * REG_BYTES(sp)
LOAD x29, 29 * REG_BYTES(sp)
LOAD x30, 30 * REG_BYTES(sp)
LOAD x31, 31 * REG_BYTES(sp)
addi sp, sp, CONTEXT_SIZE
/* load float reg */
#if (OS_CFG_CPU_MPU_PRESENT)
FLOAD f0, 0 * REG_BYTES(sp)
FLOAD f1, 1 * REG_BYTES(sp)
FLOAD f2, 2 * REG_BYTES(sp)
FLOAD f3, 3 * REG_BYTES(sp)
FLOAD f4, 4 * REG_BYTES(sp)
FLOAD f5, 5 * REG_BYTES(sp)
FLOAD f6, 6 * REG_BYTES(sp)
FLOAD f7, 7 * REG_BYTES(sp)
FLOAD f8, 8 * REG_BYTES(sp)
FLOAD f9, 9 * REG_BYTES(sp)
FLOAD f10, 10 * REG_BYTES(sp)
FLOAD f11, 11 * REG_BYTES(sp)
FLOAD f12, 12 * REG_BYTES(sp)
FLOAD f13, 13 * REG_BYTES(sp)
FLOAD f14, 14 * REG_BYTES(sp)
FLOAD f15, 15 * REG_BYTES(sp)
FLOAD f16, 16 * REG_BYTES(sp)
FLOAD f17, 17 * REG_BYTES(sp)
FLOAD f18, 18 * REG_BYTES(sp)
FLOAD f19, 19 * REG_BYTES(sp)
FLOAD f20, 20 * REG_BYTES(sp)
FLOAD f21, 21 * REG_BYTES(sp)
FLOAD f22, 22 * REG_BYTES(sp)
FLOAD f23, 23 * REG_BYTES(sp)
FLOAD f24, 24 * REG_BYTES(sp)
FLOAD f25, 25 * REG_BYTES(sp)
FLOAD f26, 26 * REG_BYTES(sp)
FLOAD f27, 27 * REG_BYTES(sp)
FLOAD f28, 28 * REG_BYTES(sp)
FLOAD f29, 29 * REG_BYTES(sp)
FLOAD f30, 30 * REG_BYTES(sp)
FLOAD f31, 31 * REG_BYTES(sp)
addi sp, sp, 32 * REG_BYTES
#endif
mret
.endfunc
.section .text.SW_Handler,"ax",%progbits
.align 8
.func
.global SW_Handler
.extern g_os_port_switch_from_sp
.extern g_os_port_switch_to_sp
.extern os_isr_enter
.extern os_isr_leave
.extern os_port_on_switch_success
.extern g_t0
SW_Handler:
#if (OS_CFG_CPU_FPU_PRESENT)
addi sp, sp, -32 * REG_BYTES
FSTORE f0, 0 * REG_BYTES(sp)
FSTORE f1, 1 * REG_BYTES(sp)
FSTORE f2, 2 * REG_BYTES(sp)
FSTORE f3, 3 * REG_BYTES(sp)
FSTORE f4, 4 * REG_BYTES(sp)
FSTORE f5, 5 * REG_BYTES(sp)
FSTORE f6, 6 * REG_BYTES(sp)
FSTORE f7, 7 * REG_BYTES(sp)
FSTORE f8, 8 * REG_BYTES(sp)
FSTORE f9, 9 * REG_BYTES(sp)
FSTORE f10, 10 * REG_BYTES(sp)
FSTORE f11, 11 * REG_BYTES(sp)
FSTORE f12, 12 * REG_BYTES(sp)
FSTORE f13, 13 * REG_BYTES(sp)
FSTORE f14, 14 * REG_BYTES(sp)
FSTORE f15, 15 * REG_BYTES(sp)
FSTORE f16, 16 * REG_BYTES(sp)
FSTORE f17, 17 * REG_BYTES(sp)
FSTORE f18, 18 * REG_BYTES(sp)
FSTORE f19, 19 * REG_BYTES(sp)
FSTORE f20, 20 * REG_BYTES(sp)
FSTORE f21, 21 * REG_BYTES(sp)
FSTORE f22, 22 * REG_BYTES(sp)
FSTORE f23, 23 * REG_BYTES(sp)
FSTORE f24, 24 * REG_BYTES(sp)
FSTORE f25, 25 * REG_BYTES(sp)
FSTORE f26, 26 * REG_BYTES(sp)
FSTORE f27, 27 * REG_BYTES(sp)
FSTORE f28, 28 * REG_BYTES(sp)
FSTORE f29, 29 * REG_BYTES(sp)
FSTORE f30, 30 * REG_BYTES(sp)
FSTORE f31, 31 * REG_BYTES(sp)
#endif
addi sp, sp, -CONTEXT_SIZE //
STORE t0, 5*REG_BYTES(sp) // t0
li t0, 0x80
STORE t0, 0 * REG_BYTES(sp) // MPIE
csrr t0, mepc
STORE t0, 2*REG_BYTES(sp) // pc
STORE x1, 1 * REG_BYTES(sp) // return address
STORE x4, 4 * REG_BYTES(sp)
STORE x6, 6 * REG_BYTES(sp)
STORE x7, 7 * REG_BYTES(sp)
STORE x8, 8 * REG_BYTES(sp)
STORE x9, 9 * REG_BYTES(sp)
STORE x10, 10 * REG_BYTES(sp)
STORE x11, 11 * REG_BYTES(sp)
STORE x12, 12 * REG_BYTES(sp)
STORE x13, 13 * REG_BYTES(sp)
STORE x14, 14 * REG_BYTES(sp)
STORE x15, 15 * REG_BYTES(sp)
STORE x16, 16 * REG_BYTES(sp)
STORE x17, 17 * REG_BYTES(sp)
STORE x18, 18 * REG_BYTES(sp)
STORE x19, 19 * REG_BYTES(sp)
STORE x20, 20 * REG_BYTES(sp)
STORE x21, 21 * REG_BYTES(sp)
STORE x22, 22 * REG_BYTES(sp)
STORE x23, 23 * REG_BYTES(sp)
STORE x24, 24 * REG_BYTES(sp)
STORE x25, 25 * REG_BYTES(sp)
STORE x26, 26 * REG_BYTES(sp)
STORE x27, 27 * REG_BYTES(sp)
STORE x28, 28 * REG_BYTES(sp)
STORE x29, 29 * REG_BYTES(sp)
STORE x30, 30 * REG_BYTES(sp)
STORE x31, 31 * REG_BYTES(sp)
la s0, g_os_port_switch_from_sp
LOAD s1, 0(s0)
STORE sp, 0(s1) // sp g_os_port_switch_from_sp
// isr stack
csrrw sp,mscratch,sp
jal os_port_on_switch_success
csrrw sp,mscratch,sp
la s0, g_os_port_switch_to_sp
LOAD s1, 0(s0)
LOAD sp, 0(s1) // sp g_os_port_switch_to_sp
LOAD a0, 2 * REG_BYTES(sp) // / mepc
csrw mepc, a0
LOAD x1, 1*REG_BYTES(sp)
li t0, 0x1800
csrs mstatus, t0 // M
LOAD t0, 0*REG_BYTES(sp) // mstatus
csrs mstatus, t0 // mstatus
LOAD x4, 4 * REG_BYTES(sp)
LOAD x5, 5 * REG_BYTES(sp)
LOAD x6, 6 * REG_BYTES(sp)
LOAD x7, 7 * REG_BYTES(sp)
LOAD x8, 8 * REG_BYTES(sp)
LOAD x9, 9 * REG_BYTES(sp)
LOAD x10, 10 * REG_BYTES(sp)
LOAD x11, 11 * REG_BYTES(sp)
LOAD x12, 12 * REG_BYTES(sp)
LOAD x13, 13 * REG_BYTES(sp)
LOAD x14, 14 * REG_BYTES(sp)
LOAD x15, 15 * REG_BYTES(sp)
LOAD x16, 16 * REG_BYTES(sp)
LOAD x17, 17 * REG_BYTES(sp)
LOAD x18, 18 * REG_BYTES(sp)
LOAD x19, 19 * REG_BYTES(sp)
LOAD x20, 20 * REG_BYTES(sp)
LOAD x21, 21 * REG_BYTES(sp)
LOAD x22, 22 * REG_BYTES(sp)
LOAD x23, 23 * REG_BYTES(sp)
LOAD x24, 24 * REG_BYTES(sp)
LOAD x25, 25 * REG_BYTES(sp)
LOAD x26, 26 * REG_BYTES(sp)
LOAD x27, 27 * REG_BYTES(sp)
LOAD x28, 28 * REG_BYTES(sp)
LOAD x29, 29 * REG_BYTES(sp)
LOAD x30, 30 * REG_BYTES(sp)
LOAD x31, 31 * REG_BYTES(sp)
addi sp, sp, CONTEXT_SIZE //
/* load float reg */
#if (OS_CFG_CPU_FPU_PRESENT)
FLOAD f0, 0 * REG_BYTES(sp)
FLOAD f1, 1 * REG_BYTES(sp)
FLOAD f2, 2 * REG_BYTES(sp)
FLOAD f3, 3 * REG_BYTES(sp)
FLOAD f4, 4 * REG_BYTES(sp)
FLOAD f5, 5 * REG_BYTES(sp)
FLOAD f6, 6 * REG_BYTES(sp)
FLOAD f7, 7 * REG_BYTES(sp)
FLOAD f8, 8 * REG_BYTES(sp)
FLOAD f9, 9 * REG_BYTES(sp)
FLOAD f10, 10 * REG_BYTES(sp)
FLOAD f11, 11 * REG_BYTES(sp)
FLOAD f12, 12 * REG_BYTES(sp)
FLOAD f13, 13 * REG_BYTES(sp)
FLOAD f14, 14 * REG_BYTES(sp)
FLOAD f15, 15 * REG_BYTES(sp)
FLOAD f16, 16 * REG_BYTES(sp)
FLOAD f17, 17 * REG_BYTES(sp)
FLOAD f18, 18 * REG_BYTES(sp)
FLOAD f19, 19 * REG_BYTES(sp)
FLOAD f20, 20 * REG_BYTES(sp)
FLOAD f21, 21 * REG_BYTES(sp)
FLOAD f22, 22 * REG_BYTES(sp)
FLOAD f23, 23 * REG_BYTES(sp)
FLOAD f24, 24 * REG_BYTES(sp)
FLOAD f25, 25 * REG_BYTES(sp)
FLOAD f26, 26 * REG_BYTES(sp)
FLOAD f27, 27 * REG_BYTES(sp)
FLOAD f28, 28 * REG_BYTES(sp)
FLOAD f29, 29 * REG_BYTES(sp)
FLOAD f30, 30 * REG_BYTES(sp)
FLOAD f31, 31 * REG_BYTES(sp)
addi sp, sp, 32 * REG_BYTES
#endif
mret // M 退
.endfunc
.align 4
.end