Cygwin: pinfo: raise MAX_PID to 4194304
[newlib-cygwin.git] / libgloss / or1k / interrupts-asm.S
blob82b796f51e307f71b03c4f65dc9d52c503a135d1
1 /* interrupts-asm.S -- interrupt handling for OpenRISC 1000.
2  *
3  * Copyright (c) 2011, 2012, 2014 Authors
4  *
5  * Contributor Julius Baxter <juliusbaxter@gmail.com>
6  * Contributor Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
7  * Contributor Stefan Wallentowitz <stefan.wallentowitz@tum.de>
8  *
9  * The authors hereby grant permission to use, copy, modify, distribute,
10  * and license this software and its documentation for any purpose, provided
11  * that existing copyright notices are retained in all copies and that this
12  * notice is included verbatim in any distributions. No written agreement,
13  * license, or royalty fee is required for any of the authorized uses.
14  * Modifications to this software may be copyrighted by their authors
15  * and need not follow the licensing terms described here, provided that
16  * the new terms are clearly indicated on the first page of each file where
17  * they apply.
18  */
20 /* -------------------------------------------------------------------------- */
21 /*!Generic interrupt handler function for or1k
22                                                                               */
23 /* -------------------------------------------------------------------------- */
25 #include "include/or1k-asm.h"
26 #include "include/or1k-sprs.h"
28         .extern _or1k_interrupt_handler_table
29         .extern _or1k_interrupt_handler_data_ptr_table
31 /* -------------------------------------------------------------------------- */
32 /*!Function to call appropriate interrupt handler
33                                                                               */
34 /* -------------------------------------------------------------------------- */
36         .section .text
37         .global _or1k_interrupt_handler
38         .type   _or1k_interrupt_handler,@function
40 _or1k_interrupt_handler:
41         /* Make room on stack, save link address register */
42         l.addi  r1,r1,-4
43         l.sw    0(r1),r9
45         /* Read PICSR */
46         l.mfspr r20,r0,OR1K_SPR_PIC_PICSR_ADDR
48         /* Load handler table base address */
49         // Needs to be callee-saved register
50         l.movhi r16,hi(_or1k_interrupt_handler_table)
51         l.ori   r16,r16,lo(_or1k_interrupt_handler_table)
52         /* Load data pointer table base address */
53         // Needs to be callee-saved register
54         l.movhi r18,hi(_or1k_interrupt_handler_data_ptr_table)
55         l.ori   r18,r18,lo(_or1k_interrupt_handler_data_ptr_table)
56 #ifdef __OR1K_MULTICORE__
57         /* Read the addresses of the arrays of cores */
58         /* r7 = (*or1k_interrupt_handler_table)  */
59         l.lwz   r16,0(r16)
60         /* r12 = (*or1k_interrupt_handler_data_ptr_table)  */
61         l.lwz   r18,0(r18)
62         /* Generate offset in arrays */
63         /* r14 = coreid */
64         l.mfspr r14,r0,OR1K_SPR_SYS_COREID_ADDR
65         /* r14 = coreid*32*4 = off */
66         l.slli  r14,r14,7
67         /* r7 = (*or1k_exception_handler_table)[coreid] */
68         l.add   r16,r16,r14
69         /* r12 = (*or1k_exception_handler_table)[coreid] */
70         l.add   r18,r18,r14
71 #endif
73 .L0:
74         /* Find first set bit in PICSR */
75         l.ff1   r4,r20
76         /* Any bits set? */
77         l.sfne  r4,r0
78         /* If none, finish */
79         OR1K_DELAYED_NOP(OR1K_INST(l.bnf .L2))
80         /* What is IRQ function table offset? */
81         l.addi  r22,r4,-1
82         l.slli  r6,r22,2
83         /* Add this to table bases */
84         l.add   r14,r6,r16
85         l.add   r13,r6,r18
87         /* Fetch handler function address */
88         l.lwz   r14,0(r14)
90         /* Double check it's valid, compare against INTERRUPT_HANDLER_NOT_SET */
91         l.sfne  r14,r0
92         /* Skip if no handler: TODO: Indicate interrupt fired but no handler*/
93         OR1K_DELAYED_NOP(OR1K_INST(l.bnf .L1))
95         /* Call handler, load data pointer */
96         OR1K_DELAYED(
97                 OR1K_INST(l.lwz  r3,0(r13)),
98                 OR1K_INST(l.jalr r14)
99         )
101 .L1:
102         /* Clear bit from PICSR, return to start of checking loop */
103         l.ori   r6,r0,1
104         l.sll   r6,r6,r22
105         OR1K_DELAYED(
106                 OR1K_INST(l.xor r20,r20,r6),
107                 OR1K_INST(l.j   .L0)
108         )
110 .L2:
111         /* Finish up - write PICSR back, restore r9*/
112         l.lwz   r9,0(r1)
113         l.mtspr r0,r20,OR1K_SPR_PIC_PICSR_ADDR
114         OR1K_DELAYED(
115                 OR1K_INST(l.addi r1,r1,4),
116                 OR1K_INST(l.jr   r9)
117         )
119 /* -------------------------------------------------------------------------- */
120 /*!Function to enable an interrupt handler in the PICMR
121                                                                               */
122 /* -------------------------------------------------------------------------- */
123         .global or1k_interrupt_enable
124         .type   or1k_interrupt_enable,@function
126         /* r3 should have IRQ line for peripheral */
127 or1k_interrupt_enable:
128         l.addi  r1,r1,-4
129         l.sw    0(r1),r4
130         l.ori   r4,r0,0x1
131         l.sll   r4,r4,r3
132         l.mfspr r3,r0,OR1K_SPR_PIC_PICMR_ADDR
133         l.or    r3,r3,r4
134         l.mtspr r0,r3,OR1K_SPR_PIC_PICMR_ADDR
135         l.lwz   r4,0(r1)
136         OR1K_DELAYED(
137                 OR1K_INST(l.addi        r1,r1,4),
138                 OR1K_INST(l.jr  r9)
139         )
141 /* -------------------------------------------------------------------------- */
142 /*!Function to disable an interrupt handler in the PICMR
143                                                                               */
144 /* -------------------------------------------------------------------------- */
145         .global or1k_interrupt_disable
146         .type   or1k_interrupt_disable,@function
148         /* r3 should have IRQ line for peripheral */
149 or1k_interrupt_disable:
150         l.addi  r1,r1,-4
151         l.sw    0(r1),r4
152         l.ori   r4,r0,0x1
153         l.sll   r4,r4,r3
154         l.xori  r4,r4,0xffff
155         l.mfspr r3,r0,OR1K_SPR_PIC_PICMR_ADDR
156         l.and   r3,r3,r4
157         l.mtspr r0,r3,OR1K_SPR_PIC_PICMR_ADDR
158         l.lwz   r4,0(r1)
159         OR1K_DELAYED(
160                 OR1K_INST(l.addi r1,r1,4),
161                 OR1K_INST(l.jr   r9)
162         )