#include "opt_m68k_arch.h"
#include <machine/asm.h>
#include <machine/trap.h>
#include "assym.h"
.file "buserr_2030.s"
.text
#if !defined(M68K_MMU_MOTOROLA) && !defined(M68K_MMU_HP) && \
!defined(M68K_MMU_SUN3)
#error Why are we even here?
#endif
#define MULTIMMU ((defined(M68K_MMU_MOTOROLA) + \
defined(M68K_MMU_HP) + \
defined(M68K_MMU_SUN3)) \
> 1)
ENTRY_NOPROFILE(busaddrerr2030)
GLOBAL(buserr2030)
GLOBAL(addrerr2030)
| 68020 and 68030 may push one of two different stack frames
| for bus error and address error:
|
| Format A - execution unit is at an instruction boundary
|
| Format B - instruction execution is in-progress
|
| Happily, the stuff we need is at the same offset in both
| stack frame types.
clrl %sp@- | stack adjust count
moveml %d0-%d7/%a0-%a7,%sp@- | save user registers
movl %usp,%a0 | save the user SP
movl %a0,%sp@(FR_SP) | in the savearea
moveq #0,%d0
movw %sp@(FR_FMTA_SSW),%d0 | grab SSW for fault processing
btst #12,%d0 | RB set?
jeq LbeX0 | no, test RC
bset #14,%d0 | yes, must set FB
movw %d0,%sp@(FR_FMTA_SSW) | for hardware too
LbeX0:
btst #13,%d0 | RC set?
jeq LbeX1 | no, skip
bset #15,%d0 | yes, must set FC
movw %d0,%sp@(FR_FMTA_SSW) | for hardware too
LbeX1:
btst #8,%d0 | data fault?
jeq Lbe0 | no, check for hard cases
movl %sp@(FR_FMTA_DCFA),%d1 | fault address is as given in frame
jra Lbe10 | thats it
Lbe0:
btst #4,%sp@(FR_FORVEC) | long (type B) stack frame?
jne Lbe4 | yes, go handle
movl %sp@(FR_PC),%d1 | no, can use save PC
btst #14,%d0 | FB set?
jeq Lbe3 | no, try FC
addql #4,%d1 | yes, adjust address
jra Lbe10 | done
Lbe3:
btst #15,%d0 | FC set?
jeq Lbe10 | no, done
addql #2,%d1 | yes, adjust address
jra Lbe10 | done
Lbe4:
movl %sp@(FR_FMTB_SBA),%d1 | long format, use stage B address
btst #15,%d0 | FC set?
jeq Lbe10 | no, all done
subql #2,%d1 | yes, adjust address
Lbe10:
movl %d1,%sp@- | push fault VA
movl %d0,%sp@- | and padded SSW
movw %sp@(8+FR_FORVEC),%d0 | get frame format/vector offset
andw #0x0FFF,%d0 | clear out frame format
cmpw #12,%d0 | address error vector?
jeq Lisaerr | yes, go to it
#if defined(M68K_MMU_SUN3)
#if MULTIMMU
#error No MULTIMMU configuration for Sun3.
#endif
Lbuserr2030_sun3_mmu:
clrl %d0 | make sure top bits are cleared too
movl %d1,%sp@- | save %d1
movc %sfc,%d1 | save %sfc to %d1
moveq #FC_CONTROL,%d0 | %sfc = FC_CONTROL
movc %d0,%sfc
movsb BUSERR_REG,%d0 | get value of bus error register
movc %d1,%sfc | restore %sfc
movl %sp@+,%d1 | restore %d1
andb #BUSERR_MMU,%d0 | is this an MMU fault?
jeq _ASM_LABEL(buserr_common) | non-MMU bus error
#if MULTIMMU
jra Lismerr | MMU fault
#endif
#endif
#if defined(M68K_MMU_HP)
#if MULTIMMU
tstl _C_LABEL(mmutype) | HP MMU?
jne Lbuserr2030_moto_mmu
#endif
Lbuserr2030_hp_mmu:
movl _C_LABEL(MMUbase),%a0 | %a0 = MMU address
movl %a0@(MMUSTAT),%d0 | read MMU status
btst #3,%d0 | MMU fault?
jeq _ASM_LABEL(buserr_common) | no, just a non-MMU bus error
andl #~MMU_FAULT,%a0@(MMUSTAT)| yes, clear fault bits
movw %d0,%sp@ | pass MMU stat in upper half of code
#if MULTIMMU
jra Lismerr | and handle it
#endif
#endif
#if defined(M68K_MMU_MOTOROLA)
Lbuserr2030_moto_mmu:
movl %d1,%a0 | fault address
movl %sp@,%d0 | function code from ssw
btst #8,%d0 | data fault?
jne Lbe10a
movql #1,%d0 | user program access FC
| (we dont separate data/program)
btst #5,%sp@(8+FR_SR) | supervisor mode?
jeq Lbe10a | if no, done
movql #5,%d0 | else supervisor program access
Lbe10a:
#ifdef M68030
ptestr %d0,%a0@,#0 | only PTEST #0 can detect transparent
pmove %psr,%sp@ | translation (TT0 or TT1).
movw %sp@,%d1
btst #6,%d1 | transparent (TT0 or TT1)?
jne Lisberr | yes -> bus error
#endif
ptestr %d0,%a0@,#7 | no, do a table search
pmove %psr,%sp@ | save result
movb %sp@,%d1
btst #2,%d1 | invalid (incl. limit viol. and berr)?
jeq Lmightnotbemerr | no -> wp check
btst #7,%d1 | is it MMU table berr?
jeq Lismerr | no, must be fast
jra Lisberr | real bus err needs not be fast.
Lmightnotbemerr:
btst #3,%d1 | write protect bit set?
jeq Lisberr | no, must be bus error
movl %sp@,%d0 | ssw into low word of d0
andw #0xc0,%d0 | write protect is set on page:
cmpw #0x40,%d0 | was it read cycle?
jeq Lisberr | yes, was not WPE, must be bus err
#endif
Lismerr:
movl #T_MMUFLT,%sp@- | show that we are an MMU fault
jra _ASM_LABEL(faultstkadj) | and deal with it
Lisaerr:
movl #T_ADDRERR,%sp@- | mark address error
jra _ASM_LABEL(faultstkadj) | and deal with it
#ifdef M68K_MMU_MOTOROLA
Lisberr:
clrw %sp@ | re-clear upper half of padded
| SSW word that we clobbered
| with PMOVE.
jra _ASM_LABEL(buserr_common)
#endif