Added platfrom_m5 - Our hacked up tsunami palcode and modified palcode
authorAli Saidi <saidi@eecs.umich.edu>
Mon, 2 Feb 2004 22:40:11 +0000 (17:40 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Mon, 2 Feb 2004 22:40:11 +0000 (17:40 -0500)
makefile to that end. Additionally made a change in console to
preserve t7 on call back because linux uses it for the "current"
pointer.

console/Makefile:
    Changed makefile back to using gcc and gas rather then trying to
    cross-compile for now
console/console.c:
    Put code in to save t7 on CallBackFixup() call and changed the
    system type to Tsunami
palcode/Makefile:
    updated palcode makefile to have targets for tlaser and tsunami

system/alpha/console/Makefile
system/alpha/console/console.c
system/alpha/palcode/Makefile
system/alpha/palcode/platform_m5.s [new file with mode: 0644]

index 48a6288a311a36aea5c63001a8d5185b889a6989..5905fa9d264526fa19ad3c3299a67b87a3c8ab2a 100644 (file)
@@ -7,10 +7,8 @@ INCLUDES        = -I$(PALCODE) -I$(INCLUDEH) -I$(M5)/dev
 SOURDIR = ./
 PALCODE  = ../palcode
 INCLUDEH = ../h
-AS=alpha-elf-as
-CC=alpha-elf-gcc
-CXX=alpha-elf-$(CXX)
-
+CC=gcc
+AS=gas
 
 dbmentry.o: dbmentry.s 
        $(AS)  $(INCLUDES) -nointrinsics -o $*.o $*.s
@@ -22,12 +20,12 @@ printf.o: printf.c
        $(CC)  -g3 $(INCLUDES) -nointrinsics -o $*.o -c $*.c
 
 paljtokern.s.o: paljtokern.s
-       $(CXX) -I ../palcode -E -P -nostdinc -nostdinc++ -x c++ paljtokern.s | \
-       $(AS) -m 21164 -o paljtokern.s.o
+       g++ -I ../palcode -E -P -nostdinc -nostdinc++ -x c++ paljtokern.s | \
+       gas -m 21164 -o paljtokern.s.o
 
 paljtoslave.s.o: paljtoslave.s
-       $(CXX) -I ../palcode -E -P -nostdinc -nostdinc++ -x c++ paljtoslave.s | \
-       $(AS) -m 21164 -o paljtoslave.s.o
+       g++ -I ../palcode -E -P -nostdinc -nostdinc++ -x c++ paljtoslave.s | \
+       gas -m 21164 -o paljtoslave.s.o
 
 paljtokern.c: paljtokern.s.o
        echo 'unsigned int palJToKern[] = {' > paljtokern.c
index 0697be63a70df8c2f1351fdb80b59abb9d5727b7..844cb4ddc17dc211ecded93f6d019b43f3316173 100644 (file)
@@ -27,7 +27,6 @@ typedef unsigned int uint32;
 #include "rpb.h"
 #include "cserve.h"
 
-
 #define CONS_INT_TX   0x01  /* interrupt enable / state bits */
 #define CONS_INT_RX   0x02
 
@@ -206,8 +205,8 @@ struct rpb xxm_rpb = {
 #if 0
    0x12,               /* 050: system type - masquarade as some random 21064 */
 #endif
-   12, /* masquerade a DEC_3000_500 (bugnion) */
-   (2<<1),             /* 058: system variation */
+   34, /* masquerade a Tsunami RGD */
+   (1<<10),            /* 058: system variation */
    'c'|('o'<<8)|('o'<<16)|('l'<< 24),          /* 060: system revision */
    1024*4096,          /* 068: scaled interval clock intr freq  OVERRIDEN*/
    0,                  /* 070: cycle counter frequency */
@@ -1184,7 +1183,23 @@ CallBackDispatcher(long a0, long a1, long a2, long a3, long a4)
 
 long CallBackFixup(int a0, int a1, int a2)
 {
-   printf("CallbackFixup %x %x \n",a0,a1);
+   long temp;
+   /* Linux uses r8 for the current pointer (pointer to data structure
+      contating info about currently running process). It is set when the
+      kernel starts and is expected to remain there... Problem is that the
+      unlike the kernel, the console does not prevent the assembler from
+      using r8. So here is a work around. So far this has only been a problem
+      in CallBackFixup() but any other call back functions could cause a problem
+      at some point */
+
+   /* save off the current pointer to a temp variable */
+   asm("bis $8, $31, %0" : "=r" (temp));
+
+   /* call original code */
+   printf("CallbackFixup %x %x, t7=%x\n",a0,a1,temp);
+
+   /* restore the current pointer */
+   asm("bis %0, $31, $8" : : "r" (temp) : "$8");
 
 #if 0
   if (first[FIRST(a1)]==0) {
index 071c8bc3964ba5bd88cb4d10a1677aad7d110c03..14a700c7362a94411c2e46ff614b77bff44aa5c7 100644 (file)
@@ -11,9 +11,10 @@ CFLAGS=-I . -E -P -D SIMOS -D BUILD_PALCODE -nostdinc -nostdinc++ -x c++
 GASFLAGS=-m21164
 LDFLAGS=-Ttext 0x4000
 
-SOURCES=osfpal.s platform_tlaser.s
+SOURCES=osfpal.s platform_tlaser.s platform_m5.s
 PREPROC := $(SOURCES:.s=.i)
-OBJS := $(SOURCES:.s=.o)
+TLOBJS = osfpal.o platform_tlaser.o
+TSOBJS = osfpal.o platform_m5.o
     
 %.i: %.s
        $(CC) $(CFLAGS) $< > $@
@@ -21,9 +22,14 @@ OBJS := $(SOURCES:.s=.o)
 %.o: %.i
        $(GAS) $(GASFLAGS) -o $@ $< 
 
+all: tlaser tsunami
+        
+tlaser: $(PREPROC) $(TLOBJS)
+       $(LD) $(LDFLAGS) -o tl_osfpal $(TLOBJS) 
 
-all: $(PREPROC) $(OBJS)
-       $(LD) $(LDFLAGS) -o osfpal $(OBJS) 
+tsunami: $(PREPROC) $(TSOBJS)
+       $(LD) $(LDFLAGS) -o ts_osfpal $(TSOBJS) 
 
 clean:
        rm -f *.o *.i osfpal
diff --git a/system/alpha/palcode/platform_m5.s b/system/alpha/palcode/platform_m5.s
new file mode 100644 (file)
index 0000000..95f01f4
--- /dev/null
@@ -0,0 +1,2658 @@
+// build_fixed_image: not sure what means
+// real_mm to be replaced during rewrite
+// remove_save_state  remove_restore_state can be remooved to save space ??
+
+
+#define egore 0
+#define acore 0
+#define beh_model 0
+#define ev5_p2 1
+#define ev5_p1 0
+#define ldvpte_bug_fix 1
+#define spe_fix 0
+#define osf_chm_fix  0
+#define build_fixed_image 0
+#define enable_p4_fixups 0
+#define osf_svmin 1
+#define enable_physical_console 0
+#define fill_err_hack 0
+#define icflush_on_tbix 0
+#define max_cpuid 1
+#define perfmon_debug 0
+#define rax_mode 0
+
+#define hw_rei_spe hw_rei
+       
+#include "ev5_defs.h"
+#include "ev5_impure.h"
+#include "ev5_alpha_defs.h"
+#include "ev5_paldef.h"
+#include "ev5_osfalpha_defs.h"
+#include "fromHudsonMacros.h"
+#include "fromHudsonOsf.h"
+#include "dc21164FromGasSources.h"
+#include "cserve.h"
+#include "tlaserreg.h"
+//#include "simos.h"
+
+        
+#define ldlp ldl_p
+#define ldqp ldq_p
+
+#define stlp stl_p        
+#define stqp stq_p
+#define stqpc stqp
+#ifdef SIMOS               
+#define ldqpl ldq_p
+#define sdqpl sdq_p
+#else
+<--bomb>
+#endif            
+                   
+#define pt_entInt pt_entint
+#define pt_entArith pt_entarith
+#define mchk_size ((mchk_cpu_base + 7  + 8) &0xfff8)
+#define mchk_flag CNS_Q_FLAG
+#define mchk_sys_base 56
+#define mchk_cpu_base (CNS_Q_LD_LOCK + 8)
+#define mchk_offsets CNS_Q_EXC_ADDR
+#define mchk_mchk_code 8
+#define mchk_ic_perr_stat CNS_Q_ICPERR_STAT
+#define mchk_dc_perr_stat CNS_Q_DCPERR_STAT
+#define mchk_sc_addr CNS_Q_SC_ADDR
+#define mchk_sc_stat CNS_Q_SC_STAT
+#define mchk_ei_addr CNS_Q_EI_ADDR
+#define mchk_bc_tag_addr CNS_Q_BC_TAG_ADDR
+#define mchk_fill_syn CNS_Q_FILL_SYN
+#define mchk_ei_stat CNS_Q_EI_STAT
+#define mchk_exc_addr CNS_Q_EXC_ADDR
+#define mchk_ld_lock CNS_Q_LD_LOCK
+#define osfpcb_q_Ksp pcb_q_ksp
+#define pal_impure_common_size ((0x200 + 7) & 0xfff8)
+
+#define ALIGN_BLOCK \
+       .align 5
+
+#define ALIGN_BRANCH \
+       .align 3
+
+#define EXPORT(_x) \
+        .align 5;      \
+        .globl _x;     \
+_x:     
+                
+// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+// XXX the following is 'made up'
+// XXX bugnion
+                
+// XXX bugnion not sure how to align 'quad'        
+#define ALIGN_QUAD \
+        .align  3
+
+#define ALIGN_128 \
+        .align  7
+             
+                   
+#define GET_IMPURE(_r) mfpr _r,pt_impure
+#define GET_ADDR(_r1,_off,_r2)  lda _r1,_off(_r2)
+                
+                
+#define BIT(_x) (1<<(_x))
+
+                                        
+// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+// XXX back to original code
+                
+// .sbttl      "System specific code - beh model version"  
+
+//
+// Entry points
+//     SYS$CFLUSH - Cache flush
+//     SYS$CSERVE - Console service
+//     SYS$WRIPIR - interprocessor interrupts
+//     SYS$HALT_INTERRUPT - Halt interrupt
+//     SYS$PASSIVE_RELEASE - Interrupt, passive release
+//     SYS$INTERRUPT - Interrupt
+//     SYS$RESET - Reset
+//     SYS$ENTER_CONSOLE
+
+//
+// Macro to read TLINTRSUMx
+//
+//  Based on the CPU_NUMBER, read either the TLINTRSUM0 or TLINTRSUM1 register
+//
+// Assumed register usage:
+//  rsum TLINTRSUMx contents
+//  raddr node space address
+//  scratch scratch register
+
+        
+// .macro Read_TLINTRSUMx      rsum, raddr, scratch, ?label1, ?label2
+//
+//     nop
+//     mfpr    'scratch', pt_whami             // Get our whami (VID)
+//
+//     extbl   'scratch', #1, 'scratch'        // shift down to bit 0
+//     lda     'raddr', ^xff88(r31)            // Get base node space address bits
+//
+//     sll     'raddr', #24, 'raddr'           // Shift up to proper position
+//     srl     'scratch', #1, 'rsum'           // Shift off the cpu number
+//
+//     sll     'rsum', #22, 'rsum'             // Get our node offset
+//     addq    'raddr', 'rsum', 'raddr'        // Get our base node space address
+//
+//     blbs    'scratch', label1
+//     lda     'raddr', <tlep$tlintrsum0_offset>('raddr')
+//
+//     br      r31, label2
+//label1:      lda     'raddr', <tlep$tlintrsum1_offset>('raddr')
+//
+//label2:      ldlp    'rsum', 0('raddr')              // read the right tlintrsum reg
+//.endm
+
+#define Read_TLINTRSUMx(_rsum,_raddr,_scratch)  \
+       nop;            \
+       mfpr    _scratch,pt_whami;      \
+       extbl   _scratch,1,_scratch;    \
+       lda     _raddr,0xff88(zero);    \
+       sll     _raddr,24,_raddr;       \
+       srl     _scratch,1,_rsum;       \
+       sll     _rsum,22,_rsum;         \
+       addq    _raddr,_rsum,_raddr;    \
+       blbs    _scratch,1f;            \
+       lda     _raddr,0x1180(_raddr); \
+       br      r31,2f;                 \
+1:                                     \
+       lda     _raddr,0x11c0(_raddr); \
+2:      ldlp    _rsum,0(_raddr)
+       
+
+
+//
+// Macro to write TLINTRSUMx
+//
+//  Based on the CPU_NUMBER, write either the TLINTRSUM0 or TLINTRSUM1 register
+//
+// Assumed register usage:
+//  rsum TLINTRSUMx write data
+//  raddr node space address
+//  scratch scratch register
+
+// .macro Write_TLINTRSUMx     rsum, raddr, whami, ?label1, ?label2
+//
+//     nop
+//     mfpr    'whami', pt_whami               // Get our whami (VID)
+//
+//     extbl   'whami', #1, 'whami'            // shift down to bit 0
+//     lda     'raddr', ^xff88(r31)            // Get base node space address bits
+//
+//     sll     'raddr', #24, 'raddr'           // Shift up to proper position
+//     blbs    'whami', label1
+//
+//     lda     'raddr', <tlep$tlintrsum0_offset>('raddr')
+//     br      r31, label2
+//
+// label1:     lda     'raddr', <tlep$tlintrsum1_offset>('raddr')
+// label2:     srl     'whami', #1, 'whami'            // Shift off the cpu number
+//
+//     sll     'whami', #22, 'whami'           // Get our node offset
+//     addq    'raddr', 'whami', 'raddr'       // Get our base node space address
+//
+//     mb
+//     stqp    'rsum', 0('raddr')              // write the right tlintrsum reg
+//     mb
+//     ldqp    'rsum', 0('raddr')              // dummy read to tlintrsum
+//     bis     'rsum', 'rsum', 'rsum'          // needed to complete the ldqp above -jpo
+// .endm
+
+
+#define Write_TLINTRSUMx(_rsum,_raddr,_whami)  \
+       nop;                            \
+       mfpr    _whami,pt_whami;        \
+       extbl   _whami,1,_whami;        \
+       lda     _raddr,0xff88(zero);    \
+       sll     _raddr,24,_raddr;       \
+       blbs    _whami,1f;              \
+       lda     _raddr,0x1180(_raddr);\
+       br      zero,2f;                \
+1:     lda     _raddr,0x11c0(_raddr);\
+2:     srl     _whami,1,_whami;        \
+       addq    _raddr,_whami,_raddr;   \
+       mb;                             \
+       stqp    _rsum,0(_raddr);        \
+       ldqp    _rsum,0(_raddr);        \
+       bis     _rsum,_rsum,_rsum       
+
+       
+//
+// Macro to determine highest priority TIOP Node ID from interrupt pending mask
+//
+// Assumed register usage:
+//  rmask - TLINTRSUMx contents, shifted to isolate IOx bits 
+//  rid - TLSB Node ID of highest TIOP
+
+//.macro Intr_Find_TIOP  rmask, rid, ?l1, ?l2, ?l3, ?l4, ?l5, ?l6
+//     srl     'rmask', #4, 'rid'              // check IOP8
+//     blbc    'rid', l1                       // not IOP8
+// 
+//     lda     'rid', 8(r31)                   // IOP8
+//     br      r31, l6
+// 
+// l1: srl     'rmask', #3, 'rid'              // check IOP7
+//     blbc    'rid', l2                       // not IOP7
+// 
+//     lda     'rid', 7(r31)                   // IOP7
+//     br      r31, l6
+// 
+// l2: srl     'rmask', #2, 'rid'              // check IOP6
+//     blbc    'rid', l3                       // not IOP6
+// 
+//     lda     'rid', 6(r31)                   // IOP6
+//     br      r31, l6
+// 
+// l3: srl     'rmask', #1, 'rid'              // check IOP5
+//     blbc    'rid', l4                       // not IOP5
+// 
+//     lda     'rid', 5(r31)                   // IOP5
+//     br      r31, l6
+// 
+// l4: srl     'rmask', #0, 'rid'              // check IOP4
+//     blbc    'rid', l5                       // not IOP4
+// 
+//     lda     r14, 4(r31)                     // IOP4
+//     br      r31, l6
+// 
+// l5: lda     r14, 0(r31)                     // passive release
+// l6:
+// .endm
+
+
+#define Intr_Find_TIOP(_rmask,_rid)     \
+       srl     _rmask,3,_rid;          \
+       blbc    _rid,1f;                \
+       lda     _rid,8(zero);           \
+       br      zero,6f;                \
+1:     srl     _rmask,3,_rid;          \
+       blbc    _rid, 2f;               \
+       lda     _rid, 7(r31);           \
+       br      r31, 6f;                \
+2:     srl     _rmask, 2, _rid;        \
+       blbc    _rid, 3f;               \
+       lda     _rid, 6(r31);           \
+       br      r31, 6f;                \
+3:     srl     _rmask, 1, _rid;        \
+       blbc    _rid, 4f;               \
+       lda     _rid, 5(r31);           \
+       br      r31, 6f;                \
+4:     srl     _rmask, 0, _rid;        \
+       blbc    _rid, 5f;               \
+       lda     r14, 4(r31);            \
+       br      r31, 6f;                \
+5:     lda     r14, 0(r31);            \
+6:     
+
+
+
+
+//
+// Macro to calculate base node space address for given node id
+//
+// Assumed register usage:
+//  rid - TLSB node id
+//  raddr - base node space address
+
+//.macro Get_TLSB_Node_Address  rid, raddr
+//     sll     'rid', #22, 'rid'               // Get offset of IOP node
+//     lda     'raddr', ^xff88(r31)            // Get base node space address bits
+//
+//     sll     'raddr', #24, 'raddr'           // Shift up to proper position
+//     addq    'raddr', 'rid', 'raddr'         // Get TIOP node space address
+//     .iif ne turbo_pcia_intr_fix,    srl     'rid', #22, 'rid'               // Restore IOP node id
+//.endm
+
+
+#define turbo_pcia_intr_fix 0
+               
+        
+#if turbo_pcia_intr_fix != 0
+#define Get_TLSB_Node_Address(_rid,_raddr) \
+       sll     _rid,22,_rid;           \
+       lda     _raddr,0xff88(zero);    \
+       sll     _raddr,24,_raddr;       \
+       addq    _raddr,_rid,_raddr;     \
+       srl     _rid,22,_rid
+#else
+#define Get_TLSB_Node_Address(_rid,_raddr) \
+       sll     _rid,22,_rid;           \
+       lda     _raddr,0xff88(zero);    \
+       sll     _raddr,24,_raddr;       \
+       addq    _raddr,_rid,_raddr
+#endif
+                
+        
+               
+\f
+
+// .macro mchk$TLEPstore rlog, rs, rs1, nodebase, tlepreg, clr, tlsb, crd
+//       .iif eq tlsb, lda     'rs1',<tlep$'tlepreg'_offset>(r31)
+//       .iif ne tlsb, lda     'rs1',<tlsb$'tlepreg'_offset>(r31)
+//       or      'rs1', 'nodebase', 'rs1'
+//       ldlp   'rs', 0('rs1')
+//       .iif eq crd,  stlp   'rs', mchk$'tlepreg'('rlog')     // store in frame
+//       .iif ne crd,  stlp   'rs', mchk$crd_'tlepreg'('rlog') // store in frame
+//       .iif ne clr, stlp 'rs',0('rs1')       // optional write to clear
+//     .endm
+
+       
+// .macro OSFmchk$TLEPstore tlepreg, clr=0, tlsb=0
+//       mchk$TLEPstore r14, r8, r4, r13, <tlepreg>, <clr>, <tlsb>, crd=0
+//     .endm
+
+#define CONCAT(_a,_b) _a ## _b
+
+#define OSFmchk_TLEPstore_1(_rlog,_rs,_rs1,_nodebase,_tlepreg)         \
+       lda     _rs1,CONCAT(tlep_,_tlepreg)(zero);              \
+       or      _rs1,_nodebase,_rs1;                            \
+       ldlp    _rs1,0(_rs1);                                   \
+       stlp    _rs,CONCAT(mchk_,_tlepreg)(_rlog)
+
+        
+#define OSFmchk_TLEPstore(_tlepreg) OSFmchk_TLEPstore_1(r14,r8,r4,r13,_tlepreg)
+       
+
+// .macro OSFcrd$TLEPstore tlepreg, clr=0, tlsb=0
+//       mchk$TLEPstore r14, r10, r1, r0, <tlepreg>, <clr>, <tlsb>, crd=1
+//     .endm
+
+#define OSFcrd_TLEPstore_1(_rlog,_rs,_rs1,_nodebase,_tlepreg)  \
+       lda     _rs1,CONCAT(tlep_,_tlepreg)(zero);              \
+       or      _rs1,_nodebase,_rs1;                            \
+       ldlp    _rs1,0(_rs1);                                   \
+       stlp    _rs,CONCAT(mchk_crd_,_tlepreg)(_rlog)
+
+#define OSFcrd_TLEPstore_tlsb_1(_rlog,_rs,_rs1,_nodebase,_tlepreg)     \
+       lda     _rs1,CONCAT(tlsb_,_tlepreg)(zero);              \
+       or      _rs1,_nodebase,_rs1;                            \
+       ldlp    _rs1,0(_rs1);                                   \
+       stlp    _rs,CONCAT(mchk_crd_,_tlepreg)(_rlog)
+
+#define OSFcrd_TLEPstore_tlsb_clr_1(_rlog,_rs,_rs1,_nodebase,_tlepreg)         \
+       lda     _rs1,CONCAT(tlsb_,_tlepreg)(zero);              \
+       or      _rs1,_nodebase,_rs1;                            \
+       ldlp    _rs1,0(_rs1);                                   \
+       stlp    _rs,CONCAT(mchk_crd_,_tlepreg)(_rlog);          \
+        stlp    _rs,0(_rs1)
+        
+        
+#define OSFcrd_TLEPstore(_tlepreg) OSFcrd_TLEPstore_1(r14,r8,r4,r13,_tlepreg)
+#define OSFcrd_TLEPstore_tlsb(_tlepreg) OSFcrd_TLEPstore_tlsb_1(r14,r8,r4,r13,_tlepreg)
+#define OSFcrd_TLEPstore_tlsb_clr(_tlepreg) OSFcrd_TLEPstore_tlsb_clr_1(r14,r8,r4,r13,_tlepreg)
+
+        
+\f
+
+// .macro save_pcia_intr irq
+//     and     r13, #^xf, r25                  // isolate low 4 bits
+//     addq    r14, #4, r14                    // format the TIOP Node id field
+//     sll     r14, #4, r14                    // shift the TIOP Node id
+//     or      r14, r25, r10                   // merge Node id/hose/HPC
+//     mfpr    r14, pt14                       // get saved value
+//     extbl   r14, #'irq', r25                // confirm none outstanding
+//     bne     r25, sys$machine_check_while_in_pal
+//     insbl   r10, #'irq', r10                // align new info
+//     or      r14, r10, r14                   // merge info
+//     mtpr    r14, pt14                       // save it
+//     bic     r13, #^xf, r13                  // clear low 4 bits of vector
+//     .endm
+
+#define save_pcia_intr(_irq)  \
+       and     r13, 0xf, r25;  \
+       addq    r14, 4, r14;    \
+       sll     r14, 4, r14;    \
+       or      r14, r25, r10;  \
+       mfpr    r14, pt14;      \
+       extbl   r14, _irq, r25; \
+       bne     r25, sys_machine_check_while_in_pal; \
+       insbl   r10, _irq, r10; \
+       or      r14, r10, r14;  \
+       mtpr    r14, pt14;      \
+       bic     r13, 0xf, r13
+
+
+
+       ALIGN_BLOCK
+\f
+// .sbttl      "wripir - PALcode for wripir instruction"
+//orig SYS$WRIPIR:                             // R16 has the processor number.
+
+EXPORT(sys_wripir)
+        
+//++
+// Convert the processor number to a CPU mask
+//--
+
+       and     r16,0xf, r14            // mask the top stuff (16 CPUs supported)
+       bis     r31,0x1,r16             // get a one
+       sll     r16,r14,r14             // shift the bit to the right place
+
+//++
+// Build the Broadcast Space base address
+//--
+       lda     r13,0xff8e(r31)         // Load the upper address bits
+       sll     r13,24,r13              // shift them to the top
+  
+//++
+// Send out the IP Intr
+//--
+       stqp    r14, 0x40(r13)  // Write to TLIPINTR reg WAS  TLSB_TLIPINTR_OFFSET  
+       wmb                             // Push out the store
+
+       hw_rei
+
+\f
+       ALIGN_BLOCK
+// .sbttl      "CFLUSH- PALcode for CFLUSH instruction"
+//+
+// SYS$CFLUSH
+// Entry:
+//
+//     R16 - contains the PFN of the page to be flushed
+//
+// Function:
+//     Flush all Dstream caches of 1 entire page
+//
+//-
+        
+EXPORT(sys_cflush)
+        
+//      #convert pfn to addr, and clean off <63:20>
+//      #sll   r16, <page_offset_size_bits>+<63-20>>, r12
+       sll     r16, page_offset_size_bits+(63-20),r12 
+
+//      #ldah  r13,<<1@22>+32768>@-16(r31)// + xxx<31:16>
+//      # stolen from srcmax code. XXX bugnion
+       lda     r13, 0x10(r31)                             // assume 16Mbytes of cache  
+       sll     r13, 20, r13                               // convert to bytes
+
+
+       srl     r12, 63-20, r12 // shift back to normal position
+       xor     r12, r13, r12           // xor addr<18>
+       
+       or      r31, 8192/(32*8), r13   // get count of loads
+       nop
+
+cflush_loop:    
+       subq    r13, 1, r13             // decr counter
+       mfpr    r25, ev5__intid         // Fetch level of interruptor
+
+       ldqp    r31, 32*0(r12)          // do a load
+       ldqp    r31, 32*1(r12)          // do next load
+
+       ldqp    r31, 32*2(r12)          // do next load
+       ldqp    r31, 32*3(r12)          // do next load
+
+       ldqp    r31, 32*4(r12)          // do next load
+       ldqp    r31, 32*5(r12)          // do next load
+
+       ldqp    r31, 32*6(r12)          // do next load
+       ldqp    r31, 32*7(r12)          // do next load
+
+       mfpr    r14, ev5__ipl           // Fetch current level
+       lda     r12, (32*8)(r12)        // skip to next cache block addr
+
+       cmple   r25, r14, r25           // R25 = 1 if intid .less than or eql ipl
+       beq     r25, 1f         // if any int's pending, re-queue CFLUSH -- need to check for hlt interrupt???
+
+       bne     r13, cflush_loop        // loop till done
+       hw_rei                          // back to user
+       
+       ALIGN_BRANCH
+1:                                     // Here if interrupted
+       mfpr    r12, exc_addr
+       subq    r12, 4, r12             // Backup PC to point to CFLUSH
+       
+       mtpr    r12, exc_addr
+       nop
+       
+       mfpr    r31, pt0                // Pad exc_addr write   
+       hw_rei
+
+\f
+       ALIGN_BLOCK
+// .sbttl      "CSERVE- PALcode for CSERVE instruction"
+//+
+// SYS$CSERVE
+//
+// Function:
+//     Various functions for private use of console software
+//
+//     option selector in r0
+//     arguments in r16....
+//
+//
+//     r0 = 0  unknown
+//
+//     r0 = 1  ldqp
+//     r0 = 2  stqp
+//             args, are as for normal STQP/LDQP in VMS PAL
+//
+//     r0 = 3  dump_tb's
+//     r16 = detination PA to dump tb's to.
+//
+//     r0<0> = 1, success
+//     r0<0> = 0, failure, or option not supported
+//     r0<63:1> = (generally 0, but may be function dependent)
+//     r0 - load data on ldqp
+//
+//-
+EXPORT(sys_cserve)        
+        
+#ifdef SIMOS
+        /* taken from scrmax */
+       cmpeq   r18, CSERVE_K_RD_IMPURE, r0
+       bne     r0, Sys_Cserve_Rd_Impure
+       
+       cmpeq   r18, CSERVE_K_JTOPAL, r0
+       bne     r0, Sys_Cserve_Jtopal
+        call_pal        0
+
+       or      r31, r31, r0
+       hw_rei                          // and back we go
+
+Sys_Cserve_Rd_Impure:
+       mfpr    r0, pt_impure           // Get base of impure scratch area.
+       hw_rei
+
+       ALIGN_BRANCH
+
+Sys_Cserve_Jtopal:
+               bic     a0, 3, t8               // Clear out low 2 bits of address
+               bis     t8, 1, t8               // Or in PAL mode bit
+        mtpr    t8,exc_addr
+        hw_rei
+       
+        
+#else /* SIMOS */
+        
+       cmpeq   r16, cserve_ldlp, r12   // check for ldqp
+       bne     r12, 1f         // br if
+
+       cmpeq   r16, cserve_stlp, r12   // check for stqp
+       bne     r12, 2f         // br if
+
+       cmpeq   r16, cserve_callback, r12 // check for callback entry
+       bne     r12, csrv_callback      // br if
+
+       cmpeq   r16, cserve_identify, r12 // check for callback entry
+       bne     r12, csrv_identify      // br if
+
+       or      r31, r31, r0            // set failure
+       nop                             // pad palshadow write
+        
+       hw_rei                          // and back we go
+#endif /* SIMOS */
+               
+// ldqp
+       ALIGN_QUAD
+1:
+       ldqp    r0,0(r17)               // get the data
+       nop                             // pad palshadow write
+
+       hw_rei                          // and back we go
+
+
+// stqp
+       ALIGN_QUAD
+2:
+       stqp    r18, 0(r17)             // store the data
+#ifdef SIMOS
+        lda     r0,17(r31) // bogus
+#else
+       lda     r0, CSERVE_SUCCESS(r31) // set success
+#endif
+       hw_rei                          // and back we go
+
+
+       ALIGN_QUAD
+csrv_callback:
+       ldq     r16, 0(r17)             // restore r16
+       ldq     r17, 8(r17)             // restore r17
+       lda     r0, hlt_c_callback(r31)
+       br      r31, sys_enter_console
+
+
+csrv_identify:
+       mfpr    r0, pal_base
+       ldqp    r0, 8(r0)
+       hw_rei
+
+
+// dump tb's
+       ALIGN_QUAD
+0:
+       // DTB PTEs - 64 entries
+       addq    r31, 64, r0             // initialize loop counter
+       nop
+
+1:     mfpr    r12, ev5__dtb_pte_temp  // read out next pte to temp
+       mfpr    r12, ev5__dtb_pte       // read out next pte to reg file
+
+       subq    r0, 1, r0               // decrement loop counter
+       nop                             // Pad - no Mbox instr in cycle after mfpr
+
+       stqp    r12, 0(r16)             // store out PTE
+       addq    r16, 8 ,r16             // increment pointer
+
+       bne     r0, 1b
+
+       ALIGN_BRANCH
+       // ITB PTEs - 48 entries
+       addq    r31, 48, r0             // initialize loop counter
+       nop
+
+2:     mfpr    r12, ev5__itb_pte_temp  // read out next pte to temp
+       mfpr    r12, ev5__itb_pte       // read out next pte to reg file
+
+       subq    r0, 1, r0               // decrement loop counter
+       nop                             // 
+
+       stqp    r12, 0(r16)             // store out PTE
+       addq    r16, 8 ,r16             // increment pointer
+
+       bne     r0, 2b
+       or      r31, 1, r0              // set success
+
+       hw_rei                          // and back we go
+
+\f
+// .sbttl      "SYS$INTERRUPT - Interrupt processing code"
+
+//+
+// SYS$INTERRUPT
+//
+//     Current state:
+//             Stack is pushed
+//             ps, sp and gp are updated
+//             r12, r14 - available
+//             r13 - INTID (new EV5 IPL)
+//             r25 - ISR
+//             r16, r17, r18 - available
+//
+//-
+
+  
+EXPORT(sys_interrupt)
+       cmpeq   r13, 31, r12
+       bne     r12, sys_int_mchk_or_crd // Check for level 31 interrupt (machine check or crd)
+
+       cmpeq   r13, 30, r12
+       bne     r12, sys_int_powerfail  // Check for level 30 interrupt (powerfail)
+
+       cmpeq   r13, 29, r12
+       bne     r12, sys_int_perf_cnt   // Check for level 29 interrupt (performance counters)
+
+       cmpeq   r13, 23, r12
+       bne     r12, sys_int_23                 // Check for level 23 interrupt
+       
+       cmpeq   r13, 22, r12
+       bne     r12, sys_int_22                 // Check for level 22 interrupt (might be 
+                                               //  interprocessor or timer interrupt)
+
+       cmpeq   r13, 21, r12
+       bne     r12, sys_int_21                 // Check for level 21 interrupt
+
+       cmpeq   r13, 20, r12
+       bne     r12, sys_int_20                 // Check for level 20 interrupt (might be corrected 
+                                               // system error interrupt)
+
+       mfpr    r14, exc_addr                   // ooops, something is wrong
+       br      r31, pal_pal_bug_check_from_int
+
+
+
+\f
+//+
+//sys$int_2*
+//     Routines to handle device interrupts at IPL 23-20.
+//     System specific method to ack/clear the interrupt, detect passive release,
+//       detect interprocessor (22),  interval clock (22),  corrected
+//       system error (20)
+//
+//     Current state:
+//             Stack is pushed
+//             ps, sp and gp are updated
+//             r12, r14 - available
+//             r13 - INTID (new EV5 IPL)
+//             r25 - ISR
+//
+//     On exit:
+//             Interrupt has been ack'd/cleared
+//             a0/r16 - signals IO device interrupt
+//             a1/r17 - contains interrupt vector
+//             exit to ent_int address
+//
+//-
+       ALIGN_BRANCH
+sys_int_23:
+       Read_TLINTRSUMx(r13,r10,r14)            // read the right TLINTRSUMx
+       srl     r13, 22, r13                    // shift down to examine IPL17
+
+       Intr_Find_TIOP(r13,r14)
+       beq     r14, 1f
+
+       Get_TLSB_Node_Address(r14,r10)
+       lda     r10, 0xac0(r10) // Get base TLILID address
+
+       ldlp    r13, 0(r10)                     // Read the TLILID register
+       bne     r13, pal_post_dev_interrupt
+
+1:     lda     r16, osfint_c_passrel(r31)      // passive release
+       br      r31, pal_post_interrupt         // 
+
+
+       ALIGN_BRANCH
+sys_int_22:
+        or      r31,1,r16                       // a0 means it is a I/O interrupt
+        lda     r8,0x101(r31)
+        sll     r8,16,r8
+        lda     r8,0xa000(r8)
+        sll     r8,16,r8
+        lda     r8,0x080(r8)
+        or      r31,0x10,r9
+        stq_p   r9, 0(r8)                       // clear the rtc interrupt
+         
+        br     r31, pal_post_interrupt         // 
+
+
+       ALIGN_BRANCH
+sys_int_21:
+       Read_TLINTRSUMx(r13,r10,r14)            // read the right TLINTRSUMx
+       srl     r13, 12, r13                    // shift down to examine IPL15
+
+       Intr_Find_TIOP(r13,r14)
+       beq     r14, 1f
+
+       Get_TLSB_Node_Address(r14,r10)
+       lda     r10, 0xa40(r10) // Get base TLILID address
+
+       ldlp    r13, 0(r10)                     // Read the TLILID register
+#if turbo_pcia_intr_fix == 0        
+//orig .if eq  turbo_pcia_intr_fix
+       bne     r13, pal_post_dev_interrupt
+//orig .iff
+       beq     r13, 1f
+
+       and     r13, 0x3, r10                   // check for PCIA bits
+       beq     r10, pal_post_dev_interrupt     // done if nothing set
+       save_pcia_intr(1)
+       br      r31, pal_post_dev_interrupt     // 
+// orig .endc
+#endif  /* turbo_pcia_intr_fix == 0 */
+        
+1:     lda     r16, osfint_c_passrel(r31)      // passive release
+       br      r31, pal_post_interrupt         // 
+
+
+       ALIGN_BRANCH
+sys_int_20:
+        or      r31,3,r16                       // a0 means it is a I/O interrupt
+        bis     r31,0x801,r8
+        sll     r8,4,r8
+        bis     r8,0xa000,r8
+        sll     r8,4,r8
+        bis     r8,0x300,r8
+        ldl_p   r17, 0(r8)                      // read the drir, which is actually
+                                                // the srm vector
+        
+        br      r31, pal_post_interrupt
+
+        
+       ALIGN_BRANCH
+pal_post_dev_interrupt:
+       or      r13, r31, r17                   // move vector to a1
+       or      r31, osfint_c_dev, r16          // a0 signals IO device interrupt
+
+pal_post_interrupt:
+       mfpr    r12, pt_entint
+
+       mtpr    r12, exc_addr
+
+       nop
+       nop
+
+       hw_rei_spe
+
+
+\f
+//+
+// sys_passive_release
+//     Just pretend the interrupt never occurred.
+//-
+
+EXPORT(sys_passive_release)
+       mtpr    r11, ev5__dtb_cm        // Restore Mbox current mode for ps
+       nop
+       
+       mfpr    r31, pt0                // Pad write to dtb_cm
+       hw_rei
+
+//+
+//sys_int_powerfail
+//     A powerfail interrupt has been detected.  The stack has been pushed.
+//     IPL and PS are updated as well.
+//
+//     I'm not sure what to do here, I'm treating it as an IO device interrupt
+//
+//-
+
+       ALIGN_BLOCK
+sys_int_powerfail:
+       lda     r12, 0xffc4(r31)                // get GBUS_MISCR address bits
+       sll     r12, 24, r12                    // shift to proper position
+       ldqp    r12, 0(r12)                     // read GBUS_MISCR
+       srl     r12, 5, r12                     // isolate bit <5>
+       blbc    r12, 1f                         // if clear, no missed mchk
+
+                                               // Missed a CFAIL mchk
+       lda     r13, 0xffc7(r31)                // get GBUS$SERNUM address bits
+       sll     r13, 24, r13                    // shift to proper position
+       lda     r14, 0x40(r31)                  // get bit <6> mask
+       ldqp    r12, 0(r13)                     // read GBUS$SERNUM
+       or      r12, r14, r14                   // set bit <6>
+       stqp    r14, 0(r13)                     // clear GBUS$SERNUM<6>
+       mb
+       mb
+
+1:     br      r31, sys_int_mchk               // do a machine check
+       
+       lda     r17, scb_v_pwrfail(r31) // a1 to interrupt vector
+       mfpr    r25, pt_entint
+
+       lda     r16, osfint_c_dev(r31)  // a0 to device code
+       mtpr    r25, exc_addr
+       
+       nop                             // pad exc_addr write
+       nop
+       
+       hw_rei_spe
+
+//+
+// sys$halt_interrupt
+//       A halt interrupt has been detected.  Pass control to the console.
+//
+//
+//-
+        EXPORT(sys_halt_interrupt)
+        
+       ldah    r13, 0x1800(r31)                // load Halt/^PHalt bits
+       Write_TLINTRSUMx(r13,r10,r14)           // clear the ^PHalt bits
+
+       mtpr    r11, dtb_cm             // Restore Mbox current mode
+       nop
+       nop
+       mtpr    r0, pt0
+#ifndef SIMOS
+        pvc_jsr updpcb, bsr=1
+        bsr     r0, pal_update_pcb      // update the pcb
+#endif
+        lda     r0, hlt_c_hw_halt(r31)  // set halt code to hw halt
+        br      r31, sys_enter_console  // enter the console
+
+
+\f
+//+
+// sys$int_mchk_or_crd
+//
+//     Current state:
+//             Stack is pushed
+//             ps, sp and gp are updated
+//             r12
+//             r13 - INTID (new EV5 IPL)
+//             r14 - exc_addr
+//             r25 - ISR
+//             r16, r17, r18 - available
+//
+//-
+       ALIGN_BLOCK
+
+sys_int_mchk_or_crd:
+       srl     r25, isr_v_mck, r12
+       blbs    r12, sys_int_mchk
+       //+
+       // Not a Machine check interrupt, so must be an Internal CRD interrupt
+       //-
+
+       mb                                      //Clear out Cbox prior to reading IPRs
+       srl     r25, isr_v_crd, r13             //Check for CRD
+       blbc    r13, pal_pal_bug_check_from_int //If CRD not set, shouldn't be here!!!  
+
+       lda     r9, 1(r31)
+       sll     r9, hwint_clr_v_crdc, r9        // get ack bit for crd
+       mtpr    r9, ev5__hwint_clr              // ack the crd interrupt
+
+       or      r31, r31, r12                   // clear flag
+       lda     r9, mchk_c_ecc_c(r31)           // Correctable error MCHK code
+
+sys_merge_sys_corr:
+       ldah    r14, 0xfff0(r31)
+       mtpr    r0, pt0                         // save r0 for scratch
+       zap     r14, 0xE0, r14                  // Get Cbox IPR base
+       mtpr    r1, pt1                         // save r0 for scratch
+
+       ldqp    r0, ei_addr(r14)                // EI_ADDR IPR
+       ldqp    r10, fill_syn(r14)              // FILL_SYN IPR
+       bis     r0, r10, r31                    // Touch lds to make sure they complete before doing scrub
+
+       blbs    r12, 1f                         // no scrubbing for IRQ0 case
+// XXX bugnion pvc_jsr crd_scrub_mem, bsr=1
+       bsr     r13, sys_crd_scrub_mem          // and go scrub
+
+                                               // ld/st pair in scrub routine will have finished due
+                                               // to ibox stall of stx_c.  Don't need another mb.
+       ldqp    r8, ei_stat(r14)                // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
+       or      r8, r31, r12                    // Must only be executed once in this flow, and must
+       br      r31, 2f                         // be after the scrub routine.
+
+1:     ldqp    r8, ei_stat(r14)                // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
+                                               // For IRQ0 CRD case only - meaningless data.
+
+2:     mfpr    r13, pt_mces                    // Get MCES
+       srl     r12, ei_stat_v_ei_es, r14       // Isolate EI_STAT:EI_ES
+       blbc    r14, 6f                 // branch if 630
+       srl     r13, mces_v_dsc, r14            // check if 620 reporting disabled
+       blbc    r14, 5f                         // branch if enabled
+       or      r13, r31, r14                   // don't set SCE if disabled
+       br      r31, 8f                 // continue
+5:     bis     r13, BIT(mces_v_sce), r14       // Set MCES<SCE> bit
+       br      r31, 8f
+
+6:             srl     r13, mces_v_dpc, r14            // check if 630 reporting disabled
+       blbc    r14, 7f                 // branch if enabled
+       or      r13, r31, r14                   // don't set PCE if disabled
+       br      r31, 8f                 // continue
+7:     bis     r13, BIT(mces_v_pce), r14       // Set MCES<PCE> bit
+
+       // Setup SCB if dpc is not set
+8:     mtpr    r14, pt_mces                    // Store updated MCES
+       srl     r13, mces_v_sce, r1             // Get SCE
+       srl     r13, mces_v_pce, r14            // Get PCE
+       or      r1, r14, r1                     // SCE OR PCE, since they share
+                                               // the CRD logout frame
+       // Get base of the logout area.  
+       GET_IMPURE(r14)                          // addr of per-cpu impure area
+       GET_ADDR(r14,(pal_logout_area+mchk_crd_base),r14)
+
+       blbc    r1, sys_crd_write_logout_frame  // If pce/sce not set, build the frame
+
+       // Set the 2nd error flag in the logout area:
+       
+       lda     r1, 3(r31)                      // Set retry and 2nd error flags
+       sll     r1, 30, r1                      // Move to bits 31:30 of logout frame flag longword
+       stlp    r1, mchk_crd_flag+4(r14)        // store flag longword
+       br      sys_crd_ack                
+                                          
+sys_crd_write_logout_frame:               
+       // should only be here if neither the pce or sce bits are set
+                                          
+       //+                                
+       // Write the mchk code to the logout area
+       //-                                
+       stqp    r9, mchk_crd_mchk_code(r14)   
+
+
+       //+                                
+       // Write the first 2 quadwords of the logout area:
+       //-                                
+       lda     r1, 1(r31)                      // Set retry flag
+       sll     r1, 63, r9                      // Move retry flag to bit 63
+       lda     r1, mchk_crd_size(r9)           // Combine retry flag and frame size
+       stqp    r1, mchk_crd_flag(r14)          // store flag/frame size
+                                   
+#ifndef SIMOS
+        /* needed? bugnion */               
+       lda     r1, mchk_crd_sys_base(r31)      // sys offset
+       sll     r1, 32, r1
+       lda     r1, mchk_crd_cpu_base(r1)       // cpu offset
+       stqp    r1, mchk_crd_offsets(r14)       // store sys offset/cpu offset into logout frame
+                         
+#endif                         
+       //+                                
+       // Write error IPRs already fetched to the logout area
+       //-                                
+       stqp    r0, mchk_crd_ei_addr(r14)    
+       stqp    r10, mchk_crd_fill_syn(r14)   
+       stqp    r8, mchk_crd_ei_stat(r14)    
+       stqp    r25, mchk_crd_isr(r14)    
+       //+
+       // Log system specific info here
+       //-
+crd_storeTLEP_:
+       lda     r1, 0xffc4(r31)                 // Get GBUS$MISCR address
+       sll     r1, 24, r1
+       ldqp    r1, 0(r1)                       // Read GBUS$MISCR 
+       sll     r1, 16, r1                      // shift up to proper field
+       mfpr    r10, pt_whami                   // get our node id
+       extbl   r10, 1, r10                     // shift to bit 0
+       or      r1, r10, r1                     // merge MISCR and WHAMI
+       stlp    r1, mchk_crd_whami(r14)         // write to crd logout area
+       srl     r10, 1, r10                     // shift off cpu number
+
+       Get_TLSB_Node_Address(r10,r0)           // compute our nodespace address
+
+       OSFcrd_TLEPstore_tlsb(tldev)
+       OSFcrd_TLEPstore_tlsb_clr(tlber)
+       OSFcrd_TLEPstore_tlsb_clr(tlesr0)
+       OSFcrd_TLEPstore_tlsb_clr(tlesr1)
+       OSFcrd_TLEPstore_tlsb_clr(tlesr2)
+       OSFcrd_TLEPstore_tlsb_clr(tlesr3)
+
+sys_crd_ack:                               
+       mfpr    r0, pt0                                 // restore r0
+       mfpr    r1, pt1                                 // restore r1
+
+       srl     r12, ei_stat_v_ei_es, r12
+       blbc    r12, 5f
+       srl     r13, mces_v_dsc, r10                    // logging enabled?
+       br      r31, 6f
+5:     srl     r13, mces_v_dpc, r10                    // logging enabled?
+6:     blbc    r10, sys_crd_post_interrupt             // logging enabled -- report it
+
+                                                       // logging not enabled -- 
+       // Get base of the logout area.  
+       GET_IMPURE(r13)                          // addr of per-cpu impure area
+       GET_ADDR(r13,(pal_logout_area+mchk_crd_base),r13)
+       ldlp    r10, mchk_crd_rsvd(r13)                 // bump counter
+       addl    r10, 1, r10
+       stlp    r10, mchk_crd_rsvd(r13)
+       mb
+       br      r31, sys_crd_dismiss_interrupt          // just return
+                                          
+       //+
+       // The stack is pushed.  Load up a0,a1,a2 and vector via entInt
+       //
+       //-
+
+       ALIGN_BRANCH
+sys_crd_post_interrupt:
+       lda     r16, osfint_c_mchk(r31) // flag as mchk/crd in a0
+       lda     r17, scb_v_proc_corr_err(r31) // a1 <- interrupt vector
+
+       blbc    r12, 1f
+       lda     r17, scb_v_sys_corr_err(r31) // a1 <- interrupt vector
+
+1:     subq    r31, 1, r18            // get a -1
+       mfpr    r25, pt_entInt
+
+        srl     r18, 42, r18           // shift off low bits of kseg addr
+       mtpr    r25, exc_addr           // load interrupt vector
+
+        sll     r18, 42, r18           // shift back into position
+        or     r14, r18, r18           // EV4 algorithm - pass pointer to mchk frame as kseg address
+       
+       hw_rei_spe                      // done
+
+
+       //+ 
+       // The stack is pushed.  Need to back out of it all. 
+       //-
+
+sys_crd_dismiss_interrupt:
+       br      r31, Call_Pal_Rti
+
+\f
+// .sbttl      sys_crd_scrub_mem
+
+       //+
+       //
+       // sys_crd_scrub_mem
+       //      called
+       //      jsr r13, sys$crd_scrub_mem
+       //      r0 = addr of cache block 
+       //
+       //-
+
+       
+       
+       ALIGN_BLOCK     // align for branch target
+sys_crd_scrub_mem:
+       // now find error in memory, and attempt to scrub that cache block
+       // This routine just scrubs the failing octaword
+       // Only need to "touch" one quadword per octaword to accomplish the scrub
+       srl     r0, 39, r8              // get high bit of bad pa
+       blbs    r8, 1f                  // don't attempt fixup on IO space addrs
+       nop                             // needed to align the ldqpl to octaword boundary
+       nop                             //             "
+
+       ldqpl   r8,  0(r0)              // attempt to read the bad memory
+                                       // location
+                                       //    (Note bits 63:40,3:0 of ei_addr 
+                                       //     are set to 1, but as long as 
+                                       //     we are doing a phys ref, should 
+                                       //     be ok)
+       nop                             // Needed to keep the Ibox from swapping the ldqpl into E1
+
+       stqpc   r8,  0(r0)              // Store it back if it is still there.
+                                       // If store fails, location already 
+                                       //  scrubbed by someone else    
+
+       nop                             // needed to align the ldqpl to octaword boundary
+
+       lda     r8, 0x20(r31)           // flip bit 5 to touch next hexaword
+       xor     r8, r0, r0              
+       nop                             // needed to align the ldqpl to octaword boundary
+       nop                             //             "
+
+       ldqpl   r8,  0(r0)              // attempt to read the bad memory
+                                       // location
+                                       //    (Note bits 63:40,3:0 of ei_addr 
+                                       //     are set to 1, but as long as 
+                                       //     we are doing a phys ref, should 
+                                       //     be ok)
+       nop                             // Needed to keep the Ibox from swapping the ldqpl into E1
+
+       stqpc   r8,  0(r0)              // Store it back if it is still there.
+                                       // If store fails, location already 
+                                       //  scrubbed by someone else    
+
+       lda     r8, 0x20(r31)           // restore r0 to original address
+       xor     r8, r0, r0              
+
+       //at this point, ei_stat could be locked due to a new corr error on the ld, 
+       //so read ei_stat to unlock AFTER this routine.
+
+// XXX bugnion pvc$jsr crd_scrub_mem, bsr=1, dest=1
+1:     ret     r31, (r13)              // and back we go
+
+\f
+// .sbttl "SYS$INT_MCHK - MCHK Interrupt code"
+//+
+// Machine check interrupt from the system.  Setup and join the
+// regular machine check flow.
+// On exit:
+//       pt0     - saved r0
+//       pt1     - saved r1
+//       pt4     - saved r4
+//       pt5     - saved r5
+//       pt6     - saved r6
+//       pt10    - saved exc_addr
+//       pt_misc<47:32> - mchk code
+//       pt_misc<31:16> - scb vector
+//       r14     - base of Cbox IPRs in IO space
+//       MCES<mchk> is set
+//-
+       ALIGN_BLOCK
+sys_int_mchk:                                  
+       lda     r14, mchk_c_sys_hrd_error(r31)
+       mfpr    r12, exc_addr
+       
+       addq    r14, 1, r14                     // Flag as interrupt
+       nop
+
+       sll     r14, 32, r14                    // Move mchk code to position
+       mtpr    r12, pt10                       // Stash exc_addr
+
+       mfpr    r12, pt_misc                    // Get MCES and scratch
+       mtpr    r0, pt0                         // Stash for scratch
+
+       zap     r12, 0x3c, r12                  // Clear scratch
+        blbs    r12, sys_double_machine_check   // MCHK halt if double machine check           
+
+       or      r12, r14, r12                   // Combine mchk code 
+       lda     r14, scb_v_sysmchk(r31)         // Get SCB vector
+
+       sll     r14, 16, r14                    // Move SCBv to position
+       or      r12, r14, r14                   // Combine SCBv
+
+       bis     r14, BIT(mces_v_mchk), r14      // Set MCES<MCHK> bit
+       mtpr    r14, pt_misc                    // Save mchk code!scbv!whami!mces
+
+       ldah    r14, 0xfff0(r31)
+       mtpr    r1, pt1                         // Stash for scratch
+
+       zap     r14, 0xE0, r14                  // Get Cbox IPR base
+       mtpr    r4, pt4
+
+       mtpr    r5, pt5
+
+#if beh_model        
+//  .if ne beh_model
+       ldah    r25, 0xC000(r31)                // Get base of demon space
+       lda     r25, 0x340(r25)                 // Add interrupt demon offset
+       
+       ldqp    r13, 0(r25)                     // Read the control register
+       nop
+
+       and     r13, 0x10, r8                   // For debug, check that the interrupt is expected
+       beq     r8, interrupt_not_expected
+       
+       bic     r13, 0x10, r13
+       stqp    r13, 0(r25)                     // Ack and clear the interrupt
+// XXX bugnion pvc$violate 379                         // stqp can't trap except replay.  mt ipr only problem if mf same ipr in same shadow
+   .endc
+#endif        
+
+       mtpr    r6, pt6
+       br      r31, sys_mchk_collect_iprs      // Join common machine check flow
+
+\f
+// .sbttl  "SYS$INT_PERF_CNT - Performance counter interrupt code"
+//+
+//sys$int_perf_cnt
+//
+//     A performance counter interrupt has been detected.  The stack has been pushed.
+//     IPL and PS are updated as well.
+//
+//     on exit to interrupt entry point ENTINT:: 
+//             a0 = osfint$c_perf
+//             a1 = scb$v_perfmon (650)
+//             a2 = 0 if performance counter 0 fired
+//             a2 = 1 if performance counter 1 fired
+//             a2 = 2 if performance counter 2 fired
+//                  (if more than one counter overflowed, an interrupt will be 
+//                     generated for each counter that overflows)
+//     
+//
+//-
+       ALIGN_BLOCK
+sys_int_perf_cnt:                      // Performance counter interrupt
+       lda     r17, scb_v_perfmon(r31) // a1 to interrupt vector
+       mfpr    r25, pt_entint
+
+       lda     r16, osfint_c_perf(r31) // a0 to perf counter code
+       mtpr    r25, exc_addr
+       
+       //isolate which perf ctr fired, load code in a2, and ack
+       mfpr    r25, isr
+       or      r31, r31, r18                   // assume interrupt was pc0
+
+       srl     r25, isr_v_pc1, r25             // isolate 
+       cmovlbs r25, 1, r18                     // if pc1 set, load 1 into r14
+
+       srl     r25, 1, r25                     // get pc2
+       cmovlbs r25, 2, r18                     // if pc2 set, load 2 into r14
+
+       lda     r25, 1(r31)                     // get a one
+       sll     r25, r18, r25
+
+       sll     r25, hwint_clr_v_pc0c, r25      // ack only the perf counter that generated the interrupt
+       mtpr    r25, hwint_clr
+       
+       hw_rei_spe
+
+
+\f
+       ALIGN_BLOCK
+// .sbttl      "System specific RESET code"
+//+
+//  RESET code
+//   On entry:
+//     r1 = pal_base +8
+//
+//     Entry state on trap:
+//       r0 = whami
+//       r2 = base of scratch area
+//       r3 = halt code
+//     and the following 3 if init_cbox is enabled:
+//       r5 = sc_ctl
+//       r6 = bc_ctl
+//       r7 = bc_cnfg
+//
+//       Entry state on switch:
+//     r17 - new PC
+//     r18 - new PCBB
+//     r19 - new VPTB
+//
+//-
+
+#if rax_mode==0
+        .globl sys_reset
+sys_reset:
+//     mtpr    r31, ic_flush_ctl       // do not flush the icache - done by hardware before SROM load
+       mtpr    r31, itb_ia             // clear the ITB
+       mtpr    r31, dtb_ia             // clear the DTB
+
+       lda     r1, -8(r1)              // point to start of code
+       mtpr    r1, pal_base            // initialize PAL_BASE
+
+       // Interrupts
+       mtpr    r31, astrr              // stop ASTs
+       mtpr    r31, aster              // stop ASTs
+       mtpr    r31, sirr               // clear software interrupts
+       
+       mtpr    r0, pt1                 // r0 is whami (unless we entered via swp)
+
+//orig ldah    r1, <<1@<icsr$v_sde-16>> ! <1@<icsr$v_fpe-16>> ! <2@<icsr$v_spe-16>>>(r31)
+        ldah     r1,(BIT(icsr_v_sde-16)|BIT(icsr_v_fpe-16)|BIT(icsr_v_spe-16+1))(zero)
+        
+#if disable_crd == 0
+// .if eq disable_crd
+       bis     r31, 1, r0
+       sll     r0, icsr_v_crde, r0     // A 1 in iscr<corr_read_enable>
+       or      r0, r1, r1              // Set the bit
+#endif
+                
+       mtpr    r1, icsr                // ICSR - Shadows enabled, Floating point enable, 
+                                       //      super page enabled, correct read per assembly option
+
+       // Mbox/Dcache init
+//orig lda     r1, <1@<mcsr$v_sp1>>(r31)
+        lda     r1,BIT(mcsr_v_sp1)(zero)
+        
+       mtpr    r1, mcsr                // MCSR - Super page enabled
+       lda     r1, BIT(dc_mode_v_dc_ena)(r31)
+       ALIGN_BRANCH
+//     mtpr    r1, dc_mode             // turn Dcache on
+       nop
+       
+       mfpr    r31, pt0                // No Mbox instr in 1,2,3,4
+       mfpr    r31, pt0
+       mfpr    r31, pt0
+       mfpr    r31, pt0
+       mtpr    r31, dc_flush           // flush Dcache
+
+       // build PS (IPL=7,CM=K,VMM=0,SW=0)
+       lda     r11, 0x7(r31)           // Set shadow copy of PS - kern mode, IPL=7
+       lda     r1, 0x1F(r31)           
+       mtpr    r1, ipl                 // set internal <ipl>=1F
+       mtpr    r31, ev5__ps                    // set new ps<cm>=0, Ibox copy
+       mtpr    r31, dtb_cm             // set new ps<cm>=0, Mbox copy
+
+       // Create the PALtemp pt_intmask -
+       //   MAP:
+       //      OSF IPL         EV5 internal IPL(hex)   note
+       //      0               0
+       //      1               1
+       //      2               2
+       //      3               14                      device
+       //      4               15                      device
+       //      5               16                      device  
+       //      6               1E                      device,performance counter, powerfail
+       //      7               1F
+       //
+       
+       ldah    r1, 0x1f1E(r31)         // Create upper lw of int_mask
+       lda     r1, 0x1615(r1)
+
+       sll     r1, 32, r1
+       ldah    r1, 0x1402(r1)          // Create lower lw of int_mask
+       
+       lda     r1, 0x0100(r1)
+       mtpr    r1, pt_intmask          // Stash in PALtemp
+
+       // Unlock a bunch of chip internal IPRs
+       mtpr    r31, exc_sum            // clear out exeception summary and exc_mask
+       mfpr    r31, va                 // unlock va, mmstat
+//rig  lda     r8, <<1@icperr_stat$v_dpe> ! <1@icperr_stat$v_tpe> ! <1@icperr_stat$v_tmr>>(r31)
+        lda     r8,(BIT(icperr_stat_v_dpe)|BIT(icperr_stat_v_tpe)|BIT(icperr_stat_v_tmr))(zero)
+        
+       mtpr    r8, icperr_stat                 // Clear Icache parity error & timeout status
+//orig lda     r8, <<1@dcperr_stat$v_lock> ! <1@dcperr_stat$v_seo>>(r31)
+        lda    r8,(BIT(dcperr_stat_v_lock)|BIT(dcperr_stat_v_seo))(r31)
+        
+        mtpr   r8, dcperr_stat                 // Clear Dcache parity error status
+
+       rc      r0                      // clear intr_flag
+       mtpr    r31, pt_trap
+
+       mfpr    r0, pt_misc
+       srl     r0, pt_misc_v_switch, r1
+       blbs    r1, sys_reset_switch    // see if we got here from swppal
+
+       // Rest of the "real" reset flow
+       // ASN
+       mtpr    r31, dtb_asn
+       mtpr    r31, itb_asn
+
+       lda     r1, 0x67(r31)
+       sll     r1, hwint_clr_v_pc0c, r1
+       mtpr    r1, hwint_clr           // Clear hardware interrupt requests
+
+       lda     r1, BIT(mces_v_dpc)(r31) // 1 in disable processor correctable error
+       mfpr    r0, pt1                 // get whami
+       insbl   r0, 1, r0               // isolate whami in correct pt_misc position
+       or      r0, r1, r1              // combine whami and mces
+       mtpr    r1, pt_misc             // store whami and mces, swap bit clear
+
+       zapnot  r3, 1, r0               // isolate halt code
+       mtpr    r0, pt0                 // save entry type
+
+       // Cycle counter
+       or      r31, 1, r9              // get a one
+       sll     r9, 32, r9              // shift to <32>
+       mtpr    r31, cc                 // clear Cycle Counter
+       mtpr    r9, cc_ctl              // clear and enable the Cycle Counter
+       mtpr    r31, pt_scc             // clear System Cycle Counter
+
+
+       // Misc PALtemps
+       mtpr    r31, maf_mode           // no mbox instructions for 3 cycles
+       or      r31, 1, r1              // get bogus scbb value
+       mtpr    r1, pt_scbb             // load scbb
+       mtpr    r31, pt_prbr            // clear out prbr
+#ifdef SIMOS
+//        or      zero,kludge_initial_pcbb,r1
+        GET_ADDR(r1, (kludge_initial_pcbb-pal_base), r1)
+#else
+       mfpr    r1, pal_base
+//orig sget_addr r1, (kludge_initial_pcbb-pal$base), r1, verify=0// get address for temp pcbb
+        GET_ADDR(r1, (kludge_initial_pcbb-pal_base), r1)
+#endif        
+       mtpr    r1, pt_pcbb             // load pcbb
+       lda     r1, 2(r31)              // get a two
+       sll     r1, 32, r1              // gen up upper bits
+       mtpr    r1, mvptbr
+       mtpr    r1, ivptbr
+       mtpr    r31, pt_ptbr
+       // Performance counters
+       mtpr    r31, pmctr      
+
+#if init_cbox != 0
+//  .if ne init_cbox
+       //   Only init the Scache and the Bcache if there have been no previous
+       //   cacheable  dstream loads or stores.
+       //
+       //   Inputs:
+        //       r5    - sc_ctl
+        //       r6    - bc_ctl
+        //       r7    - bc_cnfg
+
+       ldah    r0, 0xfff0(r31)
+       zap     r0, 0xE0, r0            // Get Cbox IPR base
+       ldqp    r19, ev5__sc_ctl(r0)    // read current sc_ctl
+temp = <<<1@bc_ctl$v_ei_dis_err> + <1@bc_ctl$v_ei_ecc_or_parity> + <1@bc_ctl$v_corr_fill_dat>>@-1>
+       lda     r20, temp(r31)          // create default bc_ctl (bc disabled, errors disabled, ecc mode)
+       sll     r20, 1, r20
+temp = 0x017441                                // default bc_config
+       get_addr r21, temp, r31         // create default bc_config
+       lda     r23, <1@sc_ctl_v_sc_flush>(r31) //set flag to invalidate scache in set_sc_bc_ctl
+
+// XXX bugnion pvc$jsr scbcctl, bsr=1
+       bsr     r10, set_sc_bc_ctl
+       update_bc_ctl_shadow r6, r23    // update bc_ctl shadow using r6 as input// r23 gets adjusted impure pointer
+       store_reg1 bc_config, r7, r23, ipr=1  // update bc_config shadow in impure area
+//  .endc
+#endif 
+       // Clear pmctr_ctl in impure area
+        
+#ifndef SIMOS
+        // can't assemble ???
+        update_pmctr_ctl r31, r1       // clear pmctr_ctl // r1 trashed
+#endif
+        
+       ldah    r14, 0xfff0(r31)
+       zap     r14, 0xE0, r14          // Get Cbox IPR base
+#ifndef SIMOS
+       ldqp    r31, sc_stat(r14)       // Clear sc_stat and sc_addr
+       ldqp    r31, ei_stat(r14)
+       ldqp    r31, ei_stat(r14)       // Clear ei_stat, ei_addr, bc_tag_addr, fill_syn
+#endif
+       GET_IMPURE(r13)
+       stqpc   r31, 0(r13)             // Clear lock_flag
+
+       mfpr    r0, pt0                 // get entry type
+       br      r31, sys_enter_console  // enter the cosole
+
+#endif /* rax_mode == 0 */
+
+
+
+\f
+//.if ne rax_mode
+#if rax_mode != 0
+
+       // For RAX:
+       //      r0    - icsr at first, then used for cbox ipr base offset
+       //      r2    - mcsr
+       //      r3    - dc_mode
+       //      r4    - maf_mode
+       //      r5    - sc_ctl
+       //      r6    - bc_ctl
+       //      r7    - bc_cnfg
+        .globl  sys_reset
+sys_reset:
+       mtpr    r31, ev5__dtb_cm        // set mbox mode to kernel
+        mtpr   r31, ev5__ps            // set Ibox mode to kernel - E1 
+
+        mtpr   r0, ev5__icsr           // Load ICSR - E1 
+
+        mtpr    r2, ev5__mcsr
+       mfpr    r8, pal_base
+       
+       ldah    r0, 0xfff0(r31)
+       zap     r0, 0xE0, r0            // Get Cbox IPR base
+       
+       mtpr    r31, ev5__itb_asn       // clear asn - E1 
+       ldqp    r19, ev5__sc_ctl(r0)    // read current sc_ctl
+
+temp = <<<1@bc_ctl$v_ei_dis_err> + <1@bc_ctl$v_ei_ecc_or_parity> + <1@bc_ctl$v_corr_fill_dat>>@-1>
+       lda     r20, temp(r31)          // create default bc_ctl (bc disabled, errors disabled, ecc mode)
+       sll     r20, 1, r20
+
+temp = 0x017441                                // default bc_config
+       get_addr r21, temp, r31         // create default bc_config
+       lda     r23, <1@sc_ctl_v_sc_flush>(r31) //set flag to invalidate scache in set_sc_bc_ctl
+
+// XXX bugnion pvc$jsr scbcctl, bsr=1
+       bsr     r10, set_sc_bc_ctl
+       update_bc_ctl_shadow    r6, r2  // initialize bc_ctl shadow// adjusted impure pointer in r2
+       store_reg1      pmctr_ctl, r31, r2, ipr=1       // clear pmctr_ctl 
+       store_reg1      bc_config, r7, r2, ipr=1        // initialize bc_config shadow
+
+       mtpr    r3, ev5__dc_mode        // write dc_mode
+       mtpr    r31, ev5__dc_flush      // flush dcache
+
+       mtpr    r31, ev5__exc_sum       // clear exc_sum - E1 
+       mtpr    r31, ev5__exc_mask      // clear exc_mask - E1 
+
+       ldah    r2, 4(r31)              // For EXC_ADDR
+       mtpr    r2, ev5__exc_addr       // EXC_ADDR to 40000 (hex)
+
+       mtpr    r31, ev5__sirr          // Clear SW interrupts (for ISP)
+       mtpr    r4, ev5__maf_mode       // write maf_mode
+
+       mtpr    r31, ev5__alt_mode      // set alt_mode to kernel
+        mtpr   r31, ev5__itb_ia        // clear ITB - E1 
+
+       lda     r1, 0x1F(r31)           // For IPL
+       mtpr    r1, ev5__ipl            // IPL to 1F
+
+       mtpr    r31, ev5__hwint_clr     // clear hardware interrupts
+       mtpr    r31, ev5__aster         // disable AST interrupts
+
+       mtpr    r31, ev5__astrr         // clear AST requests
+       mtpr    r31, ev5__dtb_ia        // clear dtb
+
+       nop
+       mtpr    r31, pt_trap
+
+       srl     r2, page_offset_size_bits, r9   // Start to make PTE for address 40000
+        sll     r9, 32, r9
+
+        lda     r9, 0x7F01(r9)          // Make PTE, V set, all RE set, all but UWE set
+       nop
+
+       mtpr    r9, dtb_pte             // ACORE hack, load TB with 1-1 translation for address 40000
+       mtpr    r2, itb_tag             // ACORE hack, load TB with 1-1 translation for address 40000
+       
+       mtpr    r2, dtb_tag
+       mtpr    r9, itb_pte
+
+       and     r31, r31, r0            // clear deposited registers, note: r2 already overwritten
+       and     r31, r31, r3
+
+       and     r31, r31, r4
+       and     r31, r31, r5
+
+       and     r31, r31, r6
+       and     r31, r31, r7
+
+       hw_rei                          //May need to be a rei_stall since
+                                       //we write to TB's above
+                                       //However, it currently works ok. (JH)
+
+
+// .endc
+#endif /*rax_mode != 0 */
+
+\f
+       // swppal entry
+       // r0 - pt_misc
+       // r17 - new PC
+       // r18 - new PCBB
+       // r19 - new VPTB
+sys_reset_switch:
+       or      r31, 1, r9
+       sll     r9, pt_misc_v_switch, r9
+       bic     r0, r9, r0              // clear switch bit
+       mtpr    r0, pt_misc
+
+       rpcc    r1                      // get cyccounter
+
+       ldqp    r22, osfpcb_q_fen(r18)  // get new fen/pme
+       ldlp    r23, osfpcb_l_cc(r18)   // get cycle counter
+       ldlp    r24, osfpcb_l_asn(r18)  // get new asn
+
+
+       ldqp    r25, osfpcb_q_Mmptr(r18)// get new mmptr
+       sll     r25, page_offset_size_bits, r25 // convert pfn to pa
+       mtpr    r25, pt_ptbr            // load the new mmptr
+       mtpr    r18, pt_pcbb            // set new pcbb
+
+       bic     r17, 3, r17             // clean use pc
+       mtpr    r17, exc_addr           // set new pc
+       mtpr    r19, mvptbr
+       mtpr    r19, ivptbr
+
+       ldqp    r30, osfpcb_q_Usp(r18)  // get new usp
+       mtpr    r30, pt_usp             // save usp
+       
+       sll     r24, dtb_asn_v_asn, r8
+       mtpr    r8, dtb_asn
+       sll     r24, itb_asn_v_asn, r24
+       mtpr    r24, itb_asn
+
+       mfpr    r25, icsr               // get current icsr
+       lda     r24, 1(r31)
+       sll     r24, icsr_v_fpe, r24    // 1 in icsr<fpe> position
+       bic     r25, r24, r25           // clean out old fpe
+       and     r22, 1, r22             // isolate new fen bit
+       sll     r22, icsr_v_fpe, r22
+       or      r22, r25, r25           // or in new fpe
+       mtpr    r25, icsr               // update ibox ipr
+
+       subl    r23, r1, r1             // gen new cc offset
+       insll   r1, 4, r1               // << 32
+       mtpr    r1, cc                  // set new offset
+
+       or      r31, r31, r0            // set success
+       ldqp    r30, osfpcb_q_Ksp(r18)  // get new ksp
+       mfpr    r31, pt0                // stall
+       hw_rei_stall
+\f
+// .sbttl      "SYS_MACHINE_CHECK - Machine check PAL"
+       ALIGN_BLOCK
+//+
+//sys$machine_check
+//     A machine_check trap has occurred.  The Icache has been flushed.
+//
+//-
+
+EXPORT(sys_machine_check)
+                                               // Need to fill up the refill buffer (32 instructions) and
+                                               // then flush the Icache again.
+                                               // Also, due to possible 2nd Cbox register file write for
+                                               // uncorrectable errors, no register file read or write for 7 cycles.
+
+       nop
+       mtpr    r0, pt0                         // Stash for scratch -- OK if Cbox overwrites r0 later
+
+       nop
+       nop
+
+       nop
+       nop
+
+       nop
+       nop
+
+       nop
+       nop
+                                               // 10 instructions// 5 cycles
+
+       nop
+       nop
+
+       nop
+       nop
+
+                                               // Register file can now be written
+       lda     r0, scb_v_procmchk(r31)         // SCB vector
+       mfpr    r13, pt_mces                    // Get MCES
+       sll     r0, 16, r0                      // Move SCBv to correct position
+//     bis     r13, #<1@mces$v_mchk>, r14      // Set MCES<MCHK> bit
+       bis     r13, BIT(mces_v_mchk), r14      // Set MCES<MCHK> bit
+
+
+       zap     r14, 0x3C, r14                  // Clear mchk_code word and SCBv word 
+       mtpr    r14, pt_mces
+                                               // 20 instructions
+
+       nop
+       or      r14, r0, r14                    // Insert new SCB vector
+       lda     r0, mchk_c_proc_hrd_error(r31)  // MCHK code
+       mfpr    r12, exc_addr
+
+       sll     r0, 32, r0                      // Move MCHK code to correct position
+       mtpr    r4, pt4
+       or      r14, r0, r14                    // Insert new MCHK code
+       mtpr    r14, pt_misc                    // Store updated MCES, MCHK code, and SCBv
+
+       ldah    r14, 0xfff0(r31)
+       mtpr    r1, pt1                         // Stash for scratch - 30 instructions
+
+       zap     r14, 0xE0, r14                  // Get Cbox IPR base
+       mtpr    r12, pt10                       // Stash exc_addr
+
+
+
+       mtpr    r31, ic_flush_ctl                       // Second Icache flush, now it is really flushed.
+       blbs    r13, sys_double_machine_check           // MCHK halt if double machine check
+
+       mtpr    r6, pt6
+       mtpr    r5, pt5
+
+       // Look for the powerfail cases here....
+       mfpr    r4, isr
+       srl     r4, isr_v_pfl, r4
+       blbc    r4, sys_mchk_collect_iprs       // skip if no powerfail interrupt pending
+       lda     r4, 0xffc4(r31)                 // get GBUS$MISCR address bits
+       sll     r4, 24, r4                      // shift to proper position
+       ldqp    r4, 0(r4)                       // read GBUS$MISCR
+       srl     r4, 5, r4                       // isolate bit <5>
+       blbc    r4, sys_mchk_collect_iprs       // skip if already cleared
+                                               // No missed CFAIL mchk
+       lda     r5, 0xffc7(r31)                 // get GBUS$SERNUM address bits
+       sll     r5, 24, r5                      // shift to proper position
+       lda     r6, 0x40(r31)                   // get bit <6> mask
+       ldqp    r4, 0(r5)                       // read GBUS$SERNUM
+       or      r4, r6, r6                      // set bit <6>
+       stqp    r6, 0(r5)                       // clear GBUS$SERNUM<6>
+       mb
+       mb
+
+\f      
+       //+
+       // Start to collect the IPRs.  Common entry point for mchk flows.
+       //
+       // Current state:
+       //      pt0     - saved r0
+       //      pt1     - saved r1
+       //      pt4     - saved r4
+       //      pt5     - saved r5
+       //      pt6     - saved r6
+       //      pt10    - saved exc_addr
+       //      pt_misc<47:32> - mchk code 
+       //      pt_misc<31:16> - scb vector
+       //      r14     - base of Cbox IPRs in IO space
+       //      r0, r1, r4, r5, r6, r12, r13, r25 - available
+       //      r8, r9, r10 - available as all loads are physical
+       //      MCES<mchk> is set
+       //
+       //-
+
+EXPORT(sys_mchk_collect_iprs)
+       mb                                              // MB before reading Scache IPRs
+       mfpr    r1, icperr_stat
+
+       mfpr    r8, dcperr_stat
+       mtpr    r31, dc_flush                           // Flush the Dcache
+       
+       mfpr    r31, pt0                                // Pad Mbox instructions from dc_flush
+       mfpr    r31, pt0
+       nop
+       nop
+
+       ldqp    r9, sc_addr(r14)                        // SC_ADDR IPR
+       bis     r9, r31, r31                            // Touch ld to make sure it completes before
+                                                       // read of SC_STAT
+       ldqp    r10, sc_stat(r14)                       // SC_STAT, also unlocks SC_ADDR
+
+       ldqp    r12, ei_addr(r14)                       // EI_ADDR IPR
+       ldqp    r13, bc_tag_addr(r14)                   // BC_TAG_ADDR IPR
+       ldqp    r0, fill_syn(r14)                       // FILL_SYN IPR
+       bis     r12, r13, r31                           // Touch lds to make sure they complete before reading EI_STAT
+       bis     r0, r0, r31                             // Touch lds to make sure they complete before reading EI_STAT
+       ldqp    r25, ei_stat(r14)                       // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
+       ldqp    r31, ei_stat(r14)                       // Read again to insure it is unlocked
+
+
+       
+\f
+       //+
+       // Look for nonretryable cases
+       // In this segment:
+       //      r5<0> = 1 means retryable
+       //      r4, r6, and r14 are available for scratch
+       //
+       //-
+
+
+       bis     r31, r31, r5                            // Clear local retryable flag
+       srl     r25, ei_stat_v_bc_tperr, r25            // Move EI_STAT status bits to low bits
+       
+       lda     r4, 1(r31)
+       sll     r4, icperr_stat_v_tmr, r4
+       and     r1, r4, r4                              // Timeout reset
+       bne     r4, sys_cpu_mchk_not_retryable
+
+       and     r8, BIT(dcperr_stat_v_lock), r4         // DCache parity error locked
+       bne     r4, sys_cpu_mchk_not_retryable
+
+       lda     r4, 1(r31)
+       sll     r4, sc_stat_v_sc_scnd_err, r4
+       and     r10, r4, r4                             // 2nd Scache error occurred
+       bne     r4, sys_cpu_mchk_not_retryable
+       
+
+       bis     r31, 0xa3, r4                           // EI_STAT Bcache Tag Parity Error, Bcache Tag Control
+                                                       // Parity Error, Interface Parity Error, 2nd Error
+
+       and     r25, r4, r4
+       bne     r4, sys_cpu_mchk_not_retryable
+       
+//     bis     r31, #<1@<ei_stat$v_unc_ecc_err-ei_stat$v_bc_tperr>>, r4
+       bis     r31, BIT((ei_stat_v_unc_ecc_err-ei_stat_v_bc_tperr)), r4
+       and     r25, r4, r4                             // Isolate the Uncorrectable Error Bit
+//     bis     r31, #<1@<ei_stat$v_fil_ird-ei_stat$v_bc_tperr>>, r6
+       bis     r31, BIT((ei_stat_v_fil_ird-ei_stat_v_bc_tperr)), r6 // Isolate the Iread bit
+       cmovne  r6, 0, r4                               // r4 = 0 if IRD or if No Uncorrectable Error
+        bne     r4, sys_cpu_mchk_not_retryable         
+
+       lda     r4, 7(r31)
+       and     r10, r4, r4                             // Isolate the Scache Tag Parity Error bits
+       bne     r4, sys_cpu_mchk_not_retryable          // All Scache Tag PEs are not retryable
+
+
+       lda     r4, 0x7f8(r31)
+       and     r10, r4, r4                             // Isolate the Scache Data Parity Error bits
+       srl     r10, sc_stat_v_cbox_cmd, r6
+       and     r6, 0x1f, r6                            // Isolate Scache Command field
+       subq    r6, 1, r6                               // Scache Iread command = 1
+       cmoveq  r6, 0, r4                               // r4 = 0 if IRD or if No Parity Error
+        bne     r4, sys_cpu_mchk_not_retryable
+
+       // Look for the system unretryable cases here....
+
+       mfpr    r4, isr                                 // mchk_interrupt pin asserted
+       srl     r4, isr_v_mck, r4
+       blbs    r4, sys_cpu_mchk_not_retryable
+
+
+\f
+       //+
+       // Look for retryable cases
+       // In this segment:
+       //      r5<0> = 1 means retryable
+       //      r6 - holds the mchk code
+       //      r4 and r14 are available for scratch
+       //
+       //-
+
+
+       // Within the chip, the retryable cases are Istream errors
+       lda     r4, 3(r31)
+       sll     r4, icperr_stat_v_dpe, r4
+       and     r1, r4, r4
+       cmovne  r4, 1, r5                               // Retryable if just Icache parity error
+
+
+       lda     r4, 0x7f8(r31)
+       and     r10, r4, r4                             // Isolate the Scache Data Parity Error bits
+       srl     r10, sc_stat_v_cbox_cmd, r14
+       and     r14, 0x1f, r14                          // Isolate Scache Command field
+       subq    r14, 1, r14                             // Scache Iread command = 1
+       cmovne  r4, 1, r4                               // r4 = 1 if Scache data parity error bit set
+       cmovne  r14, 0, r4                              // r4 = 1 if Scache PE and Iread
+       bis     r4, r5, r5                              // Accumulate
+
+
+       bis     r31, BIT((ei_stat_v_unc_ecc_err-ei_stat_v_bc_tperr)), r4
+       and     r25, r4, r4                             // Isolate the Uncorrectable Error Bit
+       and     r25, BIT((ei_stat_v_fil_ird-ei_stat_v_bc_tperr)), r14 // Isolate the Iread bit
+       cmovne  r4, 1, r4                               // r4 = 1 if uncorr error
+       cmoveq  r14, 0, r4                              // r4 = 1 if uncorr and Iread
+       bis     r4, r5, r5                              // Accumulate
+
+       mfpr    r6, pt_misc
+       extwl   r6, 4, r6                               // Fetch mchk code
+       bic     r6, 1, r6                               // Clear flag from interrupt flow
+       cmovne  r5, mchk_c_retryable_ird, r6            // Set mchk code 
+
+
+
+       // In the system, the retryable cases are ...
+       // (code here handles beh model read NXM)
+
+#if beh_model != 0        
+//     .if ne beh_model
+       ldah    r4, 0xC000(r31)                 // Get base of demon space
+       lda     r4, 0x550(r4)                   // Add NXM demon flag offset
+       
+       ldqp    r4, 0(r4)                       // Read the demon register
+       lda     r14, mchk_c_read_nxm(r31) 
+       cmovlbs r4, r14, r6                     // Set mchk code if read NXM
+       cmovlbs r4, 1, r4                       
+       bis     r4, r5, r5                      // Accumulate retry bit
+#endif
+
+\f
+       //+
+       // Write the logout frame
+       //
+       // Current state:
+       //      r0      - fill_syn
+       //      r1      - icperr_stat
+       //      r4      - available
+       //      r5<0>   - retry flag
+       //      r6      - mchk code
+       //      r8      - dcperr_stat
+       //      r9      - sc_addr
+       //      r10     - sc_stat
+       //      r12     - ei_addr
+       //      r13     - bc_tag_addr
+       //      r14     - available
+       //      r25     - ei_stat (shifted)
+       //      pt0     - saved r0
+       //      pt1     - saved r1
+       //      pt4     - saved r4
+       //      pt5     - saved r5
+       //      pt6     - saved r6
+       //      pt10    - saved exc_addr
+       //
+       //-
+
+sys_mchk_write_logout_frame:
+       // Get base of the logout area.  
+       GET_IMPURE(r14)                          // addr of per-cpu impure area
+       GET_ADDR(r14,pal_logout_area+mchk_mchk_base,r14)
+
+       // Write the first 2 quadwords of the logout area:
+       
+       sll     r5, 63, r5                              // Move retry flag to bit 63
+       lda     r4, mchk_size(r5)                       // Combine retry flag and frame size
+       stqp    r4, mchk_flag(r14)                      // store flag/frame size
+       lda     r4, mchk_sys_base(r31)                  // sys offset
+       sll     r4, 32, r4
+       lda     r4, mchk_cpu_base(r4)                   // cpu offset
+       stqp    r4, mchk_offsets(r14)                   // store sys offset/cpu offset into logout frame
+
+       //+
+       // Write the mchk code to the logout area
+       // Write error IPRs already fetched to the logout area
+       // Restore some GPRs from PALtemps
+       //-
+
+       mfpr    r5, pt5
+       stqp    r6, mchk_mchk_code(r14)
+       mfpr    r4, pt4
+       stqp    r1, mchk_ic_perr_stat(r14)
+       mfpr    r6, pt6
+       stqp    r8, mchk_dc_perr_stat(r14)
+       mfpr    r1, pt1
+       stqp    r9, mchk_sc_addr(r14)           
+       stqp    r10, mchk_sc_stat(r14)          
+       stqp    r12, mchk_ei_addr(r14)
+       stqp    r13, mchk_bc_tag_addr(r14)
+       stqp    r0,  mchk_fill_syn(r14)
+       mfpr    r0, pt0
+       sll     r25, ei_stat_v_bc_tperr, r25            // Move EI_STAT status bits back to expected position
+       // retrieve lower 28 bits again from ei_stat and restore before storing to logout frame
+       ldah    r13, 0xfff0(r31)
+       zapnot  r13, 0x1f, r13
+       ldqp    r13, ei_stat(r13)
+       sll     r13, 64-ei_stat_v_bc_tperr, r13
+       srl     r13, 64-ei_stat_v_bc_tperr, r13
+       or      r25, r13, r25
+       stqp    r25, mchk_ei_stat(r14)
+
+        
+
+\f
+       //+
+       // complete the CPU-specific part of the logout frame
+       //-
+
+#ifndef SIMOS
+        // cant' assemble.Where is the macro ?        
+       mchk_logout     mm_stat
+       mchk_logout     va                      // Unlocks VA and MM_STAT
+       mchk_logout     isr
+       mchk_logout     icsr
+       mchk_logout     pal_base
+       mchk_logout     exc_mask
+       mchk_logout     exc_sum
+#endif
+
+       ldah    r13, 0xfff0(r31)
+       zap     r13, 0xE0, r13                  // Get Cbox IPR base
+       ldqp    r13, ld_lock(r13)               // Get ld_lock IPR
+       stqp    r13, mchk_ld_lock(r14)          // and stash it in the frame
+
+       //+
+       // complete the PAL-specific part of the logout frame
+       //-
+#ifdef vms
+       t = 0           
+         .repeat 24
+         pt_mchk_logout \t
+         t = t + 1
+         .endr
+#endif
+#ifndef SIMOS
+        //can't assemble ?
+        pt_mchk_logout 0
+        pt_mchk_logout 1
+        pt_mchk_logout 2
+        pt_mchk_logout 3
+        pt_mchk_logout 4
+        pt_mchk_logout 5
+        pt_mchk_logout 6
+        pt_mchk_logout 7
+        pt_mchk_logout 8
+        pt_mchk_logout 9
+        pt_mchk_logout 10
+        pt_mchk_logout 11
+        pt_mchk_logout 12
+        pt_mchk_logout 13
+        pt_mchk_logout 14
+        pt_mchk_logout 15
+        pt_mchk_logout 16
+        pt_mchk_logout 17
+        pt_mchk_logout 18
+        pt_mchk_logout 19
+        pt_mchk_logout 20
+        pt_mchk_logout 21
+        pt_mchk_logout 22
+        pt_mchk_logout 23
+#endif      
+
+        
+       //+
+       // Log system specific info here
+       //-
+
+#if alpha_fw != 0        
+//     .if ne alpha_fw
+storeTLEP_:
+       lda     r13, 0xffc4(r31)                // Get GBUS$MISCR address
+       sll     r13, 24, r13
+       ldqp    r13, 0(r13)                     // Read GBUS$MISCR 
+       sll     r13, 16, r13                    // shift up to proper field
+       mfpr    r8, pt_whami                    // get our node id
+       extbl   r8, 1, r8                       // shift to bit 0
+       or      r13, r8, r13                    // merge MISCR and WHAMI
+       stlp    r13, mchk$gbus(r14)             // write to logout area
+       srl     r8, 1, r8                       // shift off cpu number
+
+       Get_TLSB_Node_Address r8,r13            // compute our nodespace address
+
+       OSFmchk_TLEPstore       tldev, tlsb=1
+       OSFmchk_TLEPstore       tlber, tlsb=1, clr=1
+       OSFmchk_TLEPstore       tlcnr, tlsb=1
+       OSFmchk_TLEPstore       tlvid, tlsb=1
+       OSFmchk_TLEPstore       tlesr0, tlsb=1, clr=1
+       OSFmchk_TLEPstore       tlesr1, tlsb=1, clr=1
+       OSFmchk_TLEPstore       tlesr2, tlsb=1, clr=1
+       OSFmchk_TLEPstore       tlesr3, tlsb=1, clr=1
+       OSFmchk_TLEPstore       tlmodconfig
+       OSFmchk_TLEPstore       tlepaerr, clr=1
+       OSFmchk_TLEPstore       tlepderr, clr=1
+       OSFmchk_TLEPstore       tlepmerr, clr=1
+       OSFmchk_TLEPstore       tlintrmask0
+       OSFmchk_TLEPstore       tlintrmask1
+       OSFmchk_TLEPstore       tlintrsum0
+       OSFmchk_TLEPstore       tlintrsum1
+       OSFmchk_TLEPstore       tlep_vmg
+//     .endc
+#endif  /*alpha_fw != 0 */
+       // Unlock IPRs
+       lda     r8, (BIT(dcperr_stat_v_lock)|BIT(dcperr_stat_v_seo))(r31)
+       mtpr    r8, dcperr_stat                 // Clear Dcache parity error status
+
+       lda     r8, (BIT(icperr_stat_v_dpe)|BIT(icperr_stat_v_tpe)|BIT(icperr_stat_v_tmr))(r31)
+       mtpr    r8, icperr_stat                 // Clear Icache parity error & timeout status
+
+1:     ldqp    r8, mchk_ic_perr_stat(r14)      // get ICPERR_STAT value
+       GET_ADDR(r0,0x1800,r31)         // get ICPERR_STAT value
+       and     r0, r8, r0                      // compare 
+       beq     r0, 2f                          // check next case if nothing set
+       lda     r0, mchk_c_retryable_ird(r31)   // set new MCHK code
+       br      r31, do_670                     // setup new vector
+
+2:     ldqp    r8, mchk_dc_perr_stat(r14)      // get DCPERR_STAT value
+       GET_ADDR(r0,0x3f,r31)                   // get DCPERR_STAT value
+       and     r0, r8, r0                      // compare 
+       beq     r0, 3f                          // check next case if nothing set
+       lda     r0, mchk_c_dcperr(r31)          // set new MCHK code
+       br      r31, do_670                     // setup new vector
+
+3:     ldqp    r8, mchk_sc_stat(r14)           // get SC_STAT value
+       GET_ADDR(r0,0x107ff,r31)                // get SC_STAT value
+       and     r0, r8, r0                      // compare 
+       beq     r0, 4f                          // check next case if nothing set
+       lda     r0, mchk_c_scperr(r31)          // set new MCHK code
+       br      r31, do_670                     // setup new vector
+
+4:     ldqp    r8, mchk_ei_stat(r14)           // get EI_STAT value
+       GET_ADDR(r0,0x30000000,r31)             // get EI_STAT value
+       and     r0, r8, r0                      // compare 
+       beq     r0, 5f                          // check next case if nothing set
+       lda     r0, mchk_c_bcperr(r31)          // set new MCHK code
+       br      r31, do_670                     // setup new vector
+
+5:     ldlp    r8, mchk_tlber(r14)             // get TLBER value
+       GET_ADDR(r0,0xfe01,r31)                 // get high TLBER mask value
+       sll     r0, 16, r0                      // shift into proper position
+       GET_ADDR(r1,0x03ff,r31)                 // get low TLBER mask value
+       or      r0, r1, r0                      // merge mask values
+       and     r0, r8, r0                      // compare 
+       beq     r0, 6f                          // check next case if nothing set
+       GET_ADDR(r0, 0xfff0, r31)               // set new MCHK code
+       br      r31, do_660                     // setup new vector
+
+6:     ldlp    r8, mchk_tlepaerr(r14)          // get TLEPAERR value
+       GET_ADDR(r0,0xff7f,r31)                 // get TLEPAERR mask value
+       and     r0, r8, r0                      // compare 
+       beq     r0, 7f                          // check next case if nothing set
+       GET_ADDR(r0, 0xfffa, r31)               // set new MCHK code
+       br      r31, do_660                     // setup new vector
+
+7:     ldlp    r8, mchk_tlepderr(r14)          // get TLEPDERR value
+       GET_ADDR(r0,0x7,r31)                    // get TLEPDERR mask value
+       and     r0, r8, r0                      // compare 
+       beq     r0, 8f                          // check next case if nothing set
+       GET_ADDR(r0, 0xfffb, r31)               // set new MCHK code
+       br      r31, do_660                     // setup new vector
+
+8:     ldlp    r8, mchk_tlepmerr(r14)          // get TLEPMERR value
+       GET_ADDR(r0,0x3f,r31)                   // get TLEPMERR mask value
+       and     r0, r8, r0                      // compare 
+       beq     r0, 9f                          // check next case if nothing set
+       GET_ADDR(r0, 0xfffc, r31)               // set new MCHK code
+       br      r31, do_660                     // setup new vector
+
+9:     ldqp    r8, mchk_ei_stat(r14)           // get EI_STAT value
+       GET_ADDR(r0,0xb,r31)                    // get EI_STAT mask value
+       sll     r0, 32, r0                      // shift to upper lw
+       and     r0, r8, r0                      // compare 
+       beq     r0, 1f                          // check next case if nothing set
+       GET_ADDR(r0,0xfffd,r31)                 // set new MCHK code
+       br      r31, do_660                     // setup new vector
+
+1:     ldlp    r8, mchk_tlepaerr(r14)          // get TLEPAERR value
+       GET_ADDR(r0,0x80,r31)                   // get TLEPAERR mask value
+       and     r0, r8, r0                      // compare 
+       beq     r0, cont_logout_frame           // check next case if nothing set
+       GET_ADDR(r0, 0xfffe, r31)               // set new MCHK code
+       br      r31, do_660                     // setup new vector
+
+do_670:        lda     r8, scb_v_procmchk(r31)         // SCB vector
+       br      r31, do_6x0_cont
+do_660:        lda     r8, scb_v_sysmchk(r31)          // SCB vector
+do_6x0_cont:
+       sll     r8, 16, r8                      // shift to proper position
+       mfpr    r1, pt_misc                     // fetch current pt_misc
+       GET_ADDR(r4,0xffff, r31)                // mask for vector field
+       sll     r4, 16, r4                      // shift to proper position
+       bic     r1, r4, r1                      // clear out old vector field
+       or      r1, r8, r1                      // merge in new vector
+       mtpr    r1, pt_misc                     // save new vector field
+       stlp    r0, mchk_mchk_code(r14)         // save new mchk code
+
+cont_logout_frame:
+       // Restore some GPRs from PALtemps
+       mfpr    r0, pt0
+       mfpr    r1, pt1
+       mfpr    r4, pt4
+
+       mfpr    r12, pt10                       // fetch original PC
+       blbs    r12, sys_machine_check_while_in_pal     // MCHK halt if machine check in pal
+
+//XXXbugnion        pvc_jsr armc, bsr=1
+        bsr     r12, sys_arith_and_mchk        // go check for and deal with arith trap
+
+       mtpr    r31, exc_sum                    // Clear Exception Summary
+
+       mfpr    r25, pt10                       // write exc_addr after arith_and_mchk to pickup new pc
+       stqp    r25, mchk_exc_addr(r14)
+
+       //+
+       // Set up the km trap
+       //-
+
+        
+sys_post_mchk_trap:
+       mfpr    r25, pt_misc            // Check for flag from mchk interrupt
+       extwl   r25, 4, r25
+       blbs    r25, sys_mchk_stack_done // Stack from already pushed if from interrupt flow
+       
+       bis     r14, r31, r12           // stash pointer to logout area
+       mfpr    r14, pt10               // get exc_addr
+
+       sll     r11, 63-3, r25          // get mode to msb
+       bge     r25, 3f 
+
+       mtpr    r31, dtb_cm
+       mtpr    r31, ev5__ps
+
+       mtpr    r30, pt_usp             // save user stack
+       mfpr    r30, pt_ksp
+
+3:      
+       lda     sp, 0-osfsf_c_size(sp)  // allocate stack space         
+       nop
+
+       stq     r18, osfsf_a2(sp)       // a2
+       stq     r11, osfsf_ps(sp)       // save ps
+
+       stq     r14, osfsf_pc(sp)       // save pc
+       mfpr    r25, pt_entint          // get the VA of the interrupt routine
+
+       stq     r16, osfsf_a0(sp)       // a0
+       lda     r16, osfint_c_mchk(r31) // flag as mchk in a0
+
+       stq     r17, osfsf_a1(sp)       // a1
+       mfpr    r17, pt_misc            // get vector
+
+       stq     r29, osfsf_gp(sp)       // old gp
+       mtpr    r25, exc_addr           // 
+
+       or      r31, 7, r11             // get new ps (km, high ipl)
+       subq    r31, 1, r18             // get a -1
+
+       extwl   r17, 2, r17             // a1 <- interrupt vector
+       bis     r31, ipl_machine_check, r25
+
+       mtpr    r25, ipl                // Set internal ipl
+       srl     r18, 42, r18            // shift off low bits of kseg addr
+
+       sll     r18, 42, r18            // shift back into position
+       mfpr    r29, pt_kgp             // get the kern r29
+
+        or     r12, r18, r18           // EV4 algorithm - pass pointer to mchk frame as kseg address
+       hw_rei_spe                      // out to interrupt dispatch routine
+
+\f
+       //+
+       // The stack is pushed.  Load up a0,a1,a2 and vector via entInt
+       //
+       //-
+       ALIGN_BRANCH
+sys_mchk_stack_done:
+       lda     r16, osfint_c_mchk(r31) // flag as mchk/crd in a0
+       lda     r17, scb_v_sysmchk(r31) // a1 <- interrupt vector
+
+        subq    r31, 1, r18            // get a -1
+       mfpr    r25, pt_entInt
+
+        srl     r18, 42, r18           // shift off low bits of kseg addr
+       mtpr    r25, exc_addr           // load interrupt vector
+
+        sll     r18, 42, r18           // shift back into position
+        or     r14, r18, r18           // EV4 algorithm - pass pointer to mchk frame as kseg address
+       
+       hw_rei_spe                      // done
+
+
+       ALIGN_BRANCH
+sys_cpu_mchk_not_retryable:
+       mfpr    r6, pt_misc
+       extwl   r6, 4, r6                               // Fetch mchk code
+       br      r31,  sys_mchk_write_logout_frame       //
+       
+
+\f
+//+
+//sys$double_machine_check - a machine check was started, but MCES<MCHK> was
+//     already set.  We will now double machine check halt.
+//
+//     pt0 - old R0
+//
+//+
+        
+EXPORT(sys_double_machine_check)
+#ifndef SIMOS
+        pvc$jsr updpcb, bsr=1
+        bsr    r0, pal_update_pcb       // update the pcb
+#endif
+       lda     r0, hlt_c_dbl_mchk(r31)
+       br      r31, sys_enter_console
+
+//+
+//sys$machine_check_while_in_pal - a machine check was started, exc_addr points to
+//     a PAL PC.  We will now machine check halt.
+//
+//     pt0 - old R0
+//
+//+
+sys_machine_check_while_in_pal:
+       stqp    r12, mchk_exc_addr(r14)         // exc_addr has not yet been written
+
+#ifndef SIMOS
+        pvc$jsr updpcb, bsr=1
+        bsr    r0, pal_update_pcb       // update the pcb
+#endif
+       lda     r0, hlt_c_mchk_from_pal(r31)
+       br      r31, sys_enter_console
+
+
+//ARITH and MCHK
+//  Check for arithmetic errors and build trap frame,
+//  but don't post the trap.
+//  on entry:
+//     pt10 - exc_addr
+//     r12  - return address
+//     r14  - logout frame pointer
+//     r13 - available
+//     r8,r9,r10 - available except across stq's
+//     pt0,1,6 - available
+//
+//  on exit:
+//     pt10 - new exc_addr
+//     r17 = exc_mask
+//     r16 = exc_sum
+//     r14 - logout frame pointer
+//
+       ALIGN_BRANCH
+sys_arith_and_mchk:
+       mfpr    r13, ev5__exc_sum
+       srl     r13, exc_sum_v_swc, r13
+       bne     r13, handle_arith_and_mchk
+
+// XXX bugnion        pvc$jsr armc, bsr=1, dest=1
+        ret     r31, (r12)              // return if no outstanding arithmetic error
+
+handle_arith_and_mchk:
+        mtpr    r31, ev5__dtb_cm        // Set Mbox current mode to kernel -
+                                        //     no virt ref for next 2 cycles
+       mtpr    r14, pt0        
+
+       mtpr    r1, pt1                 // get a scratch reg
+       and     r11, osfps_m_mode, r1 // get mode bit
+
+       bis     r11, r31, r25           // save ps
+        beq     r1, 1f                 // if zero we are in kern now
+
+        bis     r31, r31, r25           // set the new ps
+        mtpr    r30, pt_usp             // save user stack
+
+        mfpr    r30, pt_ksp             // get kern stack
+1: 
+        mfpr    r14, exc_addr           // get pc into r14 in case stack writes fault
+
+       lda     sp, 0-osfsf_c_size(sp)  // allocate stack space
+        mtpr    r31, ev5__ps            // Set Ibox current mode to kernel
+
+        mfpr    r1, pt_entArith
+        stq     r14, osfsf_pc(sp)       // save pc
+
+        stq     r17, osfsf_a1(sp)
+        mfpr    r17, ev5__exc_mask      // Get exception register mask IPR - no mtpr exc_sum in next cycle
+
+        stq     r29, osfsf_gp(sp)
+        stq     r16, osfsf_a0(sp)       // save regs
+
+       bis     r13, r31, r16           // move exc_sum to r16
+        stq     r18, osfsf_a2(sp)
+
+        stq     r11, osfsf_ps(sp)       // save ps
+        mfpr    r29, pt_kgp             // get the kern gp
+
+       mfpr    r14, pt0                // restore logout frame pointer from pt0
+        bis     r25, r31, r11           // set new ps
+
+        mtpr    r1, pt10               // Set new PC
+       mfpr    r1, pt1
+
+// XXX bugnion        pvc$jsr armc, bsr=1, dest=1
+        ret     r31, (r12)              // return if no outstanding arithmetic error
+
+
+\f
+// .sbttl      "SYS$ENTER_CONSOLE - Common PALcode for ENTERING console"
+
+       ALIGN_BLOCK
+
+// SYS$enter_console
+//
+// Entry:
+//     Entered when PAL wants to enter the console.
+//     usually as the result of a HALT instruction or button,
+//     or catastrophic error.
+//
+// Regs on entry...
+//
+//     R0      = halt code
+//     pt0     <- r0
+//
+// Function:
+//
+//     Save all readable machine state, and "call" the console
+//     
+// Returns:
+//
+//
+// Notes:
+//
+//     In these routines, once the save state routine has been executed,
+//     the remainder of the registers become scratchable, as the only
+//     "valid" copy of them is the "saved" copy.
+//
+//     Any registers or PTs that are modified before calling the save 
+//     routine will have there data lost. The code below will save all
+//     state, but will loose pt 0,4,5.
+//     
+//-
+
+EXPORT(sys_enter_console)
+       mtpr    r1, pt4
+       mtpr    r3, pt5
+#ifdef SIMOS
+        subq   r31, 1, r1
+       sll     r1, 42, r1
+       ldah    r1, 1(r1)
+#else /* SIMOS */
+        lda    r3, pal_enter_console_ptr(r31) //find stored vector
+       ldqp    r1, 0(r3)
+#endif /* SIMOS */
+
+#ifdef SIMOS
+        /* taken from scrmax, seems like the obvious thing to do */
+        mtpr   r1, exc_addr
+       mfpr    r1, pt4
+       mfpr    r3, pt5
+       STALL
+       STALL
+       hw_rei_stall
+#else        
+        pvc$violate    1007
+       jmp     r31, (r1)               // off to common routine
+#endif
+        
+\f
+// .sbttl      "SYS$EXIT_CONSOLE - Common PALcode for ENTERING console"
+//+
+// sys$exit_console
+//
+// Entry:
+//     Entered when console wants to reenter PAL.
+//     usually as the result of a CONTINUE.
+//
+//
+// Regs' on entry...
+//
+//
+// Function:
+//
+//     Restore all readable machine state, and return to user code.
+//     
+//
+//     
+//-
+       ALIGN_BLOCK
+sys_exit_console:
+       //Disable physical mode:
+#if enable_physical_console != 0        
+//    .if ne enable_physical_console
+       mfpr    r25, pt_ptbr
+       bic     r25, 1, r25             // clear physical console flag
+       mtpr    r25, pt_ptbr
+#endif
+
+       GET_IMPURE(r1)
+
+       // clear lock and intr_flags prior to leaving console
+       rc      r31                     // clear intr_flag
+       // lock flag cleared by restore_state
+#ifndef SIMOS
+        pvc$jsr        rststa, bsr=1
+       bsr     r3, pal_restore_state   // go restore all state
+                                       // note, R1 and R3 are NOT restored
+                                       // by restore_state.
+#endif
+       // TB's have been flushed
+
+       ldqp    r3, (cns_gpr+(8*3))(r1)         // restore r3
+       ldqp    r1, (cns_gpr+8)(r1)             // restore r1
+       hw_rei_stall                            // back to user
+
+#if turbo_pcia_intr_fix != 0        
+// .if ne      turbo_pcia_intr_fix
+check_pcia_intr:
+       mfpr    r14, pt14               // fetch saved PCIA interrupt info
+       beq     r14, check_done         // don't bother checking if no info
+       mfpr    r13, ipl                // check the current IPL
+       bic     r13, 3, r25             // isolate ipl<5:2>
+       cmpeq   r25, 0x14, r25          // is it an I/O interrupt?
+       beq     r25, check_done         // no, return
+       and     r13, 3, r25             // get I/O interrupt index
+       extbl   r14, r25, r13           // extract info for this interrupt
+       beq     r13, check_done         // if no info, return
+
+                                       // This is an RTI from a PCIA interrupt
+       lda     r12, 1(r31)             // get initial bit mask
+       sll     r12, r25, r25           // shift to select interrupt index
+       zap     r14, r25, r14           // clear out info from this interrupt
+       mtpr    r14, pt14               //  and save it
+
+       and     r13, 3, r25             // isolate HPC field
+       subq    r25, 1, r25             // subtract 1 to get HPC number
+       srl     r13, 2, r13             // generate base register address
+       sll     r13, 6, r13             // get slot/hose address bits
+       lda     r13, 0x38(r13)          // insert other high bits
+       sll     r13, 28, r13            // shift high bits into position
+
+                                       // Read the IPROGx register
+       sll     r25, 21, r14            // HPC address bit position
+       or      r13, r14, r14           // add in upper bits
+       lda     r14, 0x400(r14)         // add in lower bits
+       ldqp    r14, 0(r14)             // read IPROG 
+       srl     r14, 4, r12             // check the In Progress bit
+       blbc    r12, 1f                 // skip if none in progress
+       and     r14, 0xf, r14           // isolate interrupt source
+       lda     r12, 1(r31)             // make initial mask
+       sll     r12, r14, r14           // shift to make new intr source mask
+       br      r31, 2f
+                                       // Write the SMPLIRQx register
+1:     or      r31, r31, r14           // default interrupt source mask
+2:     GET_ADDR(r12, 0xffff, r31)      // default SMPLIRQx data
+       bic     r12, r14, r12           // clear any interrupts in progres
+//orig  lda    r14, <0xbffc@-2>(r31)   // get register address bits
+        lda     r14,(0xbffc>>2)(r31)
+
+               sll     r14, 10, r14            // shift into position
+       or      r14, r13, r14           // add in upper bits
+       sll     r25, 8, r25             // shift HPC number into position
+       or      r14, r25, r14           // add in lower bits
+       stqp    r12, 0(r14)             // write SMPLIRQx register
+       mb
+       ldqp    r12, 0(r14)             // read it back
+       bis     r12, r12, r12           // touch register to insure completion
+       
+check_done:                            // do these now and return
+       lda     r25, osfsf_c_size(sp)   // get updated sp
+       bis     r25, r31, r14           // touch r14,r25 to stall mf exc_addr
+       br      r31, pcia_check_return
+#endif
+
+\f
+// .sbttl KLUDGE_INITIAL_PCBB - PCB for Boot use only
+
+        ALIGN_128
+
+kludge_initial_pcbb:                   // PCB is 128 bytes long
+//     .repeat 16
+//     .quad   0
+//     .endr
+        
+        nop
+        nop
+        nop
+        nop
+
+        nop
+        nop
+        nop
+        nop
+        
+        nop
+        nop
+        nop
+        nop
+        
+        nop
+        nop
+        nop
+        nop                        
+\f
+// .sbttl "SET_SC_BC_CTL subroutine"
+//
+// Subroutine to set the SC_CTL, BC_CONFIG, and BC_CTL registers and flush the Scache
+// There must be no outstanding memory references -- istream or dstream -- when
+// these registers are written.  EV5 prefetcher is difficult to turn off.  So,
+// this routine needs to be exactly 32 instructions long// the final jmp must
+// be in the last octaword of a page (prefetcher doesn't go across page)
+//  
+//
+// Register expecations:
+//     r0      base address of CBOX iprs
+//       r5      value to set sc_ctl to (flush bit is added in)
+//       r6      value to set bc_ctl to
+//     r7      value to set bc_config to 
+//     r10     return address
+//     r19     old sc_ctl value
+//     r20     old value of bc_ctl
+//     r21     old value of bc_config
+//     r23     flush scache flag
+// Register usage:
+//       r17     sc_ctl with flush bit cleared
+//     r22     loop address
+//
+//
+#ifndef SIMOS        
+       align_page <32*4>               // puts start of routine at next page boundary minus 32 longwords.
+#endif
+        
+set_sc_bc_ctl:
+
+#ifndef SIMOS        
+       br      r22, sc_ctl_loop        //this branch must be in the same 4 instruction block as it's dest
+sc_ctl_loop:                           
+// XXX bugnion         pvc$jsr scloop, dest=1
+       mb
+       mb
+
+       bis     r5, r23, r5             //r5 <- same sc_ctl with flush bit set (if flag set in r23)
+
+       stqp    r19, ev5__sc_ctl(r0)    // write sc_ctl
+       stqp    r20, ev5__bc_ctl(r0)    // write bc_ctl
+       bis     r31, r6, r20            // update r20 with new bc_ctl for 2nd time through loop
+        stqp    r21, bc_config(r0)     // write bc_config register
+       bis     r31, r7, r21            // update r21 with new bc_config for 2nd time through loop
+
+       bic     r19, BIT(sc_ctl_v_sc_flush), r17        //r17 <- same sc_ctl without flush bit set
+                                                       //NOTE: only works because flush bit is in lower 16 bits
+
+       wmb                             // don't merge with other writes
+       stqp    r17, ev5__sc_ctl(r0)    // write sc_ctl without flush bit
+       ldqp    r17, ev5__sc_ctl(r0)    // read sc_ctl
+       bis     r17, r17, r17           // stall until the data comes back
+       bis     r31, r5, r19            // update r19 with new sc_ctl for 2nd time through loop
+
+       // fill with requisite number of nops (unops ok) to make exactly 32 instructions in loop
+       t = 0           
+         .repeat 15
+         unop
+         t = t + 1
+         .endr
+        $opdef  mnemonic= myjmp, -
+                format= <custom=iregister, iregister, branch_offset>, -
+                encoding= <26:31=0x1A, 21:25=%OP1,16:20=%OP2,14:15=0x00,0:13=%op3>
+
+// XXXbugnion  pvc$jsr scloop
+       myjmp   r22,r22,sc_ctl_loop     // first time, jump to sc_ctl_loop (hint will cause prefetcher to go to loop instead
+                                       //       of straight) // r22 gets sc_ctl_done
+                                       // 2nd time, code continues at sc_ctl_done (I hope)
+sc_ctl_done:
+// XXX bugnion         pvc$jsr scloop, dest=1
+// XXX bugnion         pvc$jsr scbcctl
+#endif /*SIMOS*/        
+       ret     r31, (r10)              // return to where we came from
+
+
+.end
+
+
+
+