.title SIGVEC - Condition handling facility Signal and Stop .sbttl FIGURE_2 - SIGVEC module listing .ident /V2.0/ ;++ ; ; **** USED BY PERMISSION OF THE VAX PROFESSIONAL TECHNICAL JOURNAL **** ; **** USED BY PERMISSION OF THE VAX PROFESSIONAL TECHNICAL JOURNAL **** ; **** USED BY PERMISSION OF THE VAX PROFESSIONAL TECHNICAL JOURNAL **** ; ;Disclaimer: ; This code was published in the VAX Professional technical journal of ; October 1991, Volume 13, 1991, number 5 in an article entitled ; 'Using LIB$SIGNAL To Call SYS$PUTMSG'. The code presented here is ; distributed by permission of the VAX Professional technical journal and ; may not be published or used for profit in *ANY* form without the express ; written consent of both the VAX Professional and the author. ; ; I would also like to expressly thank the editorial staff of the VAX ; Professional technical journal for both their consideration in publishing ; the original article, and for their permission to include it in this ; DECUS release. ; ;License: ; Ownership of and rights to these programs is retained by the author(s) ; and/or current copyright holders. Right to use and copy is governed ; by the appropriate U.S. copyright laws. ; ; Limited license to use and distribute the software in this library is ; hereby granted under the following conditions (insofar as these ; conditions are consistent with U.S. copyright law - in the event of ; a conflict, the U.S. copyright law has precedence): ; 1. Any and all disclaimer, authorship, ownership, copyright or licensing ; information is preserved within any source copies at all times. ; 2. Under absolutely *NO* circumstances may any of this code be used ; in any form for commercial profit without a written licensing ; agreement from the author(s) and/or copyright holders. This does not ; imply that such a written agreement could or could not be obtained. ; The availability of such an agreement will be determined when a need ; arises. ; 3. Except by written agreement under condition 2, source shall ; be freely provided with all binaries. ; 4. Publication of the materials contained in this library is ; expressly prohibited without written permission from the author(s) ; and/or current copyright holders. ; 5. Library contents may be transferred or copied in any form so ; long as all preceeding conditions are met. Nominal charges may ; be assessed for media and transferral labor without such charges ; being considered 'commercial profit' thereby violating condition 2. ; ;Warranty: ; These programs are distributed in the hopes that they will be useful, but ; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ; or FITNESS FOR A PARTICULAR PURPOSE. ; ; ; CREATION DATE: 90.09.04 ; ; AUTHOR: David G. North, CCP ; ; FACILITY: SIGVEC ; ; FUNCTIONAL DESCRIPTION: ; These routines modify a caller's argument list destined for LIB$STOP ; or LIB$SIGNAL to be compatible with what is required by SYS$PUTMSG ; so that the signal array constructed by LIB$SIGNAL may be used ; directly as a message vector for input to SYS$PUTMSG and still ; produce predictable results. ; ; CALLING FORMAT: ; LIB_SIGNAL condition-value1 [,number-of-arguments1] ; [,FAO-argument1...] [,condition-value2] ; [,number-of-arguments2] [,FAO-argument2...] ; ; Formal arguments: ; ; condition-value1 ; VMS usage: cond_value ; type: longword (unsigned) ; access: read only ; mechanism: by value ; ; number-of-arguments1 ; VMS usage: longword ; type: longword ; access: read only ; mechanism: by value ; ; FAO-argument1 ; VMS usage: varying_arg ; type: unspecified ; access: read only ; mechanism: by value ; ; condition-value2 ; VMS usage: cond_value ; type: longword ; access: read only ; mechanism: by value ; ; number-of-arguments2 ; VMS usage: longword ; type: longword ; access: read only ; mechanism: by value ; ; FAO-argument2 ; VMS usage: varying_arg ; type: unspecified ; access: read only ; mechanism: by value ; ; MODIFICATIONS: ; DGN-900904-001 Initial release ; DGN-911113-001 DECUS release (Fall '91) ;-- .sbttl Declarations .dsabl gbl .extrn SYS$SRCHANDLER ;these require linking .extrn EXE$EXCEPTABLE ; with sys$system:sys.stb .extrn LIB$STOP .extrn LIB$SIGNAL $libdef ;library status defs $rmsdef ;rms status code definitions $sfdef ;stack frame offsets $ssdef ;system status codes $stsdef ;status definitions .PSECT _LIB$CODE,PIC,SHR,NOWRT,LONG .SBTTL LIB_STOP - Stop execution via signalling .ENTRY LIB_STOP, ^m<> pushr #^m ;save R0 and R1 movaw g^LIB$STOP,r0 ;save target routine address brw common ;branch off to common processing .SBTTL LIB_SIGNAL - Signal Exceptional Condition .ENTRY LIB_SIGNAL, ^m<> pushr #^m ;save R0 and R1 movaw g^LIB$SIGNAL,r0 ;save target routine address brw common ;branch off to common processing .SBTTL COMMON - Internal Routine to handle vectoring common: extzv #SF$V_STACKOFFS,#SF$S_STACKOFFS,SF$W_SAVE_MASK(FP),r1 bbc #SF$V_CALLS,SF$W_SAVE_MASK(FP),rmvclg ;go handle CALLG call ; stack as follows: ; 00(SP) - R0'R1 ; 08(SP) - removed callframe (cond_handler) rmvcls: movl SF$L_SAVE_AP(FP),AP ;restore caller's AP movpsl -(SP) ;save PSL movw SF$W_SAVE_PSW(FP),(SP) ;update with caller's PSW pushl SF$L_SAVE_PC(FP) ;save caller's PC movl SF$L_SAVE_FP(FP),FP ;restore caller's FP ;the stack frame is now officially gone ; stack as follows: ; 00(SP) - PC ; 04(SP) - PSL ; 08(SP) - R0'R1 ; 16(SP) - removed callframe (cond_handler) ; 20(SP) - removed callframe (psw/align/regsavmsk/etc.) ; 24(SP) - removed callframe (savedAP) ; 28(SP) - removed callframe (savedFP) ; 32(SP) - removed callframe (savedPC) ; ????? - {may be some alignment trash here...R1} ; 36(SP)++- begin caller arguments movq 8(SP),28(SP) ;copy saved R0'R1 to old callframe movq (SP),20(SP) ;copy PSL'PC to old callframe moval 20(SP),SP ;remove unused stack data pushl r0 ;address of target routine ; stack as follows: ; 00(SP) - Target routine ; 04(SP) - PC ; 08(SP) - PSL ; 12(SP) - R0'R1 ; ????? - {may be some alignment trash here...R1} ; 20(SP)++- begin caller arguments bsbw align_up ;move any alignment filler to bottom brw frame_setup_commonized ;branch to common frame handling ; stack as follows: ; 00(SP) - R0'R1 ; 08(SP) - removed callframe (cond_handler) rmvclg: movpsl -(SP) ;save PSL movw SF$W_SAVE_PSW(FP),(SP) ;update with caller's PSW pushl SF$L_SAVE_PC(FP) ;save caller's PC movl SF$L_SAVE_FP(FP),FP ;restore caller's FP ;(Stack frame has been removed) movl 16+SF$L_SAVE_AP(SP),16(SP) ;Save caller's AP ; stack as follows: ; 00(SP) - PC ; 04(SP) - PSL ; 08(SP) - R0'R1 ; 16(SP) - Caller's saved AP ; 20(SP) - removed callframe (psw/align/regsavmsk/etc.) ; 24(SP) - removed callframe (savedAP) ; 28(SP) - removed callframe (savedFP) ; 32(SP) - removed callframe (savedPC) ; ????? - {may be some alignment trash here...R1} ; 36(SP)++- begin caller arguments (Not necessarily!) movq 8(SP),28(SP) ;copy saved R0'R1 to old callframe movq (SP),20(SP) ;copy PSL'PC to old callframe moval 16(SP),SP ;remove unused stack data pushl r0 ;address of target routine ; stack as follows: ; 00(SP) - Target routine ; 04(SP) - Caller's saved AP (CALLG) ; 08(SP) - PC ; 12(SP) - PSL ; 16(SP) - R0'R1 ; ????? - {may be some alignment trash here...R1} ; 24(SP)++- caller stack... point of insert (poi) ; for CALLS simulation movl @4(SP),r0 ;get caller passed # of args incl r0 ;will need to insert this # of lwords ashl #2,r0,r0 ;mul 4 giving Lword offset subl r0,SP ;create space addl SP,r0 ;point back @ old SP ; stack as follows: ; 00(SP) - ; 00(r0) - Target routine ; 04(r0) - Caller's saved AP (CALLG) ; 08(r0) - PC ; 12(r0) - PSL ; 16(r0) - R0'R1 ; ????? - {may be some alignment trash here...R1} ; 24(r0)++- caller stack... poi for CALLS simulation movq (r0),(SP) ;save target routine/caller AP movq 8(r0),8(SP) ;copy PSL'PC movq 16(r0),16(SP) ;copy R0'R1 ; stack as follows: ; 00(SP) - Target routine ; 04(SP) - Caller's saved AP (CALLG) ; 08(SP) - PC ; 12(SP) - PSL ; 16(SP) - R0'R1 ; 24(SP) - ; ????? - {may be some alignment trash here...R1} ; ??(SP)++- Original caller stack... poi for CALLS simulation movl (AP),r0 ;get called AP... i.e. arglist pointer 10$: movl (AP)[r0],24(SP)[r0] ;copy arguments... bottom first sobgeq r0,10$ ;do for whole list movl 4(SP),AP ;restore caller's AP movl (SP)+,(SP) ;copy down target routine address ; stack as follows: ; 00(SP) - Target routine ; 04(SP) - PC ; 08(SP) - PSL ; 12(SP) - R0'R1 ; 20(SP)++- begin caller arguments ; ????? - {may be some alignment trash here...R1} frame_setup_commonized: bsbw fixupsigargs ;carve the arguments into corrected mold bsbw align_down ;move data back down & alignment fill up ;... now... create a fake callframe with the appropriate save mask etc.. ; At this point the stack is as follows: ; 00(SP) - Target routine ; 04(SP) - PC ; 08(SP) - PSL ; 12(SP) - R0'R1 ; ????? - {may be some alignment trash here...R1} ; 20(SP)++- altered caller arguments movl SP,r0 ;save current SP pushr @(SP) ;create CALLS save registers ; At this point the stack is as follows: ; 00(SP) - LIB$xxx saved registers per entry mask ; 00(r0) - Target routine ; 04(r0) - PC ; 08(r0) - PSL ; 12(r0) - R0'R1 ; ????? - {may be some alignment trash here...R1} ; 20(r0)++- altered caller arguments movab 20(r0)[r1],r1 ;point at caller arguments movq 12(r0),-(SP) ;copyup R0'R1 movq 4(r0),-(SP) ;copyup PSL'PC movl (r0),-(SP) ;copyup target routine address 10$: cmpl r0,SP ;see if 'copydown' completed beql 20$ ;stack adjust completed movl -4(r0),16(r0) ;copy back down moval -4(r0),r0 ;walk up the stack copying as we go brb 10$ ;do more copying still moval 20(SP),SP ;remove extra copy of local data ; At this point the stack is as follows: ; 00(SP) - Target routine ; 04(SP) - PC ; 08(SP) - PSL ; 12(SP) - R0'R1 ; 20(SP) - LIB$xxx saved registers per entry mask ; ????? - {may be some alignment trash here...implied in R1} ; 00(r1)++- altered caller arguments 20$: movab @4(SP),-(SP) ;create savedPC pushl FP ;create savedFP pushl AP ;create savedAP movl r1,AP ;create 'new' AP ; At this point the stack is as follows: ; 00(SP) - saved AP ; 04(SP) - saved FP ; 08(SP) - saved PC (same as 16(SP)) ; 12(SP) - Target routine ; 16(SP) - PC ; 20(SP) - PSL ; 24(SP) - R0'R1 ; 32(SP) - LIB$xxx saved registers per entry mask ; ????? - {may be some alignment trash here...implied in R1} ; 00(r1)++- altered caller arguments movzwl @12(SP),r0 ;get savemask ASSUME SF$W_SAVE_MASK EQ 6 ;code below requires this ashl #16,r0,r0 ;move to high word bisl #1@,r0 ;set CALLS bit (in SAVPSW word!!!) bisw 20(SP),r0 ;poke in intercepted PSW insv r1,#SF$V_STACKOFFS+16,#SF$S_STACKOFFS,r0 ;insert stack align pushl r0 ;save to new partial frame clrl -(SP) ;add an 'empty' condition handler ; At this point the stack is as follows: ; 00(SP) - 0 (null condition handler) {Begin set of 5 Lwords} ; 04(SP) - savedPSW/savemask/CALLS/align/etc ; 08(SP) - saved AP ; 12(SP) - saved FP ; 16(SP) - saved PC (same as 16(SP)) ; {End set of 5 Lwords} ; 20(SP) - Target routine {Begin set of 5 Lwords} ; 24(SP) - PC ; 28(SP) - PSL ; 32(SP) - R0'R1 {End set of 5 Lwords} ; ; 40(SP)++- LIB$xxx saved registers per entry mask ; ??(SP)++- altered caller arguments clrl r1 ;prep for 5 exchanges 30$: xorl (SP)[r1],20(SP)[r1] ;Using a 3-XOR exchange in place xorl 20(SP)[r1],(SP)[r1] ; xorl (SP)[r1],20(SP)[r1] ; aoblss #5,r1,30$ ;do 5 times ; At this point the stack is as follows: ; 00(SP) - Target routine ; 04(SP) - PC (duplicated in callframe) ; 08(SP) - PSL ; 12(SP) - R0'R1 ; ; 20(SP) - 0 (null condition handler) ; 24(SP) - savedPSW/savemask/CALLS/align/etc ; 28(SP) - saved AP ; 32(SP) - saved FP ; 36(SP) - saved PC (same as 16(SP)) ; 40(SP)++- LIB$xxx saved registers per entry mask ; ??(SP)++- altered caller arguments movq 12(SP),r0 ;restore caller r0/r1 movl (SP),16(SP) ;move target routine address addl #2,16(SP) ;jump the entry mask in target rtn moval 16(SP),SP ;remove ramaining unused stack data moval 4(SP),FP ;insert new frame!!! rsb ;RSB into target routine!!! ; stack as follows: ; 00(SP) - RSB address ; 04(SP) - Target routine ; 08(SP) - PC ; 12(SP) - PSL ; 16(SP) - R0'R1 ; 24(SP) - argument list ; ?????? - r1 alignment bytes align_down: tstl r1 ;any re-aligment to do??? beql 10$ ;nope... skip this junk pushr #^m ;save all trashed registers movl 5*4+24(SP),r2 ;get numargs moval @#4[r2],r2 ;make into byte count incl numargs movc3 r2,5*4+24(SP),5*4+24(SP)[r1] ;shift stack popr #^m ;restore all trashed registers 10$: rsb ; stack as follows: ; 00(SP) - RSB address ; 04(SP) - Target routine ; 08(SP) - PC ; 12(SP) - PSL ; 16(SP) - R0'R1 ; ?????? - r1 alignment bytes ; 24(SP)[r1] - argument list align_up: tstl r1 ;any re-aligment to do??? beql 10$ ;nope... skip this junk pushr #^m ;save all trashed registers movzbl 5*4+24(SP)[r1],r2 ;get numargs moval @#4[r2],r2 ;make into byte count incl numargs movc3 r2,5*4+24(SP)[r1],5*4+24(SP) ;shift stack popr #^m ;restore all trashed registers 10$: rsb ; At this point the stack is as follows: ; 00(SP) - Return address ; 04(SP) - Target routine ; 08(SP) - PC ; 12(SP) - PSL ; 16(SP) - R0'R1 ; 24(SP)++- begin caller arguments ; ; The next higher location on the stack is the ; value of the caller's SP just before the CALL. ; ; AP and FP have been restored to the caller's values. ; ; Requirement is to make sure the signal array as constructed is ; reasonable in order to call SYS$PUTMSG and get rational results. ; This routine may, or may not radically modify the contents of the ; signal array. ; ; Entry is by JSB ; fixupsigargs: pushr #^m ;save some registers movab 4*8+24(SP),r1 ;point at signal arguments movab 4(r1),r0 ;point at signal array movq r0,r6 ;setup permanent pointers movl (r1),r0 ;get actual arg count (+psl'pc) moval 4(r1)[r0],r8 ;calculate first arg *past* eoargs nxtcod: cmpl r6,r8 ;see if at eoargs (end-of-args) blssu 10$ ;not yet... process another code brw argsdun ;do final processing of arguments 10$: extzv #STS$V_FAC_NO,#STS$S_FAC_NO,(r6),r0 ;extract facility moval 4(r6),r6 ;jump past condition code cmpl r6,r8 ;see if there was an omitted fao_count bneq 20$ ;jump if none required bsbw insr6 ;insert an extra zero fao_count 20$: cmpl r0,#0 ;see if facility is system (SS$_) bneq 30$ ;jump if non-system brw fixsys ;branch to system fixup code 30$: cmpl r0,#1 ;see if facility is RMS (RMS$_) bneq newcod ;user code, assume user did it correctly brw fixrms ;branch to RMS fixup code ; here, (R6) guaranteed to point to an FAO count newcod: movl (r6),r0 ;get fao count moval 4(r6)[r0],r6 ;jump to new status code brw nxtcod ;process next status (r1) ; fixup caller argument list for system type code fixsys: movl @#EXE$EXCEPTABLE,r2 ;get address of exception table movzbl (r2)+,r0 ;pick up exception count 10$: movzbl (r2)+,r3 ;pick up arg count req'd movzwl (r2)+,r1 ;pick up condition being tested cmpzv #STS$V_CODE,#STS$S_CODE,-4(r6),r1 ;see if it's this cond... beql 20$ ;yes... force correct FAO count sobgtr r0,10$ ;go back until no more codes movl (r6),r3 ;number of args to remove clrl r4 ;starting w/arg number 0 brw rmvsysargs ;remove any excess 20$: cmpl (r6),r3 ;compare passed w/req'd bgequ 30$ ;calculate more removals movl (r6),r4 ;start insertions here subl (r6),r3 ;insert this many brw inssysargs ;insert req'd args 30$: movl r3,r4 ;start removal here subl3 r3,(r6),r3 ;remove this many brw rmvsysargs ;remove any excess ; r3 = number of removals ; r4 = index of first removal (0..n) ; (r6) --> faocnt[,arg1[,arg2[,...]]] ; (all registers preserved (xr3=0)) rmvsysargs: tstl r3 ;any left to remove? bneq 10$ ;yes... continue removals brw newcodrmv ;***exit RMVSYSARGS 10$: bsbb 20$ ;remove an argument decl r3 ;count (rather un-count) the removal brb rmvsysargs ;go back 'til dun! 20$: pushl r2 ;save a trashed register decl (r6) ;dec FAO count for this code decl (r7) ;dec whole signal array count moval 4(r6)[r4],r2 ;calc address of removal 30$: movl -(r2),4(r2) ;copydown an argument cmpl r2,SP ;did we just copy (SP)??? bneq 30$ ;copy 'til hit top of stack moval 4(SP),SP ;argument floated to top of stack..rmv'd popl r2 ;restore trashed register moval 4(r6),r6 ;adjust R6 for deletion moval 4(r7),r7 ;adjust R7 for deletion rsb ; r3 = number of insertions ; r4 = index of first insertion ; (r6) --> faocnt[,arg1[,arg2[,...]]] ; (all registers preserved (xr3=0)) inssysargs: tstl r3 ;any left to insert? bneq 10$ ;yes... continue inserting brw newcodrmv ;***exit INSSYSARGS 10$: bsbb 20$ ;insert an argument incl r4 ;need to insert subsequently decl r3 ;count (rather un-count) insertion brb inssysargs ;go back 'til dun! 20$: ;inssglsysarg: subroutine to insert one system argument pushal -4(r6) ;save munged registers &fix for insert pushl r3 ;save argnum (so it can be bashed) cmpzv #STS$V_FAC_NO,#STS$S_FAC_NO,-4(r6),#0 ;was this a system code? beql 25$ ;yes... allow R3 thru untouched clrl r3 ;bash this so PSL'PC adj. won't occur 25$: incl (r6) ;inc code-specific FAO count moval 4(r6)[r4],r6 ;calc address of insertion bsbw insr6 ;insert space (r6) cmpl r3,#2 ;is this #2 insert (PC)?? beql 40$ ;go insert a PC @ (R6) cmpl r3,#1 ;is this #1 insert (PSL)?? beql 50$ ;go insert a PSL @(R6) 30$: popl r3 ;restore (possibly bashed) argnum popl r6 ;get out of inssglsysarg rsb ;back to main insertion loop 40$: ;used to insert a PC @ (R6) pushl r6 ;address to write at movl -16(r7),@(SP)+ ;pop it in place brb 30$ 50$: ;used to insert a PSL @ (R6) pushl r6 ;address to write at movl -12(r7),@(SP)+ ;pop it in place brb 30$ ; here, (R6) guaranteed to point to an FAO count newcodrmv: ;because this is a system code, need to remove FAO cnt movl (r6),r0 ;get fao count moval 4(r6)[r0],-(SP) ;save addr of new status code decl (r7) ;dec whole signal array count 10$: movl -(r6),4(r6) ;copydown an argument cmpl r6,SP ;did we just copy (SP)??? bneq 10$ ;copy 'til hit top of stack moval 4(SP),SP ;extra floated to top of stack...rmv'd popl r6 ;retrieve address of next status moval 4(r7),r7 ;compensate signal array address brw nxtcod ;process next status (r6) fixrms: movzbl #1,r3 ;always require 1 argument cmpl (r6),r3 ;compare passed w/req'd bgequ 10$ ;calculate more removals movl (r6),r4 ;start insertions here subl (r6),r3 ;insert this many brw inssysargs ;insert req'd args 10$: movl r3,r4 ;start removal here subl3 r3,(r6),r3 ;remove this many brw rmvsysargs ;remove any excess ; ; (R7) --> Signal array size ; Array is all munged up to allow direct deletion of formed PC/PSL ; instead, we will add the code SS$_OPCCUS (note that most of ; the normal system exceptions with *only* pc/psl arguments would ; work also... i.e. SS$_BREAK, SS$_OPCDEC) and set the ; STS$M_INHIB_MSG bit so that $PUTMSG will ignore the parameter. ; This allows EXE$SRCHANDLER and EXE$CONTSIG to function as expected ; and terminate with an REI instruction... if the PSL'PC is deleted, then ; any attempt to SS$_CONTINUE will cause problems because the stack is ; scrozzled at the REI from exception. Note also that STEP in the debugger ; does not work well in the SS$_CONTINUE case... the PSL has the TBIT set ; which trashes the debugger when executed at the wrong time. argsdun: movl (r7),r6 ;get current argcount bneq 10$ ;was an argument... proceed as is moval 4(r7)[r6],r6 ;addr of future PSL'PC (insert prior) bsbb insr6 ;add in NULL FAO arg cnt bsbb insr6 ;add in the space for LIB$_SIGNO_ARG movl #LIB$_SIGNO_ARG,(r6) ;code to issue NO ARG message brb argsdun ;*now* finish arglist!!! 10$: moval 4(r7)[r6],r6 ;addr of future PSL'PC (insert prior) bsbb insr6 ;add in the space for SS$_OPCCUS... movl #SS$_OPCCUS!STS$M_INHIB_MSG,(r6) ;code to rmv PSL'PC popr #^m rsb ;backto mainline sigvec code ; ;insert 'space' at (r6)... ; (r6) must be left intact, ; -4(r6) upto SP will be moved negative one longword ; r6 will point to newly created cell ; all registers must be preserved insr6: pushl r0 ;save these registers clrl -(SP) ;make new cell moval 4(SP),r0 ;get address of source cell 10$: movl (r0)+,-8(r0) ;copyback cmpl r0,r6 ;was this the last item to copy? bneq 10$ ;nope... copy more clrl -(r6) ;empty newly created cell incl -(r7) ;add to signal array count (&adjust) popl r0 ;restore trashed registers rsb .end