Home | History | Annotate | Line # | Download | only in arm32
exception.S revision 1.11
      1  1.11      scw /*	$NetBSD: exception.S,v 1.11 2003/10/26 11:34:29 scw Exp $	*/
      2   1.1    chris 
      3   1.1    chris /*
      4   1.1    chris  * Copyright (c) 1994-1997 Mark Brinicombe.
      5   1.1    chris  * Copyright (c) 1994 Brini.
      6   1.1    chris  * All rights reserved.
      7   1.1    chris  *
      8   1.1    chris  * This code is derived from software written for Brini by Mark Brinicombe
      9   1.1    chris  *
     10   1.1    chris  * Redistribution and use in source and binary forms, with or without
     11   1.1    chris  * modification, are permitted provided that the following conditions
     12   1.1    chris  * are met:
     13   1.1    chris  * 1. Redistributions of source code must retain the above copyright
     14   1.1    chris  *    notice, this list of conditions and the following disclaimer.
     15   1.1    chris  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1    chris  *    notice, this list of conditions and the following disclaimer in the
     17   1.1    chris  *    documentation and/or other materials provided with the distribution.
     18   1.1    chris  * 3. All advertising materials mentioning features or use of this software
     19   1.1    chris  *    must display the following acknowledgement:
     20   1.1    chris  *	This product includes software developed by Brini.
     21   1.1    chris  * 4. The name of the company nor the name of the author may be used to
     22   1.1    chris  *    endorse or promote products derived from this software without specific
     23   1.1    chris  *    prior written permission.
     24   1.1    chris  *
     25   1.1    chris  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
     26   1.1    chris  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     27   1.1    chris  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     28   1.1    chris  * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     29   1.1    chris  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     30   1.1    chris  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     31   1.1    chris  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32   1.1    chris  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33   1.1    chris  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34   1.1    chris  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35   1.1    chris  * SUCH DAMAGE.
     36   1.1    chris  *
     37   1.1    chris  * RiscBSD kernel project
     38   1.1    chris  *
     39   1.1    chris  * exception.S
     40   1.1    chris  *
     41   1.1    chris  * Low level handlers for exception vectors
     42   1.1    chris  *
     43   1.1    chris  * Created      : 24/09/94
     44   1.1    chris  *
     45   1.1    chris  * Based on kate/display/abort.s
     46   1.1    chris  */
     47   1.1    chris 
     48   1.1    chris #include "opt_ipkdb.h"
     49   1.9      scw #include "opt_compat_netbsd.h"
     50   1.9      scw #include "opt_execfmt.h"
     51   1.9      scw #include "opt_multiprocessor.h"
     52   1.1    chris #include <machine/asm.h>
     53   1.1    chris #include <machine/cpu.h>
     54   1.1    chris #include <machine/frame.h>
     55   1.1    chris #include "assym.h"
     56   1.1    chris 
     57   1.1    chris 	.text
     58   1.1    chris 	.align	0
     59   1.1    chris 
     60   1.9      scw .Lastpending:
     61   1.9      scw 	.word	_C_LABEL(astpending)
     62   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
     63   1.9      scw .Lcpufuncs:
     64   1.9      scw 	.word	_C_LABEL(cpufuncs)
     65   1.9      scw #ifndef MULTIPROCESSOR
     66   1.9      scw .Lcurpcb:
     67   1.9      scw 	.word	_C_LABEL(curpcb)
     68   1.9      scw .Lcpu_info_store:
     69   1.9      scw 	.word	_C_LABEL(cpu_info_store)
     70   1.9      scw #define	GET_CURPCB							\
     71   1.9      scw 	ldr	r1, .Lcurpcb						;\
     72   1.9      scw 	ldr	r1, [r1]
     73   1.9      scw #define	GET_CPUINFO							\
     74   1.9      scw 	ldr	r0, .Lcpu_info_store
     75   1.9      scw #else
     76   1.9      scw .Lcpu_info:
     77   1.9      scw 	.word	_C_LABEL(cpu_info)
     78   1.9      scw #define	GET_CURPCB							\
     79   1.9      scw 	ldr	r4, .Lcpu_info						;\
     80   1.9      scw 	bl	_C_LABEL(cpu_number)					;\
     81   1.9      scw 	ldr	r0, [r4, r0, lsl #2]					;\
     82   1.9      scw 	ldr	r1, [r0, #CI_CURPCB]
     83   1.9      scw #define	GET_CPUINFO	/* nothing to do */
     84   1.9      scw #endif
     85   1.9      scw #define	ENABLE_ALIGNMENT_FAULTS						\
     86   1.9      scw 	GET_CURPCB							;\
     87  1.11      scw 	cmp	r1, #0x00		/* curpcb NULL?			;\
     88  1.11      scw 	ldrne	r1, [r1, #PCB_FLAGS]	/* Fetch curpcb->pcb_flags */	;\
     89  1.11      scw 	tstne	r1, #PCB_NOALIGNFLT					;\
     90   1.9      scw 	beq	1f		/* Alignment faults already enabled */	;\
     91   1.9      scw 	GET_CPUINFO							;\
     92   1.9      scw 	ldr	r2, .Lcpufuncs						;\
     93   1.9      scw 	ldr	r1, [r0, #CI_CTRL]	/* Fetch control register */	;\
     94   1.9      scw 	mov	r0, #-1							;\
     95   1.9      scw 	mov	lr, pc							;\
     96   1.9      scw 	ldr	pc, [r2, #CF_CONTROL]	/* Enable alignment faults */	;\
     97   1.9      scw 1:
     98   1.9      scw #endif /* COMPAT_15 && EXEC_AOUT */
     99   1.9      scw 
    100   1.1    chris 
    101   1.1    chris /*
    102   1.1    chris  * General exception exit handler
    103   1.1    chris  *
    104   1.1    chris  * It exits straight away if not returning to USR mode.
    105   1.1    chris  * This loops around delivering any pending ASTs.
    106   1.1    chris  * Interrupts are disabled at suitable points to avoid ASTs
    107   1.1    chris  * being posted between testing and exit to user mode.
    108   1.1    chris  *
    109   1.1    chris  * This function uses PULLFRAMEFROMSVCANDEXIT thus should
    110   1.1    chris  * only be called if the exception handler used PUSHFRAMEINSVC
    111   1.1    chris  */
    112   1.1    chris 
    113   1.1    chris exception_exit:
    114   1.6   briggs 	mrs     r4, cpsr		/* Get CPSR */
    115   1.1    chris 
    116   1.1    chris 	ldr	r0, [sp]		/* Get the SPSR from stack */
    117   1.1    chris 	and	r0, r0, #(PSR_MODE)	/* Test for USR32 mode before the AST */
    118   1.1    chris 	teq	r0, #(PSR_USR32_MODE)
    119   1.6   briggs 	bne	.Ldo_exit		/* Not USR mode so no AST delivery */
    120   1.1    chris 
    121   1.9      scw 	ldr	r5, .Lastpending	/* Get address of astpending */
    122   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT) && !defined(MULTIPROCESSOR)
    123   1.9      scw 	ldr	r6, .Lcurpcb
    124   1.9      scw 	ldr	r7, .Lcpu_info_store
    125   1.9      scw #endif
    126   1.1    chris 
    127   1.1    chris Lexception_exit_loop:
    128   1.1    chris 	orr     r0, r4, #(I32_bit)	/* Block IRQs */
    129   1.1    chris 	msr     cpsr_all, r0
    130   1.1    chris 
    131   1.1    chris 	ldr	r1, [r5]		/* Do we have an AST pending */
    132   1.1    chris 	teq	r1, #0x00000000
    133   1.6   briggs 	bne	.Ldo_ast
    134   1.1    chris 
    135   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
    136   1.9      scw 	/* Disable alignment faults for the process, if necessary. */
    137   1.9      scw #ifdef MULTIPROCESSOR
    138   1.9      scw 	ldr	r7, .Lcpu_info
    139   1.9      scw 	bl	_C_LABEL(cpu_number)
    140   1.9      scw 	ldr	r7, [r7, r0, lsl #2]
    141   1.9      scw 	ldr	r1, [r7, #CI_CURPCB]
    142   1.9      scw #else
    143   1.9      scw 	ldr	r1, [r6]
    144   1.9      scw #endif
    145  1.11      scw 	cmp	r1, #0x00		/* curpcb NULL? */
    146  1.11      scw 	ldrne	r1, [r1, #PCB_FLAGS]	/* Fetch curpcb->pcb_flags */
    147  1.11      scw 	tstne	r1, #PCB_NOALIGNFLT
    148   1.9      scw 	beq	1f			/* Keep alignment faults enabled */
    149   1.9      scw 	ldr	r1, [r7, #CI_CTRL]	/* Fetch control register */
    150   1.9      scw 	ldr	r2, .Lcpufuncs
    151   1.9      scw 	mov	r0, #-1
    152   1.9      scw 	bic	r1, r1, #CPU_CONTROL_AFLT_ENABLE  /* Disable alignment faults */
    153   1.9      scw 	mov	lr, pc
    154   1.9      scw 	ldr	pc, [r2, #CF_CONTROL]	/* Set the new control register value */
    155   1.9      scw 1:
    156   1.9      scw #endif
    157   1.9      scw 
    158   1.1    chris 	PULLFRAMEFROMSVCANDEXIT		/* No AST so exit */
    159   1.1    chris 
    160   1.6   briggs .Ldo_ast:
    161   1.1    chris 	mov	r1, #0x00000000		/* Clear ast pending */
    162   1.1    chris 	str	r1, [r5]
    163   1.1    chris 
    164   1.2  thorpej 	msr     cpsr_all, r4		/* Restore interrupts */
    165   1.2  thorpej 
    166   1.1    chris 	mov	r0, sp			/* arg 0 = trap frame */
    167   1.1    chris 	bl	_C_LABEL(ast)		/* call the AST handler */
    168   1.1    chris 	b	Lexception_exit_loop	/* Try and exit again */
    169   1.1    chris 
    170   1.6   briggs .Ldo_exit:
    171   1.8      wiz 	orr     r0, r4, #(I32_bit)	/* Disable interrupts */
    172   1.1    chris 	msr     cpsr_all, r0
    173   1.1    chris 
    174   1.1    chris 	PULLFRAMEFROMSVCANDEXIT		/* Restore the trap frame and exit */
    175   1.1    chris 
    176   1.3  thorpej /*
    177   1.3  thorpej  * reset_entry:
    178   1.3  thorpej  *
    179   1.3  thorpej  *	Handler for Reset exception.
    180   1.3  thorpej  */
    181   1.3  thorpej ASENTRY_NP(reset_entry)
    182   1.3  thorpej 	adr	r0, Lreset_panicmsg
    183   1.3  thorpej 	mov	r1, lr
    184   1.3  thorpej 	bl	_C_LABEL(panic)
    185   1.3  thorpej 	/* NOTREACHED */
    186   1.3  thorpej Lreset_panicmsg:
    187   1.3  thorpej 	.asciz	"Reset vector called, LR = 0x%08x"
    188   1.3  thorpej 	.balign	4
    189   1.1    chris 
    190   1.3  thorpej /*
    191   1.3  thorpej  * swi_entry
    192   1.3  thorpej  *
    193   1.3  thorpej  *	Handler for the Software Interrupt exception.
    194   1.3  thorpej  */
    195   1.3  thorpej ASENTRY_NP(swi_entry)
    196   1.3  thorpej 	PUSHFRAME
    197   1.3  thorpej 
    198   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
    199   1.9      scw 	ENABLE_ALIGNMENT_FAULTS
    200   1.9      scw #endif
    201   1.9      scw 
    202   1.3  thorpej 	mov	r0, sp			/* Pass the frame to any function */
    203   1.1    chris 
    204   1.5    bjh21 	bl	_C_LABEL(swi_handler)	/* It's a SWI ! */
    205   1.1    chris 
    206   1.9      scw 	ldr	r5, .Lastpending	/* Get address of astpending */
    207   1.6   briggs 	mrs     r4, cpsr		/* Get CPSR */
    208   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT) && !defined(MULTIPROCESSOR)
    209   1.9      scw 	ldr	r6, .Lcurpcb
    210   1.9      scw 	ldr	r7, .Lcpu_info_store
    211   1.9      scw #endif
    212   1.1    chris 
    213   1.6   briggs .Lswi_exit_loop:
    214   1.3  thorpej 	orr     r0, r4, #(I32_bit)	/* Disable IRQs */
    215   1.3  thorpej 	msr     cpsr_all, r0
    216   1.1    chris 
    217   1.3  thorpej 	ldr	r1, [r5]		/* Do we have an AST pending */
    218   1.3  thorpej 	teq	r1, #0x00000000
    219   1.6   briggs 	bne	.Ldo_swi_ast
    220   1.1    chris 
    221   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
    222   1.9      scw 	/* Disable alignment faults for the process, if necessary. */
    223   1.9      scw #ifdef MULTIPROCESSOR
    224   1.9      scw 	ldr	r7, .Lcpu_info
    225   1.9      scw 	bl	_C_LABEL(cpu_number)
    226   1.9      scw 	ldr	r7, [r7, r0, lsl #2]
    227   1.9      scw 	ldr	r1, [r7, #CI_CURPCB]
    228   1.9      scw #else
    229   1.9      scw 	ldr	r1, [r6]
    230   1.9      scw #endif
    231  1.11      scw 	cmp	r1, #0x00		/* curpcb NULL? */
    232  1.11      scw 	ldrne	r1, [r1, #PCB_FLAGS]	/* Fetch curpcb->pcb_flags */
    233  1.11      scw 	tstne	r1, #PCB_NOALIGNFLT
    234   1.9      scw 	beq	1f			/* Keep alignment faults enabled */
    235   1.9      scw 	ldr	r1, [r7, #CI_CTRL]	/* Fetch control register */
    236   1.9      scw 	ldr	r2, .Lcpufuncs
    237   1.9      scw 	mov	r0, #-1
    238   1.9      scw 	bic	r1, r1, #CPU_CONTROL_AFLT_ENABLE  /* Disable alignment faults */
    239   1.9      scw 	mov	lr, pc
    240   1.9      scw 	ldr	pc, [r2, #CF_CONTROL]	/* Set the new control register value */
    241   1.9      scw 1:
    242   1.9      scw #endif
    243   1.3  thorpej 	PULLFRAME
    244   1.3  thorpej 	movs	pc, lr			/* Exit */
    245   1.1    chris 
    246   1.6   briggs .Ldo_swi_ast:
    247   1.3  thorpej 	mov	r1, #0x00000000		/* Clear ast pending */
    248   1.3  thorpej 	str	r1, [r5]
    249   1.1    chris 
    250   1.3  thorpej 	msr     cpsr_all, r4		/* Restore interrupts */
    251   1.1    chris 
    252   1.3  thorpej 	mov	r0, sp			/* arg 0 = trap frame */
    253   1.3  thorpej 	bl	_C_LABEL(ast)		/* call the AST handler */
    254   1.6   briggs 	b	.Lswi_exit_loop		/* Try and exit again */
    255   1.1    chris 
    256   1.3  thorpej /*
    257   1.3  thorpej  * prefetch_abort_entry:
    258   1.3  thorpej  *
    259   1.3  thorpej  *	Handler for the Prefetch Abort exception.
    260   1.3  thorpej  */
    261   1.1    chris ASENTRY_NP(prefetch_abort_entry)
    262   1.1    chris         sub     lr, lr, #0x00000004     /* Adjust the lr */
    263   1.1    chris 
    264   1.1    chris 	PUSHFRAMEINSVC
    265   1.1    chris 
    266   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
    267   1.9      scw 	ENABLE_ALIGNMENT_FAULTS
    268   1.9      scw #endif
    269   1.9      scw 
    270   1.1    chris  	mov	r0, sp			/* pass the stack pointer as r0 */
    271   1.1    chris 
    272   1.7    bjh21 	adr	lr, exception_exit
    273   1.1    chris 	ldr	r1, Lprefetch_abort_handler_address
    274   1.1    chris 	ldr	pc, [r1]
    275   1.1    chris 
    276   1.1    chris Lprefetch_abort_handler_address:
    277   1.1    chris 	.word	_C_LABEL(prefetch_abort_handler_address)
    278   1.1    chris 
    279   1.1    chris 	.data
    280   1.1    chris 	.global	_C_LABEL(prefetch_abort_handler_address)
    281   1.1    chris 
    282   1.1    chris _C_LABEL(prefetch_abort_handler_address):
    283   1.1    chris 	.word	abortprefetch
    284   1.1    chris 
    285   1.1    chris 	.text
    286   1.1    chris abortprefetch:
    287   1.7    bjh21         adr     r0, abortprefetchmsg
    288   1.1    chris 	b	_C_LABEL(panic)
    289   1.1    chris 
    290   1.1    chris abortprefetchmsg:
    291   1.1    chris         .asciz  "abortprefetch"
    292   1.1    chris         .align  0
    293   1.1    chris 
    294   1.1    chris /*
    295   1.3  thorpej  * data_abort_entry:
    296   1.1    chris  *
    297   1.3  thorpej  *	Handler for the Data Abort exception.
    298   1.1    chris  */
    299   1.3  thorpej ASENTRY_NP(data_abort_entry)
    300   1.3  thorpej         sub     lr, lr, #0x00000008     /* Adjust the lr */
    301   1.1    chris 
    302   1.3  thorpej 	PUSHFRAMEINSVC			/* Push trap frame and switch */
    303   1.3  thorpej 					/* to SVC32 mode */
    304   1.1    chris 
    305   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
    306  1.10      scw 	and	r0, r0, #(PSR_MODE)	/* Test for USR32 mode (r0 = spsr_all)*/
    307  1.10      scw 	teq	r0, #(PSR_USR32_MODE)
    308  1.10      scw 	bne	99f			/* Not USR mode so skip AFLT check */
    309   1.9      scw 	ENABLE_ALIGNMENT_FAULTS
    310  1.10      scw 99:
    311   1.9      scw #endif
    312   1.9      scw 
    313   1.3  thorpej 	mov	r0, sp			/* pass the stack pointer as r0 */
    314   1.1    chris 
    315   1.7    bjh21 	adr	lr, exception_exit
    316   1.3  thorpej 	ldr	r1, Ldata_abort_handler_address
    317   1.3  thorpej 	ldr	pc, [r1]
    318   1.1    chris 
    319   1.3  thorpej Ldata_abort_handler_address:
    320   1.3  thorpej 	.word	_C_LABEL(data_abort_handler_address)
    321   1.1    chris 
    322   1.3  thorpej 	.data
    323   1.3  thorpej 	.global	_C_LABEL(data_abort_handler_address)
    324   1.3  thorpej _C_LABEL(data_abort_handler_address):
    325   1.3  thorpej 	.word	abortdata
    326   1.1    chris 
    327   1.3  thorpej 	.text
    328   1.3  thorpej abortdata:
    329   1.7    bjh21         adr     r0, abortdatamsg
    330   1.3  thorpej 	b	_C_LABEL(panic)
    331   1.1    chris 
    332   1.3  thorpej abortdatamsg:
    333   1.3  thorpej         .asciz  "abortdata"
    334   1.3  thorpej         .align  0
    335   1.1    chris 
    336   1.3  thorpej /*
    337   1.3  thorpej  * address_exception_entry:
    338   1.3  thorpej  *
    339   1.3  thorpej  *	Handler for the Address Exception exception.
    340   1.3  thorpej  *
    341   1.3  thorpej  *	NOTE: This exception isn't really used on arm32.  We
    342   1.3  thorpej  *	print a warning message to the console and then treat
    343   1.3  thorpej  *	it like a Data Abort.
    344   1.3  thorpej  */
    345   1.3  thorpej ASENTRY_NP(address_exception_entry)
    346   1.3  thorpej 	mrs	r1, cpsr_all
    347   1.3  thorpej 	mrs	r2, spsr_all
    348   1.3  thorpej 	mov	r3, lr
    349   1.3  thorpej 	adr	r0, Laddress_exception_msg
    350   1.3  thorpej 	bl	_C_LABEL(printf)	/* XXX CLOBBERS LR!! */
    351   1.3  thorpej 	b	data_abort_entry
    352   1.3  thorpej Laddress_exception_msg:
    353   1.3  thorpej 	.asciz	"Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n"
    354   1.3  thorpej 	.balign	4
    355   1.1    chris 
    356   1.1    chris /*
    357   1.3  thorpej  * undefined_entry:
    358   1.3  thorpej  *
    359   1.3  thorpej  *	Handler for the Undefined Instruction exception.
    360   1.3  thorpej  *
    361   1.3  thorpej  *	We indirect the undefined vector via the handler address
    362   1.3  thorpej  *	in the data area.  Entry to the undefined handler must
    363   1.3  thorpej  *	look like direct entry from the vector.
    364   1.1    chris  */
    365   1.1    chris ASENTRY_NP(undefined_entry)
    366   1.1    chris #ifdef IPKDB
    367   1.1    chris /*
    368   1.1    chris  * IPKDB must be hooked in at the earliest possible entry point.
    369   1.1    chris  *
    370   1.1    chris  */
    371   1.1    chris /*
    372   1.1    chris  * Make room for all registers saving real r0-r7 and r15.
    373   1.1    chris  * The remaining registers are updated later.
    374   1.1    chris  */
    375   1.1    chris 	stmfd	sp!, {r0,r1}		/* psr & spsr */
    376   1.1    chris 	stmfd	sp!, {lr}		/* pc */
    377   1.1    chris 	stmfd	sp!, {r0-r14}		/* r0-r7, r8-r14 */
    378   1.1    chris /*
    379   1.1    chris  * Get previous psr.
    380   1.1    chris  */
    381   1.1    chris 	mrs	r7, cpsr_all
    382   1.1    chris 	mrs	r0, spsr_all
    383   1.1    chris 	str	r0, [sp, #(16*4)]
    384   1.1    chris /*
    385   1.1    chris  * Test for user mode.
    386   1.1    chris  */
    387   1.1    chris 	tst	r0, #0xf
    388   1.6   briggs 	bne	.Lprenotuser_push
    389   1.1    chris 	add	r1, sp, #(8*4)
    390   1.1    chris 	stmia	r1,{r8-r14}^		/* store user mode r8-r14*/
    391   1.6   briggs 	b	.Lgoipkdb
    392   1.1    chris /*
    393   1.1    chris  * Switch to previous mode to get r8-r13.
    394   1.1    chris  */
    395   1.6   briggs .Lprenotuser_push:
    396   1.1    chris 	orr	r0, r0, #(I32_bit) /* disable interrupts */
    397   1.1    chris 	msr	cpsr_all, r0
    398   1.1    chris 	mov	r1, r8
    399   1.1    chris 	mov	r2, r9
    400   1.1    chris 	mov	r3, r10
    401   1.1    chris 	mov	r4, r11
    402   1.1    chris 	mov	r5, r12
    403   1.1    chris 	mov	r6, r13
    404   1.1    chris 	msr	cpsr_all, r7		/* back to undefined mode */
    405   1.1    chris 	add	r8, sp, #(8*4)
    406   1.1    chris 	stmia	r8, {r1-r6}		/* r8-r13 */
    407   1.1    chris /*
    408   1.1    chris  * Now back to previous mode to get r14 and spsr.
    409   1.1    chris  */
    410   1.1    chris 	msr	cpsr_all, r0
    411   1.1    chris 	mov	r1, r14
    412   1.1    chris 	mrs	r2, spsr
    413   1.1    chris 	msr	cpsr_all, r7		/* back to undefined mode */
    414   1.1    chris 	str	r1, [sp, #(14*4)]	/* r14 */
    415   1.1    chris 	str	r2, [sp, #(17*4)]	/* spsr */
    416   1.1    chris /*
    417   1.1    chris  * Now to IPKDB.
    418   1.1    chris  */
    419   1.6   briggs .Lgoipkdb:
    420   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
    421   1.9      scw 	ENABLE_ALIGNMENT_FAULTS
    422   1.9      scw #endif
    423   1.1    chris 	mov	r0, sp
    424   1.1    chris 	bl	_C_LABEL(ipkdb_trap_glue)
    425   1.6   briggs 	ldr	r1, .Lipkdb_trap_return
    426   1.1    chris 	str	r0,[r1]
    427   1.9      scw 
    428   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
    429   1.9      scw #ifdef MULTIPROCESSOR
    430   1.9      scw 	ldr	r7, .Lcpu_info
    431   1.9      scw 	bl	_C_LABEL(cpu_number)
    432   1.9      scw 	ldr	r7, [r7, r0, lsl #2]
    433   1.9      scw 	ldr	r1, [r7, #CI_CURPCB]
    434   1.9      scw #else
    435   1.9      scw 	ldr	r6, .Lcurpcb
    436   1.9      scw 	ldr	r7, .Lcpu_info_store
    437   1.9      scw 	ldr	r1, [r6]
    438   1.9      scw #endif
    439  1.11      scw 	cmp	r1, #0x00		/* curpcb NULL? */
    440  1.11      scw 	ldrne	r1, [r1, #PCB_FLAGS]	/* Fetch curpcb->pcb_flags */
    441  1.11      scw 	tstne	r1, #PCB_NOALIGNFLT
    442   1.9      scw 	beq	1f			/* Keep alignment faults enabled */
    443   1.9      scw 	ldr	r1, [r7, #CI_CTRL]	/* Fetch control register */
    444   1.9      scw 	ldr	r2, .Lcpufuncs
    445   1.9      scw 	mov	r0, #-1
    446   1.9      scw 	bic	r1, r1, #CPU_CONTROL_AFLT_ENABLE  /* Disable alignment faults */
    447   1.9      scw 	mov	lr, pc
    448   1.9      scw 	ldr	pc, [r2, #CF_CONTROL]	/* Set the new control register value */
    449   1.9      scw 1:
    450   1.9      scw #endif
    451   1.9      scw 
    452   1.1    chris /*
    453   1.1    chris  * Have to load all registers from the stack.
    454   1.1    chris  *
    455   1.1    chris  * Start with spsr and pc.
    456   1.1    chris  */
    457   1.1    chris 	ldr	r0, [sp, #(16*4)]	/* spsr */
    458   1.1    chris 	ldr	r1, [sp, #(15*4)]	/* r15 */
    459   1.1    chris 	msr	spsr_all, r0
    460   1.1    chris 	mov	r14, r1
    461   1.1    chris /*
    462   1.1    chris  * Test for user mode.
    463   1.1    chris  */
    464   1.1    chris 	tst	r0, #0xf
    465   1.6   briggs 	bne	.Lprenotuser_pull
    466   1.1    chris 	add	r1, sp, #(8*4)
    467   1.1    chris 	ldmia	r1, {r8-r14}^		/* load user mode r8-r14 */
    468   1.6   briggs 	b	.Lpull_r0r7
    469   1.6   briggs .Lprenotuser_pull:
    470   1.1    chris /*
    471   1.1    chris  * Now previous mode spsr and r14.
    472   1.1    chris  */
    473   1.1    chris 	ldr	r1, [sp, #(17*4)]		/* spsr */
    474   1.1    chris 	ldr	r2, [sp, #(14*4)]		/* r14 */
    475   1.1    chris 	orr	r0, r0, #(I32_bit)
    476   1.1    chris 	msr	cpsr_all, r0			/* switch to previous mode */
    477   1.1    chris 	msr	spsr_all, r1
    478   1.1    chris 	mov	r14, r2
    479   1.1    chris 	msr	cpsr_all, r7			/* back to undefined mode */
    480   1.1    chris /*
    481   1.1    chris  * Now r8-r13.
    482   1.1    chris  */
    483   1.1    chris 	add	r8, sp, #(8*4)
    484   1.1    chris 	ldmia	r8, {r1-r6}		/* r8-r13 */
    485   1.1    chris 	msr	cpsr_all, r0
    486   1.1    chris 	mov	r8, r1
    487   1.1    chris 	mov	r9, r2
    488   1.1    chris 	mov	r10, r3
    489   1.1    chris 	mov	r11, r4
    490   1.1    chris 	mov	r12, r5
    491   1.1    chris 	mov	r13, r6
    492   1.1    chris 	msr	cpsr_all, r7
    493   1.6   briggs .Lpull_r0r7:
    494   1.1    chris /*
    495   1.1    chris  * Now the rest of the registers.
    496   1.1    chris  */
    497   1.1    chris 	ldr	r1,Lipkdb_trap_return
    498   1.1    chris 	ldr	r0,[r1]
    499   1.1    chris 	tst	r0,r0
    500   1.1    chris 	ldmfd	sp!, {r0-r7}		/* r0-r7 */
    501   1.1    chris 	add	sp, sp, #(10*4)		/* adjust sp */
    502   1.1    chris 
    503   1.1    chris /*
    504   1.1    chris  * Did IPKDB handle it?
    505   1.1    chris  */
    506   1.1    chris 	movnes	pc, lr			/* return */
    507   1.1    chris 
    508   1.1    chris #endif
    509   1.1    chris 	stmfd	sp!, {r0, r1}
    510   1.1    chris 	ldr	r0, Lundefined_handler_indirection
    511   1.1    chris 	ldr	r1, [sp], #0x0004
    512   1.1    chris 	str	r1, [r0, #0x0000]
    513   1.1    chris 	ldr	r1, [sp], #0x0004
    514   1.1    chris 	str	r1, [r0, #0x0004]
    515   1.1    chris 	ldmia	r0, {r0, r1, pc}
    516   1.1    chris 
    517   1.1    chris #ifdef IPKDB
    518   1.1    chris Lipkdb_trap_return:
    519   1.1    chris 	.word	Lipkdb_trap_return_data
    520   1.1    chris #endif
    521   1.1    chris 
    522   1.1    chris Lundefined_handler_indirection:
    523   1.1    chris 	.word	Lundefined_handler_indirection_data
    524   1.1    chris 
    525   1.1    chris /*
    526   1.1    chris  * assembly bounce code for calling the kernel
    527   1.1    chris  * undefined instruction handler. This uses
    528   1.1    chris  * a standard trap frame and is called in SVC mode.
    529   1.1    chris  */
    530   1.1    chris 
    531   1.1    chris ENTRY_NP(undefinedinstruction_bounce)
    532   1.1    chris 	PUSHFRAMEINSVC
    533   1.9      scw #if defined(COMPAT_15) && defined(EXEC_AOUT)
    534  1.10      scw 	and	r0, r0, #(PSR_MODE)	/* Test for USR32 mode (r0 = spsr_all)*/
    535  1.10      scw 	teq	r0, #(PSR_USR32_MODE)
    536  1.10      scw 	bne	99f			/* Not USR mode so skip AFLT check */
    537   1.9      scw 	ENABLE_ALIGNMENT_FAULTS
    538  1.10      scw 99:
    539   1.9      scw #endif
    540   1.1    chris 	mov	r0, sp
    541   1.1    chris 	bl	_C_LABEL(undefinedinstruction)
    542   1.1    chris 
    543   1.1    chris 	b	exception_exit
    544   1.1    chris 
    545   1.1    chris 	.data
    546   1.1    chris 	.align	0
    547   1.1    chris 
    548   1.1    chris #ifdef IPKDB
    549   1.1    chris Lipkdb_trap_return_data:
    550   1.1    chris 	.word	0
    551   1.1    chris #endif
    552   1.1    chris 
    553   1.1    chris /*
    554   1.1    chris  * Indirection data
    555   1.1    chris  * 2 words use for preserving r0 and r1
    556   1.1    chris  * 3rd word contains the undefined handler address.
    557   1.1    chris  */
    558   1.1    chris 
    559   1.1    chris Lundefined_handler_indirection_data:
    560   1.1    chris 	.word	0
    561   1.1    chris 	.word	0
    562   1.1    chris 
    563   1.1    chris 	.global	_C_LABEL(undefined_handler_address)
    564   1.1    chris _C_LABEL(undefined_handler_address):
    565   1.1    chris 	.word	_C_LABEL(undefinedinstruction_bounce)
    566