[BACK]Return to eh_common.S CVS log [TXT][DIR] Up to [local] / sys / arch / m88k / m88k

Annotation of sys/arch/m88k/m88k/eh_common.S, Revision 1.1.1.1

1.1       nbrk        1: /*   $OpenBSD: eh_common.S,v 1.24 2007/05/18 16:35:54 miod Exp $       */
                      2: /*
                      3:  * Mach Operating System
                      4:  * Copyright (c) 1993-1991 Carnegie Mellon University
                      5:  * Copyright (c) 1991 OMRON Corporation
                      6:  * Copyright (c) 1996 Nivas Madhur
                      7:  * Copyright (c) 1998 Steve Murphree, Jr.
                      8:  * All Rights Reserved.
                      9:  *
                     10:  * Permission to use, copy, modify and distribute this software and its
                     11:  * documentation is hereby granted, provided that both the copyright
                     12:  * notice and this permission notice appear in all copies of the
                     13:  * software, derivative works or modified versions, and any portions
                     14:  * thereof, and that both notices appear in supporting documentation.
                     15:  *
                     16:  * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     17:  * CONDITION.  CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
                     18:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     19:  *
                     20:  * Carnegie Mellon requests users of this software to return to
                     21:  *
                     22:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     23:  *  School of Computer Science
                     24:  *  Carnegie Mellon University
                     25:  *  Pittsburgh PA 15213-3890
                     26:  *
                     27:  * any improvements or extensions that they make and grant Carnegie the
                     28:  * rights to redistribute these changes.
                     29:  */
                     30:
                     31: /*
                     32:  * NOTICE: This is not a standalone file.  To use it, define the PFSR_SAVE
                     33:  * macro and #include this file in your port's eh.S:
                     34:  * #include <m88k/m88k/eh_common.S>
                     35:  */
                     36:
                     37: /*
                     38:  * In the following discussion, references are made to:
                     39:  *    MC88100 - RISC MICROPROCESSOR USER'S MANUAL
                     40:  * (second edition). Reference in []s refer to section numbers.
                     41:  *
                     42:  * This discussion assumes that you are at least vaguely familiar with 88100
                     43:  * exception handling (chapter 6), the MACH kernel, and that you have a brain
                     44:  * (and use it while reading this).
                     45:  *
                     46:  * I also assume (and hope) that you're not offended by frequent misspellings.
                     47:  *
                     48:  * Jeffrey Friedl
                     49:  * jfriedl@rna.ncl.omron.co.jp
                     50:  * December, 1989
                     51:  *  -------------------------------------------------------------------
                     52:  *
                     53:  * EXCEPTIONS, INTERRUPTS, and TRAPS
                     54:  * ---------------------------------
                     55:  * This is the machine exception handler.
                     56:  * In the MC88100, various "conditions" cause an exception, where
                     57:  * processing momentarily jumps here to "service" the exception,
                     58:  * and then continues where it left off.
                     59:  *
                     60:  * There are a number of different types of exceptions.
                     61:  * For example, exception #6 is the privilege violation exception which
                     62:  * is raised when the user tries to execute a supervisor-only instruction.
                     63:  *
                     64:  * Exception #1 is the interrupt exception, and is raised when an
                     65:  * outside device raises the INT line on the CPU.  This happens,
                     66:  * for example, when the clock signals that it is time for a context
                     67:  * switch, or perhaps the disk drive signaling that some operation
                     68:  * is complete.
                     69:  *
                     70:  * Traps are also exceptions.  Traps are ways for user programs to request
                     71:  * kernel operations.  For example, "tcnd eq0, r0, 450" will raise
                     72:  * exception 450, the system call exception.
                     73:  *
                     74:  *
                     75:  * SERVICING AN EXCEPTION
                     76:  * -----------------------
                     77:  * When an exception occurs, each control register is saved in its
                     78:  * respective shadow register and execution continues from the
                     79:  * appropriate exception handler.  The exception handler must
                     80:  *      - save the context from the time of the exception
                     81:  *      - service the exception
                     82:  *      - restore the context (registers, etc)
                     83:  *      - pick up from where the exception occurred.
                     84:  *
                     85:  * The context is saved on a stack. Actually, in the user_state area
                     86:  * in the PCB if the exception happens in user mode.
                     87:  *
                     88:  * Servicing the exception is usually straightforward and in fact not dealt
                     89:  * with very much here.  Usually a C routine is called to handle it.
                     90:  * For example, when a privilege exception is raised, the routine that sends
                     91:  * an "illegal instruction" signal to the offending process is called.
                     92:  *
                     93:  * When the exception has been serviced, the context is restored from the
                     94:  * stack and execution resumes from where it left off.
                     95:  *
                     96:  * In more detail:
                     97:  *
                     98:  * Saving the exception-time context.
                     99:  * ---------------------------------
                    100:  *     In saving the exception-time context, we copy the shadow and general
                    101:  * purpose registers to memory.  Since one exception may occur while
                    102:  * servicing another, the memory used to save the exception-time context may
                    103:  * not be static (i.e. the same every time).  Thus, memory on a stack is set
                    104:  * aside for the exception frame (area where the exception-time context is
                    105:  * saved). The same stack is also used when C routines are called (to
                    106:  * service the exception).
                    107:  *
                    108:  *    Each process has a stack in kernel space (called the "kernel stack",
                    109:  * short for "process's kernel stack) as well as the user space stack.  When
                    110:  * entering the kernel from user space, the kernel stack is unused.  On this
                    111:  * stack we save the exception state and (most likely call a C routine to)
                    112:  * service the exception.
                    113:  *
                    114:  * Before servicing an exception, several issues must be addressed.
                    115:  *
                    116:  * 1) When an interrupt is recognized by the hardware, the data pipeline is
                    117:  *    allowed to clear.  However, if one of these data accesses faults (bad
                    118:  *    reference, or a reference to a page which needs to be swapped in), that
                    119:  *    reference, as well as any others in the pipeline at the time (at most
                    120:  *    three total) are left there, to be taken care of by the exception
                    121:  *    handler [6.4.1].  This involves swapping in the proper page and
                    122:  *    manually doing the appropriate load or store.
                    123:  *
                    124:  *    The other (at most, two other) data accesses that might have been in
                    125:  *    the pipeline must also be manually completed (even though they may not
                    126:  *    be at fault [yes, that's a bad pun, thank you]).
                    127:  *
                    128:  * 2) If any of the (at most three) uncompleted data access in the pipeline
                    129:  *    are loads (from memory to a register), then the bit for the destination
                    130:  *    register is set in the SSBR.  Since the hardware will never complete
                    131:  *    that load (since we do it manually), the hardware will never clear that
                    132:  *    SSBR bit.  Thus, we must clear it manually.  If this isn't done, the
                    133:  *    system will hang waiting for a bit to clear that will never.
                    134:  *
                    135:  * 3) If the exception is the privilege violation exception, the bounds
                    136:  *    check exception, or the misaligned access exception, the
                    137:  *    destination register bit in the SSBR may need to be cleared.
                    138:  *
                    139:  * 4) If the exception is one of the floating exceptions, then the
                    140:  *    destination register for that floating process won't be written,
                    141:  *    and the SSBR must be cleared explicitly.
                    142:  *
                    143:  * 5) The FPU must be enabled (as it is disabled by the exception processing
                    144:  *    hardware) and allowed to complete actions in progress. This is
                    145:  *    so that it may be used in the servicing of any instruction.
                    146:  *    When the FPU is being restarted, operations attempting to complete
                    147:  *    may themselves fault (raising another exception).
                    148:  *
                    149:  * More on Restarting the FPU
                    150:  * --------------------------
                    151:  *   The manual [section 6.4.3.4] gives only minor mention to this
                    152:  * rather complex task.  Before the FPU is restarted all SSBR bits are
                    153:  * cleared for actions that the exception handler completes (as mentioned
                    154:  * above) so that the SSBR is clear unless there are FPU operations that
                    155:  * have not actually been completed (and hence not written to the registers).
                    156:  * Also, all control registers (at least all those that we care about) are
                    157:  * saved to the stack exception frame before the FPU is restarted (this
                    158:  * is important... the reason comes later).
                    159:  *
                    160:  * The FPU is restarted by doing an rte to a trap-not-taken (the rte
                    161:  * actually enables the fpu because we ensure that the EPSR has the
                    162:  * FPU-enable bit on; the trap-not-taken ensures anything in the FPU
                    163:  * completes by waiting until scoreboard register is clear).
                    164:  *
                    165:  * At the time the FPU is restarted (the rte to the trap-not-taken) the FPU
                    166:  * can write to ANY of the general registers.  Thus, we must make sure that
                    167:  * all general registers (r1..r31) are in their pre-exception state so that
                    168:  * when saved to the exception frame after the FPU is enabled, they properly
                    169:  * reflect any changes made by the FPU in being restarted.
                    170:  *
                    171:  * Because we can't save the pointer to the exception frame in a general
                    172:  * register during the FPU restart (it could get overwritten by the FPU!),
                    173:  * we save it in a control register, SR3, during the restart.
                    174:  *
                    175:  * HOWEVER .....
                    176:  *
                    177:  * Because other uncompleted actions in the FPU may fault when the FPU is
                    178:  * restarted, a new exception may be raised during the restart. This may
                    179:  * happen recursively a number of times. Thus, during a restart, ANY register
                    180:  * whatsoever may be modified, including control registers.  Because of this
                    181:  * we must make sure that the exception handler preserves SR3 throughout
                    182:  * servicing an exception so that, if the exception had been raised during
                    183:  * an FPU restart, it is returned unmolested when control returns to the FPU
                    184:  * restart.
                    185:  *
                    186:  * Thus: if an exception is from kernel space, we MUST preserve SR3.
                    187:  * (if it from user space, no FPU-enable can be in progress and SR3 is
                    188:  *  unimportant).
                    189:  *
                    190:  * Now is a good time to recap SR1..SR3 usage:
                    191:  *   SR1 - CPU flags (exception handler flags)
                    192:  *   SR2 - generally free
                    193:  *   SR3 - free only if the exception is from user mode
                    194:  *
                    195:  * Once the FPU has been restarted, the general registers are saved to the
                    196:  * exception frame.  If the exception is not the interrupt exception,
                    197:  * interrupts are enabled and any faulted data accesses (see above) are
                    198:  * serviced.  In either case, the exception is then serviced (usually by
                    199:  * calling a C routine).  After servicing, any faulted data accesses are
                    200:  * serviced (if it had been the interrupt exception).  The context is then
                    201:  * restored and control returns to where the exception occurred.
                    202:  *
                    203:  */
                    204:
                    205: #include "assym.h"
                    206:
                    207: #include <machine/param.h>
                    208: #include <machine/asm.h>
                    209: #include <machine/trap.h>
                    210:
                    211: /*
                    212:  * SR1 - CPU FLAGS REGISTER
                    213:  *
                    214:  * SR1 contains flags about the current CPU status.
                    215:  *
                    216:  * The bit FLAG_IGNORE_DATA_EXCEPTION indicates that any data exceptions
                    217:  *     should be ignored (well, at least treated in a special way).
                    218:  * The bit FLAG_ENABLING_FPU indicates that the exception handler is
                    219:  *     in the process of enabling the FPU (so that an exception can
                    220:  *     be serviced).  This is needed because enabling the FPU can
                    221:  *     cause other exceptions to happen, and the whole system is
                    222:  *     in a rather precarious state and so special cautions must
                    223:  *     be taken.
                    224:  */
                    225: #define FLAG_IGNORE_DATA_EXCEPTION     0
                    226: #define FLAG_ENABLING_FPU              1
                    227: #define FLAG_FROM_KERNEL               2
                    228:
                    229: /* REGister OFFset into the E.F. (exception frame) */
                    230: #define REG_OFF(reg_num)  ((reg_num) * 4) /* (num * sizeof(register_t))  */
                    231: #define GENREG_OFF(num)        (REG_OFF(EF_R0 + (num))) /* GENeral REGister OFFset */
                    232:
                    233: /* Invoke a C function with 2 arguments */
                    234: #define        CALL(NAME, ARG1, ARG2) \
                    235:        or      r2, r0, ARG1; \
                    236:        bsr.n   _C_LABEL(NAME); \
                    237:         or     r3, r0, ARG2
                    238:
                    239: /* Invoke a function and return elsewhere */
                    240: /* CAREFUL: needs to have `RET' after the XCALL in memory */
                    241: #define        XCALL(NAME, RET) \
                    242:        bsr.n   NAME; \
                    243:         addu   r1, r1, RET - . - 4
                    244:
                    245: /*
                    246:  * Some registers used during the setting up of the new exception frame.
                    247:  * Don't choose r1, r30, or r31 for any of them.
                    248:  *
                    249:  * Also, if any are 'r2' or 'r3', be careful using with CALL above!
                    250:  */
                    251: #define        FLAGS           r2
                    252: #define        TMP             r3
                    253: #define        TMP2            r10
                    254: #define        TMP3            r11
                    255: #define        SAVE_TMP2       st      r10, r31, GENREG_OFF(10)
                    256: #define        SAVE_TMP3       st      r11, r31, GENREG_OFF(11)
                    257: #define        RESTORE_TMP2    ld      r10, r31, GENREG_OFF(10)
                    258: #define        RESTORE_TMP3    ld      r11, r31, GENREG_OFF(11)
                    259:
                    260: /*
                    261:  * EF_SR3
                    262:  *   A place to save the exception-time SR3 from just after the
                    263:  *   time when an exception is raised until just after the FPU
                    264:  *   has been restarted.  This does not necessarly conflict with
                    265:  *   the general registers (though it can if you're not careful)
                    266:  *   and so we can use a spot later used to save a general register.
                    267:  *
                    268:  * EF_FLAGS
                    269:  *   This is just the old EF_MODE. "EF_MODE" isn't a very good name.
                    270:  */
                    271: #define        EF_SR3          (EF_R0 + 5)
                    272: #define        EF_FLAGS        EF_MODE
                    273:
                    274:        text
                    275:        align 8
                    276:
                    277: #ifdef M88110
                    278: #define SAVE_CTX \
                    279:        stcr    r31, SRX                        ; \
                    280:        or.u    r31, r0,  hi16(_ASM_LABEL(save_frame))  ; \
                    281:        or      r31, r31, lo16(_ASM_LABEL(save_frame))  ; \
                    282:        /* save old R31 and other R registers */; \
                    283:        st.d    r0 , r31, GENREG_OFF(0)         ; \
                    284:        st.d    r2 , r31, GENREG_OFF(2)         ; \
                    285:        st.d    r4 , r31, GENREG_OFF(4)         ; \
                    286:        st.d    r6 , r31, GENREG_OFF(6)         ; \
                    287:        st.d    r8 , r31, GENREG_OFF(8)         ; \
                    288:        st.d    r10, r31, GENREG_OFF(10)        ; \
                    289:        st.d    r12, r31, GENREG_OFF(12)        ; \
                    290:        st.d    r14, r31, GENREG_OFF(14)        ; \
                    291:        st.d    r16, r31, GENREG_OFF(16)        ; \
                    292:        st.d    r18, r31, GENREG_OFF(18)        ; \
                    293:        st.d    r20, r31, GENREG_OFF(20)        ; \
                    294:        st.d    r22, r31, GENREG_OFF(22)        ; \
                    295:        st.d    r24, r31, GENREG_OFF(24)        ; \
                    296:        st.d    r26, r31, GENREG_OFF(26)        ; \
                    297:        st.d    r28, r31, GENREG_OFF(28)        ; \
                    298:        st      r30, r31, GENREG_OFF(30)        ; \
                    299:        ldcr    r1,  SRX                        ; \
                    300:        st      r1,  r31, GENREG_OFF(31)        ; \
                    301:        ldcr    r1,  EPSR                       ; \
                    302:        ldcr    r2,  EXIP                       ; \
                    303:        ldcr    r3,  ENIP                       ; \
                    304:        st      r1,  r31, REG_OFF(EF_EPSR)      ; \
                    305:        st      r2,  r31, REG_OFF(EF_EXIP)      ; \
                    306:        st      r3,  r31, REG_OFF(EF_ENIP)      ; \
                    307:        ldcr    r1,  DSR                        ; \
                    308:        ldcr    r2,  DLAR                       ; \
                    309:        ldcr    r3,  DPAR                       ; \
                    310:        st      r1,  r31, REG_OFF(EF_DSR)       ; \
                    311:        st      r2,  r31, REG_OFF(EF_DLAR)      ; \
                    312:        st      r3,  r31, REG_OFF(EF_DPAR)      ; \
                    313:        ldcr    r1,  ISR                        ; \
                    314:        ldcr    r2,  ILAR                       ; \
                    315:        ldcr    r3,  IPAR                       ; \
                    316:        st      r1,  r31, REG_OFF(EF_ISR)       ; \
                    317:        st      r2,  r31, REG_OFF(EF_ILAR)      ; \
                    318:        st      r3,  r31, REG_OFF(EF_IPAR)      ; \
                    319:        ldcr    r1, DSAP                        ; \
                    320:        ldcr    r2, DUAP                        ; \
                    321:        st      r1,  r31, REG_OFF(EF_DSAP)      ; \
                    322:        st      r2,  r31, REG_OFF(EF_DUAP)      ; \
                    323:        ldcr    r1, ISAP                        ; \
                    324:        ldcr    r2, IUAP                        ; \
                    325:        st      r1,  r31, REG_OFF(EF_ISAP)      ; \
                    326:        st      r2,  r31, REG_OFF(EF_IUAP)      ; \
                    327:        /* Restore r1, r2, r3, and r31 */       ; \
                    328:        ld      r1 , r31, GENREG_OFF(1)         ; \
                    329:        ld      r2 , r31, GENREG_OFF(2)         ; \
                    330:        ld      r3 , r31, GENREG_OFF(3)         ; \
                    331:        ld      r31, r31, GENREG_OFF(31)        ;
                    332: #endif
                    333:
                    334: /*
                    335:  *
                    336:  * #define PREP881x0(NAME, NUM, SSBR_STUFF, FLAG_CHECK)
                    337:  *
                    338:  * This is the "exception processing preparation" common to all exception
                    339:  * processing.  It is used in the following manner:
                    340:  *
                    341:  *     ASGLOBAL(foo_handler)
                    342:  *             PREP881x0("foo", 11, SSBR_Stuff, Precheck_Stuff)
                    343:  *             or      r2, r0, T_FOO_FAULT
                    344:  *             or      r3, r0, r30
                    345:  *             XCALL(trapXXX, check_ast)
                    346:  *
                    347:  * This defines the exception handler for the "foo" exception.
                    348:  * The arguments are:
                    349:  * NAME
                    350:  *     String for debugging (more info later)
                    351:  * NUM
                    352:  *     The exception number [see the manual, Table 6-1]
                    353:  * SSBR_STUFF
                    354:  *     If the exception might leave some bits in the SSBR set,
                    355:  *     this should indicate how they are cleared.
                    356:  * FLAG_PRECHECK
                    357:  *     This is for the data access exception only. See it for
                    358:  *     more info.
                    359:  *
                    360:  * What's in between PREP881x0() and check_ast (usually a XCALL)
                    361:  * is the actual servicing of the interrupt.  During this time, any
                    362:  * register may be used freely as they've all been saved in the
                    363:  * exception frame (which is pointed to by r30).
                    364:  */
                    365:
                    366: #ifdef M88100
                    367: #define PREP88100(NAME, NUM, SSBR_STUFF, FLAG_PRECHECK) \
                    368:        xcr     FLAGS, FLAGS, SR1                       ; \
                    369:        FLAG_PRECHECK                                     \
                    370:        /* the bsr later clobbers r1, so save now */      \
                    371:        stcr    r1, SR2 /* r1 now free */               ; \
                    372:        /* set or clear the FLAG_FROM_KERNEL bit */       \
                    373:        ldcr    r1, EPSR                                ; \
                    374:        bb0.n   PSR_SUPERVISOR_MODE_BIT, r1, 1f         ; \
                    375:         clr    FLAGS, FLAGS, 1<FLAG_FROM_KERNEL>       ; \
                    376:        set     FLAGS, FLAGS, 1<FLAG_FROM_KERNEL>       ; \
                    377:        /* get a stack (exception frame) */               \
                    378: 1:     bsr     _ASM_LABEL(m88100_setup_phase_one)      ; \
                    379:        /* TMP2 now free -- use to set EF_VECTOR */       \
                    380:        or      TMP2, r0, NUM                           ; \
                    381:        st      TMP2, r31, REG_OFF(EF_VECTOR)           ; \
                    382:        /* Clear any bits in the SSBR (held in TMP) */    \
                    383:        /* SSBR_STUFF may be empty, though.         */    \
                    384:        SSBR_STUFF                                        \
                    385:        /* call setup_phase_two to restart the FPU  */    \
                    386:        /* and to save all general registers.       */    \
                    387:        bsr     _ASM_LABEL(m88100_setup_phase_two)
                    388: #endif
                    389:
                    390: #ifdef M88110
                    391: #define PREP88110(NAME, NUM, FLAG_PRECHECK) \
                    392:        SAVE_CTX                                          \
                    393:        xcr     FLAGS, FLAGS, SR1                       ; \
                    394:        FLAG_PRECHECK                                     \
                    395:        /* the bsr later clobbers r1, so save now */    ; \
                    396:        stcr    r1, SR2 /* r1 now free */               ; \
                    397:        /* set or clear the FLAG_FROM_KERNEL bit */     ; \
                    398:        ldcr    r1, EPSR                                ; \
                    399:        bb0.n   PSR_SUPERVISOR_MODE_BIT, r1, 1f         ; \
                    400:         clr    FLAGS, FLAGS, 1<FLAG_FROM_KERNEL>       ; \
                    401:        set     FLAGS, FLAGS, 1<FLAG_FROM_KERNEL>       ; \
                    402:        /* get a stack (exception frame) */             ; \
                    403: 1:     bsr     _ASM_LABEL(m88110_setup_phase_one)      ; \
                    404:        /* TMP2 now free -- use to set EF_VECTOR */     ; \
                    405:        or      TMP2, r0, NUM                           ; \
                    406:        st      TMP2, r31, REG_OFF(EF_VECTOR)           ; \
                    407:        /* call setup_phase_two to restart the FPU  */  ; \
                    408:        /* and to save all general registers.       */  ; \
                    409:        bsr     _ASM_LABEL(m88110_setup_phase_two)
                    410: #endif
                    411:
                    412: /* Some defines for use with PREP88100() */
                    413: #define        Clear_SSBR_Dest \
                    414:        bsr     _ASM_LABEL(clear_dest_ssbr_bit);
                    415: #define        M88100_Data_Precheck \
                    416:        bb1.n   FLAG_IGNORE_DATA_EXCEPTION, FLAGS, \
                    417:            _ASM_LABEL(m88100_ignore_data_exception);
                    418: #define        M88110_Data_Precheck \
                    419:        bb1.n   FLAG_IGNORE_DATA_EXCEPTION, FLAGS, \
                    420:            _ASM_LABEL(m88110_ignore_data_exception);
                    421:
                    422: #ifdef M88100
                    423: /*
                    424:  * 88100 exception handlers
                    425:  */
                    426:
                    427: /* unknown exception handler */
                    428: GLOBAL(unknown_handler)
                    429:        PREP88100("unknown", 0,,)
                    430:        or      r2, r0, T_UNKNOWNFLT
                    431:        or      r3, r0, r30
                    432:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    433:
                    434: /* interrupt exception handler */
                    435: GLOBAL(interrupt_handler)
                    436:        PREP88100("interrupt", 1,,)
                    437:        or      r2, r0, T_INT
                    438:        or      r3, r0, r30
                    439:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    440:
                    441: /* instruction access exception handler */
                    442: GLOBAL(instruction_access_handler)
                    443:        PREP88100("inst", 2,,)
                    444:        or      r2, r0, T_INSTFLT
                    445:        or      r3, r0, r30
                    446:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    447:
                    448: /*
                    449:  * data access exception handler --
                    450:  *  See badaddr() below for info about Data_Precheck.
                    451:  */
                    452: GLOBAL(data_exception_handler)
                    453:        PREP88100("data", 3,, M88100_Data_Precheck)
                    454:        /* No need to call m88100_trap(T_DATAFLT) as PREP will do this for us */
                    455:        br      _ASM_LABEL(check_ast)
                    456:
                    457: /* misaligned access exception handler */
                    458: GLOBAL(misaligned_handler)
                    459:        PREP88100("misalign", 4, Clear_SSBR_Dest,)
                    460:        or      r2, r0, T_MISALGNFLT
                    461:        or      r3, r0, r30
                    462:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    463:
                    464: /* unimplemented opcode exception handler */
                    465: GLOBAL(unimplemented_handler)
                    466:        PREP88100("unimp", 5,,)
                    467:        or      r2, r0, T_ILLFLT
                    468:        or      r3, r0, r30
                    469:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    470:
                    471: /*
                    472:  * Some versions of the chip have a bug whereby false privilege
                    473:  * violation exceptions are raised. If the valid bit in the SXIP is clear,
                    474:  * it is false.  If so, just return.  The code before PREP handles this....
                    475:  */
                    476: GLOBAL(privilege_handler)
                    477:        stcr    r1, SR2         /* hold r1 for a moment */
                    478:        ldcr    r1, SXIP        /* look at the sxip... valid bit set? */
                    479:        bb1.n   RTE_VALID_BIT, r1, 1f   /* skip over if a valid exception */
                    480:         ldcr   r1, SR2         /* restore r1 */
                    481:        RTE
                    482: 1:     PREP88100("privilege", 6, Clear_SSBR_Dest,)
                    483:        or      r2, r0, T_PRIVINFLT
                    484:        or      r3, r0, r30
                    485:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    486:
                    487: /* bounds checking exception handler */
                    488: GLOBAL(bounds_handler)
                    489:        PREP88100("bounds", 7, Clear_SSBR_Dest,)
                    490:        or      r2, r0, T_BNDFLT
                    491:        or      r3, r0, r30
                    492:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    493:
                    494: /* integer divide-by-zero exception handler */
                    495: GLOBAL(divide_handler)
                    496:        PREP88100("divide", 8, Clear_SSBR_Dest,)
                    497:        or      r2, r0, T_ZERODIV
                    498:        or      r3, r0, r30
                    499:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    500:
                    501: /* integer overflow exception handler */
                    502: GLOBAL(overflow_handler)
                    503:        PREP88100("overflow", 9,,)
                    504:        or      r2, r0, T_OVFFLT
                    505:        or      r3, r0, r30
                    506:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    507:
                    508: /* Floating-point precise handler */
                    509: #define        FPp_SSBR_STUFF \
                    510:        bsr     _ASM_LABEL(clear_FPp_ssbr_bit);
                    511: GLOBAL(fp_precise_handler)
                    512:        PREP88100("FPU precise", 114, FPp_SSBR_STUFF,)
                    513:        or      r3, r0, r30
                    514:        XCALL(_ASM_LABEL(m88100_Xfp_precise), _ASM_LABEL(check_ast))
                    515:
                    516: /* Floating-point imprecise handler */
                    517: #define        FPi_SSBR_STUFF \
                    518:        bsr     _ASM_LABEL(clear_FPi_ssbr_bit);
                    519: GLOBAL(fp_imprecise_handler)
                    520:        PREP88100("FPU imprecise", 115, FPi_SSBR_STUFF,)
                    521:        or      r3, r0, r30
                    522:        XCALL(_ASM_LABEL(Xfp_imprecise), _ASM_LABEL(check_ast))
                    523:
                    524: /* trap 450: system calls */
                    525: GLOBAL(syscall_handler)
                    526:        PREP88100("syscall", 450,,)
                    527:        ld      r2, r30, GENREG_OFF(13)
                    528:        or      r3, r0, r30
                    529:        XCALL(_C_LABEL(m88100_syscall), _ASM_LABEL(check_ast))
                    530:
                    531: /* trap 451: cache flush (necessary for trampolines) */
                    532: GLOBAL(cache_flush_handler)
                    533:        PREP88100("cache_flush", 451,,)
                    534:        or      r2, r0, r30
                    535:        XCALL(_C_LABEL(cache_flush), _ASM_LABEL(check_ast))
                    536:
                    537: GLOBAL(sigsys)
                    538:        PREP88100("sigsys", 501,,)
                    539:        or      r2, r0, T_SIGSYS
                    540:        or      r3, r0, r30
                    541:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    542:
                    543: GLOBAL(stepbpt)
                    544:        PREP88100("stepbpt", 504,,)
                    545:        or      r2, r0, T_STEPBPT
                    546:        or      r3, r0, r30
                    547:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    548:
                    549: GLOBAL(userbpt)
                    550:        PREP88100("userbpt", 511,,)
                    551:        or      r2, r0, T_USERBPT
                    552:        or      r3, r0, r30
                    553:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    554:
                    555: #ifdef DDB
                    556: GLOBAL(break)
                    557:        PREP88100("break", 130,,)
                    558:        or      r2, r0, T_KDB_BREAK
                    559:        or      r3, r0, r30
                    560:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    561:
                    562: GLOBAL(trace)
                    563:        PREP88100("trace", 131,,)
                    564:        or      r2, r0, T_KDB_TRACE
                    565:        or      r3, r0, r30
                    566:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    567:
                    568: GLOBAL(entry)
                    569:        PREP88100("kdb", 132,,)
                    570:        or      r2, r0, T_KDB_ENTRY
                    571:        or      r3, r0, r30
                    572:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(check_ast))
                    573: #endif
                    574:
                    575: /*
                    576:  * The error exception and reset exception handler.
                    577:  *
                    578:  * The error exception is raised when any other non-trap exception is raised
                    579:  * while shadowing is off. This is Bad News.
                    580:  *
                    581:  * The reset exception is raised when the RST signal is asserted (machine
                    582:  * is reset), the value of VBR is changed after exceptions are enabled,
                    583:  * or when a jmp, br/bsr to addr 0 (accidents do happen :-)
                    584:  * To tell the difference, you should check the value of r1 and the valid
                    585:  * bit of SXIP.
                    586:  * Upon a real reset, VBR is set to zero (0), so code must be at addr 0
                    587:  * to handle it!!!
                    588:  *
                    589:  * The shadow registers are not valid in this case (shadowing was off, if this
                    590:  * was an error exception, and may not be on, if this was a reset exception).
                    591:  * R1-R31 may be interesting though, so we'll save them.
                    592:  *
                    593:  * We'll not worry about trashing r26-29 here,
                    594:  * since they aren't generally used.
                    595:  */
                    596: GLOBAL(error_handler)
                    597:        br.n    1f
                    598:         or     r29, r0, 10
                    599: GLOBAL(reset_handler)
                    600:        or      r29, r0, 0
                    601: 1:
                    602:        or      r26, r0,  r31   /* save old stack */
                    603:        or.u    r31, r0,  hi16(_ASM_LABEL(intstack_end))
                    604:        or      r31, r31, lo16(_ASM_LABEL(intstack_end))
                    605:
                    606: #ifdef DEBUG
                    607:        /* zero the stack, so we'll know what we're lookin' at */
                    608:        or.u    r27, r0,  hi16(_ASM_LABEL(intstack))
                    609:        or      r27, r27, lo16(_ASM_LABEL(intstack))
                    610: 1:     cmp     r28, r27, r31
                    611:        bb1     ge,  r28, 2f    /* branch if at the end of the stack */
                    612:        st      r0,  r0,  r27
                    613:        br.n    1b
                    614:         addu   r27, r27, 4     /* bump up */
                    615: 2:     /* stack has been cleared */
                    616: #endif
                    617:
                    618:        /* ensure that stack is 8-byte aligned */
                    619:        clr     r31, r31, 3<0>  /* round down to 8-byte boundary */
                    620:
                    621:        /* create exception frame on stack */
                    622:        subu    r31, r31, SIZEOF_EF     /* r31 now our E.F. */
                    623:
                    624:        /* save old R31 and other R registers */
                    625:        st.d    r0 , r31, GENREG_OFF(0)
                    626:        st.d    r2 , r31, GENREG_OFF(2)
                    627:        st.d    r4 , r31, GENREG_OFF(4)
                    628:        st.d    r6 , r31, GENREG_OFF(6)
                    629:        st.d    r8 , r31, GENREG_OFF(8)
                    630:        st.d    r10, r31, GENREG_OFF(10)
                    631:        st.d    r12, r31, GENREG_OFF(12)
                    632:        st.d    r14, r31, GENREG_OFF(14)
                    633:        st.d    r16, r31, GENREG_OFF(16)
                    634:        st.d    r18, r31, GENREG_OFF(18)
                    635:        st.d    r20, r31, GENREG_OFF(20)
                    636:        st.d    r22, r31, GENREG_OFF(22)
                    637:        st.d    r24, r31, GENREG_OFF(24)
                    638:        st      r30, r31, GENREG_OFF(30)
                    639:        st      r26, r31, GENREG_OFF(31)
                    640:
                    641:        /* save shadow registers (are OLD if error_handler, though) */
                    642:        ldcr    r10, EPSR
                    643:        st      r10, r31, REG_OFF(EF_EPSR)
                    644:        ldcr    r10, SXIP
                    645:        st      r10, r31, REG_OFF(EF_SXIP)
                    646:        ldcr    r10, SNIP
                    647:        st      r10, r31, REG_OFF(EF_SNIP)
                    648:        ldcr    r10, SR1
                    649:        st      r10, r31, REG_OFF(EF_MODE)
                    650:        ldcr    r10, SFIP
                    651:        st      r10, r31, REG_OFF(EF_SFIP)
                    652:        ldcr    r10, SSBR
                    653:        st      r10, r31, REG_OFF(EF_SSBR)
                    654:        stcr    r0,  SSBR       /* won't want shadow bits bothering us later */
                    655:
                    656:        ldcr    r10, DMT0
                    657:        st      r10, r31, REG_OFF(EF_DMT0)
                    658:        ldcr    r11, DMD0
                    659:        st      r11, r31, REG_OFF(EF_DMD0)
                    660:        ldcr    r12, DMA0
                    661:
                    662:        st      r12, r31, REG_OFF(EF_DMA0)
                    663:        ldcr    r10, DMT1
                    664:        st      r10, r31, REG_OFF(EF_DMT1)
                    665:        FLUSH_PIPELINE
                    666:        ldcr    r11, DMD1
                    667:        st      r11, r31, REG_OFF(EF_DMD1)
                    668:        ldcr    r12, DMA1
                    669:        st      r12, r31, REG_OFF(EF_DMA1)
                    670:
                    671:        ldcr    r10, DMT2
                    672:        st      r10, r31, REG_OFF(EF_DMT2)
                    673:        ldcr    r11, DMD2
                    674:        st      r11, r31, REG_OFF(EF_DMD2)
                    675:        ldcr    r12, DMA2
                    676:        st      r12, r31, REG_OFF(EF_DMA2)
                    677:
                    678:        /* shove sr2 into EF_FPLS1 */
                    679:        ldcr    r10, SR2
                    680:        st      r10, r31, REG_OFF(EF_FPLS1)
                    681:
                    682:        /* shove sr3 into EF_FPHS2 */
                    683:        ldcr    r10, SR3
                    684:        st      r10, r31, REG_OFF(EF_FPHS2)
                    685:
                    686:        /* save error vector */
                    687:        st      r29, r31, REG_OFF(EF_VECTOR)
                    688:
                    689:        /*
                    690:         * Cheap way to enable FPU and start shadowing again.
                    691:         */
                    692:        ldcr    r10, PSR
                    693:        clr     r10, r10, 1<PSR_FPU_DISABLE_BIT>        /* enable the FPU */
                    694:        clr     r10, r10, 1<PSR_SHADOW_FREEZE_BIT>      /* and shadowing */
                    695:        stcr    r10, PSR
                    696:        FLUSH_PIPELINE
                    697:
                    698:        /* put pointer to regs into r30... r31 will become a simple stack */
                    699:        or      r30, r31, r0
                    700:
                    701:        subu    r31, r31, 0x10  /* make some breathing space */
                    702:        st      r30, r31, 0x0c  /* store frame pointer on the stack */
                    703: #ifdef DDB
                    704:        st      r30, r31, 0x08  /* store again for the debugger to recognize */
                    705:        or.u    r20,  r0, hi16(0x87654321)
                    706:        or      r20, r20, lo16(0x87654321)
                    707:        st      r20, r31, 0x04
                    708:        st      r20, r31, 0x00
                    709: #endif
                    710:
                    711:        bsr.n   _C_LABEL(error_fatal)
                    712:         or     r2, r0, r30
                    713:
                    714:        /* turn interrupts back on */
                    715:        ldcr    r1, PSR
                    716:        clr     r1, r1, 1<PSR_INTERRUPT_DISABLE_BIT>
                    717:        stcr    r1, PSR
                    718:        FLUSH_PIPELINE
                    719:
                    720: 1:
                    721:        br      1b
                    722:        /* NOTREACHED */
                    723: #endif /* M88100 */
                    724:
                    725: /*
                    726:  * This is part of baddadr (below).
                    727:  */
                    728: #ifdef M88100
                    729: ASLOCAL(m88100_ignore_data_exception)
                    730:        /*
                    731:         * SR1: previous FLAGS reg
                    732:         * SR2: free
                    733:         * SR3: must preserve
                    734:         * FLAGS: CPU status flags
                    735:         */
                    736:        xcr     FLAGS, FLAGS, SR1       /* replace SR1, FLAGS */
                    737:
                    738:        /*
                    739:         * For more info, see badaddr() below.
                    740:         *
                    741:         * We just want to jump to "badaddr__return_nonzero" below.
                    742:         *
                    743:         * We don't worry about trashing r2 here because we're
                    744:         * jumping back to the function badaddr() where we're allowed
                    745:         * to blast r2..r9 as we see fit.
                    746:         */
                    747:
                    748:        /* the "+2" below is to set the VALID bit. */
                    749:        or.u    r2, r0, hi16(_ASM_LABEL(badaddr__return_nonzero) + 2)
                    750:        or      r2, r2, lo16(_ASM_LABEL(badaddr__return_nonzero) + 2)
                    751:        stcr    r2, SNIP        /* Make it the next instruction to execute */
                    752:        addu    r2, r2, 4
                    753:        stcr    r2, SFIP        /* and the next one after that, too. */
                    754:        stcr    r0, SSBR        /* make the scoreboard happy. */
                    755:        RTE
                    756: #endif /* M88100 */
                    757:
                    758: #ifdef M88110
                    759: /*
                    760:  * This is part of baddadr (below).
                    761:  */
                    762: ASLOCAL(m88110_ignore_data_exception)
                    763:        /*
                    764:         * SR1: previous FLAGS reg
                    765:         * SR2: free
                    766:         * SR3: must preserve
                    767:         * FLAGS: CPU status flags
                    768:         */
                    769:        xcr     FLAGS, FLAGS, SR1       /* replace SR1, FLAGS */
                    770:
                    771:        /*
                    772:         * For more info, see badaddr() below.
                    773:         *
                    774:         * We just want to jump to "badaddr__return_nonzero" below.
                    775:         *
                    776:         * We don't worry about trashing R2 here because we're
                    777:         * jumping back to the function badaddr() where we're allowed
                    778:         * to blast r2..r9 as we see fit.
                    779:         */
                    780:
                    781:        or.u    r2, r0, hi16(_ASM_LABEL(badaddr__return_nonzero))
                    782:        or      r2, r2, lo16(_ASM_LABEL(badaddr__return_nonzero))
                    783:        stcr    r2, EXIP        /* Make it the next instruction to execute */
                    784:        stcr    r0, DSR         /* Clear exception status */
                    785:        RTE
                    786: #endif /* M88110 */
                    787:
                    788: /*
                    789:  * extern boolean_t badaddr(unsigned addr, unsigned len)
                    790:  *
                    791:  * Returns true (non-zero) if the given LEN bytes starting at ADDR are
                    792:  * not all currently accessible by the kernel.
                    793:  *
                    794:  * If all LEN bytes starting at ADDR are accessible, zero is returned.
                    795:  *
                    796:  * Len may be be 1, 2, or 4.
                    797:  *
                    798:  * This is implemented by setting a special flag in SR1 before trying to access
                    799:  * the given address. If a data access exception is raised, the address
                    800:  * is inaccessible. The exception handler will notice the special CPU flag
                    801:  * and not try to swap the address in. Rather, it will return to
                    802:  * "badaddr__return_nonzero" in this routine so that we may return non-zero
                    803:  * to the calling routine.
                    804:  *
                    805:  * If no fault is raised, we continue to where we return zero to the calling
                    806:  * routine (after removing the special CPU flag).
                    807:  */
                    808:
                    809: GLOBAL(badaddr)
                    810:        /*
                    811:         * Disable interrupts ... don't want a context switch while we're
                    812:         * doing this! Also, save the old PSR in R8 to restore later.
                    813:         */
                    814:        ldcr    r8, PSR
                    815:        set     r4, r8, 1<PSR_INTERRUPT_DISABLE_BIT>
                    816:        stcr    r4, PSR
                    817:        FLUSH_PIPELINE
                    818:
                    819:        ldcr    r5, SR1
                    820:        set     r5, r5, 1<FLAG_IGNORE_DATA_EXCEPTION>
                    821:        /* resetting r5 to SR1 done in the delay slot below. */
                    822:
                    823:        /*
                    824:         * If it's a word we're doing, do that here. Otherwise,
                    825:         * see if it's a halfword.....
                    826:         */
                    827:        sub     r6,  r3, 4
                    828:        bcnd.n  ne0, r6, _ASM_LABEL(badaddr__maybe_halfword)
                    829:         stcr   r5,  SR1
                    830:        FLUSH_PIPELINE
                    831:
                    832:        /*
                    833:         * It's a bad address if it's misaligned.
                    834:         */
                    835:        bb1     0, r2, _ASM_LABEL(badaddr__return_nonzero)
                    836:        bb1     1, r2, _ASM_LABEL(badaddr__return_nonzero)
                    837:        /*
                    838:         * The next line will either fault or not. If it faults, execution
                    839:         * will go to:  data_access_handler (see above)
                    840:         * and then to: ignore_data_exception (see above)
                    841:         * and then to: badaddr__return_nonzero (see below)
                    842:         * which will return to the calling function.
                    843:         *
                    844:         * If there is no fault, execution just continues as normal.
                    845:         */
                    846:        ld      r5, r2, 0
                    847:        FLUSH_PIPELINE
                    848:        br.n    _ASM_LABEL(badaddr__return)
                    849:         or     r2, r0, r0      /* indicate a zero (address not bad) return.*/
                    850:
                    851: ASLOCAL(badaddr__maybe_halfword)
                    852:        /* More or less like the code for checking a word above */
                    853:        sub     r6, r3, 2
                    854:        bcnd    ne0, r6, _ASM_LABEL(badaddr__maybe_byte)
                    855:
                    856:        /* it's bad if it's misaligned */
                    857:        bb1     0, r2, _ASM_LABEL(badaddr__return_nonzero)
                    858:
                    859:        FLUSH_PIPELINE
                    860:        ld.h    r5, r2, 0
                    861:        FLUSH_PIPELINE
                    862:        br.n    _ASM_LABEL(badaddr__return)
                    863:         or     r2, r0, r0
                    864:
                    865: ASLOCAL(badaddr__maybe_byte)
                    866: #ifdef DEBUG
                    867:        /* More or less like the code for checking a word above */
                    868:        sub     r6, r3, 1
                    869:        bcnd    ne0, r6, _ASM_LABEL(badaddr__unknown_size)
                    870: #endif
                    871:        FLUSH_PIPELINE
                    872:        ld.b    r5, r2, 0
                    873:        FLUSH_PIPELINE
                    874:        br.n    _ASM_LABEL(badaddr__return)
                    875:         or     r2, r0, r0
                    876: ASLOCAL(badaddr__unknown_size)
                    877: #ifdef DEBUG
                    878:        data
                    879: 1:     string "bad length (%d) to badaddr() from 0x%x\000"
                    880:        text
                    881:        or.u    r2, r0, hi16(1b)
                    882:        or      r2, r2, lo16(1b)
                    883:        bsr.n   _C_LABEL(panic)
                    884:         or     r4, r0, r1
                    885:        /*NOTREACHED*/
                    886: #endif
                    887:
                    888: ASLOCAL(badaddr__return_nonzero)
                    889:        or      r2, r0, 1
                    890:        /* FALLTHROUGH */
                    891:
                    892: ASLOCAL(badaddr__return)
                    893:        ldcr    r4, SR1
                    894:        clr     r4, r4, 1<FLAG_IGNORE_DATA_EXCEPTION>
                    895:        stcr    r4, SR1
                    896:
                    897:        /*
                    898:         * Restore the PSR to what it was before.
                    899:         * The only difference is that we might be enabling interrupts
                    900:         * (which we turned off above).  If interrupts were already off,
                    901:         * we do not want to turn them on now, so we just restore from
                    902:         * where we saved it.
                    903:         */
                    904:        stcr    r8, PSR
                    905:        FLUSH_PIPELINE
                    906:        jmp     r1
                    907:
                    908: #ifdef M88100
                    909: ASLOCAL(m88100_setup_phase_one)
                    910:        /*
                    911:         * SR1: saved copy of exception-time register now holding FLAGS
                    912:         * SR2: saved copy of exception-time r1
                    913:         * SR3: must be preserved .. may be the exception-time stack
                    914:         * r1: return address to calling exception handler
                    915:         * FLAGS: CPU status flags
                    916:         *
                    917:         * immediate goal:
                    918:         *   Decide where we're going to put the exception frame.
                    919:         *   Might be at the end of R31, SR3, or the process pcb.
                    920:         */
                    921:
                    922:        /* Check if we are coming in from a FPU restart exception.
                    923:           If so, the pcb will be in SR3 */
                    924:        NOP
                    925:        xcr     r1,   r1,   SR2
                    926:        NOP
                    927:        NOP
                    928:        NOP
                    929:
                    930:        bb1     FLAG_ENABLING_FPU, FLAGS, _ASM_LABEL(m88100_use_SR3_pcb)
                    931:        /* are we coming in from user mode? If so, pick up process pcb */
                    932:        bb0     FLAG_FROM_KERNEL, FLAGS, _ASM_LABEL(m88100_pickup_stack)
                    933:
                    934:        /* Interrupt in kernel mode, not FPU restart */
                    935:        /*
                    936:         * SR1: saved copy of exception-time register now holding FLAGS
                    937:         * SR2: return address to the calling exception handler
                    938:         * SR3: must be preserved; may be important for other exceptions
                    939:         * FLAGS: CPU status flags
                    940:         *
                    941:         * immediate goal:
                    942:         *   We're already on the kernel stack, but not having
                    943:         *   needed to use SR3. We can just make room on the
                    944:         *   stack (r31) for our exception frame.
                    945:         */
                    946:        subu    r31,  r31,  SIZEOF_EF           /* r31 now our E.F. */
                    947:        st      FLAGS,r31,  REG_OFF(EF_FLAGS)   /* save flags */
                    948:        st      r1,   r31,  GENREG_OFF(1)       /* save prev. r1 (now free)*/
                    949:
                    950:        ldcr    r1,   SR3                       /* save previous SR3 */
                    951:        st      r1,   r31,  REG_OFF(EF_SR3)
                    952:
                    953:        addu    r1,   r31,  SIZEOF_EF           /* save previous r31 */
                    954:        br.n    _ASM_LABEL(m88100_have_pcb)
                    955:         st     r1,   r31,  GENREG_OFF(31)
                    956:
                    957: ASLOCAL(m88100_use_SR3_pcb)
                    958:        /*
                    959:         * SR1: saved copy of exception-time register now holding FLAGS
                    960:         * SR2: return address to the calling exception handler
                    961:         * SR3: must be preserved; exception-time stack pointer
                    962:         * FLAGS: CPU status flags
                    963:         *
                    964:         * immediate goal:
                    965:         *   An exception occurred while enabling the FPU. Since r31
                    966:         *   is the user's r31 while enabling the FPU, we had put
                    967:         *   our pcb pointer into SR3, so make room from
                    968:         *   there for our stack pointer.
                    969:         *   We need to check if SR3 is the old stack pointer or the
                    970:         *   pointer off to the user pcb. If it pointing to the user
                    971:         *   pcb, we need to pick up the kernel stack. Otherwise
                    972:         *   we need to allocate a frame upon it.
                    973:         *   We look at the EPSR to see if it was from user mode
                    974:         *   Unfortunately, we have no registers free at the moment
                    975:         *   But we know register 0 in the pcb frame will always be
                    976:         *   zero, so we can use it as scratch storage.
                    977:         */
                    978:        xcr     r30,  r30,  SR3                 /* r30 = old exception frame */
                    979:        st      r1,   r30,  GENREG_OFF(0)       /* free up r1 */
                    980:        ld      r1,   r30,  REG_OFF(EF_EPSR)    /* get back the epsr */
                    981:        bb0.n   PSR_SUPERVISOR_MODE_BIT, r1, 1f /* if user mode */
                    982:         ld     r1,   r30,  GENREG_OFF(0)       /* restore r1 */
                    983:        /* we were in kernel mode - dump frame upon the stack */
                    984:        st      r0,   r30,  GENREG_OFF(0)       /* repair old frame */
                    985:        subu    r30,  r30,  SIZEOF_EF           /* r30 now our E.F. */
                    986:        st      FLAGS,r30,  REG_OFF(EF_FLAGS)   /* save flags */
                    987:        st      r1,   r30,  GENREG_OFF(1)       /* save prev r1 (now free) */
                    988:
                    989:        st      r31,  r30,  GENREG_OFF(31)      /* save previous r31 */
                    990:        or      r31,  r0,   r30                 /* make r31 our pointer. */
                    991:        addu    r30,  r30,  SIZEOF_EF           /* r30 now has previous SR3 */
                    992:        st      r30,  r31,  REG_OFF(EF_SR3)     /* save previous SR3 */
                    993:        br.n    _ASM_LABEL(m88100_have_pcb)
                    994:         xcr    r30,  r30,  SR3                 /* restore r30 */
                    995: 1:
                    996:        /* we took an exception while restarting the FPU from user space.
                    997:         * Consequently, we never picked up a stack. Do so now.
                    998:         * R1 is currently free (saved in the exception frame pointed at by
                    999:         * r30) */
                   1000:        ldcr    r1,   CPU
                   1001:        ld      r1,   r1,   CI_CURPCB
                   1002:        addu    r1,   r1,   USIZE - SIZEOF_EF
                   1003:        st      FLAGS,r1,   REG_OFF(EF_FLAGS)   /* store flags */
                   1004:        st      r31,  r1,   GENREG_OFF(31)      /* store r31 - now free */
                   1005:        st      r30,  r1,   REG_OFF(EF_SR3)     /* store old SR3 (pcb) */
                   1006:        or      r31,  r1,   r0                  /* make r31 our exception fp */
                   1007:        ld      r1,   r30,  GENREG_OFF(0)       /* restore old r1 */
                   1008:        st      r0,   r30,  GENREG_OFF(0)       /* repair that frame */
                   1009:        st      r1,   r31,  GENREG_OFF(1)       /* store r1 */
                   1010:        br.n    _ASM_LABEL(m88100_have_pcb)
                   1011:         xcr    r30,  r30,  SR3                 /* restore r30 */
                   1012:
                   1013: ASLOCAL(m88100_pickup_stack)
                   1014:        /*
                   1015:         * SR1: saved copy of exception-time register now holding FLAGS
                   1016:         * SR2: return address to the calling exception handler
                   1017:         * SR3: free
                   1018:         * FLAGS: CPU status flags
                   1019:         *
                   1020:         * immediate goal:
                   1021:         *   Since we're servicing an exception from user mode, we
                   1022:         *   know that SR3 is free.  We use it to free up a temp.
                   1023:         *   register to be used in getting the process pcb
                   1024:         */
                   1025:        stcr    r31,  SR3       /* save previous r31 */
                   1026:
                   1027:        /* switch to the process kernel stack. */
                   1028:        ldcr    r31,  CPU
                   1029:        ld      r31,  r31,  CI_CURPCB
                   1030:        addu    r31,  r31,  PCB_USER_STATE      /* point to user save area */
                   1031:
                   1032:        /*
                   1033:         * WARNING! Using pcb->user_state as the exception frame
                   1034:         * AND stack pointer, means we can not afford using the stack
                   1035:         * until we have saved enough and can go back to the top of the u area,
                   1036:         * after the FPU is enabled.
                   1037:         */
                   1038:
                   1039:        st      FLAGS,r31,  REG_OFF(EF_FLAGS)   /* save flags */
                   1040:        st      r1,   r31,  GENREG_OFF(1)       /* save prev. r1 (now free) */
                   1041:        ldcr    r1,   SR3                       /* save previous r31 */
                   1042:        st      r1,   r31,  GENREG_OFF(31)
                   1043:        /* FALLTHROUGH */
                   1044:
                   1045: ASLOCAL(m88100_have_pcb)
                   1046:        /*
                   1047:         * SR1: saved copy of exception-time register now holding FLAGS
                   1048:         * SR2: return address to the calling exception handler
                   1049:         * SR3: free
                   1050:         * r1:  free
                   1051:         * FLAGS: CPU status flags
                   1052:         * r31: our exception frame
                   1053:         * Valid in the exception frame:
                   1054:         *   Exception-time r1, r31, FLAGS.
                   1055:         *   Exception SR3, if appropriate.
                   1056:         *
                   1057:         * immediate goal:
                   1058:         *   Save the shadow registers that need to be saved to
                   1059:         *   the exception frame.
                   1060:         */
                   1061:        stcr    TMP, SR3        /* free up TMP, TMP2, TMP3 */
                   1062:        SAVE_TMP2
                   1063:        SAVE_TMP3
                   1064:
                   1065:        /* save some exception-time registers to the exception frame */
                   1066:        ldcr    TMP,  EPSR
                   1067:        st      TMP,  r31,  REG_OFF(EF_EPSR)
                   1068:        ldcr    TMP3, SNIP
                   1069:        st      TMP3, r31,  REG_OFF(EF_SNIP)
                   1070:        ldcr    TMP2, SFIP
                   1071:        st      TMP2, r31,  REG_OFF(EF_SFIP)
                   1072:        /* get and store the cpu_info pointer */
                   1073:        ldcr    TMP,  CPU
                   1074:        st      TMP,  r31,  REG_OFF(EF_CPU)
                   1075:
                   1076:        /*
                   1077:         * Save Pbus fault status register from data and inst CMMU.
                   1078:         * We can afford calling a function since r1 is safe to use here.
                   1079:         */
                   1080: GLOBAL(pfsr_save)
                   1081:        PFSR_SAVE
                   1082: ASLOCAL(pfsr_done)
                   1083:
                   1084:        ldcr    TMP,  SSBR
                   1085:        ldcr    TMP2, SXIP
                   1086:        ldcr    TMP3, DMT0
                   1087:        st      TMP2, r31,  REG_OFF(EF_SXIP)
                   1088:
                   1089: /*
                   1090:  * The above shadow registers are obligatory for any and all
                   1091:  * exceptions.  Now, if the data access pipeline is not clear,
                   1092:  * we must save the DMx shadow registers, as well as clear
                   1093:  * the appropriate SSBR bits for the destination registers of
                   1094:  * loads or xmems.
                   1095:  */
                   1096:        bb0.n   DMT_VALID_BIT, TMP3, 8f
                   1097:         st     TMP3, r31,  REG_OFF(EF_DMT0)
                   1098:
                   1099:        ldcr    TMP2, DMT1
                   1100:        ldcr    TMP3, DMT2
                   1101:        st      TMP2, r31,  REG_OFF(EF_DMT1)
                   1102:        st      TMP3, r31,  REG_OFF(EF_DMT2)
                   1103:
                   1104:        ldcr    TMP2, DMA0
                   1105:        ldcr    TMP3, DMA1
                   1106:        st      TMP2, r31,  REG_OFF(EF_DMA0)
                   1107:        st      TMP3, r31,  REG_OFF(EF_DMA1)
                   1108:
                   1109:        ldcr    TMP2, DMA2
                   1110:        ldcr    TMP3, DMD0
                   1111:        st      TMP2, r31,  REG_OFF(EF_DMA2)
                   1112:        st      TMP3, r31,  REG_OFF(EF_DMD0)
                   1113:
                   1114:        FLUSH_PIPELINE
                   1115:        ldcr    TMP2, DMD1
                   1116:        ldcr    TMP3, DMD2
                   1117:        st      TMP2, r31,  REG_OFF(EF_DMD1)
                   1118:        st      TMP3, r31,  REG_OFF(EF_DMD2)
                   1119:
                   1120: /*
                   1121:  * need to clear "appropriate" bits in the SSBR before
                   1122:  * we restart the FPU
                   1123:  */
                   1124:
                   1125:        ldcr    TMP2, DMT0
                   1126:        bb0.n   DMT_VALID_BIT, TMP2, 8f
                   1127:        /* make sure an exception in fpu_enable will not see our DMT0 */
                   1128:         stcr   r0,   DMT0
                   1129:        bb1     DMT_LOCK_BIT,  TMP2, 1f
                   1130:        bb1     DMT_WRITE_BIT, TMP2, 2f
                   1131: 1:
                   1132:        extu    TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET>
                   1133:        set     TMP2, TMP2, 1<5>
                   1134:        clr     TMP,  TMP,  TMP2
                   1135: 2:
                   1136:        ldcr    TMP2, DMT1
                   1137:        bb0     DMT_VALID_BIT, TMP2, 4f
                   1138:        bb1     DMT_LOCK_BIT,  TMP2, 3f
                   1139:        bb1     DMT_WRITE_BIT, TMP2, 4f
                   1140: 3:
                   1141:        extu    TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET>
                   1142:        set     TMP2, TMP2, 1<5>
                   1143:        clr     TMP,  TMP,  TMP2
                   1144: 4:
                   1145:        ldcr    TMP2, DMT2
                   1146:        bb0     DMT_VALID_BIT, TMP2, 8f
                   1147:        bb1     DMT_LOCK_BIT,  TMP2, 5f
                   1148:        bb1     DMT_WRITE_BIT, TMP2, 8f
                   1149:        bb1     DMT_DOUBLE_BIT,TMP2, 6f
                   1150: 5:
                   1151:        extu    TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET>
                   1152:        br.n    7f
                   1153:         set    TMP2, TMP2, 1<5>        /* single */
                   1154: 6:
                   1155:        extu    TMP2, TMP2, DMT_DREG_WIDTH <DMT_DREG_OFFSET>
                   1156:        set     TMP2, TMP2, 1<6>        /* double */
                   1157: 7:
                   1158:        clr     TMP,  TMP,  TMP2
                   1159: 8:
                   1160:        /*
                   1161:         * SR1: saved copy of exception-time register now holding FLAGS
                   1162:         * SR2: return address to the calling exception handler
                   1163:         * SR3: saved TMP
                   1164:         * r1:  free
                   1165:         * TMP: possibly revised SSBR
                   1166:         * TMP2: free
                   1167:         * TMP3: free
                   1168:         * FLAGS: CPU status flags
                   1169:         * r31: exception frame
                   1170:         * Valid in the exception frame:
                   1171:         *   Exception-time r1, r31, FLAGS.
                   1172:         *   Exception-time TMP2, TMP3.
                   1173:         *   Exception-time espr, sfip, snip, sxip.
                   1174:         *   Dmt0.
                   1175:         *   Other data pipeline control registers, if appropriate.
                   1176:         *   Exception SR3, if appropriate.
                   1177:         */
                   1178:        ldcr    r1,   SR2
                   1179:        jmp     r1      /* allow the handler to clear more SSBR bits */
                   1180:
                   1181: ASLOCAL(clear_FPi_ssbr_bit)
                   1182:        /*
                   1183:         * Clear floatingpoint-imprecise ssbr bits.
                   1184:         * Also, save appropriate FPU control registers to the E.F.
                   1185:         *
                   1186:         * r1:  return address to calling exception handler
                   1187:         * TMP: (possibly) revised ssbr
                   1188:         * TMP2: free
                   1189:         * TMP3: free
                   1190:         */
                   1191:        fldcr   TMP2, FPSR
                   1192:        fldcr   TMP3, FPCR
                   1193:        st      TMP2, r31,  REG_OFF(EF_FPSR)
                   1194:        st      TMP3, r31,  REG_OFF(EF_FPCR)
                   1195:
                   1196:        fldcr   TMP2, FPECR
                   1197:        fldcr   TMP3, FPRH
                   1198:        st      TMP2, r31,  REG_OFF(EF_FPECR)
                   1199:        st      TMP3, r31,  REG_OFF(EF_FPRH)
                   1200:
                   1201:        fldcr   TMP2, FPIT
                   1202:        fldcr   TMP3, FPRL
                   1203:        st      TMP2, r31,  REG_OFF(EF_FPIT)
                   1204:        st      TMP3, r31,  REG_OFF(EF_FPRL)
                   1205:
                   1206:        /*
                   1207:         * We only need clear the bit in the SSBR for the
                   1208:         * 2nd reg of a double result [see section 6.8.5]
                   1209:         */
                   1210: #define FPIT_SIZE_BIT   10
                   1211:        bb0     FPIT_SIZE_BIT, TMP2, 1f
                   1212:        extu    TMP2, TMP2, 5<0>        /* get the reg. */
                   1213:        set     TMP2, TMP2, 1<6>        /* set width */
                   1214:        clr     TMP,  TMP,  TMP2
                   1215: 1:
                   1216:        jmp     r1
                   1217:
                   1218:
                   1219: ASLOCAL(clear_FPp_ssbr_bit)
                   1220:        /*
                   1221:         * Clear floating pont precise ssbr bits.
                   1222:         * Also, save appropriate FPU control registers to the E.F.
                   1223:         *
                   1224:         * r1:  return address to calling exception handler
                   1225:         * TMP: (possibly) revised ssbr
                   1226:         * TMP2: free
                   1227:         * TMP3: free
                   1228:         */
                   1229:        fldcr   TMP2, FPSR
                   1230:        fldcr   TMP3, FPCR
                   1231:        st      TMP2, r31,  REG_OFF(EF_FPSR)
                   1232:        st      TMP3, r31,  REG_OFF(EF_FPCR)
                   1233:
                   1234:        fldcr   TMP3, FPECR
                   1235:        st      TMP3, r31,  REG_OFF(EF_FPECR)
                   1236:        fldcr   TMP2, FPHS1
                   1237:        fldcr   TMP3, FPHS2
                   1238:        st      TMP2, r31,  REG_OFF(EF_FPHS1)
                   1239:        st      TMP3, r31,  REG_OFF(EF_FPHS2)
                   1240:
                   1241:        fldcr   TMP2, FPLS1
                   1242:        fldcr   TMP3, FPLS2
                   1243:        st      TMP2, r31,  REG_OFF(EF_FPLS1)
                   1244:        st      TMP3, r31,  REG_OFF(EF_FPLS2)
                   1245:
                   1246:        fldcr   TMP2, FPPT
                   1247:        st      TMP2, r31,  REG_OFF(EF_FPPT)
                   1248:
                   1249: #define FPPT_SIZE_BIT   5
                   1250:        bb1.n   FPPT_SIZE_BIT, TMP2, 2f
                   1251:         extu   TMP3, TMP2, 5<0>        /* get FP operation dest reg */
                   1252:        br.n    3f
                   1253:         set    TMP3, TMP3, 1<5>        /* size=1 - clear one bit for float */
                   1254: 2:
                   1255:        set     TMP3, TMP3, 1<6>        /* size=2 - clear two bit for double */
                   1256: 3:
                   1257:        jmp.n   r1
                   1258:         clr    TMP,  TMP,  TMP3        /* clear bit(s) in ssbr. */
                   1259:
                   1260:
                   1261: ASLOCAL(clear_dest_ssbr_bit)
                   1262:        /*
                   1263:         * There are various cases where an exception can leave the
                   1264:         * destination register's bit in the SB set.
                   1265:         * Examples:
                   1266:         *   misaligned or privilege exception on a LD or XMEM
                   1267:         *   DIV or DIVU by zero.
                   1268:         *
                   1269:         * I think that if the instruction is LD.D, then two bits must
                   1270:         * be cleared.
                   1271:         *
                   1272:         * Even though there are a number of instructions/exception
                   1273:         * combinations that could fire this code up, it's only required
                   1274:         * to be run for the above cases.  However, I don't think it'll
                   1275:         * ever be a problem to run this in other cases (ST instructions,
                   1276:         * for example), so I don't bother checking.  If we had to check
                   1277:         * for every possible instruction, this code would be much larger.
                   1278:         *
                   1279:         * The only checking, then, is to see if it's a LD.D or not.
                   1280:         *
                   1281:         * At the moment....
                   1282:         *  r1:  return address to calling exception handler
                   1283:         *  TMP: (possibly) revised ssbr
                   1284:         *  TMP2: free
                   1285:         *  TMP3: free
                   1286:         */
                   1287:
                   1288:        ldcr    TMP3, EPSR      /* going to check: user or system memory? */
                   1289:        ldcr    TMP2, SXIP      /* get the instruction's address */
                   1290:        bb1.n   PSR_SUPERVISOR_MODE_BIT, TMP3, 2f
                   1291:         clr    TMP2, TMP2, 2<0>        /* get rid of valid and error bits. */
                   1292:
                   1293:        /* user space load here */
                   1294: #if ERRATA__XXX_USR
                   1295:        NOP
                   1296:        ld.usr  TMP2,TMP2, r0   /* get the instruction itself */
                   1297:        NOP
                   1298:        NOP
                   1299:        NOP
                   1300:        br    3f
                   1301: #else
                   1302:        br.n  3f
                   1303:         ld.usr TMP2,TMP2, r0   /* get the instruction itself */
                   1304: #endif
                   1305:
                   1306: 2:     /* system space load here */
                   1307:        ld      TMP2, TMP2, r0  /* get the instruction itself */
                   1308:
                   1309: 3:     /* now we have the instruction..... */
                   1310:        /*
                   1311:         * Now see if it's a double load
                   1312:         * There are three forms of double load [IMM16, scaled, unscaled],
                   1313:         * which can be checked by matching against two templates:
                   1314:         *          -- 77776666555544443333222211110000 --
                   1315:         *   if (((instruction & 11111100000000000000000000000000) ==
                   1316:         *             00010000000000000000000000000000) ;;
                   1317:         *       ((instruction & 11111100000000001111110011100000) ==
                   1318:         *             11110100000000000001000000000000))
                   1319:         *   {
                   1320:         *      It's a load double, so
                   1321:         *      clear two SSBR bits.
                   1322:         *   } else {
                   1323:         *      It's not a load double.
                   1324:         *      Must be a load single, xmem, or st
                   1325:         *      Thus, clear one SSBR bit.
                   1326:         *   }
                   1327:         */
                   1328:        /* check the first pattern for ld.d */
                   1329:        extu    TMP3, TMP2, 16<16>      /* get the upper 16 bits */
                   1330:        mask    TMP3, TMP3, 0xFC00      /* apply the mask */
                   1331:        cmp     TMP3, TMP3, 0x1000      /* if equal, it's a load double */
                   1332:        bb1     eq,   TMP3, 2f
                   1333:
                   1334:        /* still could be -- check the second pattern for ld.d */
                   1335:        /* look at the upper 16 bits first */
                   1336:        extu    TMP3, TMP2, 16<16>      /* get the upper 16 bits */
                   1337:        mask    TMP3, TMP3, 0xFC00      /* apply the mask */
                   1338:        cmp     TMP3, TMP3, 0xF400      /* if equal, might be a load double */
                   1339:        bb1     ne,   TMP3, 1f          /* not equal, must be single */
                   1340:
                   1341:        /* now look at the lower 16 bits */
                   1342:        extu    TMP3, TMP2, 16<0>       /* get the lower 16 bits */
                   1343:        mask    TMP3, TMP3, 0xFCE0      /* apply the mask */
                   1344:        cmp     TMP3, TMP3, 0x1000      /* if equal, it's a load double */
                   1345:        bb1     eq,   TMP3, 2f
                   1346:
                   1347: 1:     /* misaligned single */
                   1348:        extu    TMP2, TMP2, 5<21>       /* get the destination register */
                   1349:        br.n    3f
                   1350:         set    TMP2, TMP2, 1<5>        /* set size=1 */
                   1351:
                   1352: 2:     /* misaligned double */
                   1353:        extu    TMP2, TMP2, 5<21>       /* get the destination register */
                   1354:        set     TMP2, TMP2, 1<6>        /* set size=2 -- clear two bits */
                   1355: 3:
                   1356:        jmp.n   r1
                   1357:         clr    TMP,  TMP,  TMP2        /* clear bit(s) in ssbr. */
                   1358:
                   1359: ASLOCAL(m88100_setup_phase_two)
                   1360:        /*
                   1361:         * SR1: saved copy of exception-time register now holding FLAGS
                   1362:         * SR2: free
                   1363:         * SR3: saved TMP
                   1364:         * r1:  return address to calling exception handler
                   1365:         * TMP: possibly revised SSBR
                   1366:         * TMP2: free
                   1367:         * TMP3: free
                   1368:         * FLAGS: CPU status flags
                   1369:         * r31: our exception frame
                   1370:         *    Valid in the exception frame:
                   1371:         *   Exception-time r1, r31, FLAGS.
                   1372:         *   Exception-time TMP2, TMP3.
                   1373:         *   Exception-time espr, sfip, snip, sxip.
                   1374:         *   Exception number (EF_VECTOR).
                   1375:         *   Dmt0
                   1376:         *   Other data pipeline control registers, if appropriate.
                   1377:         *   FPU control registers, if appropriate.
                   1378:         *   Exception SR3, if appropriate.
                   1379:         *
                   1380:         * immediate goal:
                   1381:         *   restore the system to the exception-time state (except
                   1382:         *   SR3 will be OUR stack pointer) so that we may resart the FPU.
                   1383:         */
                   1384:
                   1385:        stcr    TMP,  SSBR      /* done with SSBR, TMP now free */
                   1386:        RESTORE_TMP2    /* done with extra temp regs */
                   1387:        RESTORE_TMP3    /* done with extra temp regs */
                   1388:
                   1389:        /* Get the current PSR and modify for the rte to enable the FPU */
                   1390:        ldcr    TMP,  PSR
                   1391:        clr     TMP,  TMP,  1<PSR_FPU_DISABLE_BIT>      /* enable the FPU */
                   1392:        clr     TMP,  TMP,  1<PSR_SHADOW_FREEZE_BIT>    /* and shadowing */
                   1393:        stcr    TMP,  EPSR
                   1394:
                   1395:        /* the "+2" below is to set the VALID_BIT */
                   1396:        or.u    TMP,  r0,   hi16(_ASM_LABEL(m88100_fpu_enable) + 2)
                   1397:        or      TMP,  TMP,  lo16(_ASM_LABEL(m88100_fpu_enable) + 2)
                   1398:        stcr    TMP,  SNIP
                   1399:        addu    TMP,  TMP,  4
                   1400:        stcr    TMP,  SFIP
                   1401:
                   1402:        set     FLAGS, FLAGS, 1<FLAG_ENABLING_FPU>
                   1403:        xcr     FLAGS, FLAGS, SR1
                   1404:        st      r1,   r31,  REG_OFF(EF_RET)     /* save the return address */
                   1405:        ld      r1,   r31,  GENREG_OFF(1)       /* get original r1 */
                   1406:
                   1407:        xcr     TMP,  r31,  SR3 /* TMP now restored. R31 now saved in SR3 */
                   1408:        ld      r31,  r31,  GENREG_OFF(31)      /* get original r31 */
                   1409:
                   1410:        /*
                   1411:         * SR1: CPU flags
                   1412:         * SR2: free
                   1413:         * SR3: pointer to our exception frame (our stack pointer)
                   1414:         * r1 through r31: original exception-time values
                   1415:         *
                   1416:         * Valid in the exception frame:
                   1417:         *   Exception-time FLAGS.
                   1418:         *   Exception-time espr, sfip, snip, sxip.
                   1419:         *   Exception number (EF_VECTOR).
                   1420:         *   Dmt0
                   1421:         *   Other data pipeline control registers, if appropriate.
                   1422:         *   FPU control registers, if appropriate.
                   1423:         *   Exception SR3, if appropriate.
                   1424:         *   Held temporarly in the exception frame:
                   1425:         *   Return address to the calling exception handler.
                   1426:         *
                   1427:         * immediate goal:
                   1428:         *   Do an RTE to restart the fpu and jump to "fpu_enable"
                   1429:         *   Another exception (or exceptions) may be raised in
                   1430:         *   this, which is why FLAG_ENABLING_FPU is set in SR1.
                   1431:         */
                   1432:
                   1433:        RTE     /* jumps to "m88100_fpu_enable" to enable the FPU. */
                   1434:
                   1435: ASLOCAL(m88100_fpu_enable)
                   1436:        FLUSH_PIPELINE
                   1437:        xcr     TMP,  TMP,  SR3                 /* get E.F. pointer */
                   1438:        st      r30,  TMP,  GENREG_OFF(30)      /* save previous r30, r31 */
                   1439:        st      r31,  TMP,  GENREG_OFF(31)      /* save previous r30, r31 */
                   1440:        or      r31,  TMP,  r0                  /* transfer E.F. pointer to r31 */
                   1441:        ld      TMP,  r31,  REG_OFF(EF_SR3)     /* get previous SR3 */
                   1442:
                   1443:        /* make sure that the FLAG_ENABLING_FPU bit is off */
                   1444:        xcr     FLAGS,FLAGS,SR1
                   1445:        clr     FLAGS,FLAGS,1<FLAG_ENABLING_FPU>
                   1446:        xcr     FLAGS,FLAGS,SR1
                   1447:
                   1448:        xcr     TMP,  TMP,  SR3 /* replace TMP, SR3 */
                   1449:
                   1450:        /* now save all regs to the exception frame. */
                   1451:        st      r0 ,  r31,  GENREG_OFF(0)
                   1452:        st      r1 ,  r31,  GENREG_OFF(1)
                   1453:        st      r2 ,  r31,  GENREG_OFF(2)
                   1454:        st      r3 ,  r31,  GENREG_OFF(3)
                   1455:        st      r4 ,  r31,  GENREG_OFF(4)
                   1456:        st      r5 ,  r31,  GENREG_OFF(5)
                   1457:        st      r6 ,  r31,  GENREG_OFF(6)
                   1458:        st      r7 ,  r31,  GENREG_OFF(7)
                   1459:        st      r8 ,  r31,  GENREG_OFF(8)
                   1460:        st      r9 ,  r31,  GENREG_OFF(9)
                   1461:        st      r10,  r31,  GENREG_OFF(10)
                   1462:        st      r11,  r31,  GENREG_OFF(11)
                   1463:        st      r12,  r31,  GENREG_OFF(12)
                   1464:        st      r13,  r31,  GENREG_OFF(13)
                   1465:        st      r14,  r31,  GENREG_OFF(14)
                   1466:        st      r15,  r31,  GENREG_OFF(15)
                   1467:        st      r16,  r31,  GENREG_OFF(16)
                   1468:        st      r17,  r31,  GENREG_OFF(17)
                   1469:        st      r18,  r31,  GENREG_OFF(18)
                   1470:        st      r19,  r31,  GENREG_OFF(19)
                   1471:        st      r20,  r31,  GENREG_OFF(20)
                   1472:        st      r21,  r31,  GENREG_OFF(21)
                   1473:        st      r22,  r31,  GENREG_OFF(22)
                   1474:        st      r23,  r31,  GENREG_OFF(23)
                   1475:        st      r24,  r31,  GENREG_OFF(24)
                   1476:        st      r25,  r31,  GENREG_OFF(25)
                   1477:        st      r26,  r31,  GENREG_OFF(26)
                   1478:        st      r27,  r31,  GENREG_OFF(27)
                   1479:        st      r28,  r31,  GENREG_OFF(28)
                   1480:
                   1481:        /* get and save IPL */
                   1482:        bsr.n   _C_LABEL(getipl)
                   1483:         st     r29,  r31,  GENREG_OFF(29)
                   1484:        st      r2, r31, REG_OFF(EF_MASK)
                   1485:
                   1486:        /*
                   1487:         * SR1: free
                   1488:         * SR2: free
                   1489:         * SR3: previous exception-time SR3
                   1490:         * r1: return address to the calling exception handler
                   1491:         * r2 through r30: free
                   1492:         * r31: our exception frame
                   1493:         *
                   1494:         * Valid in the exception frame:
                   1495:         *   Exception-time r0 through r31.
                   1496:         *   Exception-time FLAGS.
                   1497:         *   Exception-time espr, sfip, snip, sxip.
                   1498:         *   Exception number (EF_VECTOR).
                   1499:         *   Dmt0
                   1500:         *   Other data pipeline control registers, if appropriate.
                   1501:         *   FPU control registers, if appropriate.
                   1502:         *   Exception SR3, if appropriate.
                   1503:         *
                   1504:         * immediate goal:
                   1505:         *   Pick up a stack if we came in from user mode.
                   1506:         *   Put a copy of the exception frame pointer into r30
                   1507:         *   Bump the stack a doubleword and write the exception frame pointer.
                   1508:         *   If not an interrupt exception, turn on interrupts and service any
                   1509:         *     outstanding data access exceptions.
                   1510:         *   Return to calling exception handler to service the exception.
                   1511:         */
                   1512:
                   1513:        /*
                   1514:         * If it's not the interrupt exception, enable interrupts and
                   1515:         * take care of any data access exceptions......
                   1516:         */
                   1517:        or      r30,  r0,   r31         /* get a copy of the e.f. pointer */
                   1518:        ld      r2,   r31,  REG_OFF(EF_EPSR)
                   1519:        bb1     PSR_SUPERVISOR_MODE_BIT, r2, 1f /* if in kernel mode */
                   1520:
                   1521:        ldcr    r31,  CPU
                   1522:        ld      r31,  r31,  CI_CURPCB
                   1523:        addu    r31,  r31,  USIZE       /* point at proper end */
                   1524: 1:
                   1525:
                   1526:        /*
                   1527:         * here - r30 holds a pointer to the exception frame.
                   1528:         * r31 is a pointer to the kernel stack/interrupt stack.
                   1529:         */
                   1530:        subu    r31,  r31,  8   /* make some breathing space */
                   1531:        st      r30,  r31,  0   /* store frame pointer on the stack */
                   1532: #ifdef DDB
                   1533:        st      r30,  r31,  4   /* store it for the debugger to recognize */
                   1534: #endif
                   1535:
                   1536:        ld      r2,   r30,  REG_OFF(EF_VECTOR)
                   1537:        bcnd.n  eq0,  r2,   8f                  /* error exception */
                   1538:         ld     r14,  r30,  REG_OFF(EF_RET)
                   1539:
                   1540:        /*
                   1541:         * Do not process possible data exceptions here if this is an interrupt.
                   1542:         * Instead, the interrupt handler will take care of this by itself.
                   1543:         */
                   1544:        cmp     r3,   r2,   1                   /* is an interrupt? */
                   1545:        bb1.n   eq,   r3,   8f                  /* skip if so */
                   1546:
                   1547: #ifdef DDB
                   1548:         cmp    r3,   r2,   130 /* DDB break exception */
                   1549:        bb1.n   eq,   r3,   8f
                   1550:         cmp    r3,   r2,   132 /* DDB entry exception */
                   1551:        bb1.n   eq,   r3,   8f
                   1552: #endif
                   1553:
                   1554:        /* turn interrupts back on */
                   1555:         ldcr   r2,   PSR
                   1556:        clr     r2,   r2,   1<PSR_INTERRUPT_DISABLE_BIT>
                   1557:        stcr    r2,   PSR
                   1558:        FLUSH_PIPELINE
                   1559:
                   1560:        /* service any outstanding data pipeline stuff */
                   1561:        ld      r3,   r30,  REG_OFF(EF_DMT0)
                   1562:        bb0     DMT_VALID_BIT, r3, 8f
                   1563:
                   1564:        /*
                   1565:         * r30 can be clobbered by calls. So stuff its value into a preserved
                   1566:         * register, say r15. R14 is in use (see return_to_... below).
                   1567:         */
                   1568:        or      r15,  r0,   r30
                   1569:        CALL(m88100_trap, T_DATAFLT, r15)
                   1570:        or      r30,  r0,   r15
                   1571:
                   1572: 8:
                   1573:        jmp     r14     /* loaded above */
                   1574: #endif /* M88100 */
                   1575:
                   1576: #ifdef M88110
                   1577: /*
                   1578:  * 88110 exception handlers
                   1579:  */
                   1580:
                   1581: /* unknown exception handler */
                   1582: GLOBAL(m88110_unknown_handler)
                   1583:        PREP88110("unknown", 0,)
                   1584:        or      r2, r0, T_UNKNOWNFLT
                   1585:        or      r3, r0, r30
                   1586:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1587:
                   1588: /* interrupt exception handler */
                   1589: GLOBAL(m88110_interrupt_handler)
                   1590:        PREP88110("interrupt", 1,)
                   1591:        or      r2, r0, T_INT
                   1592:        or      r3, r0, r30
                   1593:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1594:
                   1595: /* instruction access exception handler */
                   1596: GLOBAL(m88110_instruction_access_handler)
                   1597:        PREP88110("inst", 2,)
                   1598:        or      r2, r0, T_INSTFLT
                   1599:        or      r3, r0, r30
                   1600:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1601: /*
                   1602:  * data access exception handler --
                   1603:  *  See badaddr() below for info about Data_Precheck.
                   1604:  */
                   1605: GLOBAL(m88110_data_exception_handler)
                   1606:        PREP88110("data", 3, M88110_Data_Precheck)
                   1607:        or      r2, r0, T_DATAFLT
                   1608:        or      r3, r0, r30
                   1609:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1610:
                   1611: /* misaligned access exception handler */
                   1612: GLOBAL(m88110_misaligned_handler)
                   1613:        PREP88110("misalign", 4,)
                   1614:        or      r2, r0, T_MISALGNFLT
                   1615:        or      r3, r0, r30
                   1616:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1617:
                   1618: /* unimplemented opcode exception handler */
                   1619: GLOBAL(m88110_unimplemented_handler)
                   1620:        PREP88110("unimp", 5,)
                   1621:        or      r2, r0, T_ILLFLT
                   1622:        or      r3, r0, r30
                   1623:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1624:
                   1625: /* privilege exception handler */
                   1626: GLOBAL(m88110_privilege_handler)
                   1627:        PREP88110("privilege", 6,)
                   1628:        or      r2, r0, T_PRIVINFLT
                   1629:        or      r3, r0, r30
                   1630:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1631:
                   1632: /* bounds checking exception handler */
                   1633: GLOBAL(m88110_bounds_handler)
                   1634:        PREP88110("bounds", 7,)
                   1635:        or      r2, r0, T_BNDFLT
                   1636:        or      r3, r0, r30
                   1637:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1638:
                   1639: /* integer divide-by-zero exception handler */
                   1640: GLOBAL(m88110_divide_handler)
                   1641:        PREP88110("divide", 8,)
                   1642:        or      r2, r0, T_ZERODIV
                   1643:        or      r3, r0, r30
                   1644:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1645:
                   1646: /* integer overflow exception handler */
                   1647: GLOBAL(m88110_overflow_handler)
                   1648:        PREP88110("overflow", 9,)
                   1649:        or      r2, r0, T_OVFFLT
                   1650:        or      r3, r0, r30
                   1651:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1652:
                   1653: /* Floating-point precise handler */
                   1654: GLOBAL(m88110_fp_precise_handler)
                   1655:        PREP88110("FPU precise", 114,)
                   1656:        or      r3, r0, r30
                   1657:        XCALL(_ASM_LABEL(m88110_Xfp_precise), _ASM_LABEL(check_ast))
                   1658:
                   1659: /* MVME197 non-maskable interrupt handler (ABORT button) */
                   1660: GLOBAL(m88110_nonmaskable)
                   1661:        PREP88110("NMI", 11,)
                   1662:        or      r2, r0, T_NON_MASK
                   1663:        or      r3, r0, r30
                   1664:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1665:
                   1666: /* software walk data MMU read miss handler */
                   1667: GLOBAL(m88110_data_read_miss)
                   1668:        PREP88110("88110 data read miss", 12,)
                   1669:        or      r2, r0, T_110_DRM
                   1670:        or      r3, r0, r30
                   1671:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1672:
                   1673: /* software walk data MMU write miss handler */
                   1674: GLOBAL(m88110_data_write_miss)
                   1675:        PREP88110("88110 data write miss", 13,)
                   1676:        or      r2, r0, T_110_DWM
                   1677:        or      r3, r0, r30
                   1678:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1679:
                   1680: /* software walk inst MMU ATC miss handler */
                   1681: GLOBAL(m88110_inst_atc_miss)
                   1682:        PREP88110("88110 inst ATC miss", 14,)
                   1683:        or      r2, r0, T_110_IAM
                   1684:        or      r3, r0, r30
                   1685:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1686:
                   1687: /* trap 450: system calls */
                   1688: GLOBAL(m88110_syscall_handler)
                   1689:        PREP88110("syscall", 450,)
                   1690:        ld      r2, r30, GENREG_OFF(13)
                   1691:        or      r3, r0, r30
                   1692:        XCALL(_C_LABEL(m88110_syscall), _ASM_LABEL(check_ast))
                   1693:
                   1694: /* trap 451: cache flush (necessary for trampolines) */
                   1695: GLOBAL(m88110_cache_flush_handler)
                   1696:        PREP88110("cache_flush", 451,)
                   1697:        or      r2, r0, r30
                   1698:        XCALL(_C_LABEL(cache_flush), _ASM_LABEL(check_ast))
                   1699:
                   1700: GLOBAL(m88110_sigsys)
                   1701:        PREP88110("sigsys", 501,)
                   1702:        or      r2, r0, T_SIGSYS
                   1703:        or      r3, r0, r30
                   1704:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1705:
                   1706: GLOBAL(m88110_stepbpt)
                   1707:        PREP88110("stepbpt", 504,)
                   1708:        or      r2, r0, T_STEPBPT
                   1709:        or      r3, r0, r30
                   1710:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1711:
                   1712: GLOBAL(m88110_userbpt)
                   1713:        PREP88110("userbpt", 511,)
                   1714:        or      r2, r0, T_USERBPT
                   1715:        or      r3, r0, r30
                   1716:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1717:
                   1718: #ifdef DDB
                   1719: GLOBAL(m88110_break)
                   1720:        PREP88110("break", 130,)
                   1721:        or      r2, r0, T_KDB_BREAK
                   1722:        or      r3, r0, r30
                   1723:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1724:
                   1725: GLOBAL(m88110_trace)
                   1726:        PREP88110("trace", 131,)
                   1727:        or      r2, r0, T_KDB_TRACE
                   1728:        or      r3, r0, r30
                   1729:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1730:
                   1731: GLOBAL(m88110_entry)
                   1732:        PREP88110("kdb", 132,)
                   1733:        or      r2, r0, T_KDB_ENTRY
                   1734:        or      r3, r0, r30
                   1735:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(check_ast))
                   1736: #endif
                   1737:
                   1738: /*
                   1739:  * The error exception and reset exception handler.
                   1740:  *
                   1741:  * The error exception is raised when any other non-trap exception is raised
                   1742:  * while shadowing is off. This is Bad News.
                   1743:  *
                   1744:  * The reset exception is raised when the RST signal is asserted (machine
                   1745:  * is reset), the value of VBR is changed after exceptions are enabled,
                   1746:  * or when a jmp, br/bsr to addr 0 (accidents do happen :-)
                   1747:  * Upon a real reset, VBR is set to zero (0), so code must be at addr 0
                   1748:  * to handle it!!!
                   1749:  *
                   1750:  * The shadow registers are not valid in this case (shadowing was off, if this
                   1751:  * was an error exception, and may not be on, if this was a reset exception).
                   1752:  * R1-R31 may be interesting though, so we'll save them.
                   1753:  *
                   1754:  * We'll not worry about trashing r26-29 here,
                   1755:  * since they aren't generally used.
                   1756:  */
                   1757: GLOBAL(m88110_error_handler)
                   1758:        br.n    1f
                   1759:         or     r29, r0, 10
                   1760: GLOBAL(m88110_reset_handler)
                   1761:        or      r29, r0, 0
                   1762: 1:
                   1763:        or      r26, r0, r31    /* save old stack */
                   1764:        or.u    r31, r0,  hi16(_ASM_LABEL(intstack_end))
                   1765:        or      r31, r31, lo16(_ASM_LABEL(intstack_end))
                   1766:
                   1767: #ifdef DEBUG
                   1768:        /* zero the stack, so we'll know what we're lookin' at */
                   1769:        or.u    r27, r0,  hi16(_ASM_LABEL(intstack))
                   1770:        or      r27, r27, lo16(_ASM_LABEL(intstack))
                   1771: 1:     cmp     r28, r27, r31
                   1772:        bb1     ge,  r28, 2f    /* branch if at the end of the stack */
                   1773:        st      r0,  r0,  r27
                   1774:        br.n    1b
                   1775:         addu   r27, r27, 4     /* bump up */
                   1776: 2:     /* stack has been cleared */
                   1777: #endif
                   1778:
                   1779:        /* ensure that stack is 8-byte aligned */
                   1780:        clr     r31, r31, 3<0>  /* round down to 8-byte boundary */
                   1781:
                   1782:        /* create exception frame on stack */
                   1783:        subu    r31, r31, SIZEOF_EF             /* r31 now our E.F. */
                   1784:
                   1785:        /* save old R31 and other R registers */
                   1786:        st.d    r0 , r31, GENREG_OFF(0)
                   1787:        st.d    r2 , r31, GENREG_OFF(2)
                   1788:        st.d    r4 , r31, GENREG_OFF(4)
                   1789:        st.d    r6 , r31, GENREG_OFF(6)
                   1790:        st.d    r8 , r31, GENREG_OFF(8)
                   1791:        st.d    r10, r31, GENREG_OFF(10)
                   1792:        st.d    r12, r31, GENREG_OFF(12)
                   1793:        st.d    r14, r31, GENREG_OFF(14)
                   1794:        st.d    r16, r31, GENREG_OFF(16)
                   1795:        st.d    r18, r31, GENREG_OFF(18)
                   1796:        st.d    r20, r31, GENREG_OFF(20)
                   1797:        st.d    r22, r31, GENREG_OFF(22)
                   1798:        st.d    r24, r31, GENREG_OFF(24)
                   1799:        st      r30, r31, GENREG_OFF(30)
                   1800:        st      r26, r31, GENREG_OFF(31)
                   1801:
                   1802:        /* vector is put in SRO (either 0 or 10 at this point) */
                   1803:        st      r29, r31, REG_OFF(EF_VECTOR)
                   1804:        cmp     r29, r29, 0     /* is it the reset exception? */
                   1805:        bb1.n   ne,  r29, 1f    /* if not, skip */
                   1806:
                   1807:        /* save shadow registers (are OLD if error_handler, though) */
                   1808:         ldcr   r10, EPSR
                   1809:        st      r10, r31, REG_OFF(EF_EPSR)
                   1810:        ldcr    r10, EXIP
                   1811:        st      r10, r31, REG_OFF(EF_EXIP)
                   1812:        ldcr    r10, ENIP
                   1813:        st      r10, r31, REG_OFF(EF_ENIP)
                   1814:        ldcr    r10, DSR
                   1815:        st      r10, r31, REG_OFF(EF_DSR)
                   1816:        ldcr    r10, DLAR
                   1817:        st      r10, r31, REG_OFF(EF_DLAR)
                   1818:        ldcr    r10, DPAR
                   1819:        st      r10, r31, REG_OFF(EF_DPAR)
                   1820:        ldcr    r10, ISR
                   1821:        st      r10, r31, REG_OFF(EF_ISR)
                   1822:        ldcr    r10, ILAR
                   1823:        st      r10, r31, REG_OFF(EF_ILAR)
                   1824:        ldcr    r10, IPAR
                   1825:        st      r10, r31, REG_OFF(EF_IPAR)
                   1826:        ldcr    r10, SR1
                   1827:        br.n    2f
                   1828:         st     r10, r31, REG_OFF(EF_MODE)
                   1829:
                   1830: 1:
                   1831:        /* retrieve saved shadow registers for error_handler */
                   1832:        or.u    r30, r0,  hi16(_ASM_LABEL(save_frame))
                   1833:        or      r30, r30, lo16(_ASM_LABEL(save_frame))
                   1834:        ld      r10, r30, REG_OFF(EF_EPSR)
                   1835:        st      r10, r31, REG_OFF(EF_EPSR)
                   1836:        ld      r10, r30, REG_OFF(EF_EXIP)
                   1837:        st      r10, r31, REG_OFF(EF_EXIP)
                   1838:        ld      r10, r30, REG_OFF(EF_ENIP)
                   1839:        st      r10, r31, REG_OFF(EF_ENIP)
                   1840:        ld      r10, r30, REG_OFF(EF_DSR)
                   1841:        st      r10, r31, REG_OFF(EF_DSR)
                   1842:        ld      r10, r30, REG_OFF(EF_DLAR)
                   1843:        st      r10, r31, REG_OFF(EF_DLAR)
                   1844:        ld      r10, r30, REG_OFF(EF_DPAR)
                   1845:        st      r10, r31, REG_OFF(EF_DPAR)
                   1846:        ld      r10, r30, REG_OFF(EF_ISR)
                   1847:        st      r10, r31, REG_OFF(EF_ISR)
                   1848:        ld      r10, r30, REG_OFF(EF_ILAR)
                   1849:        st      r10, r31, REG_OFF(EF_ILAR)
                   1850:        ld      r10, r30, REG_OFF(EF_IPAR)
                   1851:        st      r10, r31, REG_OFF(EF_IPAR)
                   1852:        ld      r10, r30, REG_OFF(EF_ISAP)
                   1853:        st      r10, r31, REG_OFF(EF_ISAP)
                   1854:        ld      r10, r30, REG_OFF(EF_DSAP)
                   1855:        st      r10, r31, REG_OFF(EF_DSAP)
                   1856:        ld      r10, r30, REG_OFF(EF_IUAP)
                   1857:        st      r10, r31, REG_OFF(EF_IUAP)
                   1858:        ld      r10, r30, REG_OFF(EF_DUAP)
                   1859:        st      r10, r31, REG_OFF(EF_DUAP)
                   1860:        ldcr    r10, SR1
                   1861:        st      r10, r31, REG_OFF(EF_MODE)
                   1862: 2:
                   1863:        /* shove sr2 into EF_FPLS1 */
                   1864:        ldcr    r10, SR2
                   1865:        st      r10, r31, REG_OFF(EF_FPLS1)
                   1866:
                   1867:        /* shove sr3 into EF_FPHS2 */
                   1868:        ldcr    r10, SR3
                   1869:        st      r10, r31, REG_OFF(EF_FPHS2)
                   1870:
                   1871:        /*
                   1872:         * Cheap way to enable FPU and start shadowing again.
                   1873:         */
                   1874:        ldcr    r10, PSR
                   1875:        clr     r10, r10, 1<PSR_FPU_DISABLE_BIT>        /* enable the FPU */
                   1876:        clr     r10, r10, 1<PSR_SHADOW_FREEZE_BIT>      /* and shadowing */
                   1877:        stcr    r10, PSR
                   1878:        FLUSH_PIPELINE
                   1879:
                   1880:        /* put pointer to regs into r30... r31 will become a simple stack */
                   1881:        or      r30, r31, r0
                   1882:
                   1883:        subu    r31, r31, 0x10  /* make some breathing space */
                   1884:        st      r30, r31, 0x0c  /* store frame pointer on the stack */
                   1885: #ifdef DDB
                   1886:        st      r30, r31, 0x08  /* store again for the debugger to recognize */
                   1887:        or.u    r20,  r0, hi16(0x87654321)
                   1888:        or      r20, r20, lo16(0x87654321)
                   1889:        st      r20, r31, 0x04
                   1890:        st      r20, r31, 0x00
                   1891: #endif
                   1892:
                   1893:        bsr.n   _C_LABEL(error_fatal)
                   1894:         or     r2, r0, r30
                   1895:
                   1896:        /* turn interrupts back on */
                   1897:        ldcr    r1, PSR
                   1898:        clr     r1, r1, 1<PSR_INTERRUPT_DISABLE_BIT>
                   1899:        stcr    r1, PSR
                   1900:        FLUSH_PIPELINE
                   1901:
                   1902: 1:
                   1903:        br      1b
                   1904:        /* NOTREACHED */
                   1905:
                   1906: ASLOCAL(m88110_setup_phase_one)
                   1907:        /*
                   1908:         * SR1: saved copy of exception-time register now holding FLAGS
                   1909:         * SR2: saved copy of exception-time r1
                   1910:         * SR3: must be preserved .. may be the exception-time stack
                   1911:         * r1: return address to calling exception handler
                   1912:         * FLAGS: CPU status flags
                   1913:         *
                   1914:         * immediate goal:
                   1915:         *   Decide where we're going to put the exception frame.
                   1916:         *   Might be at the end of R31, SR3, or the process pcb.
                   1917:         */
                   1918:
                   1919:        /* Check if we are coming in from a FPU restart exception.
                   1920:           If so, the pcb will be in SR3 */
                   1921:        NOP
                   1922:        xcr     r1,   r1,   SR2
                   1923:        NOP
                   1924:        NOP
                   1925:        NOP
                   1926:
                   1927:        bb1     FLAG_ENABLING_FPU, FLAGS, _ASM_LABEL(m88110_use_SR3_pcb)
                   1928:        /* are we coming in from user mode? If so, pick up process pcb */
                   1929:        bb0     FLAG_FROM_KERNEL, FLAGS, _ASM_LABEL(m88110_pickup_stack)
                   1930:
                   1931:        /* Interrupt in kernel mode, not FPU restart */
                   1932:        /*
                   1933:         * SR1: saved copy of exception-time register now holding FLAGS
                   1934:         * SR2: return address to the calling exception handler
                   1935:         * SR3: must be preserved; may be important for other exceptions
                   1936:         * FLAGS: CPU status flags
                   1937:         *
                   1938:         * immediate goal:
                   1939:         *   We're already on the kernel stack, but not having
                   1940:         *   needed to use SR3. We can just make room on the
                   1941:         *   stack (r31) for our exception frame.
                   1942:         */
                   1943:        subu    r31,  r31,  SIZEOF_EF           /* r31 now our E.F. */
                   1944:        st      FLAGS,r31,  REG_OFF(EF_FLAGS)   /* save flags */
                   1945:        st      r1,   r31,  GENREG_OFF(1)       /* save prev. r1 (now free) */
                   1946:
                   1947:        ldcr    r1,   SR3                       /* save previous SR3 */
                   1948:        st      r1,   r31,  REG_OFF(EF_SR3)
                   1949:
                   1950:        addu    r1,   r31,  SIZEOF_EF           /* save previous r31 */
                   1951:        br.n    _ASM_LABEL(m88110_have_pcb)
                   1952:         st     r1,   r31,  GENREG_OFF(31)
                   1953:
                   1954: ASLOCAL(m88110_use_SR3_pcb)
                   1955:        /*
                   1956:         * SR1: saved copy of exception-time register now holding FLAGS
                   1957:         * SR2: return address to the calling exception handler
                   1958:         * SR3: must be preserved; exception-time stack pointer
                   1959:         * FLAGS: CPU status flags
                   1960:         *
                   1961:         * immediate goal:
                   1962:         *   An exception occurred while enabling the FPU. Since r31 is the
                   1963:         *   user's r31 while enabling the FPU, we had put our pcb pointer
                   1964:         *   into SR3, so make room from there for our stack pointer.
                   1965:         *   We need to check if SR3 is the old stack pointer or the pointer
                   1966:         *   off to the user pcb. If it pointing to the user pcb, we need to
                   1967:         *   pick up the kernel stack. Otherwise we need to allocate a frame
                   1968:         *   upon it.
                   1969:         *   We look at the EPSR to see if it was from user mode
                   1970:         *   Unfortunately, we have no registers free at the moment, but we
                   1971:         *   know register 0 in the pcb frame will always be zero, so we can
                   1972:         *   use it as scratch storage.
                   1973:         */
                   1974: #if 1
                   1975:        ldcr    TMP,  PSR
                   1976:        clr     TMP,  TMP,  1<PSR_FPU_DISABLE_BIT>      /* enable the FPU */
                   1977:        clr     TMP,  TMP,  1<PSR_SHADOW_FREEZE_BIT>    /* and shadowing */
                   1978:        stcr    TMP,  EPSR
                   1979:
                   1980:        or.u    TMP,  r0,   hi16(_C_LABEL(m88110_error_handler))
                   1981:        or      TMP,  TMP,  lo16(_C_LABEL(m88110_error_handler))
                   1982:        stcr    TMP,  EXIP
                   1983:
                   1984:        RTE
                   1985: #else
                   1986:        /* Testing!!! */
                   1987:        xcr     r30,  r30,  SR3                 /* r30 = old exception frame */
                   1988:        st      r1,   r30,  GENREG_OFF(0)       /* free up r1 */
                   1989:        ld      r1,   r30,  REG_OFF(EF_EPSR)    /* get back the epsr */
                   1990:        bb0.n   PSR_SUPERVISOR_MODE_BIT, r1, 1f /* if user mode */
                   1991:         ld     r1,   r30,  GENREG_OFF(0)       /* restore r1 */
                   1992:        /* we were in kernel mode - dump frame upon the stack */
                   1993:        st      r0,   r30,  GENREG_OFF(0)       /* repair old frame */
                   1994:        subu    r30,  r30,  SIZEOF_EF           /* r30 now our E.F. */
                   1995:        st      FLAGS,r30,  REG_OFF(EF_FLAGS)   /* save flags */
                   1996:        st      r1,   r30,  GENREG_OFF(1)       /* save prev. r1 (now free) */
                   1997:
                   1998:        st      r31,  r30,  GENREG_OFF(31)      /* save previous r31 */
                   1999:        or      r31,  r0,   r30                 /* make r31 our pointer. */
                   2000:        addu    r30,  r30,  SIZEOF_EF           /* r30 now has previous SR3 */
                   2001:        st      r30,  r31,  REG_OFF(EF_SR3)     /* save previous SR3 */
                   2002:        br.n    _ASM_LABEL(m88110_have_pcb)
                   2003:         xcr    r30,  r30,  SR3                 /* restore r30 */
                   2004: 1:
                   2005:        /*
                   2006:         * We took an exception while restarting the FPU from user space.
                   2007:         * Consequently, we never picked up a stack. Do so now.
                   2008:         * R1 is currently free (saved in the exception frame pointed at by
                   2009:         * r30)
                   2010:         */
                   2011:        ldcr    r1,   CPU
                   2012:        ld      r1,   r1,   CI_CURPCB
                   2013:        addu    r1,   r1,   USIZE - SIZEOF_EF
                   2014:        st      FLAGS,r1,   REG_OFF(EF_FLAGS)   /* store flags */
                   2015:        st      r31,  r1,   GENREG_OFF(31)      /* store r31 - now free */
                   2016:        st      r30,  r1,   REG_OFF(EF_SR3)     /* store old SR3 (pcb) */
                   2017:        or      r31,  r1,   r0                  /* make r31 our exception fp */
                   2018:        ld      r1,   r30,  GENREG_OFF(0)       /* restore old r1 */
                   2019:        st      r0,   r30,  GENREG_OFF(0)       /* repair that frame */
                   2020:        st      r1,   r31,  GENREG_OFF(1)       /* store r1 */
                   2021:        br.n    _ASM_LABEL(m88110_have_pcb)
                   2022:         xcr    r30,  r30,  SR3                 /* restore r30 */
                   2023: #endif
                   2024:
                   2025: ASLOCAL(m88110_pickup_stack)
                   2026:        /*
                   2027:         * SR1: saved copy of exception-time register now holding FLAGS
                   2028:         * SR2: return address to the calling exception handler
                   2029:         * SR3: free
                   2030:         * FLAGS: CPU status flags
                   2031:         *
                   2032:         * immediate goal:
                   2033:         *   Since we're servicing an exception from user mode, we
                   2034:         *   know that SR3 is free.  We use it to free up a temporary
                   2035:         *   register to be used in getting the process pcb.
                   2036:         */
                   2037:        stcr    r31,  SR3       /* save previous r31 */
                   2038:
                   2039:        /* switch to the process kernel stack. */
                   2040:        ldcr    r31,  CPU
                   2041:        ld      r31,  r31,  CI_CURPCB
                   2042:        addu    r31,  r31,  PCB_USER_STATE      /* point to user save area */
                   2043:
                   2044:        /*
                   2045:         * WARNING! Using pcb->user_state as the exception frame
                   2046:         * AND stack pointer, means we can not afford using the stack
                   2047:         * until we have saved enough and can go back to the top of the u area,
                   2048:         * after the FPU is enabled.
                   2049:         */
                   2050:
                   2051:        st      FLAGS,r31,  REG_OFF(EF_FLAGS)   /* save flags */
                   2052:        st      r1,   r31,  GENREG_OFF(1)       /* save prev. r1 (now free)*/
                   2053:        ldcr    r1,   SR3                       /* save previous r31 */
                   2054:        st      r1,   r31,  GENREG_OFF(31)
                   2055:        /* FALLTHROUGH */
                   2056:
                   2057: ASLOCAL(m88110_have_pcb)
                   2058:        /*
                   2059:         * SR1: saved copy of exception-time register now holding FLAGS
                   2060:         * SR2: return address to the calling exception handler
                   2061:         * SR3: free
                   2062:         * r1:  free
                   2063:         * FLAGS: CPU status flags
                   2064:         * r31: our exception frame
                   2065:         * Valid in the exception frame:
                   2066:         *   Exception-time r1, r31, FLAGS.
                   2067:         *   Exception SR3, if appropriate.
                   2068:         *
                   2069:         * immediate goal:
                   2070:         *   Save the shadow registers that need to be saved to
                   2071:         *   the exception frame.
                   2072:         */
                   2073:        stcr    TMP, SR3        /* free up TMP, TMP2, TMP3 */
                   2074:        SAVE_TMP2
                   2075:        SAVE_TMP3
                   2076:
                   2077:        /* save some exception-time registers to the exception frame */
                   2078:        ldcr    TMP,  EPSR
                   2079:        st      TMP,  r31,  REG_OFF(EF_EPSR)
                   2080:        ldcr    TMP2, EXIP
                   2081:        ldcr    TMP3, ENIP
                   2082:        st      TMP2, r31,  REG_OFF(EF_EXIP)
                   2083:        st      TMP3, r31,  REG_OFF(EF_ENIP)
                   2084:
                   2085:        /* get and store the cpu_info pointer */
                   2086:        ldcr    TMP,  CPU
                   2087:        st      TMP,  r31,  REG_OFF(EF_CPU)
                   2088:
                   2089:        /*
                   2090:         * Save fault status registers from CMMU.
                   2091:         */
                   2092:        ldcr    TMP,  ISR
                   2093:        ldcr    TMP2, ILAR
                   2094:        ldcr    TMP3, IPAR
                   2095:        st      TMP,  r31,  REG_OFF(EF_ISR)
                   2096:        st      TMP2, r31,  REG_OFF(EF_ILAR)
                   2097:        st      TMP3, r31,  REG_OFF(EF_IPAR)
                   2098:        ldcr    TMP,  ISAP
                   2099:        ldcr    TMP2, IUAP
                   2100:        st      TMP,  r31,  REG_OFF(EF_ISAP)
                   2101:        st      TMP2, r31,  REG_OFF(EF_IUAP)
                   2102:        ldcr    TMP,  DSR
                   2103:        ldcr    TMP2, DLAR
                   2104:        ldcr    TMP3, DPAR
                   2105:        st      TMP,  r31,  REG_OFF(EF_DSR)
                   2106:        st      TMP2, r31,  REG_OFF(EF_DLAR)
                   2107:        st      TMP3, r31,  REG_OFF(EF_DPAR)
                   2108:        ldcr    TMP,  DSAP
                   2109:        ldcr    TMP2, DUAP
                   2110:        st      TMP,  r31,  REG_OFF(EF_DSAP)
                   2111:        st      TMP2, r31,  REG_OFF(EF_DUAP)
                   2112:
                   2113:        stcr    r0, ISR
                   2114:        stcr    r0, DSR
                   2115:
                   2116:        ldcr    r1,   SR2
                   2117:        jmp     r1
                   2118:
                   2119: ASLOCAL(m88110_setup_phase_two)
                   2120:        /*
                   2121:         * SR1: saved copy of exception-time register now holding FLAGS
                   2122:         * SR2: free
                   2123:         * SR3: saved TMP
                   2124:         * r1:  return address to calling exception handler
                   2125:         * TMP2: free
                   2126:         * TMP3: free
                   2127:         * FLAGS: CPU status flags
                   2128:         * r31: our exception frame
                   2129:         * Valid in the exception frame:
                   2130:         *   Exception-time r1, r31, FLAGS.
                   2131:         *   Exception-time TMP2, TMP3.
                   2132:         *   Exception-time espr, enip, exip.
                   2133:         *   Exception number (EF_VECTOR).
                   2134:         *   Dmt0
                   2135:         *   Other data pipeline control registers, if appropriate.
                   2136:         *   FPU control registers, if appropriate.
                   2137:         *   Exception SR3, if appropriate.
                   2138:         *
                   2139:         * immediate goal:
                   2140:         *   restore the system to the exception-time state (except SR3 will
                   2141:         *   be OUR stack pointer) so that we may resart the FPU.
                   2142:         */
                   2143:
                   2144:        RESTORE_TMP2    /* done with extra temp regs */
                   2145:        RESTORE_TMP3    /* done with extra temp regs */
                   2146:
                   2147:        ldcr    TMP,  PSR
                   2148:        clr     TMP,  TMP,  1<PSR_FPU_DISABLE_BIT>      /* enable the FPU */
                   2149:        clr     TMP,  TMP,  1<PSR_SHADOW_FREEZE_BIT>    /* and shadowing */
                   2150:        stcr    TMP,  EPSR
                   2151:
                   2152:        or.u    TMP,  r0,   hi16(_ASM_LABEL(m88110_fpu_enable))
                   2153:        or      TMP,  TMP,  lo16(_ASM_LABEL(m88110_fpu_enable))
                   2154:        stcr    TMP,  EXIP
                   2155:
                   2156:        set     FLAGS, FLAGS, 1<FLAG_ENABLING_FPU>
                   2157:        xcr     FLAGS, FLAGS, SR1
                   2158:        st      r1,   r31,  REG_OFF(EF_RET)     /* save the return address */
                   2159:        ld      r1,   r31,  GENREG_OFF(1)       /* get original r1 */
                   2160:
                   2161:        xcr     TMP,  r31, SR3  /* TMP now restored. R31 now saved in SR3 */
                   2162:        ld      r31,  r31,  GENREG_OFF(31)      /* get original r31 */
                   2163:
                   2164:        /*
                   2165:         * SR1: CPU flags
                   2166:         * SR2: free
                   2167:         * SR3: pointer to our exception frame (our stack pointer)
                   2168:         * r1 through r31: original exception-time values
                   2169:         *
                   2170:         * Valid in the exception frame:
                   2171:         *   Exception-time FLAGS.
                   2172:         *   Exception-time espr, sfip, enip, exip.
                   2173:         *   Exception number (EF_VECTOR).
                   2174:         *   Dmt0
                   2175:         *   Other data pipeline control registers, if appropriate.
                   2176:         *   FPU control registers, if appropriate.
                   2177:         *   Exception SR3, if appropriate.
                   2178:         * Held temporarily in the exception frame:
                   2179:         *   Return address to the calling exception handler.
                   2180:         *
                   2181:         * immediate goal:
                   2182:         *   Do an RTE to restart the fpu and jump to "fpu_enable"
                   2183:         *   Another exception (or exceptions) may be raised in
                   2184:         *   this, which is why FLAG_ENABLING_FPU is set in SR1.
                   2185:         */
                   2186:        RTE     /* jumps to "m88110_fpu_enable" to enable the FPU. */
                   2187:
                   2188: ASLOCAL(m88110_fpu_enable)
                   2189:        FLUSH_PIPELINE
                   2190:
                   2191:        xcr     TMP,  TMP,  SR3                 /* get E.F. pointer */
                   2192:        st      r30,  TMP,  GENREG_OFF(30)      /* save previous r30, r31 */
                   2193:        st      r31,  TMP,  GENREG_OFF(31)      /* save previous r30, r31 */
                   2194:        or      r31,  TMP,  r0                  /* transfer E.F. pointer */
                   2195:        ld      TMP,  r31,  REG_OFF(EF_SR3)     /* get previous SR3 */
                   2196:
                   2197:        /* make sure that the FLAG_ENABLING_FPU bit is off */
                   2198:        xcr     FLAGS,FLAGS,SR1
                   2199:        clr     FLAGS,FLAGS,1<FLAG_ENABLING_FPU>
                   2200:        xcr     FLAGS,FLAGS,SR1
                   2201:
                   2202:        xcr     TMP,  TMP,  SR3 /* replace TMP, SR3 */
                   2203:
                   2204:        /* now save all regs to the exception frame. */
                   2205:        st      r0 ,  r31,  GENREG_OFF(0)
                   2206:        st      r1 ,  r31,  GENREG_OFF(1)
                   2207:        st      r2 ,  r31,  GENREG_OFF(2)
                   2208:        st      r3 ,  r31,  GENREG_OFF(3)
                   2209:        st      r4 ,  r31,  GENREG_OFF(4)
                   2210:        st      r5 ,  r31,  GENREG_OFF(5)
                   2211:        st      r6 ,  r31,  GENREG_OFF(6)
                   2212:        st      r7 ,  r31,  GENREG_OFF(7)
                   2213:        st      r8 ,  r31,  GENREG_OFF(8)
                   2214:        st      r9 ,  r31,  GENREG_OFF(9)
                   2215:        st      r10,  r31,  GENREG_OFF(10)
                   2216:        st      r11,  r31,  GENREG_OFF(11)
                   2217:        st      r12,  r31,  GENREG_OFF(12)
                   2218:        st      r13,  r31,  GENREG_OFF(13)
                   2219:        st      r14,  r31,  GENREG_OFF(14)
                   2220:        st      r15,  r31,  GENREG_OFF(15)
                   2221:        st      r16,  r31,  GENREG_OFF(16)
                   2222:        st      r17,  r31,  GENREG_OFF(17)
                   2223:        st      r18,  r31,  GENREG_OFF(18)
                   2224:        st      r19,  r31,  GENREG_OFF(19)
                   2225:        st      r20,  r31,  GENREG_OFF(20)
                   2226:        st      r21,  r31,  GENREG_OFF(21)
                   2227:        st      r22,  r31,  GENREG_OFF(22)
                   2228:        st      r23,  r31,  GENREG_OFF(23)
                   2229:        st      r24,  r31,  GENREG_OFF(24)
                   2230:        st      r25,  r31,  GENREG_OFF(25)
                   2231:        st      r26,  r31,  GENREG_OFF(26)
                   2232:        st      r27,  r31,  GENREG_OFF(27)
                   2233:        st      r28,  r31,  GENREG_OFF(28)
                   2234:
                   2235:        /* get and save IPL */
                   2236:        bsr.n   _C_LABEL(getipl)
                   2237:         st     r29,  r31,  GENREG_OFF(29)
                   2238:        st      r2, r31, REG_OFF(EF_MASK)
                   2239:
                   2240:        /*
                   2241:         * SR1: free
                   2242:         * SR2: free
                   2243:         * SR3: previous exception-time SR3
                   2244:         * r1: return address to the calling exception handler
                   2245:         * r2 through r30: free
                   2246:         * r31: our exception frame
                   2247:         *
                   2248:         * Valid in the exception frame:
                   2249:         *   Exception-time r0 through r31.
                   2250:         *   Exception-time FLAGS.
                   2251:         *   Exception-time espr, enip, exip.
                   2252:         *   Exception number (EF_VECTOR).
                   2253:         *   DSR
                   2254:         *   Other data pipeline control registers, if appropriate.
                   2255:         *   FPU control registers, if appropriate.
                   2256:         *   Exception SR3, if appropriate.
                   2257:         *
                   2258:         * immediate goal:
                   2259:         *   Pick up a stack if we came in from user mode.
                   2260:         *   Put a copy of the exception frame pointer into r30
                   2261:         *   Bump the stack a doubleword and write the exception frame pointer.
                   2262:         *   If not an interrupt exception, turn on interrupts and service any
                   2263:         *     outstanding data access exceptions.
                   2264:         *   Return to calling exception handler to service the exception.
                   2265:         */
                   2266:
                   2267:        /*
                   2268:         * If it's not the interrupt exception, enable interrupts and
                   2269:         * take care of any data access exceptions......
                   2270:         */
                   2271:        or      r30,  r0,   r31         /* get a copy of the e.f. pointer */
                   2272:        ld      r2,   r31,  REG_OFF(EF_EPSR)
                   2273:        bb1     PSR_SUPERVISOR_MODE_BIT, r2, 1f /* if in kernel mode */
                   2274:
                   2275:        ldcr    r31,  CPU
                   2276:        ld      r31,  r31,  CI_CURPCB
                   2277:        addu    r31,  r31,  USIZE               /* point at proper end */
                   2278: 1:
                   2279:
                   2280:        /*
                   2281:         * here - r30 holds a pointer to the exception frame.
                   2282:         * r31 is a pointer to the kernel stack/interrupt stack.
                   2283:         */
                   2284:        subu    r31,  r31,  8   /* make some breathing space */
                   2285:        st      r30,  r31,  0   /* store frame pointer on the stack */
                   2286: #ifdef DDB
                   2287:        st      r30,  r31,  4   /* store it again for the debugger */
                   2288: #endif
                   2289:
                   2290:        ld      r2,   r30,  REG_OFF(EF_VECTOR)
                   2291:        bcnd.n  eq0,  r2,   8f
                   2292:         ld     r14,  r30,  REG_OFF(EF_RET)     /* load return value XXX!!! */
                   2293:        cmp     r3,   r2,   1   /* is an interrupt? */
                   2294:        bb1.n   eq,   r3,   8f
                   2295:         cmp    r3,   r2,   11  /* or NMI? */
                   2296:        bb1.n   eq,   r3,   8f
                   2297:
                   2298: #ifdef DDB
                   2299:         cmp    r3,   r2,   130 /* DDB break exception */
                   2300:        bb1.n   eq,   r3,   8f
                   2301:
                   2302:         cmp    r3,   r2,   132 /* DDB entry exception */
                   2303:        bb1.n   eq,   r3,   8f
                   2304: #endif
                   2305:
                   2306:        /* turn interrupts back on */
                   2307:         ldcr   r2,   PSR
                   2308:        clr     r2,   r2,   1<PSR_INTERRUPT_DISABLE_BIT>
                   2309:        stcr    r2,   PSR
                   2310:        FLUSH_PIPELINE
                   2311:
                   2312: 8:
                   2313:        jmp     r14             /* loaded above */
                   2314:
                   2315:        data
                   2316:        .align 8                /* needs align 8 for ld.d/st.d */
                   2317: ASLOCAL(save_frame)
                   2318:        space SIZEOF_EF
                   2319: #endif /* M88110 */
                   2320:
                   2321: /*
                   2322:  * void proc_trampoline(void (*func)(void *), void *proc)
                   2323:   *
                   2324:  * When a process setup by cpu_fork() resumes, it will find itself in
                   2325:  * proc_trampoline, with r31 pointing to a ksigframe. proc_trampoline will
                   2326:  * load func and proc values from ksigframe, call the function, and on return
                   2327:  * pop off the ksigframe. Then, it will load pc from the switchframe and
                   2328:  * jump there (the pc will usually be proc_do_uret).
                   2329:  */
                   2330:
                   2331: ENTRY(proc_trampoline)
                   2332: #ifdef MULTIPROCESSOR
                   2333:        bsr     _C_LABEL(proc_trampoline_mp)
                   2334: #endif
                   2335:        ld      r1, r31, 0              /* load func */
                   2336:        ld      r2, r31, 4              /* load proc pointer */
                   2337:        jsr.n   r1
                   2338:         addu   r31, r31, 8             /* release ksigframe */
                   2339:        ld      r1,  r31, 0             /* load pc */
                   2340:        ld      r2,  r31, 4             /* & proc pointer from switch frame */
                   2341:        jsr.n   r1
                   2342:         addu   r31, r31, 8
                   2343:
                   2344: #define        FPTR    r14
                   2345:
                   2346:
                   2347: ASLOCAL(check_ast)
                   2348:        /*
                   2349:         * Regs r1-r30 are free. r31 is pointing at the word
                   2350:         * on the kernel stack where our pointer to the exception frame
                   2351:         * it stored. Reload it now.
                   2352:         *
                   2353:         * We load it into r14 since it is preserved across function
                   2354:         * calls, and we may have to call some routines from within here.
                   2355:         *
                   2356:         * Control is transferred here from obvious places in this file.
                   2357:         */
                   2358:        ld      FPTR, r31, 0    /* grab exception frame pointer */
                   2359:        /*
                   2360:         * If the saved ipl is 0, then call dosoftint() to process soft
                   2361:         * interrupts.
                   2362:         * If returning to userland, look for ASTs.
                   2363:         */
                   2364:        /* do not service soft interrupts if interrupts were disabled... */
                   2365:        ld      r2, FPTR, REG_OFF(EF_EPSR)
                   2366:        bb1     PSR_INTERRUPT_DISABLE_BIT, r2, _ASM_LABEL(no_softint)
                   2367:        /* ...or we were not at spl0 */
                   2368:        ld      r2, FPTR, REG_OFF(EF_MASK)
                   2369:        bcnd    ne0, r2, _ASM_LABEL(no_softint)
                   2370:
                   2371:        /* do an inline spl0() */
                   2372:        bsr.n   _C_LABEL(setipl)
                   2373:         or     r2, r0, IPL_SOFTCLOCK
                   2374:        bsr     _C_LABEL(dosoftint)
                   2375:        bsr.n   _C_LABEL(setipl)
                   2376:         or     r2, r0, IPL_NONE
                   2377:
                   2378: ASLOCAL(no_softint)
                   2379:        /* do not service AST if not returning to user mode */
                   2380:        ld      r2, FPTR, REG_OFF(EF_EPSR)
                   2381:        bb1     PSR_SUPERVISOR_MODE_BIT, r2, _ASM_LABEL(no_ast)
                   2382:
                   2383:        ldcr    r2,  CPU
                   2384:        ld      r3,  r2, CI_CURPROC
                   2385:        bcnd    eq0, r3, _ASM_LABEL(no_ast)     /* no AST if no process! */
                   2386:        ld      r2,  r3, P_ASTPENDING
                   2387:        bcnd.n  eq0, r2, _ASM_LABEL(no_ast)     /* .n safe since the first
                   2388:                                                   instruction of CALL() is
                   2389:                                                   safe in a delay slot. */
                   2390:        /*
                   2391:         * trap(AST,...) will service ast's.
                   2392:         */
                   2393:         or     r3, r0, FPTR
                   2394:        or      r2, r0, T_ASTFLT
                   2395: #if defined(M88110) && defined(M88100)
                   2396:        or.u    r4, r0, hi16(_C_LABEL(cputyp))
                   2397:        ld      r5, r4, lo16(_C_LABEL(cputyp))
                   2398:        cmp     r4, r5, CPU_88110
                   2399:        bb0     eq, r4, 2f
                   2400: #endif
                   2401: #if defined(M88110)
                   2402:        XCALL(_C_LABEL(m88110_trap), _ASM_LABEL(no_ast))
                   2403: #endif
                   2404: #if defined(M88110) && defined(M88100)
                   2405: 2:
                   2406: #endif
                   2407: #ifdef M88100
                   2408:        XCALL(_C_LABEL(m88100_trap), _ASM_LABEL(no_ast))
                   2409: #endif
                   2410:
                   2411: /*
                   2412:  * void proc_do_uret(struct proc *p)
                   2413:  *
                   2414:  * This is called as proc_do_uret(proc) from proc_trampoline(). This function
                   2415:  * loads FPTR with a pointer to the trap frame for the given proc and continues
                   2416:  * near the end of check_ast, bypassing soft interrupts and AST checks, to
                   2417:  * load all the registers and do an RTE.
                   2418:  */
                   2419:
                   2420: ENTRY(proc_do_uret)
                   2421:        ld      FPTR, r2,   P_ADDR              /* p->p_addr */
                   2422:        addu    FPTR, FPTR, PCB_USER_STATE      /* p->p_addr.u_pcb.user_state */
                   2423:        /* FALLTHROUGH */
                   2424:
                   2425: ASLOCAL(no_ast)
                   2426:        /* disable interrupts */
                   2427:        ldcr    r1, PSR
                   2428:        set     r1, r1, 1<PSR_INTERRUPT_DISABLE_BIT>
                   2429:        stcr    r1, PSR
                   2430:        FLUSH_PIPELINE
                   2431:
                   2432:        /* now ready to return....*/
                   2433:        bsr.n   _C_LABEL(setipl)
                   2434:         ld     r2, FPTR, REG_OFF(EF_MASK)      /* get pre-exception ipl */
                   2435:
                   2436:        /*
                   2437:         * Transfer the frame pointer to r31, since we no longer need a stack.
                   2438:         * No page faults here, and interrupts are disabled.
                   2439:         */
                   2440:        or      r31, r0,  FPTR
                   2441:        /* restore r1 later */
                   2442:        ld      r2 , r31, GENREG_OFF(2)
                   2443:        ld      r3 , r31, GENREG_OFF(3)
                   2444:        ld      r4 , r31, GENREG_OFF(4)
                   2445:        ld      r5 , r31, GENREG_OFF(5)
                   2446:        ld      r6 , r31, GENREG_OFF(6)
                   2447:        ld      r7 , r31, GENREG_OFF(7)
                   2448:        ld      r8 , r31, GENREG_OFF(8)
                   2449:        ld      r9 , r31, GENREG_OFF(9)
                   2450:        ld      r10, r31, GENREG_OFF(10)
                   2451:        ld      r11, r31, GENREG_OFF(11)
                   2452:        ld      r12, r31, GENREG_OFF(12)
                   2453:        ld      r13, r31, GENREG_OFF(13)
                   2454:        ld      r14, r31, GENREG_OFF(14)
                   2455:        ld      r15, r31, GENREG_OFF(15)
                   2456:        ld      r16, r31, GENREG_OFF(16)
                   2457:        ld      r17, r31, GENREG_OFF(17)
                   2458:        ld      r18, r31, GENREG_OFF(18)
                   2459:        ld      r19, r31, GENREG_OFF(19)
                   2460:        ld      r20, r31, GENREG_OFF(20)
                   2461:        ld      r21, r31, GENREG_OFF(21)
                   2462:        ld      r22, r31, GENREG_OFF(22)
                   2463:        ld      r23, r31, GENREG_OFF(23)
                   2464:        ld      r24, r31, GENREG_OFF(24)
                   2465:        ld      r25, r31, GENREG_OFF(25)
                   2466:        ld      r26, r31, GENREG_OFF(26)
                   2467:        ld      r27, r31, GENREG_OFF(27)
                   2468:        ld      r28, r31, GENREG_OFF(28)
                   2469:        ld      r29, r31, GENREG_OFF(29)
                   2470:        /* restore r1, r30, r31 later */
                   2471:
                   2472:        /* disable shadowing */
                   2473:        ldcr    r1, PSR
                   2474:        set     r1, r1, 1<PSR_SHADOW_FREEZE_BIT>
                   2475:        stcr    r1, PSR
                   2476:        FLUSH_PIPELINE
                   2477:
                   2478:        /* reload the control regs*/
                   2479: #ifdef M88110
                   2480: #ifdef M88100
                   2481:        or.u    r1, r0, hi16(_C_LABEL(cputyp))
                   2482:        ld      r30, r1, lo16(_C_LABEL(cputyp))
                   2483:        cmp     r1, r30, CPU_88110
                   2484:        bb1     ne, r1, 1f
                   2485: #endif
                   2486:        ld      r30, r31, REG_OFF(EF_ENIP)
                   2487:        ld      r1,  r31, REG_OFF(EF_EXIP)
                   2488:        stcr    r30, ENIP
                   2489:        stcr    r1,  EXIP
                   2490: #ifdef M88100
                   2491:        br      2f
                   2492: 1:
                   2493: #endif
                   2494: #endif
                   2495: #ifdef M88100
                   2496:        /*
                   2497:         * RTE will cause execution to continue first with the
                   2498:         * instruction pointed to by the NIP and then the FIP;
                   2499:         * it is not necessary to restore XIP.
                   2500:         */
                   2501:        stcr    r0,  SSBR
                   2502:        ld      r30, r31, REG_OFF(EF_SNIP)
                   2503:        ld      r1,  r31, REG_OFF(EF_SFIP)
                   2504:        stcr    r30, SNIP
                   2505:        stcr    r1,  SFIP
                   2506: 2:
                   2507: #endif
                   2508:        ld      r30, r31, REG_OFF(EF_EPSR)
                   2509:        stcr    r30, EPSR
                   2510:
                   2511:        /* Now restore r1, r30, and r31 */
                   2512:        ld      r1,  r31, GENREG_OFF(1)
                   2513:        ld      r30, r31, GENREG_OFF(30)
                   2514:        ld      r31, r31, GENREG_OFF(31)
                   2515:
                   2516:        RTE

CVSweb