1
0
Files
irix-657m-src/irix/kern/ml/spl.s
2022-09-29 17:59:04 +03:00

1033 lines
20 KiB
ArmAsm

/**************************************************************************
* *
* Copyright (C) 1990-1997, Silicon Graphics, Inc *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
#include "ml/ml.h"
#ifdef SPLDEBUG
/* SPLDEBUG is mutually exclusive with SPLMETER */
#define SPLLEAF(x,y,x1,x2) \
LEAF(x) ; \
move y, ra ; \
j x1 ; \
END(x) ; \
LEAF(x2)
#define SPLXLEAF(x,y,x1,x2) \
move y, ra ; \
j x1 ; \
END(x) ; \
LEAF(x2)
#define SPLEND(x,x2) END(x2)
#else /* !SPLDEBUG */
#define SPLLEAF(x,y,x1,x2) LEAF(x)
#define SPLXLEAF(x,y,x1,x2) XLEAF(x)
#define SPLEND(x,x2) END(x)
#endif /* !SPLDEBUG */
/*
* spl.s - spl routines
*
*
* Among the special cases:
*
* IP20/IP22/IP28 - there is no floating point interrupt.
* the order of interrupts is not the same as for other machines and it
* has two sets of local interrupts. buserror interrupt comes in on 7 and
* the count/compare interrupt (currently unused) comes in on 8.
*
* IP24 - same as IP20/IP22 except that 5/6 (PTC) are not used and
* 8 (R4000 timer) is.
*
* IP26 - similar to IP22 on the lower half, but TFP has 11 IP levels.
*
* $Revision: 1.67 $
*
*/
/*
* These definitions should go into a per platform header file
* when I have time to do some more cleaning up.
*/
#if IP20 || IP22 || IP28
#define SR_HI_MASK SR_IMASK5
#define SR_PROF_MASK SR_IBIT7
#define SR_ALL_MASK SR_IMASK8
#define SR_IBIT_HI SR_IBIT5
#define SR_IBIT_PROF SR_IBIT6
#endif
#if IP30
#define SR_IBIT_HI SR_IBIT5
#endif
/*
* SPLMETER
*/
#ifdef SPLMETER
#define SPLHI 5 /* spl6(), splhi() */
#define SPLPROF 6 /* spl65(), splprof() */
#ifdef IP32 /* Avoid naming conflicts on IP32 */
#define SPL7_IP32 7 /* spl7() */
#else
#define SPL7 7 /* spl7() */
#endif /* IP32 */
#define SPLMETER_PROLOGUE(name) ;\
move a0,ra /* save return for raisespl() */ ;\
XLEAF(name)
/* assume noreorder, ospl = v0 */
#define SPLMETER_WORK(level) ;\
mtc0 v1,C0_SR ;\
INT_L a1,spl_level ;\
bne a1,level,2f /* needed spl level is not the same */ ;\
nop ;\
j raisespl /* return from there to our caller */ ;\
move a1,v0 ;\
2: ;\
j ra ;\
nop
#ifdef NOTDEF
LEAF(splstr)
move a0,ra
.set noreorder
j _splstr
nop
.set reorder
END(splstr)
#endif
/*
* starttimer: start timer running to fig out how long this routine take
* to execute until hit stoptimer()
*
*/
LEAF(starttimer)
move a0,ra
.set noreorder
j _starttimer
nop
.set reorder
END(starttimer)
LEAF(stoptimer)
move a0,ra
.set noreorder
j _stoptimer
nop
.set reorder
END(stoptimer)
LEAF(canceltimer)
move a0,ra
.set noreorder
j _canceltimer
nop
.set reorder
END(canceltimer)
LEAF(_cancelsplhi)
move a0,ra
move a1,sp
j cancelsplhi
END(_cancelsplhi)
#else
#define SPLMETER_PROLOGUE(lvl)
#define SPLMETER_WORK(level) ;\
j ra ;\
mtc0 v1,C0_SR
#endif /* SPLMETER */
/*
* check splx arg
*/
#ifndef STKDEBUG
#define SPLX_CK(tmp) # not turned on
#else
#define SPLX_MASK 0xCF000080 /* zeros and no coproc 2 or 3 */
#define SPLX_CK(tmp) ;\
and tmp,a0,SPLX_MASK ;\
beq tmp,zero,1f ;\
move a2,ra ;\
move a3,a0 ;\
li a0,CE_PANIC ;\
la a1,splx_msg ;\
/* jump to get a good stack frame */ ;\
j cmn_err ;\
1:
splx_msg:MSG("splx:ra: %x bad arg:%x")
#endif
/*
* disable some interrupts, but without "lowering the level"
* r0=current SR contents, r1=place for new value, possibly r0=r1
*/
#define DIS_INT(r1,r0,lvl) ;\
or r1,r0, SR_IEC | (SR_IMASK & ~(lvl)) ;\
xor r1, (SR_IMASK & ~(lvl))
#if defined(SPLDEBUG) || defined(SPLDEBUG_CPU_EVENTS)
LEAF(spldebug_log_event)
move a1, ra
j _spldebug_log_event
END(spldebug_log_event)
#endif
#if IP20 || IP22 || IP27 || IP28 || IP30 || IPMHSIM || IP33
/* IP20/IP22/IP28 spls
*
* The IP20/IP22/IP28 have two sets of local interrupts: high and low priority.
*
* Interrupts:
* 8 R4000 internal timer (only used on IP24)
* 7 bus error/timeout
* 6 profiling clock. (timer channel 1)
* 5 sched clock. (timer channel 0)
* 4 high priority vectored devices
* 3 low priority vectored devices
* 2 softnet
* 1 softclock
*/
/* base retained bits in the status register */
#ifdef R10000
#define SR_RETAIN (SR_KX|SR_UX|SR_DE|SR_ERL)
#else
#define SR_RETAIN (SR_KX|SR_DE|SR_ERL)
#endif
/*
* all of the R4000 spl routines must preserve the SR_DE, SR_ERL and SR_KX bits
* if they are already set */
/*
* spl0: Don't block against anything, and ignore the previous state.
* lowers level if asked
*/
SPLLEAF(spl0,a0,_spl0,__spl0)
#ifdef SPLMETER
move a0,ra
move a1,sp
j _spl0
END (spl0)
LEAF(__spl0)
#endif /* SPLMETER */
.set noreorder
mfc0 v0,C0_SR
li v1,SR_RETAIN # Retain base important bits
and v1,v0
or v1,SR_IE|SR_IMASK0
j ra
mtc0 v1,C0_SR # BDSLOT
.set reorder
#ifdef SPLMETER
END(__spl0)
#else
SPLEND(spl0,__spl0)
#endif
/*
* spl6: block against sched clock interrupts. (level 5 hardint).
* never lowers spl
*/
LEAF(splhi)
XLEAF(spl6)
XLEAF(splhi_relnet)
XLEAF(splhintr)
XLEAF(splgio0)
XLEAF(splgio1)
XLEAF(splgio2)
XLEAF(spl1)
XLEAF(spl3)
XLEAF(spl5)
XLEAF(splimp)
XLEAF(splnet)
XLEAF(spltty)
XLEAF(splvme)
XLEAF(splretr)
SPLXLEAF(splhi,a0,_splhi,__splhi)
SPLMETER_PROLOGUE(_splhi)
.set noreorder
mfc0 v0,C0_SR
li v1,SR_RETAIN|SR_HI_MASK|SR_IE # Retain base + intr mask
and v1,v0
SPLMETER_WORK(SPLHI)
.set reorder
SPLEND(splhi,__splhi)
#ifdef SPLMETER
LEAF(splhi_nosplmeter)
.set noreorder
mfc0 v0,C0_SR
li v1,SR_RETAIN|SR_HI_MASK|SR_IE # Retain base + intr mask
and v1,v0
j ra
mtc0 v1,C0_SR
.set reorder
END(splhi_nosplmeter)
#endif
/* a0 has processor status register
* return 1 if at splhi or higher,
* or if IE is low, or if EXL is high.
*/
LEAF(issplhi)
move v0,zero # default is not @ splhi
li v1,SR_IE
and a1,a0,SR_IE|SR_EXL
bne a1,v1,2f # disabled or at exception level
and a0,SR_IBIT_HI
bnez a0,3f
2: li v0,1 # SR_IBIT_HI bit(s) clear
3:
j ra
END(issplhi)
/* a0 has the processor status register
* return 1 if at splprof or higher,
* or if IE is low, or if EXL is high.
*/
LEAF(issplprof)
move v0,zero # default not @ splprof
li v1,SR_IE
and a1,a0,SR_IE|SR_EXL
bne a1,v1,2f # disbled or at exception level
andi a0,SR_IBIT_PROF
bnez a0,3f # re SR_IBIT_PROF bits clear?
2: li v0,1
3:
j ra
END(issplprof)
/*
** a0 has processor status register
** return 1 if at spl7 or higher
*/
LEAF(isspl7)
li v0,0
and v1,a0,SR_IE
bne v1,zero,1f /* its enabled */
li v0,1
b 2f
1:
and a0,SR_IMASK
bne a0,zero,2f
li v0,1
2:
j ra
END(isspl7)
/*
* splprof: block against all interrupts except bus-error.
* never lowers spl
*/
SPLLEAF(splprof,a0,_splprof,__splprof)
XLEAF(spl65)
SPLMETER_PROLOGUE(_splprof)
.set noreorder
mfc0 v0,C0_SR
li v1,SR_RETAIN|SR_PROF_MASK|SR_IE # Retain base + intr mask
and v1,v0
SPLMETER_WORK(SPLPROF)
.set reorder
SPLEND(splprof,__splprof)
/*
* spl7: block against all interrupts.
*/
SPLLEAF(spl7,a0,_spl7,__spl7)
XLEAF(splerr)
SPLMETER_PROLOGUE(_spl7)
.set noreorder
mfc0 v0,C0_SR
li v1,SR_RETAIN|SR_ALL_MASK|SR_IE # Retain base + intr mask
and v1,v0
SPLMETER_WORK(SPL7)
.set reorder
SPLEND(spl7,__spl7)
/*
* splecc: block against all interrupts and disable ecc exceptions.
*/
LEAF(splecc)
.set noreorder
mfc0 v0,C0_SR
li v1,SR_UX|SR_KX|SR_ERL # Keep these bits
and v1,v0
li t0,SR_DE|SR_ALL_MASK|SR_IE
or v1,t0
j ra
mtc0 v1,C0_SR # BDSLOT
.set reorder
END(splecc)
/*
* splx(ipl) -- restore previously saved ipl
*/
SPLLEAF(splx,a1,_splx,__splx)
XLEAF(splxecc)
#ifdef SPLMETER
move a1,ra
move a2,sp
j lowerspl
END (splx)
LEAF(__splx)
XLEAF(__splxecc)
#endif /* SPLMETER */
#ifdef STKDEBUG
li v0,0xC0000000 # zeros and no coproc 2 or 3
and v0,v0,a0
beq v0,zero,1f
move a2,ra
move a3,a0
PANIC("splx:ra: %x bad arg:%x");
1:
#endif
.set noreorder
mfc0 v0,C0_SR
li v1,SR_RETAIN # Retain base important bits
and v1,v0
or a0,v1
j ra
mtc0 a0,C0_SR # BDSLOT
.set reorder
#ifdef SPLMETER
END(__splx)
#else
SPLEND(splx,__splx)
#endif
#endif /* IP20 || IP22 || IP27 || IP28 || IP30 || IP33 */
#if IP32
/* IP32 spls
*
* The IP32 has one set of external interrupt sources
*
* Interrupts:
* 8 R4000 internal timer (used on IP32)
* 7 N/A
* 6 N/A
* 5 N/A
* 4 N/A
* 3 CRIME interrupts
* 2 softnet
* 1 softclock
*/
/*
* Table of SR IMASK values for various IPL levels
*/
.data
sr_iplmasks:
.dword SR_IMASK0
.dword SR_IMASK5
.dword SR_IMASK6
.dword SR_IMASK8
.dword SR_IMASK8
.dword SR_IMASK8 /* SPLMAX = 5 */
.text
/*
* SPLMETER code for case where we're already >= splhi
* Don't write back to CO_SR
*/
#ifdef SPLMETER
/* assume noreorder, ospl = v0 */
#define NOCHANGE_SPLMETER_WORK(level) ;\
INT_L a1,spl_level ;\
bne a1,level,4f /* needed spl level is not the same */ ;\
nop ;\
j raisespl /* return from there to our caller */ ;\
move a1,v0 ;\
4: ;\
j ra ;\
nop
#else
#define NOCHANGE_SPLMETER_WORK(level) ;\
j ra ;\
nop
#endif /* SPLMETER */
/*
* all of the R4000 spl routines must preserve the SR_DE, SR_ERL and SR_KX bits
* if they are already set */
/*
* spl0: Don't block against anything, and ignore the previous state.
* lowers level if asked
*/
SPLLEAF(spl0,a0,_spl0,__spl0)
#ifdef SPLMETER
move a0,ra
move a1,sp
j _spl0
END (spl0)
LEAF(__spl0)
#endif /* SPLMETER */
.set noreorder
mfc0 v0,C0_SR
# retain the KX, DE and ERL bits
li v1,SR_KX|SR_DE|SR_ERL
and v1,v0
ori v1,SR_IE|SR_IMASK0
xor t2,v1,SR_IE # disable ints for atomicity
mtc0 t2,C0_SR
LOAD_CRIME_INTMASK(zero,t0,t1)
BUILD_RETURN_VALUE(v0,t0)
sw zero,VPDA_CURSPL(zero)
j ra
mtc0 v1,C0_SR # turn CRIME interrupts back on
.set reorder
#ifdef SPLMETER
END(__spl0)
#else
SPLEND(spl0,__spl0)
#endif
/*
* spl6: block against sched clock interrupts. (level 5 hardint).
* never lowers spl
*/
LEAF(splhi)
XLEAF(spl6)
XLEAF(splhi_relnet)
XLEAF(splhintr)
XLEAF(splretr)
XLEAF(splgio2)
XLEAF(spl5)
XLEAF(splvme)
XLEAF(spltty)
XLEAF(splimp)
XLEAF(splgio0)
XLEAF(splgio1)
XLEAF(splnet)
XLEAF(spl3)
XLEAF(spl1)
SPLXLEAF(splhi,a0,_splhi,__splhi)
SPLMETER_PROLOGUE(_splhi)
.set noreorder
mfc0 v0,C0_SR
li t1,1<<3
lw t0,VPDA_CURSPL(zero)
ble t1,t0,3f # are we at a higher level?
# Retain the DE and ERL bits
li v1,SR_KX|SR_DE|SR_IMASK5|SR_ERL|SR_IE
and v1,v0
and t2,v0,~SR_IE
mtc0 t2,C0_SR
LOAD_CRIME_INTMASK(t1,t0,t2)
BUILD_RETURN_VALUE(v0,t0)
sw t1,VPDA_CURSPL(zero)
SPLMETER_WORK(SPLHI)
3: BUILD_RETURN_VALUE(v0,t0)
NOCHANGE_SPLMETER_WORK(SPLHI)
.set reorder
SPLEND(splhi,__splhi)
#ifdef SPLMETER
LEAF(splhi_nosplmeter)
.set noreorder
mfc0 v0,C0_SR
li t1,1<<3
lw t0,VPDA_CURSPL(zero)
ble t1,t0,2f # are we at a higher level?
# Retain the DE and ERL bits
li v1,SR_KX|SR_DE|SR_IMASK5|SR_ERL|SR_IE
and v1,v0
and t2,v0,~SR_IE
mtc0 t2,C0_SR
LOAD_CRIME_INTMASK(t1,t0,t2)
BUILD_RETURN_VALUE(v0,t0)
sw t1,VPDA_CURSPL(zero)
j ra
mtc0 v1,C0_SR
2: BUILD_RETURN_VALUE(v0,t0)
j ra
nop
.set reorder
END(splhi_nosplmeter)
#endif
/*
** a0 has processor status register
** return 1 if at splhi or higher
*/
LEAF(issplhi)
li v0,0
and v1,a0,SR_IE|SR_EXL
li a0,SR_IE
beq v1,a0,1f /* its enabled */
li v0,1
b 2f
1:
lw v1,VPDA_CURSPL(zero)
blt v1,1<<3,2f
li v0,1
2:
j ra
END(issplhi)
/*
* a0 has the processor status register
* return 1 if at splprof or higher
*/
LEAF(issplprof)
li v0,0
and v1,a0,SR_IE|SR_EXL
li a0,SR_IE
beq v1,a0,1f /* its enabled */
li v0,1
b 2f
1:
lw v1,VPDA_CURSPL(zero)
blt v1,2<<3,2f
li v0,1
2:
j ra
END(issplprof)
/*
* spl65: block against all interrupts except bus-error.
* never lowers spl
* Count-compare, which interrupts at level 8, is disabled.
*/
SPLLEAF(splprof,a0,_splprof,__splprof)
XLEAF(spl65)
SPLMETER_PROLOGUE(_splprof)
.set noreorder
mfc0 v0,C0_SR
li t1,2<<3
lw t0,VPDA_CURSPL(zero)
ble t1,t0,3f # are we at a higher level?
# Retain the DE and ERL bits
li v1,SR_KX|SR_DE|SR_IMASK6|SR_ERL|SR_IE
and v1,v0
and t2,v0,~SR_IE
mtc0 t2,C0_SR
LOAD_CRIME_INTMASK(t1,t0,t2)
BUILD_RETURN_VALUE(v0,t0)
sw t1,VPDA_CURSPL(zero)
SPLMETER_WORK(SPLPROF)
3: BUILD_RETURN_VALUE(v0,t0)
NOCHANGE_SPLMETER_WORK(SPLPROF)
.set reorder
SPLEND(splprof,__splprof)
/*
* spl7: block against all interrupts.
*/
SPLLEAF(spl7,a0,_spl7,__spl7)
SPLMETER_PROLOGUE(_spl7)
.set noreorder
mfc0 v0,C0_SR
li t1,3<<3
lw t0,VPDA_CURSPL(zero)
ble t1,t0,3f # are we at a higher level?
# Retain the DE and ERL bits
li v1,SR_KX|SR_DE|SR_IMASK8|SR_ERL|SR_IE
and v1,v0
and t2,v0,~SR_IE
mtc0 t2,C0_SR
LOAD_CRIME_INTMASK(t1,t0,t2)
BUILD_RETURN_VALUE(v0,t0)
sw t1,VPDA_CURSPL(zero)
SPLMETER_WORK(SPL7_IP32)
3: BUILD_RETURN_VALUE(v0,t0)
NOCHANGE_SPLMETER_WORK(SPL7_IP32)
.set reorder
SPLEND(spl7,__spl7)
/*
* splecc: block against all interrupts and disable ecc exceptions.
*/
LEAF(splecc)
.set noreorder
mfc0 v0,C0_SR
li v1,SR_ERL
and v1,v0
.set noat
li AT,SR_KX|SR_DE|SR_IMASK8|SR_IE
or v1,AT
.set at
li t0,4<<3
BUILD_RETURN_VALUE(v0,t0)
sw t0,VPDA_CURSPL(zero)
j ra
mtc0 v1,C0_SR
.set reorder
END(splecc)
/*
* splx(ipl) -- restore previously saved ipl
*/
SPLLEAF(splx,a1,_splx,__splx)
XLEAF(splxecc)
#ifdef SPLMETER
move a1,ra
move a2,sp
j lowerspl
END (splx)
LEAF(__splx)
XLEAF(__splxecc)
#endif /* SPLMETER */
#ifdef STKDEBUG
li v0,0xC0000000 # zeros and no coproc 2 or 3
and v0,v0,a0
beq v0,zero,1f
move a2,ra
move a3,a0
PANIC("splx:ra: %x bad arg:%x");
1:
#endif
.set noreorder
mfc0 v0,C0_SR
li v1,SR_KX|SR_DE|SR_ERL # Retain the DE and ERL bits
and v1,v0
BUILD_SR_IMASK(a0,t0,t1)
or a0,v1
and t2,a0,~SR_IE
mtc0 t2,C0_SR
LOAD_CRIME_INTMASK(t0,t1,t2)
sw t0,VPDA_CURSPL(zero)
j ra
mtc0 a0,C0_SR # in BDSLOT
.set reorder
#ifdef SPLMETER
END(__splx)
#else
SPLEND(splx,__splx)
#endif /* SPLMETER */
/*
* splint(ipl) -- restore previously saved ipl; set IEC
*/
LEAF(splint)
#ifdef STKDEBUG
li v0,0xC0000000 # zeros and no coproc 2 or 3
and v0,v0,a0
beq v0,zero,1f
move a2,ra
move a3,a0
PANIC("splint:ra: %x bad arg:%x");
1:
#endif
.set noreorder
mfc0 v0,C0_SR
li v1,SR_KX|SR_DE|SR_ERL # Retain the DE and ERL bits
and v1,v0
ori v1,SR_IE
LOAD_CRIME_INTMASK(a0,t0,t2)
BUILD_RETURN_VALUE(v0,t0)
sw a0,VPDA_CURSPL(zero)
j ra
mtc0 v1,C0_SR # in BDSLOT
.set reorder
END(splint)
#endif /* IP32 */
#if IP26
/* IP26 spls
*
* The IP26 has two sets of local interrupts: high and low priority.
*
* Interrupts:
*
* 11 TFP internal timer (not really used).
* 10 Odd bank G-Cache parity error
* 9 Even bank G-Cache parity error
* 8 ECC error reporting
* 7 Bus error/timeout from MC or TCC mach check. Other TCC
* and TFP bus errors reported thru SR_BE.
* 6 profiling clock. (timer channel 1)
* 5 sched clock (timer channel 0) and TCC count/compare timer
* 4 high priority vectored devices
* 3 low priority vectored devices
* 2 softnet
* 1 softclock
*
* For some baseboards in some conditions we need to not enable IP8 since
* original boards with a 33Mhz GIO the hardware sometimes, until it basically
* kills the machine.
*/
/*
* spl0: Don't block against anything, and ignore the previous state.
*/
LEAF(spl0)
.set noreorder
dmfc0 a0,C0_WORK1 # local sr_mask
ssnop
dmfc0 v0,C0_SR
LI v1,SR_DEFAULT|SR_KERN_USRKEEP
and v1,v0
or v1,SR_IE|SR_IMASK0
and v1,a0
dmtc0 v1,C0_SR
ssnop
ssnop
j ra
nada
.set reorder
END(spl0)
/*
* spl6: block against sched clock interrupts. (level 5 hardint).
*
* Never lowers spl
*/
LEAF(spl6)
XLEAF(splhi)
XLEAF(splhi_relnet)
XLEAF(spl1)
XLEAF(spl3)
XLEAF(spl5)
XLEAF(splvme)
XLEAF(splnet)
XLEAF(spltty)
XLEAF(splimp)
XLEAF(splgio0)
XLEAF(splgio1)
XLEAF(splgio2)
XLEAF(splhintr)
XLEAF(splretr)
.set noreorder
dmfc0 a0,C0_WORK1 # local sr_mask
ssnop
dmfc0 v0,C0_SR
LI t1,SR_DEFAULT|SR_KERN_USRKEEP
and t1,v0
or t1,SR_IE|SR_IMASK5
and t0,v0,SR_IBIT5 # SR_IBIT5 off -> SR_IMASK5 or higher
and t1,a0
movz t1,v0,t0 # use current SR if higher already
dmtc0 t1,C0_SR
ssnop
ssnop
j ra
nada
.set reorder
END(spl6)
/*
* issplhi: a0 has processor status register -- return 1 if at splhi or higher.
*/
LEAF(issplhi)
move v0,zero
li v1,1
and a0,(SR_IE|SR_IBIT5) # IBIT5 off -> SR_IMASK5 or higher
xor a0,(SR_IE|SR_IBIT5) # SR_IE off -> all ints disabled
movn v0,v1,a0 # set rc=1 if true
j ra
END(issplhi)
/*
* issplprof: a0 has processor status register -- return 1 if at splprof or
* higher.
*/
LEAF(issplprof)
move v0,zero
li v1,1
and a0,(SR_IE|SR_EXL|SR_IBIT6) # IBIT6 off -> SR_PROF or higher
xor a0,(SR_IE|SR_IBIT6) # SR_IE off -> all ints off
# SR_EXL on -> all ints off
movn v0,v1,a0 # set rc=1 if true
j ra
END(issplprof)
/*
* spl65: block against all interrupts except external bus-errors and
* G cache errors.
*
* Never lowers spl.
*/
LEAF(spl65)
XLEAF(splprof)
.set noreorder
dmfc0 a0,C0_WORK1 # local sr_mask
ssnop
dmfc0 v0,C0_SR
LI t1,SR_DEFAULT|SR_KERN_USRKEEP
and t1,v0
or t1,SR_IE|SR_IBIT7|SR_IBIT8|SR_IBIT9|SR_IBIT10
and t0,v0,SR_IBIT6 # SR_IBIT6 off -> spl65 or higher
and t1,a0
movz t1,v0,t0 # use current SR if higher already
dmtc0 t1,C0_SR
ssnop
ssnop
j ra
nada
.set reorder
END(spl65)
/*
* spl7: block against all interrupts except GCache parity errors (fatal).
*/
LEAF(spl7)
.set noreorder
dmfc0 v0,C0_SR
LI v1,SR_DEFAULT|SR_KERN_USRKEEP
and v1,v0
or v1,SR_IE|SR_IBIT9|SR_IBIT10 /* o+e GCache */
dmtc0 v1,C0_SR
ssnop
ssnop
j ra
nada
.set reorder
END(spl7)
/*
* splx(ipl) -- restore previously saved ipl
*/
LEAF(splx)
#ifdef STKDEBUG
LI v0,0xfffffe00c000800c # reserve bits all off
and v0,v0,a0
beq v0,zero,1f
move a2,ra
move a3,a0
PANIC("splx:ra: %x bad arg:%x");
1:
#endif
.set noreorder
dmfc0 a1,C0_WORK1 # local sr_mask
ssnop
dmfc0 v0,C0_SR
LI v1,SR_DEFAULT|SR_KERN_USRKEEP
and v1,v0
or a0,v1
and a0,a1
dmtc0 a0,C0_SR
ssnop
ssnop
j ra
nada
.set reorder
END(splx)
#endif /* IP26 */
#if DEBUG
/*
* The one-second code in os/clock.c lowers the currently spl based on
* examination of the status register at the time of interrupt. If the
* status register indicates that all interrupts were previously enabled,
* it does the one second stuff, otherwise it waits for the next clock tick.
*
* Since all spls are now spl or higher, we only now have to check that
* we were @ spl0. However, some kernel code disables SR_IE, but can
* get an interrupt before the mtc0 bubbles through the pipe, and end
* up with SR_IMASK0 ok but SR_IE=0. Hence we do not check SR_IE, which
* is good enough for the clock code.
*
* return true if it is okay to lower the spl
* a0 - EP at time of interrupt
*/
LEAF(loclkok)
lreg a0,EF_SR(a0)
#ifdef IP26
.set noreorder
dmfc0 v0,C0_WORK1
li v1,SR_IMASK0
.set reorder
and v1,v0
#else
li v1,SR_IMASK0 /* For IP32 IMASK0 != IMASK */
#endif
and a0,v1
bne a0,v1,1f
li v0,1
j ra
1:
li v0,0
j ra
END(loclkok)
#endif
LEAF(isspl0)
#ifdef IP26
.set noreorder
dmfc0 v0,C0_WORK1
li v1,SR_IMASK|SR_IE
.set reorder
and v1,v0
#else
li v1,SR_IMASK0|SR_IE /* For IP32 IMASK0 != IMASK */
#endif
and a0,v1
bne a0,v1,1f
li v0,1
j ra
1:
li v0,0
j ra
END(isspl0)
#if !(IP26 || IP27 || IP28 || IP30 || IP33)
/*
* For compatibility with Everest systems.
*/
LEAF(allowintrs)
j ra
END(allowintrs)
#endif
/* delay_for_intr()
* Routine which can be invoked to allow any pending interrupts to occur
* before we raise spl level again.
* Typical use is in long computation where code wishs to drop spl then
* immediately raise it again, but need to allow pending interrupts to
* occur.
*/
LEAF(delay_for_intr)
#if IP32
j __sysad_wbflush
#else
.set noreorder
j ra
nop
.set reorder
#endif
END(delay_for_intr)