xref: /openbmc/linux/arch/sh/kernel/cpu/sh2a/entry.S (revision 597473720f4dc69749542bfcfed4a927a43d935e)
1*234a0538SKuninori Morimoto/* SPDX-License-Identifier: GPL-2.0
2*234a0538SKuninori Morimoto *
36e80f5e8SYoshinori Sato * arch/sh/kernel/cpu/sh2a/entry.S
46e80f5e8SYoshinori Sato *
56e80f5e8SYoshinori Sato * The SH-2A exception entry
66e80f5e8SYoshinori Sato *
76e80f5e8SYoshinori Sato * Copyright (C) 2008 Yoshinori Sato
86e80f5e8SYoshinori Sato * Based on arch/sh/kernel/cpu/sh2/entry.S
96e80f5e8SYoshinori Sato */
106e80f5e8SYoshinori Sato
116e80f5e8SYoshinori Sato#include <linux/linkage.h>
126e80f5e8SYoshinori Sato#include <asm/asm-offsets.h>
136e80f5e8SYoshinori Sato#include <asm/thread_info.h>
14f15cbe6fSPaul Mundt#include <cpu/mmu_context.h>
156e80f5e8SYoshinori Sato#include <asm/unistd.h>
166e80f5e8SYoshinori Sato#include <asm/errno.h>
176e80f5e8SYoshinori Sato#include <asm/page.h>
186e80f5e8SYoshinori Sato
196e80f5e8SYoshinori Sato/* Offsets to the stack */
206e80f5e8SYoshinori SatoOFF_R0  =  0		/* Return value. New ABI also arg4 */
216e80f5e8SYoshinori SatoOFF_R1  =  4     	/* New ABI: arg5 */
226e80f5e8SYoshinori SatoOFF_R2  =  8     	/* New ABI: arg6 */
236e80f5e8SYoshinori SatoOFF_R3  =  12     	/* New ABI: syscall_nr */
246e80f5e8SYoshinori SatoOFF_R4  =  16     	/* New ABI: arg0 */
256e80f5e8SYoshinori SatoOFF_R5  =  20     	/* New ABI: arg1 */
266e80f5e8SYoshinori SatoOFF_R6  =  24     	/* New ABI: arg2 */
276e80f5e8SYoshinori SatoOFF_R7  =  28     	/* New ABI: arg3 */
286e80f5e8SYoshinori SatoOFF_SP	=  (15*4)
296e80f5e8SYoshinori SatoOFF_PC  =  (16*4)
306e80f5e8SYoshinori SatoOFF_SR	=  (16*4+2*4)
316e80f5e8SYoshinori SatoOFF_TRA	=  (16*4+6*4)
326e80f5e8SYoshinori Sato
336e80f5e8SYoshinori Sato#include <asm/entry-macros.S>
346e80f5e8SYoshinori Sato
356e80f5e8SYoshinori SatoENTRY(exception_handler)
366e80f5e8SYoshinori Sato	! stack
376e80f5e8SYoshinori Sato	! r0 <- point sp
386e80f5e8SYoshinori Sato	! r1
396e80f5e8SYoshinori Sato	! pc
406e80f5e8SYoshinori Sato	! sr
416e80f5e8SYoshinori Sato	! r0 = temporary
426e80f5e8SYoshinori Sato	! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
436e80f5e8SYoshinori Sato	mov.l	r2,@-sp
446e80f5e8SYoshinori Sato	cli
456e80f5e8SYoshinori Sato	mov.l	$cpu_mode,r2
466e80f5e8SYoshinori Sato	bld.b	#6,@(0,r2)	!previus SR.MD
476e80f5e8SYoshinori Sato	bst.b	#6,@(4*4,r15)	!set cpu mode to SR.MD
486e80f5e8SYoshinori Sato	bt	1f
496e80f5e8SYoshinori Sato	! switch to kernel mode
506e80f5e8SYoshinori Sato	bset.b	#6,@(0,r2)	!set SR.MD
516e80f5e8SYoshinori Sato	mov.l	$current_thread_info,r2
526e80f5e8SYoshinori Sato	mov.l	@r2,r2
536e80f5e8SYoshinori Sato	mov	#(THREAD_SIZE >> 8),r0
546e80f5e8SYoshinori Sato	shll8	r0
556e80f5e8SYoshinori Sato	add	r2,r0		! r0 = kernel stack tail
566e80f5e8SYoshinori Sato	mov	r15,r2		! r2 = user stack top
576e80f5e8SYoshinori Sato	mov	r0,r15		! switch kernel stack
586e80f5e8SYoshinori Sato	mov.l	r1,@-r15	! TRA
596e80f5e8SYoshinori Sato	sts.l	macl, @-r15
606e80f5e8SYoshinori Sato	sts.l	mach, @-r15
616e80f5e8SYoshinori Sato	stc.l	gbr, @-r15
626e80f5e8SYoshinori Sato	mov.l	@(4*4,r2),r0
636e80f5e8SYoshinori Sato	mov.l	r0,@-r15	! original SR
646e80f5e8SYoshinori Sato	sts.l	pr,@-r15
656e80f5e8SYoshinori Sato	mov.l	@(3*4,r2),r0
666e80f5e8SYoshinori Sato	mov.l	r0,@-r15	! original PC
676e80f5e8SYoshinori Sato	mov	r2,r0
686e80f5e8SYoshinori Sato	add	#(3+2)*4,r0	! rewind r0 - r3 + exception frame
696e80f5e8SYoshinori Sato	lds	r0,pr		! pr = original SP
706e80f5e8SYoshinori Sato	movmu.l	r3,@-r15	! save regs
716e80f5e8SYoshinori Sato	mov	r2,r8		! r8 =  previus stack top
726e80f5e8SYoshinori Sato	mov	r1,r9		! r9 = interrupt vector
736e80f5e8SYoshinori Sato	! restore previous stack
746e80f5e8SYoshinori Sato	mov.l	@r8+,r2
756e80f5e8SYoshinori Sato	mov.l	@r8+,r0
766e80f5e8SYoshinori Sato	mov.l	@r8+,r1
776e80f5e8SYoshinori Sato	bra	2f
786e80f5e8SYoshinori Sato	 movml.l r2,@-r15
796e80f5e8SYoshinori Sato1:
806e80f5e8SYoshinori Sato	! in kernel exception
816e80f5e8SYoshinori Sato	mov	r15,r2
826e80f5e8SYoshinori Sato	add	#-((OFF_TRA + 4) - OFF_PC) + 5*4,r15
836e80f5e8SYoshinori Sato	movmu.l	r3,@-r15
846e80f5e8SYoshinori Sato	mov	r2,r8		! r8 = previous stack top
856e80f5e8SYoshinori Sato	mov	r1,r9		! r9 = interrupt vector
866e80f5e8SYoshinori Sato	! restore exception frame & regs
876e80f5e8SYoshinori Sato	mov.l	@r8+,r2		! old R2
886e80f5e8SYoshinori Sato	mov.l	@r8+,r0		! old R0
896e80f5e8SYoshinori Sato	mov.l	@r8+,r1		! old R1
906e80f5e8SYoshinori Sato	mov.l	@r8+,r10	! old PC
916e80f5e8SYoshinori Sato	mov.l	@r8+,r11	! old SR
926e80f5e8SYoshinori Sato	movml.l	r2,@-r15
936e80f5e8SYoshinori Sato	mov.l	r10,@(OFF_PC,r15)
946e80f5e8SYoshinori Sato	mov.l	r11,@(OFF_SR,r15)
956e80f5e8SYoshinori Sato	mov.l	r8,@(OFF_SP,r15)	! save old sp
966e80f5e8SYoshinori Sato	mov	r15,r8
976e80f5e8SYoshinori Sato	add	#OFF_TRA + 4,r8
986e80f5e8SYoshinori Sato	mov.l	r9,@-r8
996e80f5e8SYoshinori Sato	sts.l	macl,@-r8
1006e80f5e8SYoshinori Sato	sts.l	mach,@-r8
1016e80f5e8SYoshinori Sato	stc.l	gbr,@-r8
1026e80f5e8SYoshinori Sato	add	#-4,r8
1036e80f5e8SYoshinori Sato	sts.l	pr,@-r8
1046e80f5e8SYoshinori Sato2:
1056e80f5e8SYoshinori Sato	! dispatch exception / interrupt
1066e80f5e8SYoshinori Sato	mov	#64,r8
1076e80f5e8SYoshinori Sato	cmp/hs	r8,r9
1086e80f5e8SYoshinori Sato	bt	interrupt_entry	! vec >= 64 is interrupt
1093623d138SRich Felker	mov	#31,r8
1106e80f5e8SYoshinori Sato	cmp/hs	r8,r9
1113623d138SRich Felker	bt	trap_entry	! 64 > vec >= 31  is trap
1126e80f5e8SYoshinori Sato
1136e80f5e8SYoshinori Sato	mov.l	4f,r8
1146e80f5e8SYoshinori Sato	mov	r9,r4
1156e80f5e8SYoshinori Sato	shll2	r9
1166e80f5e8SYoshinori Sato	add	r9,r8
1176e80f5e8SYoshinori Sato	mov.l	@r8,r8		! exception handler address
1186e80f5e8SYoshinori Sato	tst	r8,r8
1196e80f5e8SYoshinori Sato	bf	3f
1206e80f5e8SYoshinori Sato	mov.l	8f,r8		! unhandled exception
1216e80f5e8SYoshinori Sato3:
1226e80f5e8SYoshinori Sato	mov.l	5f,r10
1236e80f5e8SYoshinori Sato	jmp	@r8
1246e80f5e8SYoshinori Sato	 lds	r10,pr
1256e80f5e8SYoshinori Sato
1266e80f5e8SYoshinori Satointerrupt_entry:
1276e80f5e8SYoshinori Sato	mov	r9,r4
1286e80f5e8SYoshinori Sato	mov	r15,r5
1296e80f5e8SYoshinori Sato	mov.l	7f,r8
1306e80f5e8SYoshinori Sato	mov.l	6f,r9
1316e80f5e8SYoshinori Sato	jmp	@r8
1326e80f5e8SYoshinori Sato	 lds	r9,pr
1336e80f5e8SYoshinori Sato
1346e80f5e8SYoshinori Sato	.align	2
1356e80f5e8SYoshinori Sato4:	.long	exception_handling_table
1366e80f5e8SYoshinori Sato5:	.long	ret_from_exception
1376e80f5e8SYoshinori Sato6:	.long	ret_from_irq
1386e80f5e8SYoshinori Sato7:	.long	do_IRQ
1396e80f5e8SYoshinori Sato8:	.long	exception_error
1406e80f5e8SYoshinori Sato
1416e80f5e8SYoshinori Satotrap_entry:
1426e80f5e8SYoshinori Sato	mov	#0x30,r8
1433623d138SRich Felker	cmp/ge	r8,r9		! vector 0x1f-0x2f is systemcall
1446e80f5e8SYoshinori Sato	bt	1f
1453623d138SRich Felker	mov     #0x1f,r9	! convert to unified SH2/3/4 trap number
1466e80f5e8SYoshinori Sato1:
1476e80f5e8SYoshinori Sato	shll2	r9			! TRA
1486e80f5e8SYoshinori Sato	bra	system_call	! jump common systemcall entry
1496e80f5e8SYoshinori Sato	 mov	r9,r8
1506e80f5e8SYoshinori Sato
1516e80f5e8SYoshinori Sato#if defined(CONFIG_SH_STANDARD_BIOS)
1526e80f5e8SYoshinori Sato	/* Unwind the stack and jmp to the debug entry */
1536e80f5e8SYoshinori SatoENTRY(sh_bios_handler)
1546e80f5e8SYoshinori Sato	mov	r15,r0
1556e80f5e8SYoshinori Sato	add	#(22-4)*4-4,r0
1566e80f5e8SYoshinori Sato	ldc.l	@r0+,gbr
1576e80f5e8SYoshinori Sato	lds.l	@r0+,mach
1586e80f5e8SYoshinori Sato	lds.l	@r0+,macl
1596e80f5e8SYoshinori Sato	mov	r15,r0
1606e80f5e8SYoshinori Sato	mov.l	@(OFF_SP,r0),r1
1616e80f5e8SYoshinori Sato	mov.l	@(OFF_SR,r2),r3
1626e80f5e8SYoshinori Sato	mov.l	r3,@-r1
1636e80f5e8SYoshinori Sato	mov.l	@(OFF_SP,r2),r3
1646e80f5e8SYoshinori Sato	mov.l	r3,@-r1
1656e80f5e8SYoshinori Sato	mov	r15,r0
1666e80f5e8SYoshinori Sato	add	#(22-4)*4-8,r0
1676e80f5e8SYoshinori Sato	mov.l	1f,r2
1686e80f5e8SYoshinori Sato	mov.l	@r2,r2
1696e80f5e8SYoshinori Sato	stc	sr,r3
1706e80f5e8SYoshinori Sato	mov.l	r2,@r0
1716e80f5e8SYoshinori Sato	mov.l	r3,@(4,r0)
1726e80f5e8SYoshinori Sato	mov.l	r1,@(8,r0)
1736e80f5e8SYoshinori Sato	movml.l	@r15+,r14
1746e80f5e8SYoshinori Sato	add	#8,r15
1756e80f5e8SYoshinori Sato	lds.l	@r15+, pr
1766e80f5e8SYoshinori Sato	mov.l	@r15+,r15
1777a90e00dSPaul Mundt	rte
1787a90e00dSPaul Mundt	 nop
1796e80f5e8SYoshinori Sato	.align	2
1806e80f5e8SYoshinori Sato1:	.long	gdb_vbr_vector
1816e80f5e8SYoshinori Sato#endif /* CONFIG_SH_STANDARD_BIOS */
1826e80f5e8SYoshinori Sato
1836e80f5e8SYoshinori SatoENTRY(address_error_trap_handler)
1846e80f5e8SYoshinori Sato	mov	r15,r4				! regs
1856e80f5e8SYoshinori Sato	mov.l	@(OFF_PC,r15),r6		! pc
1866e80f5e8SYoshinori Sato	mov.l	1f,r0
1876e80f5e8SYoshinori Sato	jmp	@r0
1886e80f5e8SYoshinori Sato	 mov	#0,r5				! writeaccess is unknown
1896e80f5e8SYoshinori Sato
1906e80f5e8SYoshinori Sato	.align	2
1916e80f5e8SYoshinori Sato1:	.long	do_address_error
1926e80f5e8SYoshinori Sato
1936e80f5e8SYoshinori Satorestore_all:
1946e80f5e8SYoshinori Sato	stc	sr,r0
1956e80f5e8SYoshinori Sato	or	#0xf0,r0
1966e80f5e8SYoshinori Sato	ldc	r0,sr				! all interrupt block (same BL = 1)
1976e80f5e8SYoshinori Sato	! restore special register
1986e80f5e8SYoshinori Sato	! overlap exception frame
1996e80f5e8SYoshinori Sato	mov	r15,r0
2006e80f5e8SYoshinori Sato	add	#17*4,r0
2016e80f5e8SYoshinori Sato	lds.l	@r0+,pr
2026e80f5e8SYoshinori Sato	add	#4,r0
2036e80f5e8SYoshinori Sato	ldc.l	@r0+,gbr
2046e80f5e8SYoshinori Sato	lds.l	@r0+,mach
2056e80f5e8SYoshinori Sato	lds.l	@r0+,macl
2066e80f5e8SYoshinori Sato	mov	r15,r0
2076e80f5e8SYoshinori Sato	mov.l	$cpu_mode,r2
2086e80f5e8SYoshinori Sato	bld.b	#6,@(OFF_SR,r15)
2096e80f5e8SYoshinori Sato	bst.b	#6,@(0,r2)			! save CPU mode
2106e80f5e8SYoshinori Sato	mov.l	@(OFF_SR,r0),r1
2116e80f5e8SYoshinori Sato	shll2	r1
2126e80f5e8SYoshinori Sato	shlr2	r1				! clear MD bit
2136e80f5e8SYoshinori Sato	mov.l	@(OFF_SP,r0),r2
2146e80f5e8SYoshinori Sato	add	#-8,r2
2156e80f5e8SYoshinori Sato	mov.l	r2,@(OFF_SP,r0)			! point exception frame top
2166e80f5e8SYoshinori Sato	mov.l	r1,@(4,r2)			! set sr
2176e80f5e8SYoshinori Sato	mov.l	@(OFF_PC,r0),r1
2186e80f5e8SYoshinori Sato	mov.l	r1,@r2				! set pc
2196e80f5e8SYoshinori Sato	get_current_thread_info r0, r1
2206e80f5e8SYoshinori Sato	mov.l	$current_thread_info,r1
2216e80f5e8SYoshinori Sato	mov.l	r0,@r1
2226e80f5e8SYoshinori Sato	movml.l	@r15+,r14
2236e80f5e8SYoshinori Sato	mov.l	@r15,r15
2246e80f5e8SYoshinori Sato	rte
2256e80f5e8SYoshinori Sato	 nop
2266e80f5e8SYoshinori Sato
2276e80f5e8SYoshinori Sato	.align 2
2286e80f5e8SYoshinori Sato$current_thread_info:
2296e80f5e8SYoshinori Sato	.long	__current_thread_info
2306e80f5e8SYoshinori Sato$cpu_mode:
2316e80f5e8SYoshinori Sato	.long	__cpu_mode
2326e80f5e8SYoshinori Sato
2336e80f5e8SYoshinori Sato! common exception handler
2346e80f5e8SYoshinori Sato#include "../../entry-common.S"
2356e80f5e8SYoshinori Sato
2366e80f5e8SYoshinori Sato	.data
2376e80f5e8SYoshinori Sato! cpu operation mode
2386e80f5e8SYoshinori Sato! bit30 = MD (compatible SH3/4)
2396e80f5e8SYoshinori Sato__cpu_mode:
2406e80f5e8SYoshinori Sato	.long	0x40000000
2416e80f5e8SYoshinori Sato
2426e80f5e8SYoshinori Sato	.section	.bss
2436e80f5e8SYoshinori Sato__current_thread_info:
2446e80f5e8SYoshinori Sato	.long	0
2456e80f5e8SYoshinori Sato
2466e80f5e8SYoshinori SatoENTRY(exception_handling_table)
2476e80f5e8SYoshinori Sato	.space	4*32
248