view src/cs/os/nucleus/tct.s @ 303:f76436d19a7a default tip

!GPRS config: fix long-standing AT+COPS chance hanging bug There has been a long-standing bug in FreeCalypso going back years: sometimes in the AT command bring-up sequence of an ACI-only MS, the AT+COPS command would produce only a power scan followed by cessation of protocol stack activity (only L1 ADC traces), instead of the expected network search sequence. This behaviour was seen in different FC firmware versions going back to Citrine, and seemed to follow some law of chance, not reliably repeatable. This bug has been tracked down and found to be specific to !GPRS configuration, stemming from our TCS2/TCS3 hybrid and reconstruction of !GPRS support that was bitrotten in TCS3.2/LoCosto version. ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3 version and had to be pulled from TCS2 - but as it turns out, there is a new field in the MMR_REG_REQ primitive that needs to be set correctly, and that psa_mms.c module is the place where this initialization needed to be added.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Jun 2023 08:23:37 +0000
parents 4e78acac3d88
children
line wrap: on
line source

;/*************************************************************************/
;/*                                                                       */
;/*        Copyright (c) 1993-1994 Accelerated Technology, Inc.           */
;/*                                                                       */
;/* PROPRIETARY RIGHTS of Accelerated Technology are involved in the      */
;/* subject matter of this material.  All manufacturing, reproduction,    */
;/* use, and sales rights pertaining to this subject matter are governed  */
;/* by the license agreement.  The recipient of this software implicitly  */
;/* accepts the terms of the license.                                     */
;/*                                                                       */
;/*************************************************************************/
;
;/*************************************************************************/
;/*                                                                       */
;/* FILE NAME                                            VERSION          */
;/*                                                                       */
;/*      tct.s                                       PLUS/THUMB/T 1.2     */
;/*                                                                       */
;/* COMPONENT                                                             */
;/*                                                                       */
;/*      TC - Thread Control                                              */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This file contains the target processor dependent routines for   */
;/*      performing target-dependent scheduling functions.                */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* DATA STRUCTURES                                                       */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* FUNCTIONS                                                             */
;/*                                                                       */
;/*      TCT_Control_Interrupts              Enable / disable interrupts  */
;/*                                          by changing                  */
;/*                                          TCD_Interrupt_Level          */
;/*      TCT_Local_Control_Interrupts        Enable/disable interrupts    */
;/*                                          by not changing              */
;/*                                          TCD_Interrupt_Level          */
;/*      TCT_Restore_Interrupts              Restores interrupts to the   */
;/*                                          level in TCD_Interrupt_Level */
;/*      TCT_Build_Task_Stack                Build initial task stack     */
;/*      TCT_Build_HISR_Stack                Build initial HISR stack     */
;/*      TCT_Build_Signal_Frame              Build signal handler frame   */
;/*      TCT_Check_Stack                     Check current stack          */
;/*      TCT_Schedule                        Schedule the next thread     */
;/*      TCT_Control_To_Thread               Transfer control to a thread */
;/*      TCT_Control_To_System               Transfer control from thread */
;/*      TCT_Signal_Exit                     Exit from signal handler     */
;/*      TCT_Current_Thread                  Returns a pointer to current */
;/*                                            thread                     */
;/*      TCT_Set_Execute_Task                Sets TCD_Execute_Task under  */
;/*                                            protection from interrupts */
;/*      TCT_Protect                         Protect critical section     */
;/*      TCT_Unprotect                       Unprotect critical section   */
;/*      TCT_Unprotect_Specific              Release specific protection  */
;/*      TCT_Set_Current_Protect             Set the thread's current     */
;/*                                            protection field           */
;/*      TCT_Protect_Switch                  Switch to protected thread   */
;/*      TCT_Schedule_Protected              Schedule the protected thread*/
;/*      TCT_Interrupt_Context_Save          Save interrupted context     */
;/*      TCT_Interrupt_Context_Restore       Restore interrupted context  */
;/*      TCT_Activate_HISR                   Activate a HISR              */
;/*      TCT_HISR_Shell                      HISR execution shell         */
;/*                                                                       */
;/* DEPENDENCIES                                                          */
;/*                                                                       */
;/*      cs_extr.h                           Common Service functions     */
;/*      tc_extr.h                           Thread Control functions     */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*	 B. Sellew	 04-19-1996	 Added saving and restoring of    */
;/*					   v5, v6, and ip, resulting in   */
;/*					   version 1.2 (spr103)		  */
;/*	 P. Roussel (TI) 07-21-1999	 Modified TCT_Schedule for GSM    */
;/*					 small sleep implementation    	  */
;/*                                                                       */
;/*************************************************************************/
;#define         NU_SOURCE_FILE
;
;#include        "cs_extr.h"                 /* Common service functions  */
;#include        "tc_extr.h"                 /* Thread control functions  */
;
;/* Define constants used in low-level initialization.  */
;
;
LOCKOUT         .equ     00C0h              ; Interrupt lockout value
LOCK_MSK        .equ     00C0h              ; Interrupt lockout mask value
MODE_MASK       .equ     001Fh              ; Processor Mode Mask
SUP_MODE        .equ     0013h              ; Supervisor Mode (SVC)
IRQ_MODE        .equ     0012h              ; Interrupt Mode (IRQ)
FIQ_MODE        .equ     0011h              ; Fast Interrupt Mode (FIQ)
;
;
;
;/* Define a variable for saving the system stack limit in.  This value is
;   intialized in INT.S and is in effect whenever the system stack is in 
;   use.  */
;
;VOID    *TCT_System_Limit;
;
;/* Define internal variables so the C compiler can provide meaningful 
;   code with offsets into data structures.  Typically, this section is
;   removed after this file is compiled down to assembly language.  */
;   
;BYTE_PTR        REG_Stack_Base;
;BYTE_PTR        REG_Stack_End;
;BYTE_PTR        REG_Stack_Ptr;
;UNSIGNED        REG_Stack_Size;
;TC_TCB         *REG_Thread_Ptr;
;TC_HCB         *REG_HISR_Ptr;
;TC_PROTECT     *REG_Protect_Ptr;
;VOID           *REG_Function_Ptr;
;
        .def   _TCT_System_Limit
        .bss   _TCT_System_Limit, 4, 4
;
;
        .text
;
;/* Define external inner-component global data references.  */
;
;extern TC_TCB          *TCD_Execute_Task;
;extern TC_HCB          *TCD_Execute_HISR;
;extern VOID            *TCD_Current_Thread;
;extern VOID            *TCD_System_Stack;
;extern INT              TCD_Interrupt_Count;
;extern TC_HCB          *TCD_Active_HISR_Heads[TC_HISR_PRIORITIES];
;extern TC_HCB          *TCD_Active_HISR_Tails[TC_HISR_PRIORITIES];
;extern INT              TCD_Interrupt_Level;
;extern UNSIGNED         TMD_Time_Slice;
;extern INT              TMD_Time_Slice_State;
;
        .ref    _TCD_Execute_Task
        .ref    _TCD_Execute_HISR
        .ref    _TCD_Current_Thread
        .ref    _TCD_System_Stack
        .ref    _TCD_Interrupt_Count
        .ref    _TCD_Active_HISR_Heads
        .ref    _TCD_Active_HISR_Tails
        .ref    _TCD_Interrupt_Level
        .ref    _TMD_Time_Slice
        .ref    _TMD_Time_Slice_State
;
;
;/* Define external function references.  */
;VOID    TCC_Task_Shell(VOID);
;VOID    TCC_Signal_Shell(VOID);
;VOID    TCT_HISR_Shell(VOID);
;VOID    ERC_System_Error(INT error);
;
        .ref    $TCC_Task_Shell
        .ref    $TCC_Signal_Shell
        .ref    $ERC_System_Error
	.ref	IND_CALL
;
;/* Define internal function references.  */
;VOID  TCT_Schedule_Protected(VOID *thread);
;
        .def    _TCT_Schedule_Protected
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/* TCT_Control_Interrupts                                                */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function enables and disables interrupts as specified by    */
;/*      the caller.  Interrupts disabled by this call are left disabled  */
;/*      until the another call is made to enable them.                   */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application                                                      */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      new_level                           New interrupt enable level   */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      old_level                           Previous interrupt enable    */
;/*                                            level                      */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;INT TCT_Control_Interrupts (INT new_level)
;{
	.def	$TCT_Control_Interrupts
$TCT_Control_Interrupts			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Control_Interrupts
;
        .def    _TCT_Control_Interrupts
_TCT_Control_Interrupts
;
;INT     old_level;                          /* Old interrupt level       */
;
;    /* lock out all interrupts before any checking or changing */
;
;    /* Obtain the current interrupt lockout posture.  */
;    old_level =  TCD_Interrupt_Level;
;       
;    /* Setup new interrupt lockout posture.  */
;    TCD_Interrupt_Level =  new_level;
;        
;    /* renable interrupts for the specified lockout */
;
;    /* Return old interrupt lockout level.  */
;    return(old_level);
;
        MRS     a3,CPSR                     ; Pickup current CPSR
        ORR     a3,a3,#LOCKOUT              ; Build lockout CPSR
        MSR     CPSR,a3                     ; Lockout interrupts temporarily
        LDR     a2,Int_Level	            ; Pickup interrupt level
        LDR     a4,[a2, #0]                 ; Pickup current interrupt lockout
        BIC     a3,a3,#LOCK_MSK             ; Clear lockout mask
        ORR     a3,a3,a1                    ; Build new CPSR with appropriate
                                            ;   interrupts locked out
        STR     a1,[a2,#0]                  ; Save current lockout 
        MSR     CPSR,a3                     ; Setup new CPSR lockout bits
        MOV     a1,a4                       ; Return previous lockout
        BX      lr                          ; Return to caller
;}    
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/* TCT_Local_Control_Interrupts                                          */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function enables and disables interrupts as specified by    */
;/*      the caller.                                                      */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application                                                      */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      new_level                           New interrupt enable level   */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      old_level                           Previous interrupt enable    */
;/*                                            level                      */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;INT TCT_Local_Control_Interrupts (INT new_level)
;{
	.def	$TCT_Local_Control_Interrupts
$TCT_Local_Control_Interrupts		    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Local_Control_Interrupts
;
        .def    _TCT_Local_Control_Interrupts
_TCT_Local_Control_Interrupts
;
;INT     old_level;                          /* Old interrupt level       */
;
;    /* read in the old level */
;    old_level = current interrupt level of processor;
;
        MRS     a3,CPSR                     ; Pickup current CPSR
        MOV     a4,a3                       ; save the old level
;
;    /* clear out the old level and set the new level */
;    current interrupt level of processor &= ~LOCKOUT;
;    current interrupt level of processor |= new_level;
;
        BIC     a3,a3,#LOCK_MSK             ; Clear all current interrupts
        ORR     a3,a3,a1                    ; Build new CPSR with new
                                            ;   interrupt level
        MSR     CPSR,a3                     ; Setup new CPSR interrupt bits
;
;    /* Return old interrupt lockout level.  */
;    return(old_level);
;
        MOV     a1,a4                       ; Return previous lockout
        BX      lr                          ; Return to caller
;}    
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*  TCT_Restore_Interrupts                                               */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function restores interrupts to that specified in the global*/
;/*      TCD_Interrupt_Level variable.                                    */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application                                                      */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None.                                                            */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None.                                                            */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID TCT_Restore_Interrupts  (VOID)
;{
	.def	$TCT_Restore_Interrupts
$TCT_Restore_Interrupts			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Restore_Interrupts
;
        .def    _TCT_Restore_Interrupts
_TCT_Restore_Interrupts
;
;    /* lock out all interrupts before any checking or changing */
;
;    /* Obtain the current interrupt lockout posture.  */
;       
;    /* reload the level base on the TCD_Interrupt_Level variable */
;        
;
        MRS     a2,CPSR                     ; Pickup current CPSR
        MOV     a3,a2                       ; save the CPSR value
        ORR     a2,a2,#LOCKOUT              ; Build lockout CPSR
        MSR     CPSR,a2                     ; Lockout interrupts temporarily
        BIC     a3,a3,#LOCK_MSK             ; Clear current interrupt levels
        LDR     a2,Int_Level	            ; Load address of TCD_Interrupt_Level
        LDR     a1,[a2, #0]                 ; Pickup current interrupt lockout
        ORR     a3,a3,a1                    ; Build new CPSR with appropriate
                                            ;   interrupts locked out
        MSR     CPSR,a3                     ; Setup new CPSR lockout bits
        BX      lr                          ; Return to caller
;}    
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Build_Task_Stack                                             */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function builds an initial stack frame for a task.  The     */
;/*      initial stack contains information concerning initial values of  */
;/*      registers and the task's point of entry.  Furthermore, the       */
;/*      initial stack frame is in the same form as an interrupt stack    */
;/*      frame.                                                           */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCC_Create_Task                     Create a new task            */
;/*      TCC_Reset_Task                      Reset the specified task     */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      task                                Task control block pointer   */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Build_Task_Stack(TC_TCB *task)
;{
	.def	$TCT_Build_Task_Stack
$TCT_Build_Task_Stack			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Build_Task_Stack
;
        .def    _TCT_Build_Task_Stack
_TCT_Build_Task_Stack
;
;    /* Pickup the stack base.  */
;    REG_Stack_Base =  (BYTE_PTR) task -> tc_stack_start;
;    
        LDR     a3,[a1,#24h]                ; Pickup the stack starting address
;
;    /* Pickup the stack size.  */
;    REG_Stack_Size =  task -> tc_stack_size;
;    
        LDR     a2,[a1,#30h]                ; Pickup the stack size in bytes
;
;    /* Calculate the stack ending address.  */
;    REG_Stack_End =  REG_Stack_Base + REG_Stack_Size - 1;
;
        ADD     a4,a2,a3                    ; Compute the beginning of stack
        BIC     a4,a4,#3                    ; Insure word alignment
        SUB     a4,a4,#4                    ; Reserve a word
;
;    /* Save the stack ending address.  */
;    task -> tc_stack_end =  REG_Stack_End;
;    
        STR     a4,[a1,#28h]                ; Save the stack ending address
;
;    /* Reference the task shell.  */
;    REG_Function_Ptr =  (VOID *) TCC_Task_Shell;
;
;    /* Build an initial stack.  This initial stack frame facilitates an 
;       interrupt return to the TCC_Task_Shell function, which in turn 
;       invokes the application task.  The initial stack frame has the 
;       following format:
;
;               (Lower Address) Stack Top ->    1       (Interrupt stack type)
;                                               CPSR    Saved CPSR
;                                               a1      Saved a1
;                                               a2      Saved a2
;                                               a3      Saved a3
;                                               a4      Saved a4
;                                               v1      Saved v1
;                                               v2      Saved v2
;                                               v3      Saved v3
;                                               v4      Saved v4
;						v5	Saved v5
;						v6	Saved v6
;                                               v7      Saved v7
;                                               v8      Saved v8
;						ip	Saved ip
;                                               sp      Saved sp
;                                               lr      Saved lr
;               (Higher Address) Stack Bottom-> pc      Saved pc
;    */
;
        LDR     a3,Task_Shell		    ; Pickup address of shell entry
        STR     a3,[a4], #-4                ; Store entry address on stack
        MOV     a3,#0                       ; Clear value for initial registers
        STR     a3,[a4], #-4                ; Store initial lr
        ADD     a3,a4,#8h                   ; Compute initial sp
        STR     a3,[a4], #-4                ; Store initial sp (Stack Bottom)
	STR	ip,[a4], #-4		    ; Store ip
        STR     a3,[a4], #-4                ; Store initial v8
        LDR     a3,[a1,#24h]                ; Pickup the stack starting address
        STR     a3,[a4], #-4                ; Store initial v7
        MOV     a3,#0                       ; Clear value for initial registers
	STR	v6,[a4], #-4		    ; Store v6
	STR	v5,[a4], #-4		    ; Store v5
        STR     a3,[a4], #-4                ; Store initial v4
        STR     a3,[a4], #-4                ; Store initial v3
        STR     a3,[a4], #-4                ; Store initial v2
        STR     a3,[a4], #-4                ; Store initial v1
        STR     a3,[a4], #-4                ; Store initial a4
        STR     a3,[a4], #-4                ; Store initial a3
        STR     a3,[a4], #-4                ; Store initial a2
        STR     a3,[a4], #-4                ; Store initial a1
        MSR     CPSR_FLG,a3                 ; Clear the flags
        MRS     a3,CPSR                     ; Pickup the CPSR
        BIC     a3,a3,#LOCK_MSK             ; Clear initial interrupt lockout
	ORR	a3,a3,#20h		    ; Set to Thumb state
        STR     a3,[a4], #-4                ; Store CPSR on the initial stack
        MOV     a3,#1                       ; Build interrupt stack type (1)
        STR     a3,[a4, #0]                 ; Store stack type on the top 
;    
;    /* Save the minimum amount of remaining stack memory.  */
;    task -> tc_stack_minimum =  REG_Stack_Size - 72;
;    
        MOV     a3,#72                      ; Size of interrupt stack frame
        SUB     a2,a2,a3                    ; Compute minimum available bytes
        STR     a2,[a1, #34h]               ; Save in minimum stack area
;
;    /* Save the new stack pointer into the task's control block.  */
;    task -> tc_stack_pointer =  (VOID *) Stack_Top;
;
        STR     a4,[a1, #2Ch]               ; Save stack pointer
        BX      lr
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Build_HISR_Stack                                             */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function builds an HISR stack frame that allows quick       */
;/*      scheduling of the HISR.                                          */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCC_Create_HISR                     Create HISR function         */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      hisr                                HISR control block pointer   */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Build_HISR_Stack(TC_HCB *hisr)
;{
	.def	$TCT_Build_HISR_Stack
$TCT_Build_HISR_Stack			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Build_HISR_Stack
;
        .def    _TCT_Build_HISR_Stack
_TCT_Build_HISR_Stack
;
;    /* Pickup the stack base.  */
;    REG_Stack_Base =  (BYTE_PTR) hisr -> tc_stack_start;
;    
        LDR     a3,[a1,#24h]                ; Pickup the stack starting address
;
;    /* Pickup the stack size.  */
;    REG_Stack_Size =  hisr -> tc_stack_size;
;    
        LDR     a2,[a1,#30h]                ; Pickup the stack size in bytes
;
;    /* Calculate the stack ending address.  */
;    REG_Stack_End =  REG_Stack_Base + REG_Stack_Size;
;    
        ADD     a4,a2,a3                    ; Compute the beginning of stack
        BIC     a4,a4,#3                    ; Insure word alignment
        SUB     a4,a4,#4                    ; Reserve a word
;
;    /* Save the stack ending address.  */
;    hisr -> tc_stack_end =  REG_Stack_End;
;    
        STR     a4,[a1,#28h]                ; Save the stack ending address
;
;    /* Reference the HISR shell.  */
;    REG_Function_Ptr =  (VOID *) TCT_HISR_Shell;
;
;    /* Build an initial stack.  This initial stack frame facilitates an 
;       solicited return to the TCT_HISR_Shell function, which in turn 
;       invokes the appropriate HISR.  The initial HISR stack frame has the 
;       following format:
;
;               (Lower Address) Stack Top ->    0       (Solicited stack type)
;						0/0x20  Saved state mask
;                                               v1      Saved v1
;                                               v2      Saved v2
;                                               v3      Saved v3
;                                               v4      Saved v4
;						v5	Saved v5
;						v6	Saved v6
;                                               v7   	Saved v7
;                                               v8      Saved v8
;						ip	Saved ip
;               (Higher Address) Stack Bottom-> pc      Saved pc
;    */
;
        LDR     a3,HISR_Shell		    ; Pickup address of shell entry
        STR     a3,[a4], #-4                ; Store entry address on stack
        ADD     a3,a4,#4h                   ; Compute initial sp
	STR	ip,[a4], #-4		    ; Store ip
        STR     a3,[a4], #-4                ; Store initial v8
        LDR     a3,[a1,#24h]                ; Pickup the stack starting address
        STR     a3,[a4], #-4                ; Store initial v7
        MOV     a3,#0                       ; Clear value for initial registers
	STR	v6,[a4], #-4		    ; Store v6
	STR	v5,[a4], #-4		    ; Store v5
        STR     a3,[a4], #-4                ; Store initial v4
        STR     a3,[a4], #-4                ; Store initial v3
        STR     a3,[a4], #-4                ; Store initial v2
        STR     a3,[a4], #-4                ; Store initial v1
	STR	a3,[a4], #-4		    ; Store initial state mask
        STR     a3,[a4, #0]                 ; Store solicited stack type on the
                                            ;   top of the stack 
;
;    /* Save the minimum amount of remaining stack memory.  */
;    hisr -> tc_stack_minimum =  REG_Stack_Size - 44;
;        
        MOV     a3,#44                      ; Size of solicited stack frame
        SUB     a2,a2,a3                    ; Compute minimum available bytes
        STR     a2,[a1, #34h]               ; Save in minimum stack area
;
;    /* Save the new stack pointer into the task's control block.  */
;    hisr -> tc_stack_pointer =  (VOID *) Stack_Top;
;
        STR     a4,[a1, #2Ch]               ; Save stack pointer
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Build_Signal_Frame                                           */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function builds a frame on top of the task's stack to       */
;/*      cause the task's signal handler to execute the next time         */
;/*      the task is executed.                                            */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCC_Send_Signals                    Send signals to a task       */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      task                                Task control block pointer   */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Build_Signal_Frame(TC_TCB *task)
;{
	.def	$TCT_Build_Signal_Frame
$TCT_Build_Signal_Frame			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Build_Signal_Frame
;
        .def    _TCT_Build_Signal_Frame
_TCT_Build_Signal_Frame
;
;    /* Pickup the stack pointer.  */
;    REG_Stack_Ptr =  (BYTE_PTR) task -> tc_stack_pointer;
;    
        LDR     a4,[a1,#2ch]                ; Pickup the current stack pointer
;
;    /* Reference the Signal shell.  */
;    REG_Function_Ptr =  (VOID *) TCC_Signal_Shell;
;
;    /* Build a signal stack.  This signal stack frame facilitates an 
;       solicited return to the TCC_Signal_Shell function, which in turn 
;       invokes the appropriate signal handler.  The initial HISR stack frame 
;       has the following format:
;
;               (Lower Address) Stack Top ->    0       (Solicited stack type)
;						0/0x20  Saved state mask
;                                               v1      Saved v1
;                                               v2      Saved v2
;                                               v3      Saved v3
;                                               v4      Saved v4
;						v5	Saved v5
;						v6	Saved v6
;                                               v7   	Saved v7
;                                               v8      Saved v8
;						ip	Saved ip
;               (Higher Address) Stack Bottom-> pc      Saved pc
;    */
;
        LDR     a3,Signal_Shell		    ; Pickup address of shell entry
        STR     a3,[a4], #-4                ; Store entry address on stack
        ADD     a3,a4,#4h                   ; Compute initial sp
	STR	ip,[a4], #-4		    ; Store ip
        STR     a3,[a4], #-4                ; Store initial v8
        LDR     a3,[a1,#24h]                ; Pickup the stack starting address
        STR     a3,[a4], #-4                ; Store initial v7
        MOV     a3,#0                       ; Clear value for initial registers
	STR	v6,[a4], #-4		    ; Store v6
	STR	v5,[a4], #-4		    ; Store v5
        STR     a3,[a4], #-4                ; Store initial v4
        STR     a3,[a4], #-4                ; Store initial v3
        STR     a3,[a4], #-4                ; Store initial v2
        STR     a3,[a4], #-4                ; Store initial v1
	MOV	a2,#20h			    ; Get initial state mask
	STR	a2,[a4, #0]		    ; Store initial state mask
        STR     a3,[a4, #0]                 ; Store solicited stack type on the
                                            ;   top of the stack 
;
;    /* Save the new stack pointer into the task's control block.  */
;    task -> tc_stack_pointer =  (VOID *) (REG_Stack_Ptr - REG_Stack_Size);
;
        STR     a4,[a1, #2Ch]               ; Save stack pointer
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Check_Stack                                                  */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function checks the current stack for overflow conditions.  */
;/*      Additionally, this function keeps track of the minimum amount    */
;/*      of stack space for the calling thread and returns the current    */
;/*      available stack space.                                           */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCC_Send_Signals                    Send signals to a task       */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      ERC_System_Error                    System error handler         */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      available bytes in stack                                         */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;UNSIGNED  TCT_Check_Stack(void)
;{
	.def	$TCT_Check_Stack
$TCT_Check_Stack			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Check_Stack
;
        .def    _TCT_Check_Stack
_TCT_Check_Stack
;
;TC_TCB         *thread;
;UNSIGNED       remaining;
;
;    /* Pickup the current task/HISR pointer.  */
;    thread =  (TC_TCB *) TCD_Current_Thread;
;
        LDR     a1,Current_Thread	    ; Pickup address of thread pointer
        LDR     a1,[a1,#0]                  ; Pickup thread pointer
;
;    /* Determine if there is a current thread.  */
;    if (thread)
;    {
;
        CMP     a1,#0                       ; Determine if a thread is active
        MOV     a4,#0                       ; Default remaining value
        BEQ     TCT_Skip_Stack_Check        ; If NU_NULL, skip stack checking
;
;        /* Determine if the stack pointers are out of range.  */
;        if ((thread -> tc_stack_pointer < thread -> tc_stack_start) ||
;            (thread -> tc_stack_pointer > thread -> tc_stack_end))
;
        LDR     a3,[a1,#24h]                ; Pickup start of stack area
        CMP     sp,a3                       ; Compare with current stack ptr
        BLT     TCT_Stack_Range_Error       ; If less, stack is out of range
        LDR     a2,[a1,#28h]                ; Pickup end of stack area
        CMP     sp,a2                       ; Compare with current stack ptr
        BLE     TCT_Stack_Range_Okay        ; If less, stack range is okay
;
;            /* Stack overflow condition exits.  */
;            ERC_System_Error(NU_STACK_OVERFLOW);
;
TCT_Stack_Range_Error
;
        STR     lr,[sp, #4]!                ; Store lr on the stack
        MOV     a1,#3                       ; Build NU_STACK_OVERFLOW code
        LDR     a4,System_Error             ; Call system error handler.  Note:
        BX      a4                          ;   control is not returned!  
                                            ;   Examine stack to find return 
                                            ;   address of this routine.
TCT_Stack_Range_Okay
;
;        /* Calculate the amount of available space on the stack.  */
;        remaining =  (BYTE_PTR) thread -> tc_stack_pointer -
;                          (BYTE_PTR) thread -> tc_stack_start;
;
        SUB     a4,sp,a3                    ; Calculate remaining stack size
;
;        /* Determine if there is enough memory on the stack to save all of the
;           registers.  */
;        if (remaining < 80)
;
        CMP     a4,#80                      ; Is there enough room for an 
                                            ;   interrupt frame?
        BCS     TCT_No_Stack_Error          ; If so, no stack overflow yet
;
;            /* Stack overflow condition is about to happen.  */
;            ERC_System_Error(NU_STACK_OVERFLOW);
;
        STR     lr,[sp, #4]!                ; Store lr on the stack
        MOV     a1,#3                       ; Build NU_STACK_OVERFLOW code
        LDR     a4,System_Error             ; Call system error handler.  Note:
        BX      a4                          ;   control is not returned!  
                                            ;   Examine stack to find return 
                                            ;   address of this routine.
TCT_No_Stack_Error
;
;        /* Determine if this is a new minimum amount of stack space.  */
;        if (remaining < thread -> tc_stack_minimum)
;
        LDR     a3,[a1,#34h]
        CMP     a4,a3
        STRCC   a4,[a1,#34h]
;
;            /* Save the new stack minimum.  */
;            thread -> tc_stack_minimum =  remaining;
;    }
;    else
;
;        /* Set the remaining bytes to 0.  */
;        remaining =  0;
;
;    /* Return the remaining number of bytes on the stack.  */
;    return(remaining);
;
TCT_Skip_Stack_Check
        MOV     a1,a4                       ; Return remaining bytes
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCC_Schedule                                                     */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function waits for a thread to become ready.  Once a thread */
;/*      is ready, this function initiates a transfer of control to that  */
;/*      thread.                                                          */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      INC_Initialize                      Main initialization routine  */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      TCT_Control_To_Thread               Transfer control to a thread */
;/*      INT_Small_Sleep		     GSM small sleep              */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      TCD_Execute_Task                    Pointer to task to execute   */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*	 P. Roussel (TI) 07-21-1999	 Call GSM small sleep 		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Schedule(void)
;{
	.def	$TCT_Schedule
$TCT_Schedule				    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Schedule
;
        .def    _TCT_Schedule
_TCT_Schedule
;
;    /* Restore interrupts according to the value contained in 
;       TCD_Interrupt_Level.  */
;
        LDR     a2,Int_Level	            ; Build address of interrupt level
        MRS     a1,CPSR                     ; Pickup current CPSR
        LDR     a3,[a2, #0]                 ; Pickup current interrupt lockout
        BIC     a1,a1,#LOCK_MSK             ; Clear the interrupt lockout bits
        ORR     a1,a1,a3                    ; Build new interrupt lockout CPSR
        MSR     CPSR,a1                     ; Setup new CPSR 
        LDR     a3,Execute_HISR		    ; Pickup TCD_Execute_HISR address
        LDR     a4,Execute_Task		    ; Pickup TCD_Execute_Task address
;
;    /* Wait until a thread (task or HISR) is available to execute.  */
;    do
;    {
	.def	TCT_Schedule_Loop
TCT_Schedule_Loop
;
;    } while ((!TCD_Execute_HISR) && (!TCD_Execute_Task));
;
        LDR     a1,[a3, #0]                 ; Pickup highest priority HISR ptr
        CMP     a1,#0                       ; Is there a HISR active?
        BNE     TCT_Schedule_Thread         ; Found an HISR
        LDR     a1,[a4, #0]                 ; Pickup highest priority Task ptr
        CMP     a1,#0                       ; Is there a task active?

        .ref    INT_Small_Sleep
        BEQ     INT_Small_Sleep		    ; No, enter the GSM Small Sleep mode
	
;
;    /* Yes, either a task or an HISR is ready to execute.  Lockout 
;       interrupts while the thread is transferred to.  */
;
TCT_Schedule_Thread
        MRS     a2,CPSR                     ; Pickup CPSR again
        ORR     a2,a2,#LOCKOUT              ; Build interrupt lockout value
        MSR     CPSR,a2                     ; Lockout interrupts
;    
;    /* Transfer control to the thread by falling through to the following
;       routine.  */
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Control_To_Thread                                            */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function transfers control to the specified thread.  Each   */
;/*      time control is transferred to a thread, its scheduled counter   */
;/*      is incremented.  Additionally, time-slicing for task threads is  */
;/*      enabled in this routine.  The TCD_Current_Thread pointer is      */
;/*      setup by this function.                                          */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCT_Schedule                        Indirectly called            */
;/*      TCT_Protect                         Protection task switch       */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      thread                              Thread control block pointer */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Control_To_Thread(TC_TCB *thread)
;{
;
_TCT_Control_To_Thread
;
;    /* Setup the current thread pointer.  */
;    TCD_Current_Thread =  (VOID *) thread;
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a3,[a1, #1ch]               ; Pickup scheduled count
        STR     a1,[a2, #0]                 ; Setup current thread pointer
; TI CODE : Call the Function that log the Current Thread.

  .if OP_L1_STANDALONE = 0
    .if TI_NUC_MONITOR = 1
  		.global _ti_nuc_monitor_Thread_log
		STMFD	sp!,{r0-r5}
		BL		_ti_nuc_monitor_Thread_log		; Call the Thread Log function.
		LDMFD	sp!,{r0-r5}
    .endif
  .endif
;
;    /* Increment the thread scheduled counter.  */
;    thread -> tc_scheduled++;
;
        LDR     a4,[a1, #20h]               ; Pickup time slice value
        ADD     a3,a3,#1                    ; Increment the scheduled count
        STR     a3,[a1, #1ch]               ; Store new scheduled count
;
;    /* Check for time slice option.  */
;    if (thread -> tc_cur_time_slice)
;    {
        CMP     a4,#0                       ; Is there a time slice?
        BEQ     TCT_No_Start_TS_1           ; If 0, there is no time slice
;
;        /* Start a time slice.  */
;        TMD_Time_Slice =        thread -> tc_cur_time_slice;
;        TMD_Time_Slice_State =  0;
;
        LDR     a3,Time_Slice		    ; Pickup address of TMD_Time_Slice
        LDR     a2,Slice_State		    ; Pickup address of 
                                            ;   TMD_Time_Slice_State
        STR     a4,[a3,#0]                  ; Setup the time slice
        MOV     a3,#0                       ; Build active state flag
        STR     a3,[a2,#0]                  ; Set the active flag
;    }
TCT_No_Start_TS_1
;
;    /* Pickup the stack pointer and resume the thread.  */
;    REG_Stack_Ptr =  thread -> tc_stack_pointer;
;
        LDR     sp,[a1, #2ch]               ; Switch to thread's stack pointer
;         
;     /* Pop off the saved information associated with the thread. After we
;        determine which type of stack is present.  A 1 on the top of the 
;        stack indicates an interrupt stack, while a 0 on the top of the
;        stack indicates a solicited type of stack.  */
;        
;     /* Remember that the interrupt level that is restored must represent
;        the interrupt level in TCD_Interrupt_Level.  */
;
        LDR     a2,[sp], #4                 ; Pop off the stack type 
        CMP     a2,#1                       ; See if it is an interrupt stack
        BEQ     TCT_Interrupt_Resume        ; If so, an interrupt resume of
                                            ;   thread is required
        LDR     a2,Int_Level		    ; Pickup address of interrupt 
                                            ;   lockout
        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#LOCK_MSK             ; Clear lockout mask
        LDR     a3,[a2, #0]                 ; Pickup interrupt lockout mask
        ORR     a1,a1,a3                    ; Build new interrupt lockout mask
	LDR	a3,[sp], #4		    ; Pop off the state mask
	ORR	a1,a1,a3		    ; Set appropriate state
	MSR	SPSR,a1			    ; Place in the SPSR
        LDMIA   sp!,{v1-ip,pc}^       	    ; A solicited return is required.  
;
TCT_Interrupt_Resume
        LDR     a1,[sp],#4                  ; Pop off the CPSR
        LDR     a2,Int_Level		    ; Pickup address of interrupt 
                                            ;   lockout
        BIC     a1,a1,#LOCK_MSK             ; Clear lockout mask
        LDR     a3,[a2, #0]                 ; Pickup interrupt lockout mask
        ORR     a1,a1,a3                    ; Build new interrupt lockout mask
	MSR	SPSR,a1			    ; Place it into the SPSR
        LDMIA   sp,{a1-pc}^     	    ; Recover all registers and resume
        	 	                    ;   at point of interrupt
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Control_To_System                                            */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function returns control from a thread to the system.  Note */
;/*      that this service is called in a solicited manner, i.e. it is    */
;/*      not called from an interrupt thread.  Registers required by the  */
;/*      compiler to be preserved across function boundaries are saved by */
;/*      this routine.  Note that this is usually a sub-set of the total  */
;/*      number of available registers.                                   */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Other Components                                                 */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      TCT_Schedule                        Schedule the next thread     */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Control_To_System(void)
;{
	.def	$TCT_Control_To_System
$TCT_Control_To_System			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Control_To_System
;
        .def    _TCT_Control_To_System
_TCT_Control_To_System
;
;    /* Lockout interrupts.  */
;
        MRS     a1,CPSR                     ; Pickup current CPSR
        ORR     a1,a1,#LOCKOUT              ; Build interrupt lockout value
        MSR     CPSR,a1                     ; Lockout interrupts
;    
;    /* Save a minimal context of the thread.  */
;
        STMDB   sp!,{v1-ip,lr}        	    ; Save minimal context of thread on
                                            ;   the current stack
	MOV	a3,lr			    ; Determine what state the
	MOV	a3,a3,LSL #31   	    ;   caller was in and build an
	MOV	a3,a3,LSR #26		    ;   appropriate state mask
	STR	a3,[sp, #-4]!		    ; Place it on the stack
        MOV     a3,#0                       ; Build solicited stack type value
                                            ;   and NU_NULL value
        STR     a3,[sp, #-4]!               ; Place it on the top of the stack
;
;    /* Setup a pointer to the thread control block.  */
;    REG_Thread_Ptr =  (TC_TCB *) TCD_Current_Thread;
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a1,[a2, #0]                 ; Pickup current thread pointer
;
;    /* Clear the current thread control block pointer.  */
;    TCD_Current_Thread =  NU_NULL;
;    
        LDR     a4,Slice_State		    ; Pickup time slice state address
        STR     a3,[a2, #0]                 ; Set current thread pointer to 
                                            ;   NU_NULL
;
;    /* Check to see if a time slice is active.  If so, copy the original time
;       slice into the current time slice field of the task's control block. */
;    if (TMD_Time_Slice_State == 0)
;    {
        LDR     a2,[a4, #0]                 ; Pickup time slice state flag
        CMP     a2,#0                       ; Compare with active value
        BNE     TCT_No_Stop_TS_1            ; If non-active, don't disable
;
;
;        /* Insure that the next time the task runs it gets a fresh time 
;           slice.  */
;       REG_Thread_Ptr -> tc_cur_time_slice =  REG_Thread_Ptr -> tc_time_slice;
;
        LDR     a2,[a1, #40h]               ; Pickup original time slice
;
;        /* Clear any active time slice by setting the state to NOT_ACTIVE.  */
;        TMD_Time_Slice_State =  1;
;
        MOV     a3,#1                       ; Build disable value
        STR     a3,[a4, #0]                 ; Disable time slice
        STR     a2,[a1, #20h]               ; Reset current time slice
;    }
TCT_No_Stop_TS_1
;
;    /* Save off the current stack pointer in the control block.  */
;    REG_Thread_Ptr -> tc_stack_pointer =  (VOID *) REG_Stack_Ptr;
;
        STR     sp,[a1, #2ch]               ; Save the thread's stack pointer
;
;    /* Clear the task's current protection.  */
;    (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer =  NU_NULL;
;    REG_Thread_Ptr -> tc_current_protect =  NU_NULL;
;
        LDR     a2,[a1, #38h]               ; Pickup current thread pointer
        MOV     a3,#0                       ; Build NU_NULL value
        STR     a3,[a1, #38h]               ; Clear the protect pointer field
        STR     a3,[a2, #0]                 ; Release the actual protection
;
;    /* Switch to the system stack.  */
;    REG_Stack_Ptr =  TCD_System_Stack;
;
        LDR     a2,System_Stack		    ; Pickup address of stack pointer
        LDR     a3,System_Limit		    ; Pickup address of stack limit ptr
        LDR     sp,[a2, #0]                 ; Switch to system stack
        LDR     v7,[a3, #0]                 ; Setup system stack limit
;
;    /* Finished, return to the scheduling loop.  */
;
        B       _TCT_Schedule               ; Return to scheduling loop
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Signal_Exit                                                  */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function exits from a signal handler.  The primary purpose  */
;/*      of this function is to clear the scheduler protection and switch */
;/*      the stack pointer back to the normal task's stack pointer.       */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCC_Signal_Shell                    Signal handling shell func   */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      TCT_Schedule                        Scheduler                    */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Signal_Exit(void)
;{
	.def	$TCT_Signal_Exit
$TCT_Signal_Exit			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Signal_Exit
;
        .def    _TCT_Signal_Exit
_TCT_Signal_Exit
;
;    /* Lockout interrupts.  */
;
        MRS     a4,CPSR                     ; Pickup current CPSR
        ORR     a4,a4,#LOCKOUT              ; Build lockout value
        MSR     CPSR,a4                     ; Lockout interrupts
;
;    /* Setup a pointer to the thread control block.  */
;    REG_Thread_Ptr =  (TC_TCB *) TCD_Current_Thread;
;
        LDR     a2,Current_Thread	    ; Pickup address of thread pointer
        MOV     a3,#0                       ; Build NU_NULL value
        LDR     a1,[a2,#0]                  ; Pickup current thread pointer
;
;    /* Clear the current thread control block.  */
;    TCD_Current_Thread =  NU_NULL;
;
        LDR     a4,Slice_State		    ; Pickup time slice state address
        STR     a3,[a2, #0]                 ; Clear current thread pointer
;
;    /* Check to see if a time slice is active.  If so, copy the original time
;       slice into the current time slice field of the task's control block. */
;    if (TMD_Time_Slice_State == 0)
;    {
;
        LDR     a2,[a4, #0]                 ; Pickup time slice state flag
        CMP     a2,#0                       ; Compare with active value
        BNE     TCT_No_Stop_TS_2            ; If non-active, don't disable
;
;        /* Insure that the next time the task runs it gets a fresh time 
;           slice.  */
;       REG_Thread_Ptr -> tc_cur_time_slice =  REG_Thread_Ptr -> tc_time_slice;
;
        LDR     a2,[a1, #40h]               ; Pickup original time slice
;
;        /* Clear any active time slice by setting the state to NOT_ACTIVE.  */
;        TMD_Time_Slice_State =  1;
;
        MOV     a3,#1                       ; Build disable value
        STR     a3,[a4, #0]                 ; Disable time slice
        STR     a2,[a1, #20h]               ; Reset current time slice
;    }
TCT_No_Stop_TS_2
;
;    /* Switch back to the saved stack.  The saved stack pointer was saved
;       before the signal frame was built.  */
;    REG_Thread_Ptr -> tc_stack_pointer =  
;                                REG_Thread_Ptr -> tc_saved_stack_ptr;
;
        LDR     a2,[a1, #3ch]               ; Pickup saved stack pointer
        STR     a2,[a1, #2ch]               ; Place in current stack pointer
;
;    /* Clear the task's current protection.  */
;    (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer =  NU_NULL;
;    REG_Thread_Ptr -> tc_current_protect =  NU_NULL;
;
        LDR     a2,[a1, #38h]               ; Pickup current thread pointer
        MOV     a3,#0                       ; Build NU_NULL value
        STR     a3,[a1, #38h]               ; Clear the protect pointer field
        STR     a3,[a2, #0]                 ; Release the actual protection
;
;    /* Switch to the system stack.  */
;    REG_Stack_Ptr =  (BYTE_PTR) TCD_System_Stack;
;
        LDR     a2,System_Stack		    ; Pickup address of stack pointer
        LDR     a3,System_Limit	  	    ; Pickup address of stack limit ptr
        LDR     sp,[a2, #0]                 ; Switch to system stack
        LDR     v7,[a3, #0]                 ; Setup system stack limit
;
;    /* Finished, return to the scheduling loop.  */
;
        B       _TCT_Schedule               ; Return to scheduling loop
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Current_Thread                                               */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function returns the current thread pointer.                */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application                                                      */
;/*      System Components                                                */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      Pointer to current thread                                        */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  *TCT_Current_Thread(void)
;{
	.def	$TCT_Current_Thread
$TCT_Current_Thread			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Current_Thread
;
        .def    _TCT_Current_Thread
_TCT_Current_Thread
;
;    /* Return the current thread pointer.  */
;    return(TCD_Current_Thread);
;
        LDR     a1,Current_Thread	    ; Pickup address of thread pointer
        LDR     a1,[a1, #0]                 ; Pickup current thread pointer
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Set_Execute_Task                                             */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function sets the current task to execute variable under    */
;/*      protection against interrupts.                                   */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCC Scheduling Routines                                          */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      task                                Pointer to task control block*/
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      TCD_Execute_Task                    Modified variable            */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Set_Execute_Task(TC_TCB *task)
;{
	.def	$TCT_Set_Execute_Task
$TCT_Set_Execute_Task			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Set_Execute_Task
;
        .def    _TCT_Set_Execute_Task
_TCT_Set_Execute_Task
;
;    /* Now setup the TCD_Execute_Task pointer.  */
;    TCD_Execute_Task =  task;
;
        LDR     a2,Execute_Task	 	    ; Pickup execute task ptr address
        STR     a1,[a2,#0]                  ; Setup new task to execute
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Protect                                                      */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function protects against multiple thread access.           */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application                                                      */
;/*      System Components                                                */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      protect                            Pointer to protection block   */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Protect(TC_PROTECT *protect)
;{
	.def	$TCT_Protect
$TCT_Protect				    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Protect
;
        .def    _TCT_Protect
_TCT_Protect
;
;    /* Determine if the caller is in a task or HISR thread.  */
;    if (TCD_Current_Thread)
;    {
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a4,[a2, #0]                 ; Pickup current thread pointer
        CMP     a4,#0                       ; Check to see if it is non-NULL
        BEQ     TCT_Skip_Protect            ; If NULL, skip protection
;    
;        /* Lockout interrupts.  */
;
        MRS     a2,CPSR                     ; Pickup current CPSR
        ORR     a2,a2,#LOCKOUT              ; Place lockout value in
        MSR     CPSR,a2                     ; Lockout interrupts
;    
;        /* Wait until the protect structure is available.  */
;        while (protect -> tc_tcb_pointer != NU_NULL)
;        {
;
TCT_Protect_Loop
        LDR     a2,[a1, #0]                 ; Pickup protection owner field
        CMP     a2,#0                       ; Is there any protection?
        BEQ     TCT_Protect_Available       ; If NU_NULL, no current protection
;        
;            /* Protection structure is not available.  */
;            
;            /* Indicate that another thread is waiting.  */
;            protect -> tc_thread_waiting =  1;
;            
        MOV     a3,#1                       ; Build thread waiting flag
        STR     a3,[a1, #4]                 ; Set waiting field
;
;            /* Directly schedule the thread waiting.  */
;            TCT_Schedule_Protected(protect -> tc_tcb_pointer);
;            
        STR     a1,[sp, #-4]!               ; Save a1 on the stack
        STR     lr,[sp, #-4]!               ; Save lr on the stack
        MOV     a1,a4                       ; Place current thread into a1
        BL      _TCT_Schedule_Protected     ; Call routine to schedule the 
                                            ;   owner of the thread
;
        LDR     lr,[sp], #4                 ; Recover saved lr
        LDR     a1,[sp], #4                 ; Recover saved a1
;
;            /* Lockout interrupts.  */
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a4,[a2, #0]                 ; Pickup current thread pointer
        MRS     a2,CPSR                     ; Pickup current CPSR
        ORR     a2,a2,#LOCKOUT              ; Place lockout value in
        MSR     CPSR,a2                     ; Lockout interrupts
        B       TCT_Protect_Loop            ; Examine protect flags again
;        }
TCT_Protect_Available
;        
;        /* Protection structure is available.  */
;        
;        /* Indicate that this thread owns the protection.  */
;        protect -> tc_tcb_pointer =  TCD_Current_Thread;
;
        STR     a4,[a1, #0]                 ; Indicate calling thread owns this
                                            ;   protection
;        
;        /* Clear the thread waiting flag.  */
;        protect -> tc_thread_waiting =  0;
;        
        MOV     a3,#0                       ; Clear value
        STR     a3,[a1, #4]                 ; Clear the thread waiting flag
;
;        /* Save the protection pointer in the thread's control block.  Note 
;           that both task and HISR threads share the same control block 
;           format.  */
;        REG_Thread_Ptr =  (TC_TCB *) TCD_Current_Thread;
;        REG_Thread_Ptr -> tc_current_protect =  protect;
;
        STR     a1,[a4, #38h]               ; Setup current protection
;
;        /* Restore interrupts.  */
;
        LDR     a3,Int_Level	 	    ; Pickup address of interrupt level
        MRS     a2,CPSR                     ; Pickup current CPSR
        LDR     a4,[a3, #0]                 ; Pickup interrupt lockout level
        BIC     a2,a2,#LOCK_MSK             ; Clear lockout bits
        ORR     a2,a2,a4                    ; Build new interrupt lockout
        MSR     CPSR,a2                     ; Setup CPSR appropriately
;    }
;
TCT_Skip_Protect
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Unprotect                                                    */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function releases protection of the currently active        */
;/*      thread.  If the caller is not an active thread, then this        */
;/*      request is ignored.                                              */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application                                                      */
;/*      System Components                                                */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Unprotect(void)
;{
	.def	$TCT_Unprotect
$TCT_Unprotect				    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Unprotect
;
        .def    _TCT_Unprotect
_TCT_Unprotect
;
;
;    /* Determine if the caller is in a task or HISR thread.  */
;    if (TCD_Current_Thread)
;    {
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a4,[a2, #0]                 ; Pickup current thread pointer
        CMP     a4,#0                       ; Check to see if it is non-NULL
        BEQ     TCT_Skip_Unprotect          ; If NULL, skip unprotection
;
;        /* Setup a thread control block pointer.  */
;        REG_Thread_Ptr =  (TC_TCB *) TCD_Current_Thread;
;        
;        /* Determine if there is a currently active protection.  */
;        if (REG_Thread_Ptr -> tc_current_protect)
;        {
;
        LDR     a1,[a4, #38h]               ; Pickup current protect field
        CMP     a1,#0                       ; Is there a protection in force?
        BEQ     TCT_Skip_Unprotect          ; If not, nothing is protected
;        
;             /* Lockout interrupts.  */
;    
        MRS     a2,CPSR                     ; Pickup current CPSR
        ORR     a2,a2,#LOCKOUT              ; Place lockout value in
        MSR     CPSR,a2                     ; Lockout interrupts
;
;            /* Yes, this thread still has this protection structure.  */
;            REG_Protect_Ptr =  REG_Thread_Ptr -> tc_current_protect;
;
;            /* Is there a higher priority thread waiting for the protection
;               structure?  */
;            if (REG_Protect_Ptr -> tc_thread_waiting)
;            
        LDR     a3,[a1, #4]                 ; Pickup thread waiting flag
        CMP     a3,#0                       ; Are there any threads waiting?
        BEQ     TCT_Not_Waiting_Unpr        ; If not, just release protection
;
;                /* Transfer control to the system.  Note that this 
;                   automatically clears the current protection and it returns
;                   to the caller of this routine instead of this routine.  */
;                TCT_Control_To_System();
;
        B       _TCT_Control_To_System      ; Return control to the system
;
;            else
;            {
TCT_Not_Waiting_Unpr
;            
;                /* Clear the protection.  */
;                REG_Thread_Ptr -> tc_current_protect =  NU_NULL;
;                REG_Protect_Ptr -> tc_tcb_pointer =  NU_NULL;
;
        MOV     a3,#0                       ; Build NU_NULL value
        STR     a3,[a1, #0]                 ; Release the protection
        STR     a3,[a4, #38h]               ; Clear protection pointer in the
                                            ;   control block
;                
;            }
;
TCT_Not_Protected
;            /* Restore interrupts again.  */
;
        LDR     a3,Int_Level		    ; Pickup address of interrupt level
        MRS     a2,CPSR                     ; Pickup current CPSR
        LDR     a4,[a3, #0]                 ; Pickup interrupt lockout level
        BIC     a2,a2,#LOCK_MSK             ; Clear lockout bits
        ORR     a2,a2,a4                    ; Build new interrupt lockout
        MSR     CPSR,a2                     ; Setup CPSR appropriately
;
;        }
;    }
TCT_Skip_Unprotect
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Unprotect_Specific                                           */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function releases a specific protection structure.          */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application                                                      */
;/*      System Components                                                */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      protect                            Pointer to protection block   */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID   TCT_Unprotect_Specific(TC_PROTECT *protect)
;{
	.def	$TCT_Unprotect_Specific
$TCT_Unprotect_Specific			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Unprotect_Specific
;
        .def    _TCT_Unprotect_Specific
_TCT_Unprotect_Specific
;
;    /* Determine if the caller is in a task or HISR thread.  */
;    if (TCD_Current_Thread)
;    {
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a4,[a2, #0]                 ; Pickup current thread pointer
        CMP     a4,#0                       ; Check to see if it is non-NULL
        BEQ     TCT_Skip_Unprot_Spec        ; If NULL, skip unprotect specific
;     
;        /* Lockout interrupts.  */
;
        MRS     a2,CPSR                     ; Pickup current CPSR
        ORR     a2,a2,#LOCKOUT              ; Place lockout value in
        MSR     CPSR,a2                     ; Lockout interrupts
;
;        /* Clear the protection pointer.  */
;        protect -> tc_tcb_pointer =  NU_NULL;
;        
        MOV     a3,#0                       ; Build NU_NULL value
        STR     a3,[a1, #0]                 ; Clear protection ownership
;
;        /* Determine if a thread is waiting.  */
;        if (protect -> tc_thread_waiting)
;        {
;
        LDR     a2,[a1, #4]                 ; Pickup the waiting field
        CMP     a2,#0                       ; Is there another thread waiting?
        BEQ     TCT_Not_Waiting_Unspec      ; No, restore interrupts and return
;        
;            /* A higher-priority thread is waiting.  */
;
;            /* Save a minimal context of the thread.  */
;
        STMDB   sp!,{v1-ip,lr}              ; Save minimal context of thread on
                                            ;   the current stack
	MOV	a3,lr			    ; Determine what state the
	MOV	a3,a3,LSL #31   	    ;   caller was in and build an
	MOV	a3,a3,LSR #26		    ;   appropriate state mask
	STR	a3,[sp, #-4]!		    ; Place it on the stack
        MOV     a3,#0                       ; Build solicited stack type value
                                            ;   and NU_NULL value
        STR     a3,[sp, #-4]!               ; Place it on the top of the stack
;
;            /* Setup a pointer to the thread control block.  */
;            REG_Thread_Ptr =  (TC_TCB *) TCD_Current_Thread;
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a1,[a2, #0]                 ; Pickup current thread pointer
;
;            /* Clear the current thread control block pointer.  */
;            TCD_Current_Thread =  NU_NULL;
;    
        LDR     a4,Slice_State		    ; Pickup time slice state address
        STR     a3,[a2, #0]                 ; Set current thread pointer to 
                                            ;   NU_NULL
;
;            /* Check to see if a time slice is active.  If so, copy the 
;               original time slice into the current time slice field of the 
;               thread's control block. */
;            if (TMD_Time_Slice_State == 0)
;            {
;
        LDR     a2,[a4, #0]                 ; Pickup time slice state flag
        CMP     a2,#0                       ; Compare with active value
        BNE     TCT_No_Stop_TS_3            ; If non-active, don't disable
;
;               /* Insure that the next time the task runs it gets a fresh time
;                   slice.  */
;                REG_Thread_Ptr -> tc_cur_time_slice =  
;                                        REG_Thread_Ptr -> tc_time_slice;
;
        LDR     a2,[a1, #40h]               ; Pickup original time slice
;
;                /* Clear any active time slice by setting the state to 
;                   NOT_ACTIVE.  */
;                TMD_Time_Slice_State =  1;
;
        MOV     a3,#1                       ; Build disable value
        STR     a3,[a4, #0]                 ; Disable time slice
        STR     a2,[a1, #20h]               ; Reset current time slice
;            }
;
TCT_No_Stop_TS_3
;
;            /* Save off the current stack pointer in the control block.  */
;            REG_Thread_Ptr -> tc_stack_pointer =  (VOID *) REG_Stack_Ptr;
;
        STR     sp,[a1, #2ch]               ; Save the thread's stack pointer
;
;            /* Switch to the system stack.  */
;            REG_Stack_Ptr =  TCD_System_Stack;
;
        LDR     a2,System_Stack		    ; Pickup address of stack pointer
        LDR     a3,System_Limit		    ; Pickup address of stack limit ptr
        LDR     sp,[a2, #0]                 ; Switch to system stack
        LDR     v7,[a3, #0]                 ; Setup system stack limit
;
;            /* Finished, return to the scheduling loop.  */
;
        B       _TCT_Schedule               ; Return to scheduling loop
;
;        }
;        else
;        {
TCT_Not_Waiting_Unspec
;        
;            /* No higher-priority thread is waiting.  */
;            
;            /* Restore interrupts.  */
;
        LDR     a3,Int_Level		    ; Pickup address of interrupt level
        MRS     a2,CPSR                     ; Pickup current CPSR
        LDR     a4,[a3, #0]                 ; Pickup interrupt lockout level
        BIC     a2,a2,#LOCK_MSK             ; Clear lockout bits
        ORR     a2,a2,a4                    ; Build new interrupt lockout
        MSR     CPSR,a2                     ; Setup CPSR appropriately
;
;        }
;    }
;
TCT_Skip_Unprot_Spec
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Set_Current_Protect                                          */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function sets the current protection field of the current   */
;/*      thread's control block to the specified protection pointer.      */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCC_Resume_Task                    Resume task function          */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      protect                            Pointer to protection block   */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Set_Current_Protect(TC_PROTECT *protect)
;{
	.def	$TCT_Set_Current_Protect
$TCT_Set_Current_Protect		    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Set_Current_Protect
;
        .def    _TCT_Set_Current_Protect
_TCT_Set_Current_Protect
;
;    /* Determine if the caller is in a task or HISR thread.  */
;    if (TCD_Current_Thread)
;    {
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a4,[a2, #0]                 ; Pickup current thread pointer
        CMP     a4,#0                       ; Check to see if a thread is 
                                            ;   active
;
;        /* Point at the current thread control block.  */
;        REG_Thread_Ptr =  (TC_TCB *) TCD_Current_Thread;
;    
;        /* Modify the current protection.  */
;        REG_Thread_Ptr -> tc_current_protect =  protect;
;
        STRNE   a1,[a4, #38h]               ; Setup new protection
;    }
;
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Protect_Switch                                               */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function waits until a specific task no longer has any      */
;/*      protection associated with it.  This is necessary since task's   */
;/*      cannot be suspended or terminated unless they have released all  */
;/*      of their protection.                                             */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      System Components                                                */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      thread                             Pointer to thread control blk */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Protect_Switch(VOID *thread)
;{
	.def	$TCT_Protect_Switch
$TCT_Protect_Switch			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Protect_Switch
;
        .def    _TCT_Protect_Switch
_TCT_Protect_Switch
;
;    /* Lockout interrupts.  */
;    
        MRS     a2,CPSR                     ; Pickup current CPSR
        ORR     a2,a2,#LOCKOUT              ; Place lockout value in
        MSR     CPSR,a2                     ; Lockout interrupts
;
;    REG_Thread_Ptr =  (TC_TCB *) thread;
;    
;    /* Wait until the specified task has no protection associated with it.  */
;    while (REG_Thread_Ptr -> tc_current_protect)
;    {
;
        LDR     a2,[a1, #38h]               ; Pickup protection of specified
                                            ;   thread
        CMP     a2,#0                       ; Does the specified thread have
                                            ;   an active protection?
        BEQ     TCT_Switch_Done             ; If not, protect switch is done
;    
;        /* Let the task run again in an attempt to clear its protection.  */
;        
;        /* Indicate that a higher priority thread is waiting.  */
;        (REG_Thread_Ptr -> tc_current_protect) -> tc_thread_waiting =  1;
;        
        MOV     a3,#1                       ; Build waiting flag value
        STR     a3,[a2, #4]                 ; Set waiting flag of the 
                                            ;   protection owned by the other
                                            ;   thread
;
;        /* Directly schedule the thread waiting.  */
;        TCT_Schedule_Protected((REG_Thread_Ptr -> tc_current_protect)  
;                                                        -> tc_tcb_pointer);
;
        LDR     a3,Current_Thread	    ; Pickup current thread ptr address
        STR     a1,[sp, #-4]!               ; Save a1 on the stack
        STR     lr,[sp, #-4]!               ; Save lr on the stack
        MOV     a2,a1                       ; Move new thread into a2
        LDR     a1,[a3, #0]                 ; Pickup current thread pointer
        BL      _TCT_Schedule_Protected     ; Call routine to schedule the 
                                            ;   owner of the thread
;
        LDR     lr,[sp], #4                 ; Recover saved lr
        LDR     a1,[sp], #4                 ; Recover saved a1
;            
;        /* Lockout interrupts.  */
;
        B       _TCT_Protect_Switch         ; Branch to top of routine and 
                                            ;   start over
;    }
TCT_Switch_Done
;
;    /* Restore interrupts.  */
;
        LDR     a3,Int_Level	            ; Pickup address of interrupt level
        MRS     a2,CPSR                     ; Pickup current CPSR
        LDR     a4,[a3, #0]                 ; Pickup interrupt lockout level
        BIC     a2,a2,#LOCK_MSK             ; Clear lockout bits
        ORR     a2,a2,a4                    ; Build new interrupt lockout
        MSR     CPSR,a2                     ; Setup CPSR appropriately
;
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Schedule_Protected                                           */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function saves the minimal context of the thread and then   */
;/*      directly schedules the thread that has protection over the       */
;/*      the thread that called this routine.                             */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCT_Protect                                                      */
;/*      TCT_Protect_Switch                                               */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      TCT_Control_To_Thread               Transfer control to protected*/
;/*                                              thread                   */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Schedule_Protected(VOID *thread)
;{
;
_TCT_Schedule_Protected
;
;    /* Interrupts are already locked out by the caller.  */
;    
;    /* Save minimal context required by the system.  */
;
        STMDB   sp!,{v1-ip,lr}              ; Save minimal context of thread on
                                            ;   the current stack
	MOV	a3,lr			    ; Determine what state the
	MOV	a3,a3,LSL #31   	    ;   caller was in and build an
	MOV	a3,a3,LSR #26		    ;   appropriate state mask
	STR	a3,[sp, #-4]!		    ; Place it on the stack
        MOV     a3,#0                       ; Build solicited stack type value
                                            ;   and NU_NULL value
        STR     a3,[sp, #-4]!               ; Place it on the top of the stack
        MOV     v1,a2                       ; Save thread to schedule
;
;    /* Setup a pointer to the thread control block.  */
;    REG_Thread_Ptr =  (TC_TCB *) TCD_Current_Thread;
;    
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
;
;    /* Clear the current thread control block.  */
;    TCD_Current_Thread =  NU_NULL;
;
        LDR     a4,Slice_State		    ; Pickup time slice state address
        STR     a3,[a2, #0]                 ; Set current thread pointer to 
                                            ;   NU_NULL
;
;    /* Check to see if a time slice is active.  If so, copy the original time
;       slice into the current time slice field of the task's control block. */
;    if (TMD_Time_Slice_State == 0)
;    {
;
        LDR     a2,[a4, #0]                 ; Pickup time slice state flag
        CMP     a2,#0                       ; Compare with active value
        BNE     TCT_No_Stop_TS_4            ; If non-active, don't disable
;    
;        /* Insure that the next time the task runs it gets a fresh time 
;           slice.  */
;       REG_Thread_Ptr -> tc_cur_time_slice =  REG_Thread_Ptr -> tc_time_slice;
;
        LDR     a2,[a1, #40h]               ; Pickup original time slice
;
;        /* Clear any active time slice by setting the state to NOT_ACTIVE.  */
;        TMD_Time_Slice_State =  1;
;
        MOV     a3,#1                       ; Build disable value
        STR     a3,[a4, #0]                 ; Disable time slice
        STR     a2,[a1, #20h]               ; Reset current time slice
;
;    }
TCT_No_Stop_TS_4
;
;    /* Save off the current stack pointer in the control block.  */
;    REG_Thread_Ptr -> tc_stack_pointer =  (VOID *) REG_Stack_Ptr;
;
        STR     sp,[a1, #2ch]               ; Save the thread's stack pointer
;
;    /* Switch to the system stack.  */
;    TCD_System_Stack =  (VOID *) REG_Stack_Ptr;
;
        LDR     a2,System_Stack		    ; Pickup address of stack pointer
        LDR     a3,System_Limit		    ; Pickup address of stack limit ptr
        LDR     sp,[a2, #0]                 ; Switch to system stack
        LDR     v7,[a3, #0]                 ; Setup system stack limit
;
;    /* Transfer control to the specified thread directly. */
;    TCT_Control_To_Thread(thread);
;
        LDR     a3,Int_Level		    ; Pickup address of interrupt level
        MRS     a2,CPSR                     ; Pickup current CPSR
        LDR     a4,[a3, #0]                 ; Pickup interrupt lockout level
        BIC     a2,a2,#LOCK_MSK             ; Clear lockout bits
        ORR     a2,a2,a4                    ; Build new interrupt lockout
        MOV     a1,v1                       ; Indicate thread to schedule
        MSR     CPSR,a2                     ; Setup CPSR appropriately
        ORR     a2,a2,#LOCKOUT              ; Build lockout value again
        MSR     CPSR,a2                     ; Lockout interrupts again
        B       _TCT_Control_To_Thread      ; Schedule the thread indirectly
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Interrupt_Context_Save                                       */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function saves the interrupted thread's context.  Nested    */
;/*      interrupts are also supported.  If a task or HISR thread was     */
;/*      interrupted, the stack pointer is switched to the system stack   */
;/*      after the context is saved.                                      */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application ISRs                    Assembly language ISRs       */
;/*      INT_Interrupt_Shell                 Interrupt handler shell      */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      vector                              Interrupt's vector number    */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Interrupt_Context_Save(INT vector)
;{
	.def	$TCT_Interrupt_Context_Save
$TCT_Interrupt_Context_Save		    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Interrupt_Context_Save
;
        .def    _TCT_Interrupt_Context_Save
_TCT_Interrupt_Context_Save
;
;    /* This routine is designed to handle THUMB IRQ interrupts.  The IRQ
;       stack is used as a temporary area.  Actual context is saved either
;       on the interrupted thread's stack or the system stack- both of which
;       are in the Supervisor (SVC) mode.  Note:  upon entry to this routine 
;       a1-a4 are saved on the current stack and a4 contains the original
;       (interrupt return address) lr value.  The current lr contains the 
;       ISR return address.  */
;
;    /* Determine if this is a nested interrupt.  */
;    if (TCD_Interrupt_Count++)
;    {
;
        LDR     a1,Int_Count		    ; Pickup address of interrupt count
        LDR     a2,[a1, #0]                 ; Pickup interrupt counter
        CMP     a2,#0                       ; Is it the first interrupt?
        BEQ     TCT_Not_Nested_Save         ; If so, not a nested interrupt
;    
;        /* Nested interrupt.  Save complete context on the current stack.  */
;        
        ADD     a2,a2,#1                    ; Increment the interrupt counter
        STR     a2,[a1, #0]                 ; Store in interrupt counter
        STMDB   sp!,{v1-v3}                 ; Save more registers on current
                                            ;   stack
        MRS     v1,SPSR                     ; Pickup and save current SPSR
        MOV     v2,lr                       ; Save current lr 
        MOV     v3,sp                       ; Save current sp
        ADD     sp,sp,#28                   ; Adjust sp for future interrupts
        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            ; Clear the mode bits
        ORR     a1,a1,#SUP_MODE             ; Prepare to switch to supervisor
                                            ;   mode (SVC)
        MSR     CPSR,a1                     ; Switch to SVC mode
        MOV     a2,sp                       ; Use a non sp register
        NOP                                 ; 
        STR     a4,[a2, #-4]!               ; Save interrupted pc on sys stack
        STMDB   a2!,{v4-lr}   		    ; Save v4-lr on the system stack
        MOV     sp,a2                       ; Setup sp again
        LDMIA   v3!,{v4-v6}                 ; Recover v1-v3 from int stack
        STMDB   sp!,{v4-v6}                 ; Save v1-v3 on the system stack
        LDMIA   v3,{a1-a4}                  ; Recover a1-a4
        STMDB   sp!,{a1-a4}                 ; Save a1-a4 on the system stack
        STR     v1,[sp, #-4]!               ; Save CPSR on the stack
        BX      v2                          ; Return to calling ISR        
;    }
;    else
;    {
TCT_Not_Nested_Save
;    
        ADD     a2,a2,#1                    ; Increment the interrupt counter
        STR     a2,[a1, #0]                 ; Store in interrupt counter
;
;        /* Determine if a thread was interrupted.  */
;        if (TCD_Current_Thread)
;        {
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a2,[a2, #0]                 ; Pickup the current thread pointer
        CMP     a2,#0                       ; Is it NU_NULL?
        BEQ     TCT_Idle_Context_Save       ; If no, no real save is necessary
        
;        
;            /* Yes, a thread was interrupted.  Save complete context on the
;               thread's stack.  */
;
        STMDB   sp!,{v1-v3}                 ; Save more registers on temp stack
        MOV     v2,lr                       ; Save interrupt lr in v2
        MRS     v1,SPSR                     ; Save interrupt SPSR in v1
        MOV     v3,sp                       ; Save current sp in v3
        ADD     sp,sp,#28                   ; Adjust sp for future interrupts
        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            ; Clear the mode bits
        ORR     a1,a1,#SUP_MODE             ; Prepare to switch to supervisor
                                            ;   mode (SVC)
        MSR     CPSR,a1                     ; Switch to supervisor mode (SVC)
        MOV     a2,sp                       ; Use a non-stack pointer register
        NOP                                 ; 
        STR     a4,[a2, #-4]!               ; Save interrupted pc on the stack
        STMDB   a2!,{v4-lr} 	            ; Save v4-lr on the stack
        MOV     sp,a2                       ; Setup sp again
        LDMIA   v3!,{v4-v6}                 ; Recover v1-v3 into v4-v6
        STMDB   sp!,{v4-v6}                 ; Save v1-v3 on the stack
        LDMIA   v3,{a1-a4}                  ; Recover a1-a4
        STMDB   sp!,{a1-a4}                 ; Save a1-a4 on the stack
        STR     v1,[sp, #-4]!               ; Save CPSR on the stack
        MOV     a2,#1                       ; Interrupt stack type
        STR     a2,[sp, #-4]!               ; Put interrupt stack type on top 
                                            ;   of stack
;
;            /* Save the thread's stack pointer in the control block.  */
;            REG_Thread_Ptr =  (TC_TCB *) TCD_Current_Thread;
;            REG_Thread_Ptr -> tc_stack_pointer =  (VOID *) REG_Stack_Ptr;
;   
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a1,[a2, #0]                 ; Pickup current thread pointer
        LDR     a4,Slice_State		    ; Pickup time slice state address
        STR     sp,[a1, #2ch]               ; Save stack pointer
;
;            /* Switch to the system stack.  */
;            REG_Stack_Ptr =  TCD_System_Stack;
;
        LDR     a2,System_Stack	  	    ; Pickup address of stack pointer
        LDR     a3,System_Limit		    ; Pickup address of stack limit ptr
        LDR     sp,[a2, #0]                 ; Switch to system stack
        LDR     v7,[a3, #0]                 ; Setup system stack limit
;
;            /* Return to caller ISR.  */
;
        BX      v2                          ; Return to caller ISR
;
;        }
;
TCT_Idle_Context_Save
;
        MOV     v2,lr                       ; Save lr in v2
        ADD     sp,sp,#16                   ; Adjust sp for future interrupts
        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            ; Clear the current mode
        ORR     a1,a1,#SUP_MODE             ; Prepare to switch to supervisor
                                            ;   mode (SVC)
        MSR     CPSR,a1                     ; Switch to supervisor mode (SVC)
        BX      v2                          ; Return to caller ISR
;    }
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Interrupt_Context_Restore                                    */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function restores the interrupt context if a nested         */
;/*      interrupt condition is present.  Otherwise, this routine         */
;/*      transfers control to the scheduling function.                    */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application ISRs                    Assembly language ISRs       */
;/*      INT_Interrupt_Shell                 Interrupt handler shell      */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      TCT_Schedule                        Thread scheduling function   */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID  TCT_Interrupt_Context_Restore(void)
;{
	.def	$TCT_Interrupt_Context_Restore
$TCT_Interrupt_Context_Restore		    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Interrupt_Context_Restore
;
        .def    _TCT_Interrupt_Context_Restore
_TCT_Interrupt_Context_Restore
;
;    /* It is assumed that anything pushed on the stack by ISRs has been 
;       removed upon entry into this routine.  */
;
;    /* Lockout interrupts.  */
;    
        MRS     a2,CPSR                     ; Pickup current CPSR
        ORR     a2,a2,#LOCKOUT              ; Build lockout value
        MSR     CPSR,a2                     ; Lockout interrupts
;
;    /* Decrement and check for nested interrupt conditions.  */
;    if (--TCD_Interrupt_Count)
;    {
;
        LDR     a1,Int_Count		    ; Pickup address of interrupt count
        LDR     a2,[a1, #0]                 ; Pickup interrupt counter
        SUB     a2,a2,#1                    ; Decrement interrupt counter
        STR     a2,[a1, #0]                 ; Store interrupt counter
        CMP     a2,#0                       ; Is this a nested interrupt?
        BEQ     TCT_Not_Nested_Restore      ; If not, skip nested interrupt 
                                            ;   restoration
;    
;        /* Restore previous context.  */
;
        LDR     a1,[sp], #4                 ; Pickup the saved CPSR
	MSR	SPSR,a1			    ; Put in SPSR
        LDMIA   sp,{a1-pc}^  		    ; Return to the point of interrupt
;
;    }
;    else
;    {
;
TCT_Not_Nested_Restore
;    
;        /* Determine if a thread is active.  */
;        if (TCD_Current_Thread)
;        {
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        LDR     a1,[a2, #0]                 ; Pickup current thread pointer
        CMP     a1,#0                       ; Determine if a thread is active
        BEQ     TCT_Idle_Context_Restore    ; If not, idle system restore
;
;            /* Clear the current thread pointer.  */
;            TCD_Current_Thread =  NU_NULL;
;
        LDR     a4,Slice_State		    ; Pickup time slice state address
        MOV     a3,#0                       ; Build NU_NULL value
        STR     a3,[a2, #0]                 ; Set current thread ptr to NU_NULL
;        
;            /* Determine if a time slice is active.  If so, the remaining
;               time left on the time slice must be saved in the task's
;               control block.  */
;            if (TMD_Time_Slice_State == 0)
;            {
;
        LDR     a2,[a4, #0]                 ; Pickup time slice state
        CMP     a2,#0                       ; Determine if time slice active
        BNE     TCT_Idle_Context_Restore    ; If not, skip time slice reset
;            
;                /* Pickup the remaining portion of the time slice and save it
;                   in the task's control block.  */
;                REG_Thread_Ptr -> tc_cur_time_slice =  TMD_Time_Slice;
;                TMD_Time_Slice_State =  1;
;
        LDR     a3,Time_Slice		    ; Pickup address of time slice left
        MOV     a2,#1                       ; Build disable time slice value
        LDR     a3,[a3, #0]                 ; Pickup remaining time slice
        STR     a2,[a4, #0]                 ; Disable time slice
        STR     a3,[a1, #20h]               ; Store remaining time slice       
;
;            }
;        }
TCT_Idle_Context_Restore
;
;        /* Reset the system stack pointer.  */
;
        LDR     a2,System_Stack		    ; Pickup address of stack pointer
        LDR     a3,System_Limit		    ; Pickup address of stack limit ptr
        LDR     sp,[a2, #0]                 ; Switch to system stack
        LDR     v7,[a3, #0]                 ; Setup system stack limit
;
;        /* Return to scheduler.  */
;
        B       _TCT_Schedule               ; Return to scheduling loop
;
;    }
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_Activate_HISR                                                */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function activates the specified HISR.  If the HISR is      */
;/*      already activated, the HISR's activation count is simply         */
;/*      incremented.  Otherwise, the HISR is placed on the appropriate   */
;/*      HISR priority list in preparation for execution.                 */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application LISRs                                                */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      hisr                                Pointer to HISR to activate  */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      NU_SUCCESS                          Successful completion        */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;STATUS  TCT_Activate_HISR(TC_HCB *hisr)
;{
	.def	$TCT_Activate_HISR
$TCT_Activate_HISR			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_Activate_HISR
;
        .def    _TCT_Activate_HISR
_TCT_Activate_HISR
;
;INT     priority;
;
;
;    /* Lockout interrupts.  */
;
        STR     v1,[sp, #-4]!               ; Save v1
        MRS     v1,CPSR                     ; Pickup current CPSR
        ORR     a2,v1,#LOCKOUT              ; Build interrupt lockout value
        MSR     CPSR,a2                     ; Lockout interrupts
;
;    /* Determine if the HISR is already active.  */
;    if (hisr -> tc_activation_count)
;    {
;
        LDR     a2,[a1,#40h]                ; Pickup current activation count
        CMP     a2,#0                       ; Is it the first activation?
        BEQ     TCT_First_Activate          ; Yes, place it on the correct list
;
;        /* Increment the activation count.  Make sure that it does not go
;           to zero.  */
;        hisr -> tc_activation_count++;
;
        ADDS    a2,a2,#1                    ; Increment the activation count
        STR     a2,[a1,#40h]                ; Store new activation count
;
;        if (hisr -> tc_activation_count == 0)
;        
;            hisr -> tc_activation_count =  0xFFFFFFFFUL;
;
        MVNEQ   a2,#0                       ; If counter rolled-over reset
        STREQ   a2,[a1,#40h]                ; Store all ones count
        B       TCT_Activate_Done           ; Finished with activation
;    }
;    else
;    {
TCT_First_Activate
;
;
;        /* Set the activation count to 1.  */
;        hisr -> tc_activation_count =  1;
;
        MOV     a2,#1                       ; Initial activation count
        STR     a2,[a1,#40h]                ; Store initial activation count
;
;        /* Pickup the HISR's priority.  */
;        priority =  hisr -> tc_priority;
;
;        /* Determine if there is something in the given priority list.  */
;        if (TCD_Active_HISR_Tails[priority])
;        {
;
        LDRB    a2,[a1,#1ah]                ; Pickup priority of HISR
        LDR     a3,HISR_Tails	            ; Pickup tail pointer base
        LDR     a4,[a3,a2,LSL #2]           ; Pickup tail pointer for priority
        CMP     a4,#0                       ; Is this first HISR at priority?
        BEQ     TCT_First_HISR              ; No, append to end of HISR list
;
;            /* Something is already on this list.  Add after the tail.  */
;            (TCD_Active_HISR_Tails[priority]) -> tc_active_next =  hisr;
;            TCD_Active_HISR_Tails[priority] =  hisr;
;
        STR     a1,[a4,#3ch]                ; Setup the active next pointer
        STR     a1,[a3,a2,LSL #2]           ; Setup the tail pointer
        B       TCT_Activate_Done           ; Finished with activate processing
;        }
;        else
;        {
TCT_First_HISR
;
;           /* Nothing is on this list.  */
;           TCD_Active_HISR_Heads[priority] =  hisr;
;           TCD_Active_HISR_Tails[priority] =  hisr;
;
        LDR     a4,HISR_Heads		    ; Pickup address of head pointers
        STR     a1,[a3,a2,LSL #2]           ; Set tail pointer to this HISR
        STR     a1,[a4,a2,LSL #2]           ; Set head pointer to this HISR
;
;           /* Determine the highest priority HISR.  */
;           if (TCD_Active_HISR_Heads[0])
;               TCD_Execute_HISR =  TCD_Active_HISR_Heads[0];
;           else if (TCD_Active_HISR_Heads[1])
;               TCD_Execute_HISR =  TCD_Active_HISR_Heads[1];
;           else
;               TCD_Execute_HISR =  TCD_Active_HISR_Heads[2];
;
        LDR     a2,[a4,#0]                  ; Pickup priority 0 head pointer
        LDR     a1,Execute_HISR		    ; Build address to execute HISR ptr
        CMP     a2,#0                       ; Is priority 0 active?
        LDREQ   a2,[a4,#4]                  ; If not, pickup priority 1 head 
        CMPEQ   a2,#0                       ; Is priority 1 active?
        LDREQ   a2,[a4,#8]                  ; Else, must be priority 2 active
        STR     a2,[a1,#0]                  ; Store which ever priority is the
                                            ;   active one
;       }
;    }
TCT_Activate_Done
;
        MSR     CPSR,v1                     ; Restore interrupt lockout
        LDR     v1,[sp], #4                 ; Restore corrupted v1
;
;    return(NU_SUCCESS);
;
        MOV     a1,#0                       ; Always return NU_SUCCESS
        BX      lr                          ; Return to caller
;}
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      TCT_HISR_Shell                                                   */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function is the execution shell of each and every HISR.  If */
;/*      the HISR has completed its processing, this shell routine exits  */
;/*      back to the system.  Otherwise, it sequentially calls the HISR   */
;/*      routine until the activation count goes to zero.                 */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      HISR Scheduling                                                  */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      hisr -> tc_entry                    Actual entry function of HISR*/
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0		  */
;/*                                                                       */
;/*************************************************************************/
;VOID    TCT_HISR_Shell(void)
;{
	.def	$TCT_HISR_Shell
$TCT_HISR_Shell				    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_TCT_HISR_Shell
;
        .def    _TCT_HISR_Shell
_TCT_HISR_Shell
;
;    /* Point at the HISR.  */
;    REG_HISR_Ptr =  (TC_HCB *) TCD_Current_Thread;
;
        LDR     a1,Current_Thread	    ; Build address of thread pointer
        LDR     v2,[a1, #0]                 ; Pickup control block pointer
;
;    do
;    {
TCT_HISR_Loop
;
;        /* Call the HISR's entry routine.  */
;        (*(REG_HISR_Ptr -> tc_entry)) ();
;
        LDR     v1,[v2,#44h]                ; Call HISR entry function
	BL	IND_CALL		    ;    indirectly
;
;        /* Lockout interrupts.  */
;
        MRS     a2,CPSR                     ; Pickup current CPSR
        ORR     a2,a2,#LOCKOUT              ; Build interrupt lockout 
        MSR     CPSR,a2                     ; Lockout interrupts
;
;        /* On return, decrement the activation count and check to see if 
;           it is 0.  Once it reaches 0, the HISR should be made inactive. */
;        REG_HISR_Ptr -> tc_activation_count--;
;
        LDR     a1,[v2, #40h]               ; Pickup current activation count
        SUBS    a1,a1,#1                    ; Subtract and set condition codes
        STR     a1,[v2, #40h]               ; Store new activation count
        BEQ     TCT_HISR_Finished           ; Finished processing HISR

;        /* Restore interrupts.  */
;
        LDR     a3,Int_Level		    ; Pickup address of interrupt level
        MRS     a2,CPSR                     ; Pickup current CPSR
        LDR     a4,[a3, #0]                 ; Pickup interrupt lockout level
        BIC     a2,a2,#LOCK_MSK             ; Clear lockout bits
        ORR     a2,a2,a4                    ; Build new interrupt lockout
        MSR     CPSR,a2                     ; Setup CPSR appropriately
        B       TCT_HISR_Loop               ; Return to HISR loop
;    }
;    while (REG_HISR_Ptr -> tc_activation_count);
;
TCT_HISR_Finished
;
;    /* At this point, the HISR needs to be made inactive.  */
;
;    /* Determine if this is the only HISR on the given priority list.  */
;    if (REG_HISR_Ptr == TCD_Active_HISR_Tails[REG_HISR_Ptr -> tc_priority])
;    {
;
        LDR     lr,HISR_Tails		    ; Pickup tail pointers address
        LDRB    a4,[v2,#1ah]                ; Pickup priority
        LDR     v3,[lr,a4,LSL #2]           ; Pickup this priority tail pointer
        LDR     a3,Execute_HISR		    ; Build address to execute HISR ptr
        MOV     a1,#0                       ; Clear a1
        LDR     a2,HISR_Heads		    ; Pickup head pointers address
        CMP     v3,v2                       ; Is this priority tail the same as
                                            ;   the current HISR?
        BNE     TCT_More_HISRs              ; If not, more HISRs at this 
                                            ;   priority
;
;        /* The only HISR on the list.  Clean up the list and check for the
;           highest priority HISR.  */
;       TCD_Active_HISR_Heads[REG_HISR_Ptr -> tc_priority] =  NU_NULL;
;       TCD_Active_HISR_Tails[REG_HISR_Ptr -> tc_priority] =  NU_NULL;
;
        STR     a1,[a2,a4,LSL #2]           ; Set head pointer to NU_NULL
        STR     a1,[lr,a4,LSL #2]           ; Set tail pointer to NU_NULL
;
;       /* Determine the highest priority HISR.  */
;       if (TCD_Active_HISR_Heads[0])
;           TCD_Execute_HISR =  TCD_Active_HISR_Heads[0];
;       else if (TCD_Active_HISR_Heads[1])
;           TCD_Execute_HISR =  TCD_Active_HISR_Heads[1];
;       else
;           TCD_Execute_HISR =  TCD_Active_HISR_Heads[2];
;
        LDR     a4,[a2,#0]                  ; Pickup priority 0 head pointer
        CMP     a4,#0                       ; Is there an HISR active?
        LDREQ   a4,[a2,#4]                  ; If not, pickup priority 1 pointer
        CMPEQ   a4,#0                       ; Is there an HISR active?
        LDREQ   a4,[a2,#8]                  ; If not, pickup priority 2 pointer
        STR     a4,[a3,#0]                  ; Setup execute HISR pointer
        B       TCT_HISR_Exit               ; Exit HISR processing
;    }
;    else
;    {
;
TCT_More_HISRs
;
;        /* Move the head pointer to the next HISR in the list.  */
;        TCD_Active_HISR_Heads[REG_HISR_Ptr -> tc_priority] =  
;                                        REG_HISR_Ptr -> tc_active_next;
;
;        /* Also set the TCD_Execute_HISR pointer.  */
;        TCD_Execute_HISR =  REG_HISR_Ptr -> tc_active_next;
;
        LDR     lr,[v2,#3ch]                ; Pickup next HISR to activate
        STR     lr,[a2,a4,LSL #2]           ; Setup new head pointer
        STR     lr,[a3, #0]                 ; Setup execute HISR pointer
;    }
;
TCT_HISR_Exit
;
;    /* Build fake return to the top of this loop.  The next time the HISR
;       is activated, it will return to the top of this function.  */
;
        LDR     lr,HISR_Shell		    ; Pickup address of shell entry
        STMDB   sp!,{v1-ip,lr}              ; Save minimal context of thread on
                                            ;   the current stack
        MOV     a3,#0                       ; Build solicited stack type value
                                            ;   and NU_NULL value
	STR	a3,[sp, #-4]!		    ; Save state mask
        STR     a3,[sp, #-4]!               ; Place it on the top of the stack
;
;    /* Clear the current thread control block.  */
;    TCD_Current_Thread =  NU_NULL;
;
        LDR     a2,Current_Thread	    ; Pickup current thread ptr address
        STR     a3,[a2, #0]                 ; Set current thread pointer to 
                                            ;   NU_NULL
;
;    /* Save off the current stack pointer in the control block.  */
;    REG_HISR_Ptr -> tc_stack_pointer =  (VOID *) REG_Stack_Ptr;
;
        STR     sp,[v2, #2ch]               ; Save the thread's stack pointer
;
;    /* Switch to the system stack.  */
;    REG_Stack_Ptr =  (BYTE_PTR) TCD_System_Stack;
;
        LDR     a2,System_Stack		    ; Pickup address of stack pointer
        LDR     a3,System_Limit		    ; Pickup address of stack limit ptr
        LDR     sp,[a2, #0]                 ; Switch to system stack
        LDR     v7,[a3, #0]                 ; Setup system stack limit
;
;    /* Transfer control to the main scheduling loop.  */
;
        B       _TCT_Schedule               ; Return to main scheduling loop
;}
;
;/* Define the global addresses used in this section */
;
System_Limit
        .word   _TCT_System_Limit
;
Int_Level
        .word   _TCD_Interrupt_Level
;
Task_Shell
        .word   $TCC_Task_Shell
;
HISR_Shell
        .word   _TCT_HISR_Shell
;
Signal_Shell
        .word   $TCC_Signal_Shell
;
Current_Thread
        .word   _TCD_Current_Thread
;
Execute_HISR
        .word   _TCD_Execute_HISR
;
Execute_Task
        .word   _TCD_Execute_Task
;
Time_Slice
        .word   _TMD_Time_Slice
;
Slice_State
        .word   _TMD_Time_Slice_State
;
System_Stack
        .word   _TCD_System_Stack
;
Int_Count
        .word   _TCD_Interrupt_Count
;
HISR_Tails
        .word   _TCD_Active_HISR_Tails
;
HISR_Heads
        .word   _TCD_Active_HISR_Heads
;
System_Error
	.word	$ERC_System_Error
;
        .end