/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION  1986,1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:lopckrt0.s 12.0$ */
/* $ACIS:lopckrt0.s 12.0$ */
/* $Source: /ibm/acis/usr/sys/ca/RCS/lopckrt0.s,v $ */

	.data
#if !defined(NO_RCS_HDRS)
rcsidlopckrt0:	.asciz	"$Header:lopckrt0.s 12.0$"
#endif
	.text

 #
 #  program check level 0 interrupt service routine
 #
 #
 #  assumptions:  All the interesting (ones passed to trap.c) bits in the
 #       storage exception register are included in the lower order 11 (the
 #       number of bits required for hardware page offsets).
 #
 # r10 = mcs_pcs	value with (possibly) simulated bit values for certain
 #		conditions.
 # r11 = exception information
 #
 # in cases where the debugger is present we pass control to it for 
 # kernel faults (other than data page faults)
 # otherwise everything gets passed to fault to handle

 # when debugger is present we go off program check level ASAP so that
 # can set breakpoints in locore routines.
	.align	2
#define PCK_TRACE	0x400
pck_vec1:
	.long	pck1 -real0		# New IAR
	.short	NOTRANS_ICS+INTMASK_ICS+INT_PRI0,0	# New ICS
	.globl pck_ptr
pck_ptr: .long	PCK_TRACE		# we will use 400...4ff as trace table
        .using real0,r0
eye_catcher(pck0):
	.globl _pck0
_pck0:
#ifdef ROMPC
	cas	r0,r0,r0		# nop
	st	r15,low_save15		# these instructions prevent "death-by-88"
 #	bala	0f - real0		# on both SGP and ROMPC
	.long BALA + 0f - real0		# can't have above instn - sigh
0:	l	r15,low_save15
#else
	b	0f	# this instruction is necessary for certain page-faults
			# that will result in a "death-by-88" without it.
0:
#endif

        stm   r10,low_save10    # copy interrupt time rx into low_save var
        mfs   scr_mcspcs,r10    # r10 = program check status
	lps	1,pck_vec1		# get off program check level ASAP
pck1:
        st    r1,low_save1      # copy interrupt time r1 into low_save var
#ifdef DEBUG
        lm	r14,pck_ps+old_iar# r14, r15 = iar, ics_cs at time of fault
	l	r11,pck_ptr	# pick up trace pointer
	st	r1,8(r11)	# save stack pointer
	st	r10,12(r11)	# save mcspcs
	stm	r14,0(r11)	# save them
	cal	r12,16(r11)	# point to next
	ni	r12,r12,PCK_TRACE+0xff	#mask down
	st	r12,pck_ptr	# store pointer
#endif

#ifdef ROMPC
        nilz  r12,r10,PCS_TRAP+PCS_PRIV_I+PCS_BAD_I+PCS_RESERVED
#else
        nilz  r12,r10,PCS_UNKNOWN+PCS_TRAP+PCS_PRIV_I+PCS_BAD_I+PCS_RESERVED
#endif
        bnz   pck_notstg        # branch if any of those bad guys

 #	cau   r15,(MMUBASE)>>16(r0) # i/o base address of MMU
 #	oil   r15,r15,(MMUBASE)&0xffff
	get	r15,$MMUBASE	# i/o base address of MMU
        ior   r14,MMU_SER(r15) # r14 = storage exception register
	st	r14,_ser	# save ser
#ifdef DEBUG
	st	r14,8(r11)	# save instead of sp
#endif
        niuo  r13,r14,MMU_EX_OHOH_UPPER  # unexpected upper bits
        nilo  r13,r13,MMU_EX_OHOH_LOWER  # unexpected lower bits
        bnz   pck_debug          # branch if any unexpected bits are on

    # Following added by mjb to deal with lm and stm data faults.
    # Maybe I even got it right this time.
_pck2:
	nilz  r13,r14,MMU_EX_MULTX  # Multiple exceptions indicated?
	jz    pck05		# Nope.
        mttbil r10,30-16        # d-fetch vs i-fetch bit
        bntb  pck_debug          # jump if i-fetch -- this is not normal
	nilo  r14,r14,0xFFFF-MMU_EX_MULTX # Let's not get confused
pck05:
    # End of lines added by mjb to deal with lm and stm exceptions.

        ior   r12,MMU_SEAR(r15)# r12 = storage exception address register
#ifdef DEBUG
	st	r12,_sear	# save for debugging
#endif
        mttbil r10,30-16        # d-fetch vs i-fetch bit
        jtb   pck10             # jump if d-fetch (SEAR correct)
        l     r12,pck_ps+old_iar# r12 = iar at time of fault
        nilz  r13,r12,PAGESIZE-1# r13 = page offset
        ci    r13,PAGESIZE-6    # if inst (or subject of bx) w/in page
        jl    pck10             # then jump (iar in faulting page)

        iow   r12,MMU_CRA(r15) # compute real addr of lower page
        ior   r13,MMU_TRAR(r15)# r13 = translated real addr register
        cis   r13,0             # if high bit is on, translation failed
        jl    pck10             # then jump (lower page faulted)
        ais   r12,6             # else put iar into higher page
pck10:
 #***    nilo  r12,0-PAGESIZE    | zero page offset bits in exception address
        nilo  r12,r12,0-PAGESIZE    # zero page offset bits in exception address
        nilz  r11,r14,PAGESIZE-1# zero all but page offset bits in exception reg
        o     r11,r12           # fold interesting exception bits into pg offset
	s	r14,r14		# zippo
	iow   r14,MMU_SER(r15) # Clear the exception register
	get	r14,$SEAR_VALUE # get value to reset SEAR
	iow   r14,MMU_SEAR(r15) # set the exception address register
        b     pck_fault         # go handle page fault
 #
 #  program check, but not a storage fault
 #  if debugger present and in kernel mode pass to the debugger
 #  otherwise pass to 'trap'.
 #
pck_notstg:
#ifdef RDB
	l	r11,pck_ps+old_ics_cs # get the ics into r11
	mttbiu	r11,PROBSTATE-16	#copy problem state bit from old ics
	jntb	pck_debug	#transfer control to debugger if not user mode
#endif
         mttbil r10,26-16        # if not a trap inst (bit 26 from PCS)
         jntb  pck_real          # then jump
	 get   r10,$(BKPT)	#  mcs_pcs value for breakpoint inst "check"
 #
 #  real program checks - call fault to handle
 #
pck_real:
	lis r11,0             # no additional information required
	b	pck_fault	# handle as a fault
 #
 # pass control to debugger if it is present
 #
pck_debug:
#ifndef RDB
	j	pck_real
#endif
        mts   scr_mcspcs,r10    # r10 = program check status
	bx	pck_jump_to_dan	# too bad no cnop's
	lm    r10,low_save10    # restore regs
	.align	2		# align it 
pck_jump_to_dan: b real0         # jump to original owner of program check
