Google
 

Trailing-Edge - PDP-10 Archives - bb-h138f-bm - 7-sources/facerr.mac
There are 3 other files named facerr.mac in the archive. Click here to see a list.
TITLE FACERR -- Facility error handling information for the RTL

;
;	COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1984, 1986.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED  AND
;	COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH
;	THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE.   THIS  SOFTWARE  OR
;	ANY  OTHER  COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE
;	AVAILABLE TO ANY OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE
;	SOFTWARE IS HEREBY TRANSFERRED.
;
;	THE INFORMATION IN THIS SOFTWARE IS  SUBJECT  TO  CHANGE  WITHOUT
;	NOTICE  AND  SHOULD  NOT  BE CONSTRUED AS A COMMITMENT BY DIGITAL
;	EQUIPMENT CORPORATION.
;
;	DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR  RELIABILITY  OF
;	ITS SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
;

; Edit History

; Version 1.0

; Version 1.1
;
;.EDIT 50	Formally go to version 1.1, update copyright, insert V1.1
;			development changes (formally V2)
;		DDB,15-Jan-85,SPR:NONE


SEARCH DYNSYM, DDBSYM, MONSYM, MACSYM

SALL

EXTERNAL ME$ALM, SG$DLG, RL$FAO, SG.LER, SG$SIG

SEGMENT DATA

; Data and code for handling error message generation in the RTL

; The RTL must contain several different facilities; their facility
; numbers may not all be assigned together.
; Therefore a table indexed by facility number is a Bad Idea.

; Facility table

.FTCOD==0			;The facility code
.FTNAM==1			;A local or 1-word global BP to the name string
.FTMSG==2			;xFIW address of message table for this facility
.FTLEN==3			;Number of words per entry in this table

; The table is terminated with a .FTCOD < 0

DEFINE FACDEF (code, number, name) <
    EXP number, <POINT 7, [ASCIZ name]>, <IFIW!'code'MSG>
>

FACTBL:
	$FACS
	EXP -1

; Message tables.

; There is one message table for each facility.  It is indexed by message
; number.

.MGLNG==0			;Max expanded length of FAO string (0 if empty)
				;(this is obnoxious, but we must allocate fixed
				;space in the signal block for FAO to expand
				;into and I don't want it to come out too 
				;short)
.MGSTR==1			;One-word byte pointer to FAO string for message
.MGNAM==2			;One-word byte pointer to 3-character name
				;for this message
.MGLEN==3			;Length of this block

; Macro for building message table entries:

DEFINE MSGDEF (fac, mnam, sev, length, msg) <
    ..cnt==0
    IRPC msg, <
	..cnt==..cnt+1
    >
    EXP length+..cnt
    EXP <POINT 7, [ASCIZ msg]>
    EXP <POINT 7, [ASCIZ /mnam/]>
>

MTMSG:	$MTMSG

DYMSG:	$DYMSG

MEMSG:	$MEMSG

SGMSG:	$SGMSG

RLMSG:	$RLMSG
SUBTTL RTLERR -- Signal an RTL error with a clean stack

; This routine essentially performs an RTLERS followed by an RTLSER.
; That is, it takes arguments on the stack, makes a signal block, and
; passes that signal block to RTLSER.  The only difference is that you
; are not given the opportunity to clean up your stack between the calls.
; This is suitable for use in simple routines that have no cleanup to do.

SEGMENT CODE

RTLERR::
	CALL RTLERS
	JRST RTLSER
SUBTTL RTLERS -- Make signal block for error

; This routine produces a signal block for an RTL error.  The expected sequence
; of events for handling a complicated error is as follows:
;	1.  Call RTLERS to make an appropriate signal block
;	2.  Clean up your stack
;	3.  Call RTLSER	to signal the error
; If you don't need to clean up your stack, there is a routine RTLERR which
; combines the functions of RTLERS and RTLSER.

; Note that this only works for RTL errors, which can be described as a
; condition code and a sequence of FAO args.  This is not a general purpose
; error reporter by any stretch of the imagination.

; Args pushed on the stack for RTLERS are as follows:
;   FAO args in normal order order (that is, write the pushes in normal order)
;   Extra words,,Number of args pushed
;   Condition code
; These args have been removed from the stack on return.

; RTLERS preserves registers 6-17.

; On return, T1 contains the address of the signal block (a dynamic signal
; block is built using space from the error processing chunk).

; The SG block built looks like this:
;	SIG block (fixed fields)
;	Extra space (number of words specified in LH of next-to-last arg)
;	Args (the FAO args, in the same order)  .SGDAT points to here
;	Message string.  .SGMSG points to here (byte pointer)

; Stack setup:

; First arg pushed, many args pushed in middle, then...

ERRLRG==-15			;Last argument pushed onto stack
ERRACN==-14			;Count of FAO args pushed
ERRCC==-13			;Condition code to signal

; Return address
ERRPC==-12			;PC of our caller (plus 1, really)

; Saved registers
ERRAC6==-11
ERRAC7==-10
ERRA10==-7
ERRA11==-6
ERRA12==-5
ERRA13==-4
ERRA14==-3
ERRA15==-2
ERRA16==-1

; Locals
ERRSG==0			;SG block address

ERRSPC==12			;Amount of stack space to allocate
				;for registers plus locals
; Register use:
;	P1	SG block address
;	P2	Address of facility table entry
;	P3	Address of message table
;	P4	Address of ARG words in SG block
;	P5	Address of MSG string in SG block

RTLERS::
	ADJSP P, ERRSPC		;Allocate register and local space

; Save registers
	DMOVEM 6, ERRAC6(P)
	DMOVEM 10, ERRA10(P)
	DMOVEM 12, ERRA12(P)
	DMOVEM 14, ERRA14(P)
	MOVEM 16, ERRA16(P)

; First we must determine the size SG block to allocate (it must contain
; the message string for this error after FAO expansion).  To do this we
; need to find the message block, which gives the message length.  To do
; this we need to find the facility block, which points to the message block.
; The facility block may be found from the facility code part of the
; condition word.

	MOVE T1, ERRCC(P)	;Get condition code
	CALL FNDFAC		;Find the facility entry in FACTBL
	  JRST ERRDIE		;Lose seriously -- invalid facility
	MOVE P2, T1		;Save facility table entry address
	XMOVEI P3, @.FTMSG(P2)	;Get address of message table
	LDB T2, [POINTR ERRCC(P), SG%MSG] ;Get message code
	;What about customer-defined bit?  This causes trouble?
	SUBI T2, 1		;Subtract min subscript
	IMULI T2, .MGLEN	;Multiply by entry size
	ADD P3, T2		;Get address of entry for this message
	MOVE T2, .MGLNG(P3)	;Get string length (max)
	IDIVI T2, 4		;Convert to words
	SKIPE T3
	    AOS T2		;Round up always
	ADDI T2, .SGLEN+1	;Total length we want to allocate
				;The +1 is for the count word in the list of
				;ARG words
	HRRZ P5, ERRACN(P)	;FAO arg count
	AOS P5			;Plus one for vector count
	HLRZ P4, ERRACN(P)	;Extra words count
	ADD T2, P4
	ADD T2, P5		;Sum them all
	MOVX T1, .MEERR		;Chunk reserved for error processing
	CALL ME$ALM		;Allocate us a signal block
				;This infinite-loops if it fails
	MOVEM T2, ERRSG(P)	;Address returned in T2
	MOVE P1, T2		;Preserve SG adr
	ADDI T2, .SGLEN
	ADD P5, P4
	ADD P4, T2		;Address, as promised
	ADD P5, T2		;Ditto

; Now fill in the signal block we have allocated
	MOVE T1, ERRCC(P)	;Get condition code
	MOVEM T1, .SGCC(P1)	;Condition code into SG
	;SETZM .SGNXT(P1)	;No next pointer in SG
				;The SG block was zeroed by the allocator
	GETBP T0, .FTNAM(P2), T4
	MOVEM T0, .SGFAC(P1)	;OWGBP to static facility string into SG
	GETBP T0, .MGNAM(P3), T4
	MOVEM T0, .SGCND(P1)	;OWGBP to static condition name string into SG
	MOVE T1, P5		;Get address of message string
	TXO T1, 67B5		;Use 9-bit OWGBP here to cause confusion
				;and make the code Much simpler (don't have
				;to figure out byte size of source BP)
	MOVEM T1, .SGMSG(P1)	;OWGBP to message string (at end of SG block)
	MOVE T0, ERRPC(P)	;Get our caller's PC
	MOVEM T0, .SGPC(P1)	;PC into SG
	MOVX T0, SG%SOF
	MOVEM T0, .SGCLS(P1)	;Class flags into SG
	MOVX T0, SG%DYN
	MOVEM T0, .SGFLG(P1)	;General flags into SG
	MOVEM P4, .SGDAT(P1)	;Put in address of data section

	MOVE T2, .MGLNG(P3)	;Maximum length of destination string
	GETBP T3, .MGSTR(P3), T4
	XMOVEI T4, ERRLRG+1(P)	;Address of last FAO arg PLUS ONE
	HRRZ T5, ERRACN(P)	;Count of FAO args
	SUB T4, T5		;Address of first FAO arg
	CALL RL$FAO
	  ERJMP .+1		;We can't afford to screw up now!

; Move args to data field of block
	HRRZ T0, ERRACN(P)	;Get count of args
	MOVEM T0, 0(P4)		;Put away the count
	AOS 0(P4)		;Count includes this count word
	XMOVEI T1, ERRLRG+1(P)	;Get address of last arg on stack +1
	SUB T1, T0		;Compute address of first arg
	XMOVEI T2, 1(P4)	;Place to start putting args
	EXTEND 0, [XBLT]	;Copy all args

; Restore registers
	DMOVE 6, ERRAC6(P)
	DMOVE 10, ERRA10(P)
	DMOVE 12, ERRA12(P)
	DMOVE 14, ERRA14(P)
	MOVE 16, ERRA16(P)

; Clean up stack and return
	XMOVEI T0, ERRLRG+1(P)	;Address of last FAO arg PLUS ONE
	HRRZ T1, ERRACN(P)
	SUB T0, T1		;Minus count = address of first fao arg
	MOVE T1, ERRPC(P)	;Our return address
	MOVEM T1, @T0		;Onto first word of our stack frame
	MOVE T1, ERRSG(P)	;Must leave address of sig block in T1
	MOVE P, T0		;Remove our stack frame
	RET

; THE SKY IS FALLING
ERRDIE:
	TMSG <
?? Severe error in error processing routine
? Please submit an SPR
?? Program terminated due to previous error
>
	HALTF%
	JRST .-1
	
SUBTTL RTLSER -- Signal an RTL error

; This routine accepts a signal block and signals it, or returns
; it to its caller's caller if that caller has an ERJMP/ERCAL after the
; call.

; Arguments:
;	t1/	Address of signal block

; RTLSER must be called only after the stack has been cleaned up -- the
; top item must be the return address of RTLSER's caller.

; RTLSER is reached via a JRST,   N O T   A   C A L L ! ! ! !
; RTLSER does not return.

; RTLSER preserves registers 2-16

SERSPC==5			;Space used on stack
SERAC1==-4
SERAC2==-3
SERAC3==-2
SERAC4==-1
SERAC5==0

RTLSER::
	ADJSP P,SERSPC		;Make space to save things
	DMOVEM 1, SERAC1(P)	;Note that this saves our arg
	DMOVEM 3, SERAC3(P)
	MOVEM 5, SERAC5(P)

; Make this the LER
	;First free any existing block
	SKIPE T1, SG.LER	;Skip if no error stored yet, load T1
	  CALL SG$DLG		;Deallocate signal block chain
	  ERJMP .+1		;NOP if reached by SKIPE

	MOVE T1, SERAC1(P)	;Get our arg back
	MOVEM T1, SG.LER	;Set this error as last error found

; Restore registers
	DMOVE 2, SERAC2(P)
	DMOVE 4, SERAC4(P)
	ADJSP P, -SERSPC
	JRST RTLCER		;Continue the error -- upwards away!
SUBTTL RTLCER -- Continue error upwards

; This routine is for internal RTL use only.  It is used for passing an
; error on up to the next highest level with RTL-style error handling.

; Arguments:
;	T1/	Address of SG block

; This routine is invoked with a JRST, N O T  A  C A L L !
; This first item on the stack must be the return address of our invoker's
; caller.  For example, if RTLFOO called some routine RTLBAR that returned RTL-
; style errors, and FOO didn't want to use a condition handler, it could
; put an ERJMP/ERCAL after the call to RTLBAR which transferred control to a
; routine which restored registers (if necessary), cleaned up the stack, and
; then came here.  Now, any caller to RTLFOO will see the error from RTLBAR
; as a normal RTL-style error (either signal or ERJMP/ERCAL).

; This routine must preserve registers 2-16.

; If control is transferred to an ERJMP/ERCAL, T1 must contain the address
; of the signal block being passed.

CERRAD==0			;Stack offset to return address

RTLCER::
	MOVE T0, @CERRAD(P)	;Get our caller's return instruction
	TXZ T0, MASKB(13,35)	;Leave only instruction and register

	CAMN T0, [ERJMP]
	    JRST ERRJMP
	CAMN T0, [ERCAL]
	    JRST ERRCAL

; No magic, we need a signal
	CALL SG$SIG

; RTL errors signalled cannot be continued
	TMSG <
?? RTL errors can't be continued
? Program terminated due to previous error
>
	HALTF%			;Is there any graceful alternative?
	JRST .-1

; User wants us to jump to a routine
ERRJMP:	XMOVEI T0, @CERRAD(P)	;Get section to jump into
	HRR T0, @CERRAD(P)	;Get in-section address to go to
	MOVEM T0, CERRAD(P)	;Heh, heh.  Return will be to where WE specify

	JRST ERRDOI

; User wants us to call a routine for him
; In this case, store desired return address for call in ERRINS
ERRCAL:	XMOVEI T0, @CERRAD(P)	;Get section to call into
	HRR T0, @CERRAD(P)	;Get in-section address to call
	AOS CERRAD(P)		;Increment return for fake CALL
	PUSH P, T0		;Push address to go to
	;Fall through to ERRDOI

; Clean up and do user return as specified
ERRDOI:	RET
SUBTTL FNDFAC -- Find facility table entry

; Given a condition code in T1, return the facility table entry address
; in T1, and skip return.  If no such facility, normal return.  This is
; a really disastrous situation normally...

; Trashes T2

FNDFAC:	LDB T2, [POINTR T1, SG%FAC]
	XMOVEI T1, FACTBL-.FTLEN ;Set up global index into FACTBL

FND001:	ADDI T1, .FTLEN		;Step to next (first) entry
	SKIPGE .FTCOD(T1)	;Skip if not yet at end of table
	  JRST FNDLOS		;Lose, lose

	CAME T2, .FTCOD(T1)	;Skip if found
	  JRST FND001		;Loop

; Found it
	AOS 0(P)		;Skip return
	RET

FNDLOS:	SETZ T1,		;Indicate lossage
	RET
SUBTTL RTLJER -- Make JSYS signal error block for last JSYS error

; This routine makes a SG block for the last jsys error (including
; the message text).

; Arguments: None

; Returns block address in T1
; Registers 6-17 are preserved

; If errors are detected, participates in normal RTL error handling.

RTLJER::
	PUSH P, P1		;Save
	MOVX T1, .FHSLF
	GETER%	
	HRRZ P1, T2		;Clear process handle and save
	PUSH P, P1
	PUSH P, [1]
	PUSH P, [DY$JER]
	CALL RTLERS		;Make error block
	MOVX T0, 2
	MOVEM T0, .SGLEN+JERWRD(T1) ;Count of user words
	MOVEM P1, .SGLEN+JERWRD+1(T1) ;Value: the jsys error
	XMOVEI T0, .SGLEN+JERWRD(T1) ;Set user word to point to counted vector
	MOVEM T0, .SGDAT(T1)
	POP P, P1
	RET

	END