TITLE "mp6.a by Douglas Jones, Dec. 8, 2019" ; this version tries to be optimal, but the payoff is small USE "hawk.h" USE "stdio.h" USE "ascii.h" ; the following code is based on code from Chapter 13 in the notes COMMON MP6SAVEAREA,SAVESIZE + TRAPSTACK PCSAVE = 0 << 2 ; displacements in the save area R1SAVE = 1 << 2 R2SAVE = 2 << 2 R3SAVE = 3 << 2 R4SAVE = 4 << 2 R5SAVE = 5 << 2 R6SAVE = 6 << 2 R7SAVE = 7 << 2 R8SAVE = 8 << 2 R9SAVE = 9 << 2 RASAVE = 10 << 2 RBSAVE = 11 << 2 RCSAVE = 12 << 2 RDSAVE = 13 << 2 RESAVE = 14 << 2 RFSAVE = 15 << 2 PSWSAVE = 16 << 2 SAVESIZE= 17 << 2 TRAPSTACK= 32 ; an 8-word stack if the trap handler needs it LC = . ; save the relocatable location counter . = #20 ; code for the instruction trap vector CPUSET R2,TSV ; partially save R2 LIL R2,MP6SAVEAREA ; get the save area pointer STORE R1,R2,R1SAVE ; save R1 LIL R1,MP6HANDLER JUMPS R1 ; go finish work in relocatable code . = LC ; back to relocatable code ; the following code is based on code from Chapter 13 in the notes MP6HANDLER: ; expects R2 points to the register save area ; R1 has been saved properly ; TSV still holds the saved value of R2 ; PSW (including CCs) still unsaved CPUGET R1,PSW STORE R1,R2,PSWSAVE ; PSW is now properly saved CPUGET R1,TSV STORE R1,R2,R2SAVE ; R1 is now properly saved CPUGET R1,TPC STORE R1,R2,PCSAVE ; PC is now properly saved STORE R3,R2,R3SAVE ; continue saving R3 to R15 STORE R4,R2,R4SAVE STORE R5,R2,R5SAVE STORE R6,R2,R6SAVE STORE R7,R2,R7SAVE STORE R8,R2,R8SAVE STORE R9,R2,R9SAVE STORE R10,R2,RASAVE STORE R11,R2,RBSAVE STORE R12,R2,RCSAVE STORE R13,R2,RDSAVE STORE R14,R2,RESAVE STORE R15,R2,RFSAVE ; entire CPU state is now saved ; see if the unimplemented instr was 1111dddd 0001ssss (#1sFd) ; expects all registers have been saved ; R2 points to the register save area LOAD R3,R2,PCSAVE ; get the saved program counter LOADS R4,R3 EXTH R5,R4,R3 ; get the halfword it points to ; -- the instruction that trapped! LIL R6,#F0F0 AND R6,R5 ; clear all but the opcode bits CMPI R6,#10F0 ; is it the target instruction? BNE NOGOOD ; the following code is original for this problem ; it is the LOADNA instruction. ; R2 points to the register save area ; R3 holds the user's PC ; R5 holds the instruction halfword LIS R6,#F MOVESL R7,R6,8 ; masks for X and SRC fields AND R7,R5 ; X field in R7 format xxxx 0000 0000 AND R6,R5 ; DST field in R6 format 0000 dddd BZS NOGOOD ; DST must not be zero SR R7,6 ADD R7,R7,R2 ; add of R[X] in R7 ADDSL R6,R2,2 ; addr of R[DST] in R6 ADDSI R3,2 LOADS R4,R3 EXTH R5,R4,R3 SXT R5,16 ; get the index displacement ADDSI R3,2 STORE R3,R2,PCSAVE ; update the program counter LOADS R7,R7 ; get R[X] ADD R7,R7,R5 ; get EA in R7 ; the following code block is an attempt to be fast. ; it replaces 15 halfwords of code from the posted solution to HW6, problem 2 ; with more code that involves only 9, 4, 9 and 7 halfwords of code ; for an average of 7.25 assuming all alignments are equally probable. BTRUNC R7,2 BR LDNA0 BR LDNA1 BR LDNA2 ; select (EA & 2) { ; case 3: LOADS R4,R7 SRU R4,12 SRU R4,12 ; temp = M[EA] >> 24 LOAD R5,R7,4 ADDSL R5,R4,8 ; result = (M[EA+4] << 8) + temp BR LDNAX ; break (9) LDNA0: ; case 0: LOADS R5,R7 ; result = M[EA] BR LDNAX ; break (4) LDNA1: ; case 1: LOADS R4,R7 SRU R4,8 ; temp = M[EA] >> 8 LOAD R5,R7,4 SL R5,12 ADDSL R5,R4,12 ; result = (M[EA+4] << 24) + temp BR LDNAX ; break (9) LDNA2: ; case 2: LOADS R4,R7 SRU R4,16 ; temp = M[EA] >> 16 LOAD R5,R7,4 ADDSL R5,R4,16 ; result = (M[EA+4] << 16) + temp ; break (7) LDNAX: STORES R5,R6 ; store result in R[DST] BR TRAPEXIT ; go return ; the following code is modified from the Hawk monitor ; it is not the LOADNA instruction, so report a trap and halt NOGOOD: ADDI R2,R2,SAVESIZE ; setup to use save area stack LEA R3,TRAPMSG LIL R1,PUTSTR JSRS R1,R1 ; putstr( trapmsg ) LOAD R3,R2,PCSAVE-SAVESIZE LIS R4,8 LIL R1,PUTHEX JSRS R1,R1 ; puthex( pcsave, 8 ) LEA R3,TMAMSG LIL R1,PUTSTR JSRS R1,R1 ; putstr( tmamsg ) CPUGET R3,TMA LIS R4,8 LIL R1,PUTHEX JSRS R1,R1 ; puthex( tma, 8 ) ADDI R2,R2,-SAVESIZE ; get ready to return from trap STORE R0,R2,PCSAVE ; force return to 0 ; the following code is based on code from Chapter 13 in the notes ; return from any trap handler TRAPEXIT: ; expects R2 points to the register save area LOAD R15,R2,RFSAVE ; start restoring registers LOAD R14,R2,RESAVE LOAD R13,R2,RDSAVE LOAD R12,R2,RCSAVE LOAD R11,R2,RBSAVE LOAD R10,R2,RASAVE LOAD R9,R2,R9SAVE LOAD R8,R2,R8SAVE LOAD R7,R2,R7SAVE LOAD R6,R2,R6SAVE LOAD R5,R2,R5SAVE LOAD R4,R2,R4SAVE LOAD R3,R2,R3SAVE ; R15 to R3 now all restored LOAD R1,R2,PCSAVE CPUSET R1,TPC ; PC partially restored LOAD R1,R2,PSWSAVE CPUSET R1,PSW ; PSW now restored LOAD R1,R2,R1SAVE ; R1 restored without changing CCs LOAD R2,R2,R2SAVE ; R2 restored without changing CCs CPUGET R0,TPC ; return from trap! TRAPMSG:ASCII "",LF,"Instruktion Trap." ASCII " Trap PC = #",0 TMAMSG: ASCII "",LF," " ASCII " TRAP MA = #",0 END