TITLE "mp6.a -- by ##your name here##" ; unimplemented instruction trap handler ; creates virtual LIW (load immediate word) instruction USE "hawk.h" USE "monitor.h" LIWOP = #00F0 ; LIW opcode 1111dddd 00000000 (where dddd is Rd) STACKSIZE = 8 ; a tiny little stack (4 is really enough!) ; this is based on examination of monitor.a ; where PUTAT had ARSIZE=4, calling TIMES ; TIMES had ARSIZE=0 ; PUTS had ARSIZE=0, calling PUTCHAR ; PUTCHAR had ARSIZE=0 ; PUTHEX had ARSIZE=0 calling PUTCHAR ; therefore, 4 is enough, 8 is generous ; trap save area record structure ; (all fields are 1 word, so displacements are shown in words) ; 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 svR4 = 6 <<2 svR5 = 7 <<2 svR6 = 8 <<2 svR7 = 9 <<2 svR8 = 10 <<2 svR9 = 11 <<2 svRA = 12 <<2 svRB = 13 <<2 svRC = 14 <<2 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 ARSIZE = svSIZE SAVEAREASIZE = svSIZE + STACKSIZE INSTRTRAP = #20 COMMON INSTSAVEAREA,SAVEAREASIZE LCSAVE = . . = INSTRTRAP ; trap vector entry CPUSET R2,TSV ; partially save R2 LIL R2,INSTSAVEAREA ; get the save area pointer STORE R1,R2,svR1 ; save R1 LIL R1,HANDLER JUMPS R1 ; go save my registers . = LCSAVE HANDLER: ; enter with: R2 points to the save area and stack ; TPC holds the user's PC ; TSV holds the user's R2 ; R1 saved in the 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 STORE R4,R2,svR4 STORE R5,R2,svR5 STORE R6,R2,svR6 STORE R7,R2,svR7 STORE R8,R2,svR8 STORE R9,R2,svR9 STORE RA,R2,svRA STORE RB,R2,svRB STORE RC,R2,svRC STORE RD,R2,svRD STORE RE,R2,svRE STORE RF,R2,svRF ; everything is saved ; body of handler LOAD R3,R2,svPC ; get saved PC LOADS R4,R3 EXTH R4,R4,R3 ; get halfword it points to MOVE R5,R4 TRUNC R5,4 ; R5 = Rd field of instruction SUB R4,R4,R5 ; R4 = instruction halfword with Rd zeroed CMPI R4,LIWOP BNE NOTLIW ; if (instr is LIW) { -- virtualize LIW ADDSI R3,2 ; saved PC + 2 -- skips opcode LOADS R6,R3 EXTH R6,R6,R3 ; R6 gets first half word ADDSI R3,2 ; saved PC + 2 -- skips first half word LOADS R7,R3 EXTH R7,R7,R3 ; R7 gets second half word ADDSI R3,2 ; saved PC + 2 -- skips second half word SL R7,16 OR R6,R7 ; R6 holds the one-word operand LEA R7,R2,svPC ; R7 holds base of array of saved registers ADDSL R5,R7,2 ; R4 holds address of saved register STORES R6,R5 ; saved Rdst = operand BR RETURN ; } else { -- output error message NOTLIW: ADDI R2,R2,ARSIZE ; push my AR LIS R3,0 LIS R4,0 LIL R1,PUTAT JSRS R1,R1 ; call putat(0,0) LIL R3,TRAPMSG LIL R1,PUTS JSRS R1,R1 ; call puts(trapmsg) LOAD R3,R2,svPC-ARSIZE LIL R1,PUTHEX JSRS R1,R1 ; call puthex( saved PC ) ADDI R2,R2,-ARSIZE ; pop my AR LIS R3,0 ; saved PC = 0 RETURN: ; } ; R3 is still saved PC STORE R3,R2,svPC ; restore saved PC ; restore everything LOAD RF,R2,svRF LOAD RE,R2,svRE LOAD RD,R2,svRD LOAD RC,R2,svRC LOAD RB,R2,svRB LOAD RA,R2,svRA LOAD R9,R2,svR9 LOAD R8,R2,svR8 LOAD R7,R2,svR7 LOAD R6,R2,svR6 LOAD R5,R2,svR5 LOAD R4,R2,svR4 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! TRAPMSG:ASCII "Instruction trap. TRAP PC = ",0 END