From 8a8a2928e51db186aa5d2b73a294423e76441aef Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Thu, 23 Jun 2016 20:10:01 -0700 Subject: [PATCH] nios2: implement fiberRtnValueSet() The return value of _Swap() is often treated as a "don't care" value and thus often ignored. However, there are cases when it is desirable to have a meaningful return value. This meaningful value can be assigned via fiberRtnValueSet(). To that end, a new field has been added to the coop register struct to store this value for when _Swap() needs to return that meaningful value. Change-Id: Ic4967fa7d602850c09ebde18e8bfd4c97cda9ec8 Signed-off-by: Andrew Boie --- arch/nios2/core/offsets/offsets.c | 1 + arch/nios2/core/swap.S | 15 ++++++++++++--- arch/nios2/include/nano_private.h | 5 ++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/arch/nios2/core/offsets/offsets.c b/arch/nios2/core/offsets/offsets.c index 333a574f155..9147affa431 100644 --- a/arch/nios2/core/offsets/offsets.c +++ b/arch/nios2/core/offsets/offsets.c @@ -55,6 +55,7 @@ GEN_OFFSET_SYM(t_coop, r28); GEN_OFFSET_SYM(t_coop, ra); GEN_OFFSET_SYM(t_coop, sp); GEN_OFFSET_SYM(t_coop, key); +GEN_OFFSET_SYM(t_coop, retval); /* size of the struct tcs structure sans save area for floating point regs */ GEN_ABSOLUTE_SYM(__tTCS_NOFLOAT_SIZEOF, sizeof(tTCS)); diff --git a/arch/nios2/core/swap.S b/arch/nios2/core/swap.S index f07426e5fb1..bb0724ea810 100644 --- a/arch/nios2/core/swap.S +++ b/arch/nios2/core/swap.S @@ -93,15 +93,24 @@ BRANCH_LABEL(next_chosen) ldw ra, __tTCS_coopReg_OFFSET + __t_coop_ra_OFFSET(r11) ldw sp, __tTCS_coopReg_OFFSET + __t_coop_sp_OFFSET(r11) - /* Restore interrupt state in status.PIE */ - ldw r2, __tTCS_coopReg_OFFSET + __t_coop_key_OFFSET(r11) - andi r3, r2, NIOS2_STATUS_PIE_MSK + /* Load return value into r2 (return value register). garbage + * unless someone previously called fiberRtnValueSet(). Do this + * before we potentially unlock interrupts. + */ + ldw r2, __tTCS_coopReg_OFFSET + __t_coop_retval_OFFSET(r11) + + /* irq_unlock(fiber->coopReg.key); + * key was supplied as argument to _Swap() + */ + ldw r3, __tTCS_coopReg_OFFSET + __t_coop_key_OFFSET(r11) + andi r3, r3, NIOS2_STATUS_PIE_MSK beq r3, zero, no_unlock rdctl r3, status ori r3, r3, NIOS2_STATUS_PIE_MSK wrctl status, r3 BRANCH_LABEL(no_unlock) + ret diff --git a/arch/nios2/include/nano_private.h b/arch/nios2/include/nano_private.h index b4c028da67d..f81fa2d1b20 100644 --- a/arch/nios2/include/nano_private.h +++ b/arch/nios2/include/nano_private.h @@ -91,6 +91,7 @@ struct s_coop { uint32_t ra; /* Return address */ uint32_t sp; /* Stack pointer */ uint32_t key; /* IRQ status before irq_lock() and call to _Swap() */ + uint32_t retval; /* Return value of _Swap() */ }; typedef struct s_coop t_coop; @@ -170,9 +171,7 @@ static ALWAYS_INLINE void nanoArchInit(void) static ALWAYS_INLINE void fiberRtnValueSet(struct tcs *fiber, unsigned int value) { - ARG_UNUSED(fiber); - ARG_UNUSED(value); - /* STUB */ + fiber->coopReg.retval = value; } static inline void _IntLibInit(void)