summaryrefslogtreecommitdiff
path: root/newlib/libc/sys/a29khif/signal.s
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/sys/a29khif/signal.s')
-rw-r--r--newlib/libc/sys/a29khif/signal.s452
1 files changed, 452 insertions, 0 deletions
diff --git a/newlib/libc/sys/a29khif/signal.s b/newlib/libc/sys/a29khif/signal.s
new file mode 100644
index 00000000000..29273a0d30a
--- /dev/null
+++ b/newlib/libc/sys/a29khif/signal.s
@@ -0,0 +1,452 @@
+;@(#)signal.s 2.15 90/10/14 21:57:55, AMD
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Copyright 1990 Advanced Micro Devices, Inc.
+;
+; This software is the property of Advanced Micro Devices, Inc (AMD) which
+; specifically grants the user the right to modify, use and distribute this
+; software provided this notice is not removed or altered. All other rights
+; are reserved by AMD.
+;
+; AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS
+; SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL
+; DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR
+; USE OF THIS SOFTWARE.
+;
+; So that all may benefit from your experience, please report any problems
+; or suggestions about this software to the 29K Technical Support Center at
+; 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131 in the UK, or
+; 0031-11-1129 in Japan, toll free. The direct dial number is 512-462-4118.
+;
+; Advanced Micro Devices, Inc.
+; 29K Support Products
+; Mail Stop 573
+; 5900 E. Ben White Blvd.
+; Austin, TX 78741
+; 800-292-9263
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ .file "signal.s"
+
+; SigEntry is the address of an array of C-level user code signal handlers.
+; They must return to the top-level before doing a sigret() return function.
+; Nested signals are supported.
+
+ .extern V_SPILL, V_FILL
+ .extern fill ; In crt0.s
+
+ .align 4
+ .comm WindowSize, 4
+ .data
+SigEntry:
+ .word 0 ; reserved
+ .word 0 ; adds. of #2 SIGINT handler
+ .word 0 ; reserved
+ .word 0 ; reserved
+ .word 0 ; reserved
+ .word 0 ; reserved
+ .word 0 ; reserved
+ .word 0 ; adds. of #8 SIGFPE handler
+
+ .text
+
+ .reg v0, gr96
+ .reg v1, gr97
+ .reg v2, gr98
+ .reg v3, gr99
+
+ .reg tav, gr121
+ .reg tpc, gr122
+ .reg lrp, gr123
+ .reg slp, gr124
+ .reg msp, gr125
+ .reg rab, gr126
+ .reg rfb, gr127
+
+;=================================================================== setjmp()
+; int
+; setjmp(label_t jmpbuf)
+; {
+; *jmpbuf = {gr1, msp, lr0, lr1};
+; return 0;
+; }
+;
+ .global _setjmp
+_setjmp:
+ store 0, 0, gr1, lr2
+ add lr2, lr2, 4
+ store 0, 0, msp, lr2
+ add lr2, lr2, 4
+ store 0, 0, lr0, lr2
+ add lr2, lr2, 4
+ store 0, 0, lr1, lr2
+ jmpi lr0
+ const v0, 0
+;
+;==================================================================== longjmp()
+; int
+; longjmp(label_t jmpbuf, int value)
+; {
+; /* BUG: check for this
+; if (msp > jmpbuf->msp || gr1 > jmpbuf->gr1)
+; longjmperror();
+; */
+;
+; gr1 = jmpbuf->gr1;
+; lr2addr = jmpbuf->gr1 + 8;
+; msp = jmpbuf->msp;
+;
+; /* saved lr1 is invalid if saved lr2addr > rfb */
+; if (lr2addr > rfb) {
+; /*
+; * None of the registers are useful.
+; * Set rfb to lr2addr - 512 & rab to rfb - 512.
+; * the FILL assert will take care of filling
+; */
+; lr1 = jmpbuf->lr1;
+; rab = lr2addr - windowsize;
+; rfb = lr2addr;
+; }
+;
+; lr0 = jmpbuf->lr0;
+; if (rfb < lr1)
+; raise V_FILL;
+; return value;
+; }
+;
+ .global _longjmp
+_longjmp:
+ load 0, 0, tav, lr2 ; copy in gr1
+ add v1, lr2, 4 ; v1 points to msp
+ ; make sure we return a non-zero value
+ cpeq v0, lr3, 0
+ srl v0, v0, 31
+ or v0, lr3, v0
+
+ add gr1, tav, 0 ; now update gr1
+ add tav, tav, 8 ; calculate lr2addr
+ load 0, 0, msp, v1 ; update msp from jmpbuf
+ cpleu v3, tav, rfb ; if (lr2addr > rfb)
+ jmpt v3, $1 ; {
+ add v1, v1, 4 ; v1 points to lr0
+ add v2, v1, 4 ; v2 points to lr1
+ load 0, 0, lr1, v2 ; lr1 = value from jmpbuf
+ sub v3, rfb, rab ;
+ sub rab, tav, v3 ; rab = lr2addr - windowsize
+ add rfb, tav, 0 ; rfb = lr2addr
+$1: ; }
+ load 0, 0, lr0, v1
+ jmpi lr0
+ asgeu V_FILL, rfb, lr1 ; may fill from rfb to lr1
+;
+;================================================================== sigcode
+; About to deliver a signal to a user mode signal handler.
+; msp+(15*4) = signal_number
+; msp+(14*4) = gr1
+; msp+(13*4) = rab
+; msp+(12*4) = PC0
+; msp+(11*4) = PC1
+; msp+(10*4) = PC2
+; msp+( 9*4) = CHA
+; msp+( 8*4) = CHD
+; msp+( 7*4) = CHC
+; msp+( 6*4) = ALU
+; msp+( 5*4) = OPS
+; msp+( 4*4) = gr121
+; msp+( 3*4) = gr99
+; msp+( 2*4) = gr98
+; msp+( 1*4) = gr97
+; msp = gr96
+; The state of all the registers (except for msp, chc and rab)
+; is the same as when the process was interrupted.
+;
+; We must make the stack and window consistent before calling the handler
+; The orignal rab value is on the stack. The interrupt handler placed
+; rfb-Windowsize in rab. This is required to support nested interrupts.
+;
+; Note that the window becomes incosistent only during certain
+; critical sections in spill, fill, longjmp and sigcode.
+; rfb - rab > windowsize => we are in spill
+; rfb - rab < windowsize => we are in fill
+; gr1 + 8 > rfb => we are in long-longjmp case
+; In case of spill, fill and lonjmp; rab is modified first,
+; so if we are in one of these critical sections,
+; we set rab to rfb - WINDOWSIZE.
+;
+ .equ SIGCTX_SIZE, (16)*4
+ .equ SIGCTX_SIGNUMB, (15)*4
+ .equ SIGCTX_GR1_OFFSET, (14)*4
+ .equ SIGCTX_RAB_OFFSET, (13)*4
+ .equ SIGCTX_PC0_OFFSET, (12)*4
+ .equ SIGCTX_PC1_OFFSET, (11)*4
+ .equ SIGCTX_PC2_OFFSET, (10)*4
+ .equ SIGCTX_CHC_OFFSET, (7)*4
+ .equ SIGCTX_OPS_OFFSET, (5)*4
+ .equ SIGCTX_TAV_OFFSET, (4)*4
+ .global sigcode
+sigcode:
+; -------------------------------------------------------- R-Stack fixup
+ const v0, WindowSize ; get register cache size
+ consth v0, WindowSize
+ load 0, 0, v0, v0
+ add v2, msp, SIGCTX_RAB_OFFSET
+ load 0, 0, v2, v2 ; get interrupted rab value
+ sub v1, rfb, v2 ; determine if rfb-rab <= WINDOW_SIZE
+ cpgeu v1, v1, v0 ;
+ jmpt v1, nfill ; jmp if spill or 'normal' interrupt
+ add v1, gr1, 8
+ cpgt v1, v1, rfb ; interrupted longjmp can look like fill
+ jmpf v1, nfill ; test for long-longjmp interruption
+ nop ; jmp if gr1+8 <= rfb
+; Fixup signal stack to re-start interrupted fill
+; backup pc1 -- this is needed for the partial fill case.
+; Clear chc so an interrupted load/store does not restart.
+; Reset rab to a window distance below rfb, rab shall be
+; decremented again on re-starting the interrupted fill.
+; The interrupt handler set rab=rfb-WindowSize.
+;
+ add v0, msp, SIGCTX_RAB_OFFSET
+ store 0, 0, rab, v0 ; re-store (rfb-WindowSize) for rab
+ const v2, fill
+ consth v2, fill
+ add v0, msp, SIGCTX_PC1_OFFSET
+ store 0, 0, v2, v0
+ sub v2, v2, 4 ; determine pc0
+ add v0, msp, SIGCTX_PC0_OFFSET
+ store 0, 0, v2, v0
+ const v2, 0 ; clear chc
+ add v0, msp, SIGCTX_CHC_OFFSET
+ store 0, 0, v2, v0
+
+nfill:
+ cpgt v0, gr1, rfb ; if gr1 > rfb then gr1 = rfb
+ jmpt v0, lower
+ cplt v0, gr1, rab ; if gr1 < rab then gr1 = rab
+ jmpt v0, raise
+ nop
+; -------------------------------------------------------- save_regs
+sig1: sub msp, msp, (4+2+25)*4 ; reserve space for regs
+ mfsr gr96, ipc
+ mfsr gr97, ipa
+ mfsr gr98, ipb
+ mfsr gr99, q
+ mtsrim cr, 4-1
+ storem 0, 0, gr96, msp
+; "push" registers stack support
+ add gr96, lr1, 0
+ add gr97, rfb, 0
+ mtsrim cr, 2-1
+ add gr99, msp, 2*4
+ storem 0, 0, gr96, gr99
+; "push" remaining global registers
+ mtsrim cr, 25-1 ; gr100-gr124
+ add gr96, msp, (4+2)*4
+ storem 0, 0, gr100, gr96
+;
+; -------------------------------------------------------- Dummy Call
+ .equ RALLOC, 4*4 ; make space for function calls
+ add v0, rfb, 0 ; store original rfb
+ sub gr1, gr1, RALLOC
+ asgeu V_SPILL, gr1, rab
+ add lr1, v0, 0 ; set lr1 = original rfb
+ add v1, msp, (4+2+25)*4 + SIGCTX_SIGNUMB
+ load 0, 0, lr2, v1 ; restore signal number
+ sub v1, lr2, 1 ; get handler index
+ sll v1, v1, 2 ; point to addresses
+;
+; -------------------------------------------------------- call C-level
+; Handler must not use HIF services other than the _sigret() type.
+ const v0, SigEntry
+ consth v0, SigEntry
+ add v0, v0, v1
+ load 0, 0, v0, v0 ; determine if handler registered
+ cpeq v1, v0, 0
+ jmpt v1, NoHandler
+ nop
+ calli lr0, v0 ; call C-level signal handler
+ nop
+;
+; -------------------------------------------------------- default return
+NoHandler:
+ jmp __sigdfl
+ nop
+
+; -------------------------------------------------------- support bits
+lower: sll gr1, rfb, 0
+ jmp sig1
+ nop
+raise: sll gr1, rab, 0
+ jmp sig1
+ nop
+/*
+; -------------------------------------------------------- repair_regs
+ mtsrim cr, 4-1
+ loadm 0, 0, gr96, msp
+ mtsr ipc, gr96
+ mtsr ipa, gr97
+ mtsr ipb, gr98
+ mtsr Q, gr99
+; "pop" registers stack support
+ mtsrim cr, 2-1
+ add gr99, msp, 2*4
+ loadm 0, 0, gr96, gr99
+ add lr1, gr96, 0
+ add rfb, gr97, 0
+; "pop" remaining global registers
+ mtsrim cr, 25-1 ; gr100-gr124
+ add gr96, msp, (4+2)*4
+ loadm 0, 0, gr100, gr96
+ add msp, msp, (4+2+25)*4 ; repair msp to save_regs entry value
+; -------------------------------------------------------- end repair
+*/
+
+; ======================================================== _sigret()
+ .global __sigret
+__sigret:
+; repair_regs
+; -------------------------------------------------------- repair_regs
+ mtsrim cr, 4-1
+ loadm 0, 0, gr96, msp
+ mtsr ipc, gr96
+ mtsr ipa, gr97
+ mtsr ipb, gr98
+ mtsr q, gr99
+; "pop" registers stack support
+ mtsrim cr, 2-1
+ add gr99, msp, 2*4
+ loadm 0, 0, gr96, gr99
+ add lr1, gr96, 0
+ add rfb, gr97, 0
+; "pop" remaining global registers
+ mtsrim cr, 25-1 ; gr100-gr124
+ add gr96, msp, (4+2)*4
+ loadm 0, 0, gr100, gr96
+ add msp, msp, (4+2+25)*4 ; repair msp to save_regs entry value
+; -------------------------------------------------------- end repair
+ const tav, 323 ; HIF _sigret
+ asneq 69, gr1,gr1
+ halt ; commit suicide if returns
+
+; ======================================================== _sigdfl()
+ .global __sigdfl
+__sigdfl:
+; repair_regs
+; -------------------------------------------------------- repair_regs
+ mtsrim cr, 4-1
+ loadm 0, 0, gr96, msp
+ mtsr ipc, gr96
+ mtsr ipa, gr97
+ mtsr ipb, gr98
+ mtsr q, gr99
+; "pop" registers stack support
+ mtsrim cr, 2-1
+ add gr99, msp, 2*4
+ loadm 0, 0, gr96, gr99
+ add lr1, gr96, 0
+ add rfb, gr97, 0
+; "pop" remaining global registers
+ mtsrim cr, 25-1 ; gr100-gr124
+ add gr96, msp, (4+2)*4
+ loadm 0, 0, gr100, gr96
+ add msp, msp, (4+2+25)*4 ; repair msp to save_regs entry value
+; -------------------------------------------------------- end repair
+ const tav, 322 ; HIF _sigdfl
+ asneq 69, gr1,gr1
+ halt ; commit suicide if returns
+
+; ======================================================== _sigrep()
+__sigrep:
+ .global __sigrep
+; repair_regs
+; -------------------------------------------------------- repair_regs
+ mtsrim cr, 4-1
+ loadm 0, 0, gr96, msp
+ mtsr ipc, gr96
+ mtsr ipa, gr97
+ mtsr ipb, gr98
+ mtsr q, gr99
+; "pop" registers stack support
+ mtsrim cr, 2-1
+ add gr99, msp, 2*4
+ loadm 0, 0, gr96, gr99
+ add lr1, gr96, 0
+ add rfb, gr97, 0
+; "pop" remaining global registers
+ mtsrim cr, 25-1 ; gr100-gr124
+ add gr96, msp, (4+2)*4
+ loadm 0, 0, gr100, gr96
+ add msp, msp, (4+2+25)*4 ; repair msp to save_regs entry value
+; -------------------------------------------------------- end repair
+ const tav, 324 ; HIF _sigrep
+ asneq 69, gr1,gr1
+ halt ; commit suicide if returns
+
+; ======================================================== _sigskp()
+ .global __sigskp
+__sigskp:
+; repair_regs
+; -------------------------------------------------------- repair_regs
+ mtsrim cr, 4-1
+ loadm 0, 0, gr96, msp
+ mtsr ipc, gr96
+ mtsr ipa, gr97
+ mtsr ipb, gr98
+ mtsr q, gr99
+; "pop" registers stack support
+ mtsrim cr, 2-1
+ add gr99, msp, 2*4
+ loadm 0, 0, gr96, gr99
+ add lr1, gr96, 0
+ add rfb, gr97, 0
+; "pop" remaining global registers
+ mtsrim cr, 25-1 ; gr100-gr124
+ add gr96, msp, (4+2)*4
+ loadm 0, 0, gr100, gr96
+ add msp, msp, (4+2+25)*4 ; repair msp to save_regs entry value
+; -------------------------------------------------------- end repair
+ const tav, 325 ; HIF _sigskp
+ asneq 69, gr1,gr1
+ halt ; commit suicide if returns
+
+; ======================================================== _sendsig()
+; lr2 = signal number
+ .global _raise
+ .global __sendsig
+_raise:
+__sendsig:
+ const tav, 326 ; HIF sendsig
+ asneq 69, gr1,gr1
+ jmpi lr0
+ nop
+
+;
+; ======================================================== signal()
+; lr2 = signal number
+; lr3 = handler address
+ .global _signal
+_signal:
+; the memory variable WindowSize must be initalised at the
+; start when rfb and rab are a window size apart.
+ const v0, WindowSize ; get register cache size
+ consth v0, WindowSize
+ load 0, 0, v1, v0
+ cpeq v1, v1, 0
+ jmpf v1, WindowSizeOK
+ sub v1, rfb, rab ; rfb-rab = WINDOW_SIZE
+ store 0, 0, v1, v0
+WindowSizeOK:
+ const v1, SigEntry
+ consth v1, SigEntry
+ sub v3, lr2, 1 ; get handler index
+ sll v3, v3, 2 ; pointer to addresses
+ add v1, v1, v3
+ store 0,0, lr3, v1 ; save new handler
+
+ const lr2, sigcode
+ consth lr2, sigcode
+ ;Fall through to __signal
+; ======================================================== _signal()
+ .global __signal
+__signal:
+ const tav, 321 ; HIF signal
+ asneq 69, gr1,gr1
+ jmpi lr0
+ nop