xref: /kernel/linux/linux-6.6/arch/sh/lib/copy_page.S (revision 62306a36)
162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * copy_page, __copy_user_page, __copy_user implementation of SuperH
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2001  Niibe Yutaka & Kaz Kojima
662306a36Sopenharmony_ci * Copyright (C) 2002  Toshinobu Sugioka
762306a36Sopenharmony_ci * Copyright (C) 2006  Paul Mundt
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci#include <linux/linkage.h>
1062306a36Sopenharmony_ci#include <asm/page.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * copy_page
1462306a36Sopenharmony_ci * @to: P1 address
1562306a36Sopenharmony_ci * @from: P1 address
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci * void copy_page(void *to, void *from)
1862306a36Sopenharmony_ci */
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
2262306a36Sopenharmony_ci * r8 --- from + PAGE_SIZE
2362306a36Sopenharmony_ci * r9 --- not used
2462306a36Sopenharmony_ci * r10 --- to
2562306a36Sopenharmony_ci * r11 --- from
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_ciENTRY(copy_page)
2862306a36Sopenharmony_ci	mov.l	r8,@-r15
2962306a36Sopenharmony_ci	mov.l	r10,@-r15
3062306a36Sopenharmony_ci	mov.l	r11,@-r15
3162306a36Sopenharmony_ci	mov	r4,r10
3262306a36Sopenharmony_ci	mov	r5,r11
3362306a36Sopenharmony_ci	mov	r5,r8
3462306a36Sopenharmony_ci	mov	#(PAGE_SIZE >> 10), r0
3562306a36Sopenharmony_ci	shll8	r0
3662306a36Sopenharmony_ci	shll2	r0
3762306a36Sopenharmony_ci	add	r0,r8
3862306a36Sopenharmony_ci	!
3962306a36Sopenharmony_ci1:	mov.l	@r11+,r0
4062306a36Sopenharmony_ci	mov.l	@r11+,r1
4162306a36Sopenharmony_ci	mov.l	@r11+,r2
4262306a36Sopenharmony_ci	mov.l	@r11+,r3
4362306a36Sopenharmony_ci	mov.l	@r11+,r4
4462306a36Sopenharmony_ci	mov.l	@r11+,r5
4562306a36Sopenharmony_ci	mov.l	@r11+,r6
4662306a36Sopenharmony_ci	mov.l	@r11+,r7
4762306a36Sopenharmony_ci#if defined(CONFIG_CPU_SH4)
4862306a36Sopenharmony_ci	movca.l	r0,@r10
4962306a36Sopenharmony_ci#else
5062306a36Sopenharmony_ci	mov.l	r0,@r10
5162306a36Sopenharmony_ci#endif
5262306a36Sopenharmony_ci	add	#32,r10
5362306a36Sopenharmony_ci	mov.l	r7,@-r10
5462306a36Sopenharmony_ci	mov.l	r6,@-r10
5562306a36Sopenharmony_ci	mov.l	r5,@-r10
5662306a36Sopenharmony_ci	mov.l	r4,@-r10
5762306a36Sopenharmony_ci	mov.l	r3,@-r10
5862306a36Sopenharmony_ci	mov.l	r2,@-r10
5962306a36Sopenharmony_ci	mov.l	r1,@-r10
6062306a36Sopenharmony_ci	cmp/eq	r11,r8
6162306a36Sopenharmony_ci	bf/s	1b
6262306a36Sopenharmony_ci	 add	#28,r10
6362306a36Sopenharmony_ci	!
6462306a36Sopenharmony_ci	mov.l	@r15+,r11
6562306a36Sopenharmony_ci	mov.l	@r15+,r10
6662306a36Sopenharmony_ci	mov.l	@r15+,r8
6762306a36Sopenharmony_ci	rts
6862306a36Sopenharmony_ci	 nop
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/*
7162306a36Sopenharmony_ci * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
7262306a36Sopenharmony_ci * Return the number of bytes NOT copied
7362306a36Sopenharmony_ci */
7462306a36Sopenharmony_ci#define EX(...)			\
7562306a36Sopenharmony_ci	9999: __VA_ARGS__ ;		\
7662306a36Sopenharmony_ci	.section __ex_table, "a";	\
7762306a36Sopenharmony_ci	.long 9999b, 6000f	;	\
7862306a36Sopenharmony_ci	.previous
7962306a36Sopenharmony_ci#define EX_NO_POP(...)			\
8062306a36Sopenharmony_ci	9999: __VA_ARGS__ ;		\
8162306a36Sopenharmony_ci	.section __ex_table, "a";	\
8262306a36Sopenharmony_ci	.long 9999b, 6005f	;	\
8362306a36Sopenharmony_ci	.previous
8462306a36Sopenharmony_ciENTRY(__copy_user)
8562306a36Sopenharmony_ci	! Check if small number of bytes
8662306a36Sopenharmony_ci	mov	#11,r0
8762306a36Sopenharmony_ci	mov	r4,r3
8862306a36Sopenharmony_ci	cmp/gt	r0,r6		! r6 (len) > r0 (11)
8962306a36Sopenharmony_ci	bf/s	.L_cleanup_loop_no_pop
9062306a36Sopenharmony_ci	 add	r6,r3		! last destination address
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	! Calculate bytes needed to align to src
9362306a36Sopenharmony_ci	mov.l	r11,@-r15
9462306a36Sopenharmony_ci	neg	r5,r0
9562306a36Sopenharmony_ci	mov.l	r10,@-r15
9662306a36Sopenharmony_ci	add	#4,r0
9762306a36Sopenharmony_ci	mov.l	r9,@-r15
9862306a36Sopenharmony_ci	and	#3,r0
9962306a36Sopenharmony_ci	mov.l	r8,@-r15
10062306a36Sopenharmony_ci	tst	r0,r0
10162306a36Sopenharmony_ci	bt	2f
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci1:
10462306a36Sopenharmony_ci	! Copy bytes to long word align src
10562306a36Sopenharmony_ciEX(	mov.b	@r5+,r1		)
10662306a36Sopenharmony_ci	dt	r0
10762306a36Sopenharmony_ci	add	#-1,r6
10862306a36Sopenharmony_ciEX(	mov.b	r1,@r4		)
10962306a36Sopenharmony_ci	bf/s	1b
11062306a36Sopenharmony_ci	 add	#1,r4
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	! Jump to appropriate routine depending on dest
11362306a36Sopenharmony_ci2:	mov	#3,r1
11462306a36Sopenharmony_ci	mov	r6, r2
11562306a36Sopenharmony_ci	and	r4,r1
11662306a36Sopenharmony_ci	shlr2	r2
11762306a36Sopenharmony_ci	shll2	r1
11862306a36Sopenharmony_ci	mova	.L_jump_tbl,r0
11962306a36Sopenharmony_ci	mov.l	@(r0,r1),r1
12062306a36Sopenharmony_ci	jmp	@r1
12162306a36Sopenharmony_ci	 nop
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	.align 2
12462306a36Sopenharmony_ci.L_jump_tbl:
12562306a36Sopenharmony_ci	.long	.L_dest00
12662306a36Sopenharmony_ci	.long	.L_dest01
12762306a36Sopenharmony_ci	.long	.L_dest10
12862306a36Sopenharmony_ci	.long	.L_dest11
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/*
13162306a36Sopenharmony_ci * Come here if there are less than 12 bytes to copy
13262306a36Sopenharmony_ci *
13362306a36Sopenharmony_ci * Keep the branch target close, so the bf/s callee doesn't overflow
13462306a36Sopenharmony_ci * and result in a more expensive branch being inserted. This is the
13562306a36Sopenharmony_ci * fast-path for small copies, the jump via the jump table will hit the
13662306a36Sopenharmony_ci * default slow-path cleanup. -PFM.
13762306a36Sopenharmony_ci */
13862306a36Sopenharmony_ci.L_cleanup_loop_no_pop:
13962306a36Sopenharmony_ci	tst	r6,r6		! Check explicitly for zero
14062306a36Sopenharmony_ci	bt	1f
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci2:
14362306a36Sopenharmony_ciEX_NO_POP(	mov.b	@r5+,r0		)
14462306a36Sopenharmony_ci	dt	r6
14562306a36Sopenharmony_ciEX_NO_POP(	mov.b	r0,@r4		)
14662306a36Sopenharmony_ci	bf/s	2b
14762306a36Sopenharmony_ci	 add	#1,r4
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci1:	mov	#0,r0		! normal return
15062306a36Sopenharmony_ci5000:
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci# Exception handler:
15362306a36Sopenharmony_ci.section .fixup, "ax"
15462306a36Sopenharmony_ci6005:
15562306a36Sopenharmony_ci	mov.l	8000f,r1
15662306a36Sopenharmony_ci	mov	r3,r0
15762306a36Sopenharmony_ci	jmp	@r1
15862306a36Sopenharmony_ci	 sub	r4,r0
15962306a36Sopenharmony_ci	.align	2
16062306a36Sopenharmony_ci8000:	.long	5000b
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci.previous
16362306a36Sopenharmony_ci	rts
16462306a36Sopenharmony_ci	 nop
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci! Destination = 00
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci.L_dest00:
16962306a36Sopenharmony_ci	! Skip the large copy for small transfers
17062306a36Sopenharmony_ci	mov	#(32+32-4), r0
17162306a36Sopenharmony_ci	cmp/gt	r6, r0		! r0 (60) > r6 (len)
17262306a36Sopenharmony_ci	bt	1f
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	! Align dest to a 32 byte boundary
17562306a36Sopenharmony_ci	neg	r4,r0
17662306a36Sopenharmony_ci	add	#0x20, r0
17762306a36Sopenharmony_ci	and	#0x1f, r0
17862306a36Sopenharmony_ci	tst	r0, r0
17962306a36Sopenharmony_ci	bt	2f
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	sub	r0, r6
18262306a36Sopenharmony_ci	shlr2	r0
18362306a36Sopenharmony_ci3:
18462306a36Sopenharmony_ciEX(	mov.l	@r5+,r1		)
18562306a36Sopenharmony_ci	dt	r0
18662306a36Sopenharmony_ciEX(	mov.l	r1,@r4		)
18762306a36Sopenharmony_ci	bf/s	3b
18862306a36Sopenharmony_ci	 add	#4,r4
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci2:
19162306a36Sopenharmony_ciEX(	mov.l	@r5+,r0		)
19262306a36Sopenharmony_ciEX(	mov.l	@r5+,r1		)
19362306a36Sopenharmony_ciEX(	mov.l	@r5+,r2		)
19462306a36Sopenharmony_ciEX(	mov.l	@r5+,r7		)
19562306a36Sopenharmony_ciEX(	mov.l	@r5+,r8		)
19662306a36Sopenharmony_ciEX(	mov.l	@r5+,r9		)
19762306a36Sopenharmony_ciEX(	mov.l	@r5+,r10	)
19862306a36Sopenharmony_ciEX(	mov.l	@r5+,r11	)
19962306a36Sopenharmony_ci#ifdef CONFIG_CPU_SH4
20062306a36Sopenharmony_ciEX(	movca.l	r0,@r4		)
20162306a36Sopenharmony_ci#else
20262306a36Sopenharmony_ciEX(	mov.l	r0,@r4		)
20362306a36Sopenharmony_ci#endif
20462306a36Sopenharmony_ci	add	#-32, r6
20562306a36Sopenharmony_ciEX(	mov.l	r1,@(4,r4)	)
20662306a36Sopenharmony_ci	mov	#32, r0
20762306a36Sopenharmony_ciEX(	mov.l	r2,@(8,r4)	)
20862306a36Sopenharmony_ci	cmp/gt	r6, r0		! r0 (32) > r6 (len)
20962306a36Sopenharmony_ciEX(	mov.l	r7,@(12,r4)	)
21062306a36Sopenharmony_ciEX(	mov.l	r8,@(16,r4)	)
21162306a36Sopenharmony_ciEX(	mov.l	r9,@(20,r4)	)
21262306a36Sopenharmony_ciEX(	mov.l	r10,@(24,r4)	)
21362306a36Sopenharmony_ciEX(	mov.l	r11,@(28,r4)	)
21462306a36Sopenharmony_ci	bf/s	2b
21562306a36Sopenharmony_ci	 add	#32,r4
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci1:	mov	r6, r0
21862306a36Sopenharmony_ci	shlr2	r0
21962306a36Sopenharmony_ci	tst	r0, r0
22062306a36Sopenharmony_ci	bt	.L_cleanup
22162306a36Sopenharmony_ci1:
22262306a36Sopenharmony_ciEX(	mov.l	@r5+,r1		)
22362306a36Sopenharmony_ci	dt	r0
22462306a36Sopenharmony_ciEX(	mov.l	r1,@r4		)
22562306a36Sopenharmony_ci	bf/s	1b
22662306a36Sopenharmony_ci	 add	#4,r4
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	bra	.L_cleanup
22962306a36Sopenharmony_ci	 nop
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci! Destination = 10
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci.L_dest10:
23462306a36Sopenharmony_ci	mov	r2,r7
23562306a36Sopenharmony_ci	shlr2	r7
23662306a36Sopenharmony_ci	shlr	r7
23762306a36Sopenharmony_ci	tst	r7,r7
23862306a36Sopenharmony_ci	mov	#7,r0
23962306a36Sopenharmony_ci	bt/s	1f
24062306a36Sopenharmony_ci	 and	r0,r2
24162306a36Sopenharmony_ci2:
24262306a36Sopenharmony_ci	dt	r7
24362306a36Sopenharmony_ci#ifdef CONFIG_CPU_LITTLE_ENDIAN
24462306a36Sopenharmony_ciEX(	mov.l	@r5+,r0		)
24562306a36Sopenharmony_ciEX(	mov.l	@r5+,r1		)
24662306a36Sopenharmony_ciEX(	mov.l	@r5+,r8		)
24762306a36Sopenharmony_ciEX(	mov.l	@r5+,r9		)
24862306a36Sopenharmony_ciEX(	mov.l	@r5+,r10	)
24962306a36Sopenharmony_ciEX(	mov.w	r0,@r4		)
25062306a36Sopenharmony_ci	add	#2,r4
25162306a36Sopenharmony_ci	xtrct	r1,r0
25262306a36Sopenharmony_ci	xtrct	r8,r1
25362306a36Sopenharmony_ci	xtrct	r9,r8
25462306a36Sopenharmony_ci	xtrct	r10,r9
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ciEX(	mov.l	r0,@r4		)
25762306a36Sopenharmony_ciEX(	mov.l	r1,@(4,r4)	)
25862306a36Sopenharmony_ciEX(	mov.l	r8,@(8,r4)	)
25962306a36Sopenharmony_ciEX(	mov.l	r9,@(12,r4)	)
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ciEX(	mov.l	@r5+,r1		)
26262306a36Sopenharmony_ciEX(	mov.l	@r5+,r8		)
26362306a36Sopenharmony_ciEX(	mov.l	@r5+,r0		)
26462306a36Sopenharmony_ci	xtrct	r1,r10
26562306a36Sopenharmony_ci	xtrct	r8,r1
26662306a36Sopenharmony_ci	xtrct	r0,r8
26762306a36Sopenharmony_ci	shlr16	r0
26862306a36Sopenharmony_ciEX(	mov.l	r10,@(16,r4)	)
26962306a36Sopenharmony_ciEX(	mov.l	r1,@(20,r4)	)
27062306a36Sopenharmony_ciEX(	mov.l	r8,@(24,r4)	)
27162306a36Sopenharmony_ciEX(	mov.w	r0,@(28,r4)	)
27262306a36Sopenharmony_ci	bf/s	2b
27362306a36Sopenharmony_ci	 add	#30,r4
27462306a36Sopenharmony_ci#else
27562306a36Sopenharmony_ciEX(	mov.l	@(28,r5),r0	)
27662306a36Sopenharmony_ciEX(	mov.l	@(24,r5),r8	)
27762306a36Sopenharmony_ciEX(	mov.l	@(20,r5),r9	)
27862306a36Sopenharmony_ciEX(	mov.l	@(16,r5),r10	)
27962306a36Sopenharmony_ciEX(	mov.w	r0,@(30,r4)	)
28062306a36Sopenharmony_ci	add	#-2,r4
28162306a36Sopenharmony_ci	xtrct	r8,r0
28262306a36Sopenharmony_ci	xtrct	r9,r8
28362306a36Sopenharmony_ci	xtrct	r10,r9
28462306a36Sopenharmony_ciEX(	mov.l	r0,@(28,r4)	)
28562306a36Sopenharmony_ciEX(	mov.l	r8,@(24,r4)	)
28662306a36Sopenharmony_ciEX(	mov.l	r9,@(20,r4)	)
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ciEX(	mov.l	@(12,r5),r0	)
28962306a36Sopenharmony_ciEX(	mov.l	@(8,r5),r8	)
29062306a36Sopenharmony_ci	xtrct	r0,r10
29162306a36Sopenharmony_ciEX(	mov.l	@(4,r5),r9	)
29262306a36Sopenharmony_ci	mov.l	r10,@(16,r4)
29362306a36Sopenharmony_ciEX(	mov.l	@r5,r10		)
29462306a36Sopenharmony_ci	xtrct	r8,r0
29562306a36Sopenharmony_ci	xtrct	r9,r8
29662306a36Sopenharmony_ci	xtrct	r10,r9
29762306a36Sopenharmony_ciEX(	mov.l	r0,@(12,r4)	)
29862306a36Sopenharmony_ciEX(	mov.l	r8,@(8,r4)	)
29962306a36Sopenharmony_ci	swap.w	r10,r0
30062306a36Sopenharmony_ciEX(	mov.l	r9,@(4,r4)	)
30162306a36Sopenharmony_ciEX(	mov.w	r0,@(2,r4)	)
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	add	#32,r5
30462306a36Sopenharmony_ci	bf/s	2b
30562306a36Sopenharmony_ci	 add	#34,r4
30662306a36Sopenharmony_ci#endif
30762306a36Sopenharmony_ci	tst	r2,r2
30862306a36Sopenharmony_ci	bt	.L_cleanup
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci1:	! Read longword, write two words per iteration
31162306a36Sopenharmony_ciEX(	mov.l	@r5+,r0		)
31262306a36Sopenharmony_ci	dt	r2
31362306a36Sopenharmony_ci#ifdef CONFIG_CPU_LITTLE_ENDIAN
31462306a36Sopenharmony_ciEX(	mov.w	r0,@r4		)
31562306a36Sopenharmony_ci	shlr16	r0
31662306a36Sopenharmony_ciEX(	mov.w 	r0,@(2,r4)	)
31762306a36Sopenharmony_ci#else
31862306a36Sopenharmony_ciEX(	mov.w	r0,@(2,r4)	)
31962306a36Sopenharmony_ci	shlr16	r0
32062306a36Sopenharmony_ciEX(	mov.w	r0,@r4		)
32162306a36Sopenharmony_ci#endif
32262306a36Sopenharmony_ci	bf/s	1b
32362306a36Sopenharmony_ci	 add	#4,r4
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	bra	.L_cleanup
32662306a36Sopenharmony_ci	 nop
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci! Destination = 01 or 11
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci.L_dest01:
33162306a36Sopenharmony_ci.L_dest11:
33262306a36Sopenharmony_ci	! Read longword, write byte, word, byte per iteration
33362306a36Sopenharmony_ciEX(	mov.l	@r5+,r0		)
33462306a36Sopenharmony_ci	dt	r2
33562306a36Sopenharmony_ci#ifdef CONFIG_CPU_LITTLE_ENDIAN
33662306a36Sopenharmony_ciEX(	mov.b	r0,@r4		)
33762306a36Sopenharmony_ci	shlr8	r0
33862306a36Sopenharmony_ci	add	#1,r4
33962306a36Sopenharmony_ciEX(	mov.w	r0,@r4		)
34062306a36Sopenharmony_ci	shlr16	r0
34162306a36Sopenharmony_ciEX(	mov.b	r0,@(2,r4)	)
34262306a36Sopenharmony_ci	bf/s	.L_dest01
34362306a36Sopenharmony_ci	 add	#3,r4
34462306a36Sopenharmony_ci#else
34562306a36Sopenharmony_ciEX(	mov.b	r0,@(3,r4)	)
34662306a36Sopenharmony_ci	shlr8	r0
34762306a36Sopenharmony_ci	swap.w	r0,r7
34862306a36Sopenharmony_ciEX(	mov.b	r7,@r4		)
34962306a36Sopenharmony_ci	add	#1,r4
35062306a36Sopenharmony_ciEX(	mov.w	r0,@r4		)
35162306a36Sopenharmony_ci	bf/s	.L_dest01
35262306a36Sopenharmony_ci	 add	#3,r4
35362306a36Sopenharmony_ci#endif
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci! Cleanup last few bytes
35662306a36Sopenharmony_ci.L_cleanup:
35762306a36Sopenharmony_ci	mov	r6,r0
35862306a36Sopenharmony_ci	and	#3,r0
35962306a36Sopenharmony_ci	tst	r0,r0
36062306a36Sopenharmony_ci	bt	.L_exit
36162306a36Sopenharmony_ci	mov	r0,r6
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci.L_cleanup_loop:
36462306a36Sopenharmony_ciEX(	mov.b	@r5+,r0		)
36562306a36Sopenharmony_ci	dt	r6
36662306a36Sopenharmony_ciEX(	mov.b	r0,@r4		)
36762306a36Sopenharmony_ci	bf/s	.L_cleanup_loop
36862306a36Sopenharmony_ci	 add	#1,r4
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci.L_exit:
37162306a36Sopenharmony_ci	mov	#0,r0		! normal return
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci5000:
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci# Exception handler:
37662306a36Sopenharmony_ci.section .fixup, "ax"
37762306a36Sopenharmony_ci6000:
37862306a36Sopenharmony_ci	mov.l	8000f,r1
37962306a36Sopenharmony_ci	mov	r3,r0
38062306a36Sopenharmony_ci	jmp	@r1
38162306a36Sopenharmony_ci	 sub	r4,r0
38262306a36Sopenharmony_ci	.align	2
38362306a36Sopenharmony_ci8000:	.long	5000b
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci.previous
38662306a36Sopenharmony_ci	mov.l	@r15+,r8
38762306a36Sopenharmony_ci	mov.l	@r15+,r9
38862306a36Sopenharmony_ci	mov.l	@r15+,r10
38962306a36Sopenharmony_ci	rts
39062306a36Sopenharmony_ci	 mov.l	@r15+,r11
391