Cygwin: Add new APIs tc[gs]etwinsize()
[newlib-cygwin.git] / newlib / libc / sys / a29khif / signal.S
blob29273a0d30a5f495806b2dbbe8dbda04936148a7
1 ;@(#)signal.s   2.15 90/10/14 21:57:55, AMD
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ; Copyright 1990 Advanced Micro Devices, Inc.
5 ; This software is the property of Advanced Micro Devices, Inc  (AMD)  which
6 ; specifically  grants the user the right to modify, use and distribute this
7 ; software provided this notice is not removed or altered.  All other rights
8 ; are reserved by AMD.
10 ; AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS
11 ; SOFTWARE.  IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL
12 ; DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR
13 ; USE OF THIS SOFTWARE.
15 ; So that all may benefit from your experience, please report  any  problems
16 ; or  suggestions about this software to the 29K Technical Support Center at
17 ; 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131  in  the  UK,  or
18 ; 0031-11-1129 in Japan, toll free.  The direct dial number is 512-462-4118.
20 ; Advanced Micro Devices, Inc.
21 ; 29K Support Products
22 ; Mail Stop 573
23 ; 5900 E. Ben White Blvd.
24 ; Austin, TX 78741
25 ; 800-292-9263
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27         .file   "signal.s"
29 ; SigEntry is the address of an array of C-level user code signal handlers.
30 ; They must return to the top-level before doing a sigret() return function.
31 ; Nested signals are supported.
33         .extern V_SPILL, V_FILL
34         .extern fill            ; In crt0.s
36         .align  4
37         .comm   WindowSize, 4
38         .data
39 SigEntry:
40         .word   0               ; reserved
41         .word   0               ; adds. of #2 SIGINT handler
42         .word   0               ; reserved
43         .word   0               ; reserved
44         .word   0               ; reserved
45         .word   0               ; reserved
46         .word   0               ; reserved
47         .word   0               ; adds. of #8 SIGFPE handler
49         .text
51         .reg    v0,     gr96
52         .reg    v1,     gr97
53         .reg    v2,     gr98
54         .reg    v3,     gr99
56         .reg    tav,    gr121
57         .reg    tpc,    gr122
58         .reg    lrp,    gr123
59         .reg    slp,    gr124
60         .reg    msp,    gr125
61         .reg    rab,    gr126
62         .reg    rfb,    gr127
64 ;=================================================================== setjmp()
65 ; int
66 ; setjmp(label_t jmpbuf)
67 ; {
68 ;       *jmpbuf = {gr1, msp, lr0, lr1};
69 ;       return 0;
70 ; }
72         .global _setjmp
73 _setjmp:
74         store   0, 0, gr1, lr2
75         add     lr2, lr2, 4
76         store   0, 0, msp, lr2
77         add     lr2, lr2, 4
78         store   0, 0, lr0, lr2
79         add     lr2, lr2, 4
80         store   0, 0, lr1, lr2
81         jmpi    lr0
82          const  v0, 0
84 ;==================================================================== longjmp()
85 ; int
86 ; longjmp(label_t jmpbuf, int value)
87 ; {
88 ;       /* BUG: check for this
89 ;         if (msp > jmpbuf->msp || gr1 > jmpbuf->gr1)
90 ;               longjmperror();
91 ;        */
93 ;       gr1 = jmpbuf->gr1;
94 ;       lr2addr = jmpbuf->gr1 + 8;
95 ;       msp = jmpbuf->msp;
97 ;       /* saved lr1 is invalid if saved lr2addr > rfb */
98 ;       if (lr2addr > rfb) {
99 ;               /*
100 ;                * None of the registers are useful.
101 ;                * Set rfb to lr2addr - 512 & rab to rfb - 512.
102 ;                * the FILL assert will take care of filling
103 ;                */
104 ;               lr1 = jmpbuf->lr1;
105 ;               rab = lr2addr - windowsize;
106 ;               rfb = lr2addr;
107 ;       }
109 ;       lr0 = jmpbuf->lr0;
110 ;       if (rfb < lr1)
111 ;               raise V_FILL;
112 ;       return value;
113 ; }
115         .global _longjmp
116 _longjmp:
117         load    0, 0, tav, lr2          ; copy in gr1
118         add     v1, lr2, 4              ; v1 points to msp
119         ; make sure we return a non-zero value
120         cpeq    v0, lr3, 0
121         srl     v0, v0, 31
122         or      v0, lr3, v0
124         add     gr1, tav, 0             ; now update gr1
125         add     tav, tav, 8             ; calculate lr2addr
126         load    0, 0, msp, v1           ; update msp from jmpbuf
127         cpleu   v3, tav, rfb            ; if (lr2addr > rfb)
128         jmpt    v3, $1                  ; {
129          add    v1, v1, 4               ; v1 points to lr0
130         add     v2, v1, 4               ;       v2 points to lr1
131         load    0, 0, lr1, v2           ;       lr1 = value from jmpbuf
132         sub     v3, rfb, rab            ;
133         sub     rab, tav, v3            ;       rab = lr2addr - windowsize
134         add     rfb, tav, 0             ;       rfb = lr2addr
135 $1:     ; }
136         load    0, 0, lr0, v1
137         jmpi    lr0
138          asgeu   V_FILL, rfb, lr1       ; may fill from rfb to lr1
140 ;================================================================== sigcode
141 ; About to deliver a signal to a user mode signal handler.
142 ;       msp+(15*4) = signal_number
143 ;       msp+(14*4) = gr1
144 ;       msp+(13*4) = rab
145 ;       msp+(12*4) = PC0
146 ;       msp+(11*4) = PC1
147 ;       msp+(10*4) = PC2
148 ;       msp+( 9*4) = CHA
149 ;       msp+( 8*4) = CHD
150 ;       msp+( 7*4) = CHC
151 ;       msp+( 6*4) = ALU
152 ;       msp+( 5*4) = OPS
153 ;       msp+( 4*4) = gr121
154 ;       msp+( 3*4) = gr99
155 ;       msp+( 2*4) = gr98
156 ;       msp+( 1*4) = gr97
157 ;       msp        = gr96
158 ; The state of all the registers (except for msp, chc and rab)
159 ; is the same as when the process was interrupted.
161 ; We must make the stack and window consistent before calling the handler
162 ; The orignal rab value is on the stack. The interrupt handler placed
163 ; rfb-Windowsize in rab. This is required to support nested interrupts.
165 ; Note that the window becomes incosistent only during certain
166 ; critical sections in spill, fill, longjmp and sigcode.
167 ;       rfb - rab > windowsize => we are in spill
168 ;       rfb - rab < windowsize => we are in fill
169 ;       gr1 + 8   > rfb        => we are in long-longjmp case
170 ; In case of spill, fill and lonjmp; rab is modified first,
171 ; so if we are in one of these critical sections,
172 ; we set rab to rfb - WINDOWSIZE.
174         .equ    SIGCTX_SIZE,            (16)*4
175         .equ    SIGCTX_SIGNUMB,         (15)*4
176         .equ    SIGCTX_GR1_OFFSET,      (14)*4
177         .equ    SIGCTX_RAB_OFFSET,      (13)*4
178         .equ    SIGCTX_PC0_OFFSET,      (12)*4
179         .equ    SIGCTX_PC1_OFFSET,      (11)*4
180         .equ    SIGCTX_PC2_OFFSET,      (10)*4
181         .equ    SIGCTX_CHC_OFFSET,      (7)*4
182         .equ    SIGCTX_OPS_OFFSET,      (5)*4
183         .equ    SIGCTX_TAV_OFFSET,      (4)*4
184         .global sigcode
185 sigcode:
186 ; --------------------------------------------------------  R-Stack fixup
187         const   v0, WindowSize          ; get register cache size
188         consth  v0, WindowSize
189         load    0, 0, v0, v0
190         add     v2, msp, SIGCTX_RAB_OFFSET
191         load    0, 0, v2, v2            ; get interrupted rab value
192         sub     v1, rfb, v2             ; determine if  rfb-rab <= WINDOW_SIZE
193         cpgeu   v1, v1, v0              ;
194         jmpt    v1, nfill               ; jmp if spill or 'normal' interrupt
195         add     v1, gr1, 8
196          cpgt   v1, v1, rfb             ; interrupted longjmp can look like fill
197         jmpf    v1, nfill               ; test for long-longjmp interruption
198          nop                            ; jmp if gr1+8 <= rfb
199 ; Fixup signal stack to re-start interrupted fill
200 ; backup pc1 -- this is needed for the partial fill case.
201 ; Clear chc so an interrupted load/store does not restart.
202 ; Reset rab to a window distance below rfb, rab shall be
203 ; decremented again on re-starting the interrupted fill.
204 ; The interrupt handler set rab=rfb-WindowSize.
206         add     v0, msp, SIGCTX_RAB_OFFSET
207         store   0, 0, rab, v0           ; re-store (rfb-WindowSize) for rab
208         const   v2, fill
209         consth  v2, fill
210         add     v0, msp, SIGCTX_PC1_OFFSET
211         store   0, 0, v2, v0
212         sub     v2, v2, 4               ; determine pc0
213         add     v0, msp, SIGCTX_PC0_OFFSET
214         store   0, 0, v2, v0
215         const   v2, 0                   ; clear chc
216         add     v0, msp, SIGCTX_CHC_OFFSET
217         store   0, 0, v2, v0
219 nfill:
220         cpgt    v0, gr1, rfb            ; if gr1 > rfb then gr1 = rfb
221         jmpt    v0, lower
222          cplt   v0, gr1, rab            ; if gr1 < rab then gr1 = rab
223         jmpt    v0, raise
224          nop
225 ; -------------------------------------------------------- save_regs
226 sig1:   sub     msp, msp, (4+2+25)*4    ; reserve space for regs
227         mfsr    gr96, ipc
228         mfsr    gr97, ipa
229         mfsr    gr98, ipb
230         mfsr    gr99, q
231         mtsrim  cr, 4-1
232         storem  0, 0, gr96, msp
233 ;                                        "push" registers stack support
234         add     gr96, lr1, 0
235         add     gr97, rfb, 0
236         mtsrim  cr, 2-1
237         add     gr99, msp, 2*4
238         storem  0, 0, gr96, gr99
239 ;                                         "push" remaining global registers
240         mtsrim  cr, 25-1                ; gr100-gr124
241         add     gr96, msp, (4+2)*4
242         storem  0, 0, gr100, gr96
244 ; -------------------------------------------------------- Dummy Call
245         .equ    RALLOC, 4*4             ; make space for function calls
246         add     v0, rfb, 0              ; store original rfb
247         sub     gr1, gr1, RALLOC
248         asgeu   V_SPILL, gr1, rab
249         add     lr1, v0, 0              ; set lr1 = original rfb
250         add     v1, msp, (4+2+25)*4 + SIGCTX_SIGNUMB
251         load    0, 0, lr2, v1           ; restore signal number
252         sub     v1, lr2, 1              ; get handler index
253         sll     v1, v1, 2               ; point to addresses
255 ; -------------------------------------------------------- call C-level
256 ; Handler must not use HIF services other than the _sigret() type.
257         const   v0, SigEntry
258         consth  v0, SigEntry
259         add     v0, v0, v1
260         load    0, 0, v0, v0            ; determine if handler registered
261         cpeq    v1, v0, 0
262         jmpt    v1, NoHandler
263          nop
264         calli   lr0, v0                 ; call C-level signal handler
265          nop
267 ; -------------------------------------------------------- default return
268 NoHandler:
269         jmp     __sigdfl
270          nop
272 ; -------------------------------------------------------- support bits
273 lower:  sll     gr1, rfb, 0
274         jmp     sig1
275          nop
276 raise:  sll     gr1, rab, 0
277         jmp     sig1
278          nop
280 ; -------------------------------------------------------- repair_regs
281         mtsrim  cr, 4-1
282         loadm   0, 0, gr96, msp
283         mtsr    ipc, gr96
284         mtsr    ipa, gr97
285         mtsr    ipb, gr98
286         mtsr    Q, gr99
287 ;                                        "pop" registers stack support
288         mtsrim  cr, 2-1
289         add     gr99, msp, 2*4
290         loadm   0, 0, gr96, gr99
291         add     lr1, gr96, 0
292         add     rfb, gr97, 0
293 ;                                         "pop" remaining global registers
294         mtsrim  cr, 25-1                ; gr100-gr124
295         add     gr96, msp, (4+2)*4
296         loadm   0, 0, gr100, gr96
297         add     msp, msp, (4+2+25)*4    ; repair msp to save_regs entry value
298 ; -------------------------------------------------------- end repair
301 ; ======================================================== _sigret()
302         .global __sigret
303 __sigret:
304 ;       repair_regs
305 ; -------------------------------------------------------- repair_regs
306         mtsrim  cr, 4-1
307         loadm   0, 0, gr96, msp
308         mtsr    ipc, gr96
309         mtsr    ipa, gr97
310         mtsr    ipb, gr98
311         mtsr    q, gr99
312 ;                                        "pop" registers stack support
313         mtsrim  cr, 2-1
314         add     gr99, msp, 2*4
315         loadm   0, 0, gr96, gr99
316         add     lr1, gr96, 0
317         add     rfb, gr97, 0
318 ;                                         "pop" remaining global registers
319         mtsrim  cr, 25-1                ; gr100-gr124
320         add     gr96, msp, (4+2)*4
321         loadm   0, 0, gr100, gr96
322         add     msp, msp, (4+2+25)*4    ; repair msp to save_regs entry value
323 ; -------------------------------------------------------- end repair
324         const   tav, 323                ; HIF _sigret
325         asneq   69, gr1,gr1
326         halt                            ; commit suicide if returns
328 ; ======================================================== _sigdfl()
329         .global __sigdfl
330 __sigdfl:
331 ;       repair_regs
332 ; -------------------------------------------------------- repair_regs
333         mtsrim  cr, 4-1
334         loadm   0, 0, gr96, msp
335         mtsr    ipc, gr96
336         mtsr    ipa, gr97
337         mtsr    ipb, gr98
338         mtsr    q, gr99
339 ;                                        "pop" registers stack support
340         mtsrim  cr, 2-1
341         add     gr99, msp, 2*4
342         loadm   0, 0, gr96, gr99
343         add     lr1, gr96, 0
344         add     rfb, gr97, 0
345 ;                                         "pop" remaining global registers
346         mtsrim  cr, 25-1                ; gr100-gr124
347         add     gr96, msp, (4+2)*4
348         loadm   0, 0, gr100, gr96
349         add     msp, msp, (4+2+25)*4    ; repair msp to save_regs entry value
350 ; -------------------------------------------------------- end repair
351         const   tav, 322                ; HIF _sigdfl
352         asneq   69, gr1,gr1
353         halt                            ; commit suicide if returns
355 ; ======================================================== _sigrep()
356 __sigrep:
357         .global __sigrep
358 ;       repair_regs
359 ; -------------------------------------------------------- repair_regs
360         mtsrim  cr, 4-1
361         loadm   0, 0, gr96, msp
362         mtsr    ipc, gr96
363         mtsr    ipa, gr97
364         mtsr    ipb, gr98
365         mtsr    q, gr99
366 ;                                        "pop" registers stack support
367         mtsrim  cr, 2-1
368         add     gr99, msp, 2*4
369         loadm   0, 0, gr96, gr99
370         add     lr1, gr96, 0
371         add     rfb, gr97, 0
372 ;                                         "pop" remaining global registers
373         mtsrim  cr, 25-1                ; gr100-gr124
374         add     gr96, msp, (4+2)*4
375         loadm   0, 0, gr100, gr96
376         add     msp, msp, (4+2+25)*4    ; repair msp to save_regs entry value
377 ; -------------------------------------------------------- end repair
378         const   tav, 324                ; HIF _sigrep
379         asneq   69, gr1,gr1
380         halt                            ; commit suicide if returns
382 ; ======================================================== _sigskp()
383         .global __sigskp
384 __sigskp:
385 ;       repair_regs
386 ; -------------------------------------------------------- repair_regs
387         mtsrim  cr, 4-1
388         loadm   0, 0, gr96, msp
389         mtsr    ipc, gr96
390         mtsr    ipa, gr97
391         mtsr    ipb, gr98
392         mtsr    q, gr99
393 ;                                        "pop" registers stack support
394         mtsrim  cr, 2-1
395         add     gr99, msp, 2*4
396         loadm   0, 0, gr96, gr99
397         add     lr1, gr96, 0
398         add     rfb, gr97, 0
399 ;                                         "pop" remaining global registers
400         mtsrim  cr, 25-1                ; gr100-gr124
401         add     gr96, msp, (4+2)*4
402         loadm   0, 0, gr100, gr96
403         add     msp, msp, (4+2+25)*4    ; repair msp to save_regs entry value
404 ; -------------------------------------------------------- end repair
405         const   tav, 325                ; HIF _sigskp
406         asneq   69, gr1,gr1
407         halt                            ; commit suicide if returns
409 ; ======================================================== _sendsig()
410 ; lr2 = signal number
411         .global _raise
412         .global __sendsig
413 _raise:
414 __sendsig:
415         const   tav, 326                ; HIF sendsig
416         asneq   69, gr1,gr1
417         jmpi    lr0
418          nop
421 ; ======================================================== signal()
422 ;       lr2 = signal number
423 ;       lr3 = handler address
424         .global _signal
425 _signal:
426 ; the memory variable WindowSize must be initalised at the
427 ; start when rfb and rab are a window size apart.
428         const   v0, WindowSize          ; get register cache size
429         consth  v0, WindowSize
430         load    0, 0, v1, v0
431         cpeq    v1, v1, 0
432         jmpf    v1, WindowSizeOK
433          sub    v1, rfb, rab            ; rfb-rab = WINDOW_SIZE
434         store   0, 0, v1, v0
435 WindowSizeOK:
436         const   v1, SigEntry
437         consth  v1, SigEntry
438         sub     v3, lr2, 1              ; get handler index
439         sll     v3, v3, 2               ; pointer to addresses
440         add     v1, v1, v3
441         store   0,0, lr3, v1            ; save new handler
443         const   lr2, sigcode
444         consth  lr2, sigcode
445         ;Fall through to __signal
446 ; ======================================================== _signal()
447         .global __signal
448 __signal:
449         const   tav, 321                ; HIF signal
450         asneq   69, gr1,gr1
451         jmpi    lr0
452          nop