From: rtel Date: Sun, 30 Dec 2018 20:00:43 +0000 (+0000) Subject: Move the RISC-V pxPortInitialiseStack() implementation to the assembly port file... X-Git-Tag: V10.2.0~26 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=61ff033c790eab87bc90169ee89e47ad7340789e;p=freertos Move the RISC-V pxPortInitialiseStack() implementation to the assembly port file from the C port file so it can have access to the number of chip specific registers it needs to save space for on the stack. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2616 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h index 40a7d8562..724426b1d 100644 --- a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h @@ -107,6 +107,7 @@ #define configUSE_APPLICATION_TASK_TAG 0 #define configUSE_COUNTING_SEMAPHORES 1 #define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 @@ -142,7 +143,4 @@ to exclude the API function. */ header file. */ #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); __asm volatile( "ebreak" ); for( ;; ); } -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 - - #endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch index 8f9f92c98..3a67cbcc1 100644 --- a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch @@ -57,6 +57,6 @@ - + diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/CLINT_no_extensions/freertos_risc_v_port_specific_extensions.h b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/CLINT_no_extensions/freertos_risc_v_port_specific_extensions.h index 0252ecda5..a5544b061 100644 --- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/CLINT_no_extensions/freertos_risc_v_port_specific_extensions.h +++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/CLINT_no_extensions/freertos_risc_v_port_specific_extensions.h @@ -44,7 +44,7 @@ * base set of RISC-V registers. There are additional * freertos_risc_v_port_specific_extensions.h files for RISC-V implementations * that do not include a standard CLINT or do add to the base set of RISC-V - * regiters. + * registers. * * CARE MUST BE TAKEN TO INCLDUE THE CORRECT * freertos_risc_v_port_specific_extensions.h HEADER FILE FOR THE CHIP @@ -62,5 +62,15 @@ #define __FREERTOS_RISC_V_EXTENSIONS_H__ #define portasmHAS_CLINT 1 +#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */ + +.macro portasmSAVE_ADDITIONAL_REGISTERS + /* No additional registers to save, so this macro does nothing. */ + .endm + +/* Restore the additional registers found on the Pulpino. */ +.macro portasmRESTORE_ADDITIONAL_REGISTERS + /* No additional registers to restore, so this macro does nothing. */ + .endm #endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */ diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/Pulpino_Vega_RV32M1RM/freertos_risc_v_port_specific_extensions.h b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/Pulpino_Vega_RV32M1RM/freertos_risc_v_port_specific_extensions.h index e106b7223..2448d8a78 100644 --- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/Pulpino_Vega_RV32M1RM/freertos_risc_v_port_specific_extensions.h +++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/Pulpino_Vega_RV32M1RM/freertos_risc_v_port_specific_extensions.h @@ -44,7 +44,7 @@ * base set of RISC-V registers. There are additional * freertos_risc_v_port_specific_extensions.h files for RISC-V implementations * that do not include a standard CLINT or do add to the base set of RISC-V - * regiters. + * registers. * * CARE MUST BE TAKEN TO INCLDUE THE CORRECT * freertos_risc_v_port_specific_extensions.h HEADER FILE FOR THE CHIP @@ -62,12 +62,49 @@ #define portasmHAS_CLINT 0 +/* Constants to define the additional registers found on the Pulpino RI5KY. */ +#define lpstart0 0x7b0 +#define lpend0 0x7b1 +#define lpcount0 0x7b2 +#define lpstart1 0x7b4 +#define lpend1 0x7b5 +#define lpcount1 0x7b6 + +/* Six additional registers to save and restore, as per the #defines above. */ +#define portasmADDITIONAL_CONTEXT_SIZE 6 /* Must be even number on 32-bit cores. */ + +/* Save additional registers found on the Pulpino. */ .macro portasmSAVE_ADDITIONAL_REGISTERS + addi sp, sp, -portasmADDITIONAL_CONTEXT_SIZE /* Make room for the additional registers. */ + csrr t0, lpstart0 /* Load additional registers into accessable temporary registers. */ + csrr t1, lpend0 + csrr t2, lpcount0 + csrr t3, lpstart1 + csrr t4, lpend1 + csrr t5, lpcount1 + sw t0, 1 * portWORD_SIZE( sp ) + sw t1, 2 * portWORD_SIZE( sp ) + sw t2, 3 * portWORD_SIZE( sp ) + sw t3, 4 * portWORD_SIZE( sp ) + sw t4, 5 * portWORD_SIZE( sp ) + sw t5, 6 * portWORD_SIZE( sp ) .endm +/* Restore the additional registers found on the Pulpino. */ .macro portasmRESTORE_ADDITIONAL_REGISTERS - /* This file is for use with chips that do not add to the standard RISC-V - * register set, so there is nothing to do here. */ + lw t0, 1 * portWORD_SIZE( sp ) /* Load additional registers into accessable temporary registers. */ + lw t1, 2 * portWORD_SIZE( sp ) + lw t2, 3 * portWORD_SIZE( sp ) + lw t3, 4 * portWORD_SIZE( sp ) + lw t4, 5 * portWORD_SIZE( sp ) + lw t5, 6 * portWORD_SIZE( sp ) + csrw lpstart0, t0 + csrw lpend0, t1 + csrw lpcount0, t2 + csrw lpstart1, t3 + csrw lpend1, t4 + csrw lpcount1, t5 + addi sp, sp, -portasmADDITIONAL_CONTEXT_SIZE /* Remove space added for additional registers. */ .endm #endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */ diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c index 3f9a98147..a8b492898 100644 --- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c +++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c @@ -34,13 +34,28 @@ #include "task.h" #include "portmacro.h" -#ifdef configISR_STACK_SIZE - /* The stack used by interrupt service routines. */ - static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE ] = { 0 }; - const StackType_t * const xISRStackTop = &( xISRStack[ ( configISR_STACK_SIZE & ~portBYTE_ALIGNMENT_MASK ) - 1 ] ); +/* Let the user override the pre-loading of the initial LR with the address of +prvTaskExitError() in case it messes up unwinding of the stack in the +debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/* The stack used by interrupt service routines. Set configISR_STACK_SIZE_WORDS +to use a statically allocated array as the interrupt stack. Alternative leave +configISR_STACK_SIZE_WORDS undefined and update the linker script so that a +linker variable names __freertos_irq_stack_top has the same value as the top +of the stack used by main. Using the linker script method will repurpose the +stack that was used by main before the scheduler was started for use as the +interrupt stack after the scheduler has started. */ +#ifdef configISR_STACK_SIZE_WORDS + static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 }; + const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ ( configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ) - 1 ] ); #else extern const uint32_t __freertos_irq_stack_top[]; - const uint32_t xISRStackTop = ( uint32_t ) __freertos_irq_stack_top; + const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top; #endif /* @@ -89,10 +104,10 @@ task stack, not the ISR stack). */ /*-----------------------------------------------------------*/ -void prvTaskExitError( void ) +static void prvTaskExitError( void ) { volatile uint32_t ulx = 0; - +#warning Not currently used /* A function that implements a task must not exit or attempt to return to its caller as there is nothing to return to. If a task wants to exit it should instead call vTaskDelete( NULL ). @@ -105,107 +120,6 @@ volatile uint32_t ulx = 0; } /*-----------------------------------------------------------*/ -/* - * See header file for description. - */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) -{ -uint32_t mstatus; -const uint32_t ulMPIE_Bit = 0x80, ulMPP_Bits = 0x1800; - /* - X1 to X31 integer registers for the 'I' profile, X1 to X15 for the 'E' profile. - - Register ABI Name Description Saver - x0 zero Hard-wired zero - - x1 ra Return address Caller - x2 sp Stack pointer Callee - x3 gp Global pointer - - x4 tp Thread pointer - - x5-7 t0-2 Temporaries Caller - x8 s0/fp Saved register/Frame pointer Callee - x9 s1 Saved register Callee - x10-11 a0-1 Function Arguments/return values Caller - x12-17 a2-7 Function arguments Caller - x18-27 s2-11 Saved registers Callee - x28-31 t3-6 Temporaries Caller - */ - - /* Start task with interrupt enabled. */ - __asm volatile ("csrr %0, mstatus" : "=r"(mstatus)); - mstatus |= ulMPIE_Bit | ulMPP_Bits; - pxTopOfStack--; - *pxTopOfStack = mstatus; - - /* Numbers correspond to the x register number. */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 31; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 30; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 29; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 28; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 27; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 26; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 25; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 24; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 23; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 22; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 21; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 20; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 19; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 18; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 17; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 16; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 15; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 14; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 13; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 12; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 11; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pvParameters; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 9; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 8; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 7; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 6; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 5; - pxTopOfStack--; -// *pxTopOfStack = ( StackType_t ) 4; /* Thread pointer. */ -// pxTopOfStack--; -// *pxTopOfStack = ( StackType_t ) 3; /* Global pointer. */ -// pxTopOfStack--; -// *pxTopOfStack = ( StackType_t ) 2; /* Stack pointer. */ -// pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) prvTaskExitError; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - #if( configCLINT_BASE_ADDRESS != 0 ) void vPortSetupTimerInterrupt( void ) diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S index 2abafd461..12cc49b4d 100644 --- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S +++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S @@ -25,6 +25,15 @@ * 1 tab == 4 spaces! */ +#if __riscv_xlen == 64 + #error Not implemented yet - change lw to ld, and sw to sd. + #define portWORD_SIZE 8 +#elif __riscv_xlen == 32 + #define portWORD_SIZE 4 +#else + #error Assembler did not define __riscv_xlen +#endif + /* * The FreeRTOS kernel's RISC-V port is split between the the code that is * common across all currently supported RISC-V chips (implementations of the @@ -42,7 +51,7 @@ * base set of RISC-V registers. There are additional * freertos_risc_v_port_specific_extensions.h files for RISC-V implementations * that do not include a standard CLINT or do add to the base set of RISC-V - * regiters. + * registers. * * CARE MUST BE TAKEN TO INCLDUE THE CORRECT * freertos_risc_v_port_specific_extensions.h HEADER FILE FOR THE CHIP @@ -67,27 +76,6 @@ definitions. */ #error portasmHANDLE_INTERRUPT must be defined to the function to be called to handle external/peripheral interrupts. portasmHANDLE_INTERRUPT can be defined on the assmbler command line or in the appropriate freertos_risc_v_port_specific_extensions.h header file. #endif -#ifndef portasmSAVE_ADDITIONAL_REGISTERS - /* portasmSAVE_ADDITIONAL_REGISTERS is not defined so assume no additional - registers need to be saved. */ - #define portasmSAVE_ADDITIONAL_REGISTERS -#endif - -#ifndef portasmRESTORE_ADDITIONAL_REGISTERS - /* portasmRESTORE_ADDITIONAL_REGISTERS is not defined so assume no - additional registers need to be restored. */ - #define portasmRESTORE_ADDITIONAL_REGISTERS -#endif - -#if __riscv_xlen == 64 - #error Not implemented yet - change lw to ld, and sw to sd. - #define portWORD_SIZE 8 -#elif __riscv_xlen == 32 - #define portWORD_SIZE 4 -#else - #error Assembler did not define __riscv_xlen -#endif - /* Only the standard core registers are stored by default. Any additional registers must be saved by the portasmSAVE_ADDITIONAL_REGISTERS and portasmRESTORE_ADDITIONAL_REGISTERS macros - which can be defined in a chip @@ -97,6 +85,7 @@ at the top of this file. */ .global xPortStartFirstTask .global vFreeRTOSPortTrapHandler +.global pxPortInitialiseStack .extern pxCurrentTCB .extern ulPortTrapHandler .extern vTaskSwitchContext @@ -105,11 +94,11 @@ at the top of this file. */ .extern pullNextTime .extern ulTimerIncrementsForOneTick .extern xISRStackTop -.extern vPortHandleInterrupt /*-----------------------------------------------------------*/ -.align 16 +.align 8 +.func vFreeRTOSPortTrapHandler: addi sp, sp, -portCONTEXT_SIZE sw x1, 1 * portWORD_SIZE( sp ) @@ -141,11 +130,11 @@ vFreeRTOSPortTrapHandler: sw x30, 27 * portWORD_SIZE( sp ) sw x31, 28 * portWORD_SIZE( sp ) - portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to save any registers unique to the RISC-V implementation. */ - csrr t0, mstatus /* Required for MPIE bit. */ sw t0, 29 * portWORD_SIZE( sp ) + portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to save any registers unique to the RISC-V implementation. */ + lw t0, pxCurrentTCB /* Load pxCurrentTCB. */ sw sp, 0( t0 ) /* Write sp to first TCB member. */ @@ -217,16 +206,16 @@ processed_source: lw sp, pxCurrentTCB /* Load pxCurrentTCB. */ lw sp, 0( sp ) /* Read sp from first TCB member. */ - /* Load mret with the address of the next task. */ + /* Load mret with the address of the next instruction in the task to run next. */ lw t0, 0( sp ) csrw mepc, t0 + portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to restore any registers unique to the RISC-V implementation. */ + /* Load mstatus with the interrupt enable bits used by the task. */ lw t0, 29 * portWORD_SIZE( sp ) csrw mstatus, t0 /* Required for MPIE bit. */ - portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to restore any registers unique to the RISC-V implementation. */ - lw x1, 1 * portWORD_SIZE( sp ) lw x5, 2 * portWORD_SIZE( sp ) /* t0 */ lw x6, 3 * portWORD_SIZE( sp ) /* t1 */ @@ -255,12 +244,14 @@ processed_source: lw x29, 26 * portWORD_SIZE( sp ) /* t4 */ lw x30, 27 * portWORD_SIZE( sp ) /* t5 */ lw x31, 28 * portWORD_SIZE( sp ) /* t6 */ - addi sp, sp, portCONTEXT_SIZE + addi sp, sp, portCONTEXT_SIZE mret + .endfunc /*-----------------------------------------------------------*/ -.align 16 +.align 8 +.func xPortStartFirstTask: #if( portasmHAS_CLINT != 0 ) @@ -275,6 +266,12 @@ xPortStartFirstTask: lw sp, 0( sp ) /* Read sp from first TCB member. */ lw x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */ + + portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_port_specific_extensions.h to restore any registers unique to the RISC-V implementation. */ + + lw t0, 29 * portWORD_SIZE( sp ) /* mstatus */ + csrrw x0, mstatus, t0 /* Interrupts enabled from here! */ + lw x5, 2 * portWORD_SIZE( sp ) /* t0 */ lw x6, 3 * portWORD_SIZE( sp ) /* t1 */ lw x7, 4 * portWORD_SIZE( sp ) /* t2 */ @@ -303,8 +300,98 @@ xPortStartFirstTask: lw x30, 27 * portWORD_SIZE( sp ) /* t5 */ lw x31, 28 * portWORD_SIZE( sp ) /* t6 */ addi sp, sp, portCONTEXT_SIZE - csrs mstatus, 8 /* Enable machine interrupts. */ ret - + .endfunc /*-----------------------------------------------------------*/ +/* + * Unlike other ports pxPortInitialiseStack() is written in assembly code as it + * needs access to the portasmADDITIONAL_CONTEXT_SIZE constant. The prototype + * for the function is as per the other ports: + * StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ); + * + * As per the standard RISC-V ABI pxTopcOfStack is passed in in a0, pxCode in + * a1, and pvParameters in a2. The new top of stack is passed out in a0. + * + * RISC-V maps registers to ABI names as follows (X1 to X31 integer registers + * for the 'I' profile, X1 to X15 for the 'E' profile, currently I assumed). + * + * Register ABI Name Description Saver + * x0 zero Hard-wired zero - + * x1 ra Return address Caller + * x2 sp Stack pointer Callee + * x3 gp Global pointer - + * x4 tp Thread pointer - + * x5-7 t0-2 Temporaries Caller + * x8 s0/fp Saved register/Frame pointer Callee + * x9 s1 Saved register Callee + * x10-11 a0-1 Function Arguments/return values Caller + * x12-17 a2-7 Function arguments Caller + * x18-27 s2-11 Saved registers Callee + * x28-31 t3-6 Temporaries Caller + * + * The RISC-V context is saved t FreeRTOS tasks in the following stack frame, + * where the global and thread pointers are currently assumed to be constant so + * are not saved: + * + * mstatus + * x31 + * x30 + * x29 + * x28 + * x27 + * x26 + * x25 + * x24 + * x23 + * x22 + * x21 + * x20 + * x19 + * x18 + * x17 + * x16 + * x15 + * x14 + * x13 + * x12 + * x11 + * pvParameters + * x9 + * x8 + * x7 + * x6 + * x5 + * portTASK_RETURN_ADDRESS + * pxCode + */ +.align 8 +.func +pxPortInitialiseStack: + + addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */ + +chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */ + beq t0, x0, standard_stack_frame /* No more chip specific registers to save. */ + addi a0, a0, -portWORD_SIZE /* Make space for chip specific register. */ + sw x0, 0(a0) /* Give the chip specific register an initial value of zero. */ + addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */ + j chip_specific_stack_frame /* Until no more chip specific registers. */ + +standard_stack_frame: /* Now create the stack frame for the standard registers. */ + csrr t0, mstatus /* Obtain current mstatus value. */ + addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */ + slli t1, t1, 4 + or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */ + + addi a0, a0, -portWORD_SIZE + sw t0, 0(a0) /* mstatus onto the stack. */ + addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x11-x31. */ + sw a2, 0(a0) /* Task parameters (pvParameters parameter) goes into register X10/a0 on the stack. */ + addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9. */ + sw x0, 0(a0) /* Return address onto the stack, could be portTASK_RETURN_ADDRESS */ + addi a0, a0, -portWORD_SIZE + sw a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */ + ret + .endfunc +/*-----------------------------------------------------------*/