1/***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12/**************************************************************************/
13/**************************************************************************/
14/**                                                                       */
15/** ThreadX Component                                                     */
16/**                                                                       */
17/**   Timer                                                               */
18/**                                                                       */
19/**************************************************************************/
20/**************************************************************************/
21
22
23#define UserLocal       $4,2
24#define C0_TCBind       $2,2
25
26    .text
27    .set        noreorder
28/**************************************************************************/
29/*                                                                        */
30/*  FUNCTION                                               RELEASE        */
31/*                                                                        */
32/*    _tx_timer_interrupt                   MIPS32_interAptiv/Green Hills */
33/*                                                           6.2.1        */
34/*  AUTHOR                                                                */
35/*                                                                        */
36/*    Scott Larson, Microsoft Corporation                                 */
37/*                                                                        */
38/*  DESCRIPTION                                                           */
39/*                                                                        */
40/*    This function processes the hardware timer interrupt.  This         */
41/*    processing includes incrementing the system clock and checking for  */
42/*    time slice and/or timer expiration.  If either is found, the        */
43/*    interrupt context save/restore functions are called along with the  */
44/*    expiration functions.                                               */
45/*                                                                        */
46/*  INPUT                                                                 */
47/*                                                                        */
48/*    None                                                                */
49/*                                                                        */
50/*  OUTPUT                                                                */
51/*                                                                        */
52/*    None                                                                */
53/*                                                                        */
54/*  CALLS                                                                 */
55/*                                                                        */
56/*    _tx_thread_smp_protect                Get protection                */
57/*    _tx_thread_smp_unprotect              Release protection            */
58/*    _tx_timer_expiration_process          Timer expiration processing   */
59/*    _tx_thread_time_slice                 Time slice interrupted thread */
60/*                                                                        */
61/*  CALLED BY                                                             */
62/*                                                                        */
63/*    interrupt vector                                                    */
64/*                                                                        */
65/*  RELEASE HISTORY                                                       */
66/*                                                                        */
67/*    DATE              NAME                      DESCRIPTION             */
68/*                                                                        */
69/*  03-08-2023      Scott Larson            Initial Version 6.2.1         */
70/*                                                                        */
71/**************************************************************************/
72/* VOID   _tx_timer_interrupt(VOID)
73{  */
74    .globl  _tx_timer_interrupt
75_tx_timer_interrupt:
76
77    /* Check VPE and throw away any timer interrupts for anything other than VPE 0.  */
78
79    mfc0    $8, UserLocal                       # Pickup VPE ID
80    beq     $8, $0, _handle_timer_interrupt     # If 0, VPE 0 should handle the interrupt
81    nop
82    jr      $31                                 # Other VPE simply returns
83    nop
84_handle_timer_interrupt:
85
86    subu    $29, $29, 16                        # Allocate some storage on the stack
87    sw      $31, 4($29)                         # Save ra
88    sw      $16, 8($29)                         # Save preserved register s0
89
90    /* Get protection before the timer variables are updated.  */
91    /* _tx_thread_smp_protect();  */
92
93    jal     _tx_thread_smp_protect              # Get VPE protection
94    nop                                         #
95    addu    $16, $2, 0                          # Save return value
96
97    /* Increment timer interrupt active counter.  */
98    /* _tx_timer_interrupt_active++;   */
99
100    la      $9, _tx_timer_interrupt_active      # Build address of timer interrupt active count
101    lw      $8, ($9)                            # Pickup timer interrupt active count
102    addu    $8, $8, 1                           # Increment timer interrupt active count
103    sw      $8, ($9)                            # Store new timer interrupt active count
104    sync
105
106    /* Increment the system clock.  */
107    /* _tx_timer_system_clock++;  */
108
109    la      $9, _tx_timer_system_clock          # Pickup address of system clock
110    lw      $8, ($9)                            # Pickup system clock
111    addu    $8, $8, 1                           # Increment system clock
112    sw      $8, ($9)                            # Store new system clock
113
114    /* Test for timer expiration.  */
115    /* if (*_tx_timer_current_ptr)
116    {  */
117
118    la      $13, _tx_timer_expired              # Pickup address of timer expired flag
119    lw      $10, ($13)                          # Pickup the timer expired flag
120    bne     $10, $0, _tx_timer_done             # If already expired, skip expiration processing
121    nop                                         #
122    la      $9, _tx_timer_current_ptr           # Pickup address of current ptr
123    lw      $8, ($9)                            # Pickup current pointer
124    la      $13, _tx_timer_expired              # Pickup address of timer expired flag
125    lw      $10, ($8)                           # Pickup the current timer entry
126    ori     $12, $0, 1                          # Build TX_TRUE flag
127    beqz    $10, _tx_timer_no_timer             # If NULL, no timer has expired
128    nop                                         # Delay slot
129
130        /* Set expiration flag.  */
131        /* _tx_timer_expired =  TX_TRUE;  */
132
133    ori     $15, $0, 2                          # Set local expired flag
134    b       _tx_timer_done                      # Finished timer processing
135    sw      $12, ($13)                          # Set expired flag in memory
136
137
138    /* }
139    else
140    {  */
141_tx_timer_no_timer:
142
143    ori     $15, $0, 0                          # Set expired flag to false
144
145        /* No timer expired, increment the timer pointer.  */
146        /* _tx_timer_current_ptr++;  */
147
148        /* Check for wrap-around.  */
149        /* if (_tx_timer_current_ptr == _tx_timer_list_end)  */
150
151    la      $12, _tx_timer_list_end             # Pickup address of list end pointer
152    lw      $11, ($12)                          # Pickup actual list end
153    addu    $8, $8, 4                           # Point to next timer entry
154    bne     $8, $11, _tx_timer_skip_wrap        # If not same, good pointer
155    sw      $8, ($9)                            # Store new timer pointer
156
157            /* Wrap to beginning of list.  */
158            /* _tx_timer_current_ptr =  _tx_timer_list_start;  */
159
160    la      $12, _tx_timer_list_start           # Pickup address of list start pointer
161    lw      $10, ($12)                          # Pickup start of the list
162    sw      $10, ($9)                           # Store new timer pointer
163
164
165_tx_timer_skip_wrap:
166    /* }  */
167
168_tx_timer_done:
169
170    /* Did a timer expire?  */
171    /* if (_tx_timer_expired)
172    {  */
173
174    beqz    $15, _tx_timer_dont_activate        # No, timer not expired
175    nop                                         # Delay slot
176
177        /* Call the timer expiration processing.  */
178        /* _tx_timer_expiration_process(void);  */
179
180    la      $9, _tx_timer_expiration_process    # Build address of _tx_timer_expiratoin_process routine
181    jal     $9                                  # Call _tx_timer_expiration_process
182    nop
183    lw      $15, ($29)                          # Recover local expired flag
184
185    /* }  */
186_tx_timer_dont_activate:
187
188
189        /* Call time-slice processing.   */
190        /* _tx_thread_time_slice();  */
191
192    la      $9, _tx_thread_time_slice           # Pickup address of time slice function
193    jal     $9                                  # Call time slice
194    nop                                         # Delay slot
195
196    /* Decrement timer interrupt active counter.  */
197    /* _tx_timer_interrupt_active--;   */
198
199    la      $9, _tx_timer_interrupt_active      # Build address of timer interrupt active count
200    lw      $8, ($9)                            # Pickup timer interrupt active count
201    subu    $8, $8, 1                           # Decrement timer interrupt active count
202    sw      $8, ($9)                            # Store new timer interrupt active count
203    sync
204
205    /* Release VPE protection.  */
206    /* _tx_thread_smp_unprotect();  */
207
208    addu    $4, $16, 0                          # Setup input parameter
209    jal     _tx_thread_smp_unprotect            # Release protection
210    nop                                         #
211
212    lw      $31, 4($29)                         # Recover ra
213    lw      $16, 8($29)                         # Recover s0
214    addu    $29, $29, 16                        # Recover stack space
215    j       $31                                 # Return to caller
216    nop                                         # Delay slot
217
218/* }  */
219