.SN 9
.VS 1 0
.BP
.S1 "TRAPS AND INTERRUPTS"
EM provides a means for the user program to catch all traps
generated by the program itself, the hardware, or external conditions.
This mechanism uses five instructions: LIM, SIM, SIG, TRP and RTT.
This section of the manual may be omitted on the first reading since it
presupposes knowledge of the EM instruction set.
.P
The action taken when a trap occurs is determined by the value
of an internal EM trap register.
This register contains a pointer to a procedure.
Initially the pointer used is zero and all traps halt the
program with, hopefully, a useful message to the outside world.
The SIG instruction can be used to alter the trap register,
it pops a procedure pointer from the
stack into the trap register.
When a trap occurs after storing a nonzero value in the trap
register, the procedure pointed to by the trap register
is called with the trap number
as the only parameter (see below).
SIG returns the previous value of the trap register on the
stack.
Two consecutive SIGs are a no-op.
When a trap occurs, the trap register is reset to its initial
condition, to prevent recursive traps from hanging the machine up,
e.g. stack overflow in the stack overflow handling procedure.
.P
The runtime systems for some languages need to ignore some EM
traps.
EM offers a feature called the ignore mask.
It contains one bit for each of the lowest 16 trap numbers.
The bits are numbered 0 to 15, with the least significant bit
having number 0.
If a certain bit is 1 the corresponding trap never
occurs and processing simply continues.
The actions performed by the offending instruction are
described by the Pascal program in appendix A.
.N
If the bit is 0, traps are not ignored.
The instructions LIM and SIM allow copying and replacement of
the ignore mask.~
.P
The TRP instruction generates a trap, the trap number being found on the
stack.
This is, among other things,
useful for library procedures and runtime systems.
It can also be used by a low level trap procedure to pass the trap to a
higher level one (see example below).
.P
The RTT instruction returns from the trap procedure and continues after the
trap.
In the list below all traps marked with an asterisk ('*') are
considered to be fatal and it is explicitly undefined what happens if
you try to restart after the trap.
.P
The way a trap procedure is called is completely compatible
with normal calling conventions. The only way a trap procedure
differs from normal procedures is the return. It has to use RTT instead
of RET. This is necessary because the complete runtime status is saved on the
stack before calling the procedure and all this status has to be reloaded.
Error numbers are in the range 0 to 252.
The trap numbers are divided into three categories:
.IS 4
.N 1
.PS - 10
.PT ~~0\-~63
EM machine errors, e.g. illegal instruction.
.PS - 8
.PT ~0\-15
maskable
.PT 16\-63
not maskable
.PE
.PT ~64\-127
Reserved for use by compilers, run time systems, etc.
.PT 128\-252
Available for user programs.
.PE 1
.IE
EM machine errors are numbered as follows:
.DS I 5
.TS
tab(@);
n l l.
0@EARRAY@Array bound error
1@ERANGE@Range bound error
2@ESET@Set bound error
3@EIOVFL@Integer overflow
4@EFOVFL@Floating overflow
5@EFUNFL@Floating underflow
6@EIDIVZ@Divide by 0
7@EFDIVZ@Divide by 0.0
8@EIUND@Undefined integer
9@EFUND@Undefined float
10@ECONV@Conversion error
16*@ESTACK@Stack overflow
17@EHEAP@Heap overflow
18*@EILLINS@Illegal instruction
19*@EODDZ@Illegal size argument
20*@ECASE@Case error
21*@EMEMFLT@Addressing non existent memory
22*@EBADPTR@Bad pointer used
23*@EBADPC@Program counter out of range
24@EBADLAE@Bad argument of LAE
25@EBADMON@Bad monitor call
26@EBADLIN@Argument of LIN too high
27@EBADGTO@GTO descriptor error
.TE
.DE 0
.P
As an example,
suppose a subprocedure has to be written to do a numeric
calculation.
When an overflow occurs the computation has to be stopped and
the higher level procedure must be resumed.
This can be programmed as follows using the mechanism described above:
.DS B
.ta 1n 24n
	mes 2,2,2	; set sizes
ersave
	bss 2,0,0	; Room to save previous value of trap procedure
msave
	bss 2,0,0	; Room to save previous value of trap mask

	pro $calcule,0	; entry point
	lxl 0	; fill in non-local goto descriptor with LB
	ste jmpbuf+4
	lor 1	; and SP
	ste jmpbuf+2
	lim	; get current ignore mask
	ste msave	; save it
	lim
	loc 16	; bit for EFOVFL
	ior 2	; set in mask
	sim	; ignore EFOVFL from now on
	lpi $catch	; load procedure identifier
	sig	; catch wil get all traps now
	ste ersave	; save previous trap procedure identifier
		; perform calculation now, possibly generating overflow
1		; label jumped to by catch procedure
	loe ersave	; get old trap procedure
	sig	; refer all following trap to old procedure
	asp 2	; remove result of sig
	loe msave	; restore previous mask
	sim	; done now
		; load result of calculation
	ret 2	; return result
jmpbuf
	con *1,0,0
	end
.DE 0
.VS
.DS
Example of catch procedure
.ta 1n 24n
	pro $catch,0	; Local procedure that must catch the overflow trap
	lol 2	; Load trap number
	loc 4	; check for overflow
	bne *1	; if other trap, call higher trap procedure
	gto jmpbuf	; return to procedure calcule
1		; other trap has occurred
	loe ersave	; previous trap procedure
	sig	; other procedure will get the traps now
	asp 2	; remove the result of sig
	lol 2	; stack trap number
	trp	; call other trap procedure
	rtt	; if other procedure returns, do the same
	end
.DE
