13. Hawk Interrupts and Traps
the Hawk Manual
13.1. The Trap Vector
13.2. The Trap Registers
13.3. A Trap Service Example
RESTARTTRAP = #00 BUSTRAP = #10 INSTRTRAP = #20 PRIVTRAP = #30 MMUTRAP = #40 COPROCTRAP = #50
The lowest memory addresses in a Hawk machine are known as the trap and interrupt vector area. When the CPU detects an abnormal condition, either internally or signalled by external hardware, control is transferred to a location in the trap vector. The special conditions detected internally are:
Strictly speaking, the memory management unit and coprocessors are not part of the CPU, although they are closer to it than most other devices. The MMU and coprocessors report the following conditions:
These registers are documented more fully in the section on processor control registers Each of these registers can be manipulated with the CPUGET and CPUSET instructions.
When an interrupt or trap occurs, the CPU stores the program counter in the trap program counter register TPC. If the trap occurred because of a memory addressing fault, the memory address and a notice of the cause is stored in the trap memory address register TMA. The trap save register TSV is available for use by trap service software. When a trap occurs, the level field of the processor status word PSW is copied into the prior field, before setting the level field to zero. This makes the trap service routine uninterruptable and privileged, and it turns off the memory management unit.
The following model trap service routine saves the entire system state. We assume that the trap vector itself may be in ROM, with statically allocated RAM addresses for the register save areas associated with each entry in the trap vector, and no recursive trap service routines.
; code to handle illegal memory references . = BUSTRAP CPUSET R2,TSV ; partially save R2 LIL R2,BUSSAVEAREA ; get the save area pointer STORE R1,R2,svR1 ; save R1 LIL R0,SAVEREGS ; join common code for all traps
The above bit of code occupies exactly 14 bytes and allows each trap to be handled using its own register save area. The common code shared by all trap service routines saves the registers as follows:
SAVEREGS: ; enter with: R2 pointing to save area and stack ; TPC holding user's PC ; TSV holding user's R2 ; R1 saved in save area STORE R3,R2,svR3 CPUGET R1,TSV CPUGET R3,TPC STORE R1,R2,svR2 ; R2 now properly saved STORE R3,R2,svPC ; PC now properly saved CPUGET R1,TMA CPUGET R3,PSW STORE R1,R2,svMA STORE R3,R2,svPSW ; ... straightforward code to save R4-15 LOAD R3,R2,myPSW LOAD R1,R2,myCODE CPUSET R3,PSW ; this may enable interrupts ADDI R2,R2,svSIZE JSRS R1,R3 ; go serve the trap ADDI R2,R2,-svSIZE ; ... code to restore R4-15 LOAD R3,R2,svPSW LOAD R1,R2,svPC CPUSET R3,PSW ; disables interrupts CPUSET R1,TPC LOAD R3,R2,svR3 LOAD R1,R2,svR1 LOAD R2,R2,svR2 RTT ; return to user!
The above code is written using R1 and R3 as alternate temporaries in order to improve pipeilined execution. On a superscalar machines, using more registers would allow even more parallelism.
The save area specific to each trap service routine, and pointed to by R2 in the above code is assumed to be a record with field offsets declared something like the following:
; trap save area record structure ; (all fields are 1 word, so displacements are shown in words) myCODE = 0 <<2 ; pointer to trap-specific routine entry myPSW = 1 <<2 ; initial PSW to use for trap service svPC = 2 <<2 ; save area for PC svR1 = 3 <<2 ; save area for registers svR2 = 4 <<2 svR3 = 5 <<2 ... save areas for R4-12 svRD = 15 <<2 svRE = 16 <<2 svRF = 17 <<2 svPSW = 18 <<2 ; save area for PSW svMA = 19 <<2 ; save area for trap MA svSIZE = 20 <<2 ; size of register-save area
Note that the SAVEREGS code assumes that this save area is at the base of a region of memory that will serve as the stack for the trap service routine, and it assumes that the routine called as myCODE uses R2 as a stack pointer for any local variables or temporaries it may require.
The trap and interrupt entry sequence runs with the level field of the PSW set to zero, preventing interrupts. Once the state of the interrupted code is saved, the PSW may be set with a level field that enables some interrupts during the service of this trap or interrupt. The myPSW field of the trap service record allows for this.
If a trap service routines uses only a few registers before returning, an abbreviated version of SAVEREGS can be used that only saves those registers. If a trap service routine uses any coprocessors, it will need to use an extended version of SAVEREGS that saves the required coprocessor registers.
This approach to trap service is at the extreme RISC end of the spectrum! Many machines include complex trap entry hardware that automatically saves and restores blocks of registers.