#include "opt_m68k_arch.h"
#include "opt_compat_netbsd.h"
#include "opt_compat_sunos.h"
#include "opt_fpsp.h"
#include "opt_m060sp.h"
#include <machine/asm.h>
#include <machine/trap.h>
#include "assym.h"
.file "trap_subr.s"
.text
ASENTRY_NOPROFILE(fault)
movl %usp,%a0 | get and save
movl %a0,FR_SP(%sp) | the user stack pointer
clrl -(%sp) | no VA arg
clrl -(%sp) | or code arg
movl %d0,-(%sp) | push trap type
pea 12(%sp) | address of trap frame
jbsr _C_LABEL(trap) | handle trap
lea 16(%sp),%sp | pop value args
movl FR_SP(%sp),%a0 | restore
movl %a0,%usp | user SP
moveml (%sp)+,#0x7FFF | restore most user regs
addql #8,%sp | pop SP and stack adjust
jra _ASM_LABEL(rei) | all done
ASENTRY(faultstkadj)
pea 12(%sp) | address of trap frame
jbsr _C_LABEL(trap) | handle the error
lea 16(%sp),%sp | pop value args
ASGLOBAL(faultstkadjnotrap2)
movl FR_SP(%sp),%a0 | restore user SP
movl %a0,%usp | from save area
movw FR_ADJ(%sp),%d0 | need to adjust stack?
jne 1f | yes, go to it
moveml (%sp)+,#0x7FFF | no, restore most user regs
addql #8,%sp | toss SSP and stkadj
jra _ASM_LABEL(rei) | all done
1:
lea FR_HW(%sp),%a1 | pointer to HW frame
addql #8,%a1 | source pointer
movl %a1,%a0 | source
addw %d0,%a0 | + hole size = dest pointer
movl -(%a1),-(%a0) | copy
movl -(%a1),-(%a0) | 8 bytes
movl %a0,FR_SP(%sp) | new SSP
moveml (%sp)+,#0x7FFF | restore user registers
movl (%sp),%sp | and our SP
jra _ASM_LABEL(rei) | all done
ASGLOBAL(buserr_common)
tstl _C_LABEL(nofault) | catch bus error?
jeq 1f | no, handle as usual
#ifdef mac68k
movl %sp@(FR_A2+8),_C_LABEL(mac68k_a2_fromfault)
movl %sp@(4),_C_LABEL(m68k_fault_addr)
#endif
movl _C_LABEL(nofault),%sp@- | yes,
jbsr _C_LABEL(longjmp) | longjmp(nofault)
1:
movl #T_BUSERR,%sp@- | mark bus error
jra _ASM_LABEL(faultstkadj) | and deal with it
#if defined(COMPAT_13) || defined(COMPAT_SUNOS)
ENTRY_NOPROFILE(trap1)
jra _C_LABEL(m68k_compat_13_sigreturn13_stub)
#endif
ENTRY_NOPROFILE(trap2)
jra _C_LABEL(trace)
#if defined(COMPAT_16)
ENTRY_NOPROFILE(trap3)
jra _C_LABEL(m68k_compat_16_sigreturn14_stub)
#endif
ENTRY_NOPROFILE(illinst)
clrl -(%sp)
moveml #0xFFFF,-(%sp)
moveq #T_ILLINST,%d0
jra _ASM_LABEL(fault)
ENTRY_NOPROFILE(zerodiv)
clrl -(%sp)
moveml #0xFFFF,-(%sp)
moveq #T_ZERODIV,%d0
jra _ASM_LABEL(fault)
ENTRY_NOPROFILE(chkinst)
clrl -(%sp)
moveml #0xFFFF,-(%sp)
moveq #T_CHKINST,%d0
jra _ASM_LABEL(fault)
ENTRY_NOPROFILE(trapvinst)
clrl -(%sp)
moveml #0xFFFF,-(%sp)
moveq #T_TRAPVINST,%d0
jra _ASM_LABEL(fault)
ENTRY_NOPROFILE(privinst)
clrl -(%sp)
moveml #0xFFFF,-(%sp)
moveq #T_PRIVINST,%d0
jra _ASM_LABEL(fault)
#ifndef __mc68010__
ENTRY_NOPROFILE(coperr)
clrl -(%sp) | stack adjust count
moveml #0xFFFF,-(%sp)
movl %usp,%a0 | get and save
movl %a0,FR_SP(%sp) | the user stack pointer
clrl -(%sp) | no VA arg
clrl -(%sp) | or code arg
movl #T_COPERR,-(%sp) | push trap type
jra _ASM_LABEL(faultstkadj) | call trap and deal with stack
| adjustments
#endif
ENTRY_NOPROFILE(fmterr)
clrl -(%sp) | stack adjust count
moveml #0xFFFF,-(%sp)
movl %usp,%a0 | get and save
movl %a0,FR_SP(%sp) | the user stack pointer
clrl -(%sp) | no VA arg
clrl -(%sp) | or code arg
movl #T_FMTERR,-(%sp) | push trap type
jra _ASM_LABEL(faultstkadj) | call trap and deal with stack
| adjustments
#if defined(M68040) && defined(FPSP)
ENTRY_NOPROFILE(fpfline_fpsp40)
cmpw #0x202c,6(%sp) | format type 2?
jne _C_LABEL(illinst) | no, not an FP emulation
jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it
ENTRY_NOPROFILE(fpunsupp_fpsp40)
jmp _ASM_LABEL(fpsp_unsupp)
#endif
#if (defined(M68040) && !defined(FPSP)) || \
(defined(M68060) && !defined(M060SP))
ENTRY_NOPROFILE(fpunsupp_4060)
clrl -(%sp) | stack adjust count
moveml #0xFFFF,-(%sp) | save registers
moveq #T_FPEMULD,%d0 | denote as FP emulation trap
jra _ASM_LABEL(fault) | do it
#endif
ENTRY_NOPROFILE(fpfline)
clrl -(%sp) | stack adjust count
moveml #0xFFFF,-(%sp) | save registers
moveq #T_FPEMULI,%d0 | denote as FP emulation trap
jra _ASM_LABEL(fault) | do it
#ifdef M68K_FPCOPROC
ENTRY_NOPROFILE(fpfault)
clrl -(%sp) | stack adjust count
moveml #0xFFFF,-(%sp) | save registers
movl %usp,%a0 | and save
movl %a0,FR_SP(%sp) | the user stack pointer
clrl -(%sp) | no VA arg
movl _C_LABEL(curpcb),%a0 | current pcb
lea PCB_FPCTX(%a0),%a0 | address of FP savearea
fsave (%a0) | save state
#if defined(M68020) || defined(M68030)
#if defined(M68040) || defined(M68060)
cmpl #FPU_68040,_C_LABEL(fputype)
jge Lfptnull
#endif
tstb (%a0) | null state frame?
jeq Lfptnull | yes, safe
clrw %d0 | no, need to tweak BIU
movb 1(%a0),%d0 | get frame size
bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU
Lfptnull:
#endif
fmovem %fpsr,-(%sp) | push %fpsr as code argument
frestore (%a0) | restore state
movl #T_FPERR,-(%sp) | push type arg
jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
#endif
ENTRY_NOPROFILE(badtrap)
clrl -(%sp) | stack adjust count
moveml #0xFFFF,-(%sp) | save standard frame regs
jbsr _C_LABEL(straytrap) | report
moveml (%sp)+,#0x7FFF | restore all except %sp
addql #8,%sp | pop stack adjust count and %sp
jra _ASM_LABEL(rei) | all done
ENTRY_NOPROFILE(trap0)
clrl -(%sp) | stack adjust count
moveml #0xFFFF,-(%sp) | save user registers
movl %usp,%a0 | save the user SP
movl %a0,%sp@(FR_SP) | in the savearea
movl %d0,-(%sp) | push syscall number
jbsr _C_LABEL(syscall) | handle it
addql #4,%sp | pop syscall arg
tstl _C_LABEL(astpending) | AST pending?
jne _ASM_LABEL(doast) | Yup, go deal with it.
movl %sp@(FR_SP),%a0 | grab and restore
movl %a0,%usp | user SP
moveml (%sp)+,#0x7FFF | restore most registers
addql #8,%sp | pop SP and stack adjust
rte | all done
ENTRY_NOPROFILE(trap12)
#ifndef __mc68010__
movl _C_LABEL(curlwp),%a0
movl %a0@(L_PROC),-(%sp) | push current proc pointer
movl %d1,-(%sp) | push length
movl %a1,-(%sp) | push addr
movl %d0,-(%sp) | push command
jbsr _C_LABEL(cachectl1) | do it
lea %sp@(16),%sp | pop args
#endif
jra _ASM_LABEL(rei) | all done
ENTRY_NOPROFILE(trace)
clrl %sp@- | stack adjust count
moveml #0xFFFF,%sp@-
moveq #T_TRACE,%d0
| Check PSW and see what happen.
| T=0 S=0 (should not happen)
| T=1 S=0 trace trap from user mode
| T=0 S=1 trace trap on a trap instruction
| T=1 S=1 trace trap from system mode (kernel breakpoint)
movw %sp@(FR_HW),%d1 | get PSW
notw %d1 | XXX no support for T0 on 680[234]0
andw #PSL_TS,%d1 | from system mode (T=1, S=1)?
jeq Lkbrkpt | yes, kernel breakpoint
jra _ASM_LABEL(fault) | no, user-mode fault
ENTRY_NOPROFILE(trap15)
clrl %sp@- | stack adjust count
moveml #0xFFFF,%sp@-
moveq #T_TRAP15,%d0
btst #5,%sp@(FR_HW) | was supervisor mode?
jne Lkbrkpt | yes, kernel breakpoint
jra _ASM_LABEL(fault) | no, user-mode fault
Lkbrkpt:
| Kernel-mode breakpoint or trace trap. (%d0=trap_type)
| Save the system sp rather than the user sp.
movw #PSL_HIGHIPL,%sr | lock out interrupts
lea %sp@(FR_SIZE),%a6 | Save stack pointer
movl %a6,%sp@(FR_SP) | from before trap
| If were are not on tmpstk switch to it.
| (so debugger can change the stack pointer)
movl %a6,%d1
cmpl #_ASM_LABEL(tmpstk),%d1
jls 2f | already on tmpstk
| Copy frame to the temporary stack
movl %sp,%a0 | a0=src
lea _ASM_LABEL(tmpstk)-96,%a1 | a1=dst XXX MAGIC NUMBER 96
movl %a1,%sp | sp=new frame
movql #FR_SIZE,%d1
1:
movl %a0@+,%a1@+
subql #4,%d1
jbgt 1b
2:
| Call the trap handler for the kernel debugger.
| Do not call trap() to do it, so that we can
| set breakpoints in trap() if we want. We know
| the trap type is either T_TRACE or T_BREAKPOINT.
movl %sp,%a0 | frame pointer
movl %a0,%sp@- | push frame ptr
movl %d0,%sp@- | push trap type
jbsr _C_LABEL(trap_kdebug)
addql #8,%sp | pop args
| The stack pointer may have been modified, or
| data below it modified (by kgdb push call),
| so push the hardware frame at the current sp
| before restoring registers and returning.
movl %sp@(FR_SP),%a0 | modified sp
lea %sp@(FR_SIZE),%a1 | end of our frame
movl %a1@-,%a0@- | copy 2 longs with
movl %a1@-,%a0@- | ... predecrement
movl %a0,%sp@(FR_SP) | sp = h/w frame
moveml %sp@+,#0x7FFF | restore all but sp
movl %sp@,%sp | ... and sp
rte | all done
ASENTRY_NOPROFILE(rei)
tstl _C_LABEL(astpending) | AST pending?
jne 1f | yes, next check...
rte | nope, done.
1:
btst #5,%sp@ | Are we returning to user mode?
jeq 1f | yes, go do the work.
rte | nope, done.
1:
movw #PSL_LOWIPL,%sr | lower SPL
clrl %sp@- | stack adjust
moveml %d0-%d7/%a0-%a7,%sp@- | save all registers
movl %usp,%a1 | including
movl %a1,%sp@(FR_SP) | the users SP
ASGLOBAL(doast) | fast-path for syscall trap vector
clrl %sp@- | VA == none
clrl %sp@- | code == none
movl #T_ASTFLT,%sp@- | type == async system trap
pea %sp@(12) | fp == address of trap frame
jbsr _C_LABEL(trap) | go handle it
lea %sp@(16),%sp | pop value args
movl %sp@(FR_SP),%a0 | restore user SP
movl %a0,%usp | from save area
movw %sp@(FR_ADJ),%d0 | need to adjust stack?
jne Laststkadj | yes, go to it
moveml %sp@+,%d0-%d7/%a0-%a6 | no, restore most user regs
addql #8,%sp | toss SP and stack adjust
rte | done.
Laststkadj:
lea %sp@(FR_HW),%a1 | pointer to HW frame
addql #8,%a1 | source pointer
movl %a1,%a0 | source
addw %d0,%a0 | + hole size = dest pointer
movl %a1@-,%a0@- | copy
movl %a1@-,%a0@- | 8 bytes
movl %a0,%sp@(FR_SP) | new SSP
moveml %sp@+,%d0-%d7/%a0-%a6 | restore user registers
movl %sp@,%sp | and our SP
rte | done.