18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * copy_page, __copy_user_page, __copy_user implementation of SuperH 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima 68c2ecf20Sopenharmony_ci * Copyright (C) 2002 Toshinobu Sugioka 78c2ecf20Sopenharmony_ci * Copyright (C) 2006 Paul Mundt 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/linkage.h> 108c2ecf20Sopenharmony_ci#include <asm/page.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci/* 138c2ecf20Sopenharmony_ci * copy_page 148c2ecf20Sopenharmony_ci * @to: P1 address 158c2ecf20Sopenharmony_ci * @from: P1 address 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * void copy_page(void *to, void *from) 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* 218c2ecf20Sopenharmony_ci * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch 228c2ecf20Sopenharmony_ci * r8 --- from + PAGE_SIZE 238c2ecf20Sopenharmony_ci * r9 --- not used 248c2ecf20Sopenharmony_ci * r10 --- to 258c2ecf20Sopenharmony_ci * r11 --- from 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ciENTRY(copy_page) 288c2ecf20Sopenharmony_ci mov.l r8,@-r15 298c2ecf20Sopenharmony_ci mov.l r10,@-r15 308c2ecf20Sopenharmony_ci mov.l r11,@-r15 318c2ecf20Sopenharmony_ci mov r4,r10 328c2ecf20Sopenharmony_ci mov r5,r11 338c2ecf20Sopenharmony_ci mov r5,r8 348c2ecf20Sopenharmony_ci mov #(PAGE_SIZE >> 10), r0 358c2ecf20Sopenharmony_ci shll8 r0 368c2ecf20Sopenharmony_ci shll2 r0 378c2ecf20Sopenharmony_ci add r0,r8 388c2ecf20Sopenharmony_ci ! 398c2ecf20Sopenharmony_ci1: mov.l @r11+,r0 408c2ecf20Sopenharmony_ci mov.l @r11+,r1 418c2ecf20Sopenharmony_ci mov.l @r11+,r2 428c2ecf20Sopenharmony_ci mov.l @r11+,r3 438c2ecf20Sopenharmony_ci mov.l @r11+,r4 448c2ecf20Sopenharmony_ci mov.l @r11+,r5 458c2ecf20Sopenharmony_ci mov.l @r11+,r6 468c2ecf20Sopenharmony_ci mov.l @r11+,r7 478c2ecf20Sopenharmony_ci#if defined(CONFIG_CPU_SH4) 488c2ecf20Sopenharmony_ci movca.l r0,@r10 498c2ecf20Sopenharmony_ci#else 508c2ecf20Sopenharmony_ci mov.l r0,@r10 518c2ecf20Sopenharmony_ci#endif 528c2ecf20Sopenharmony_ci add #32,r10 538c2ecf20Sopenharmony_ci mov.l r7,@-r10 548c2ecf20Sopenharmony_ci mov.l r6,@-r10 558c2ecf20Sopenharmony_ci mov.l r5,@-r10 568c2ecf20Sopenharmony_ci mov.l r4,@-r10 578c2ecf20Sopenharmony_ci mov.l r3,@-r10 588c2ecf20Sopenharmony_ci mov.l r2,@-r10 598c2ecf20Sopenharmony_ci mov.l r1,@-r10 608c2ecf20Sopenharmony_ci cmp/eq r11,r8 618c2ecf20Sopenharmony_ci bf/s 1b 628c2ecf20Sopenharmony_ci add #28,r10 638c2ecf20Sopenharmony_ci ! 648c2ecf20Sopenharmony_ci mov.l @r15+,r11 658c2ecf20Sopenharmony_ci mov.l @r15+,r10 668c2ecf20Sopenharmony_ci mov.l @r15+,r8 678c2ecf20Sopenharmony_ci rts 688c2ecf20Sopenharmony_ci nop 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* 718c2ecf20Sopenharmony_ci * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); 728c2ecf20Sopenharmony_ci * Return the number of bytes NOT copied 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_ci#define EX(...) \ 758c2ecf20Sopenharmony_ci 9999: __VA_ARGS__ ; \ 768c2ecf20Sopenharmony_ci .section __ex_table, "a"; \ 778c2ecf20Sopenharmony_ci .long 9999b, 6000f ; \ 788c2ecf20Sopenharmony_ci .previous 798c2ecf20Sopenharmony_ci#define EX_NO_POP(...) \ 808c2ecf20Sopenharmony_ci 9999: __VA_ARGS__ ; \ 818c2ecf20Sopenharmony_ci .section __ex_table, "a"; \ 828c2ecf20Sopenharmony_ci .long 9999b, 6005f ; \ 838c2ecf20Sopenharmony_ci .previous 848c2ecf20Sopenharmony_ciENTRY(__copy_user) 858c2ecf20Sopenharmony_ci ! Check if small number of bytes 868c2ecf20Sopenharmony_ci mov #11,r0 878c2ecf20Sopenharmony_ci mov r4,r3 888c2ecf20Sopenharmony_ci cmp/gt r0,r6 ! r6 (len) > r0 (11) 898c2ecf20Sopenharmony_ci bf/s .L_cleanup_loop_no_pop 908c2ecf20Sopenharmony_ci add r6,r3 ! last destination address 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci ! Calculate bytes needed to align to src 938c2ecf20Sopenharmony_ci mov.l r11,@-r15 948c2ecf20Sopenharmony_ci neg r5,r0 958c2ecf20Sopenharmony_ci mov.l r10,@-r15 968c2ecf20Sopenharmony_ci add #4,r0 978c2ecf20Sopenharmony_ci mov.l r9,@-r15 988c2ecf20Sopenharmony_ci and #3,r0 998c2ecf20Sopenharmony_ci mov.l r8,@-r15 1008c2ecf20Sopenharmony_ci tst r0,r0 1018c2ecf20Sopenharmony_ci bt 2f 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci1: 1048c2ecf20Sopenharmony_ci ! Copy bytes to long word align src 1058c2ecf20Sopenharmony_ciEX( mov.b @r5+,r1 ) 1068c2ecf20Sopenharmony_ci dt r0 1078c2ecf20Sopenharmony_ci add #-1,r6 1088c2ecf20Sopenharmony_ciEX( mov.b r1,@r4 ) 1098c2ecf20Sopenharmony_ci bf/s 1b 1108c2ecf20Sopenharmony_ci add #1,r4 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci ! Jump to appropriate routine depending on dest 1138c2ecf20Sopenharmony_ci2: mov #3,r1 1148c2ecf20Sopenharmony_ci mov r6, r2 1158c2ecf20Sopenharmony_ci and r4,r1 1168c2ecf20Sopenharmony_ci shlr2 r2 1178c2ecf20Sopenharmony_ci shll2 r1 1188c2ecf20Sopenharmony_ci mova .L_jump_tbl,r0 1198c2ecf20Sopenharmony_ci mov.l @(r0,r1),r1 1208c2ecf20Sopenharmony_ci jmp @r1 1218c2ecf20Sopenharmony_ci nop 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci .align 2 1248c2ecf20Sopenharmony_ci.L_jump_tbl: 1258c2ecf20Sopenharmony_ci .long .L_dest00 1268c2ecf20Sopenharmony_ci .long .L_dest01 1278c2ecf20Sopenharmony_ci .long .L_dest10 1288c2ecf20Sopenharmony_ci .long .L_dest11 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* 1318c2ecf20Sopenharmony_ci * Come here if there are less than 12 bytes to copy 1328c2ecf20Sopenharmony_ci * 1338c2ecf20Sopenharmony_ci * Keep the branch target close, so the bf/s callee doesn't overflow 1348c2ecf20Sopenharmony_ci * and result in a more expensive branch being inserted. This is the 1358c2ecf20Sopenharmony_ci * fast-path for small copies, the jump via the jump table will hit the 1368c2ecf20Sopenharmony_ci * default slow-path cleanup. -PFM. 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_ci.L_cleanup_loop_no_pop: 1398c2ecf20Sopenharmony_ci tst r6,r6 ! Check explicitly for zero 1408c2ecf20Sopenharmony_ci bt 1f 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci2: 1438c2ecf20Sopenharmony_ciEX_NO_POP( mov.b @r5+,r0 ) 1448c2ecf20Sopenharmony_ci dt r6 1458c2ecf20Sopenharmony_ciEX_NO_POP( mov.b r0,@r4 ) 1468c2ecf20Sopenharmony_ci bf/s 2b 1478c2ecf20Sopenharmony_ci add #1,r4 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci1: mov #0,r0 ! normal return 1508c2ecf20Sopenharmony_ci5000: 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci# Exception handler: 1538c2ecf20Sopenharmony_ci.section .fixup, "ax" 1548c2ecf20Sopenharmony_ci6005: 1558c2ecf20Sopenharmony_ci mov.l 8000f,r1 1568c2ecf20Sopenharmony_ci mov r3,r0 1578c2ecf20Sopenharmony_ci jmp @r1 1588c2ecf20Sopenharmony_ci sub r4,r0 1598c2ecf20Sopenharmony_ci .align 2 1608c2ecf20Sopenharmony_ci8000: .long 5000b 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci.previous 1638c2ecf20Sopenharmony_ci rts 1648c2ecf20Sopenharmony_ci nop 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci! Destination = 00 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci.L_dest00: 1698c2ecf20Sopenharmony_ci ! Skip the large copy for small transfers 1708c2ecf20Sopenharmony_ci mov #(32+32-4), r0 1718c2ecf20Sopenharmony_ci cmp/gt r6, r0 ! r0 (60) > r6 (len) 1728c2ecf20Sopenharmony_ci bt 1f 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci ! Align dest to a 32 byte boundary 1758c2ecf20Sopenharmony_ci neg r4,r0 1768c2ecf20Sopenharmony_ci add #0x20, r0 1778c2ecf20Sopenharmony_ci and #0x1f, r0 1788c2ecf20Sopenharmony_ci tst r0, r0 1798c2ecf20Sopenharmony_ci bt 2f 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci sub r0, r6 1828c2ecf20Sopenharmony_ci shlr2 r0 1838c2ecf20Sopenharmony_ci3: 1848c2ecf20Sopenharmony_ciEX( mov.l @r5+,r1 ) 1858c2ecf20Sopenharmony_ci dt r0 1868c2ecf20Sopenharmony_ciEX( mov.l r1,@r4 ) 1878c2ecf20Sopenharmony_ci bf/s 3b 1888c2ecf20Sopenharmony_ci add #4,r4 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci2: 1918c2ecf20Sopenharmony_ciEX( mov.l @r5+,r0 ) 1928c2ecf20Sopenharmony_ciEX( mov.l @r5+,r1 ) 1938c2ecf20Sopenharmony_ciEX( mov.l @r5+,r2 ) 1948c2ecf20Sopenharmony_ciEX( mov.l @r5+,r7 ) 1958c2ecf20Sopenharmony_ciEX( mov.l @r5+,r8 ) 1968c2ecf20Sopenharmony_ciEX( mov.l @r5+,r9 ) 1978c2ecf20Sopenharmony_ciEX( mov.l @r5+,r10 ) 1988c2ecf20Sopenharmony_ciEX( mov.l @r5+,r11 ) 1998c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_SH4 2008c2ecf20Sopenharmony_ciEX( movca.l r0,@r4 ) 2018c2ecf20Sopenharmony_ci#else 2028c2ecf20Sopenharmony_ciEX( mov.l r0,@r4 ) 2038c2ecf20Sopenharmony_ci#endif 2048c2ecf20Sopenharmony_ci add #-32, r6 2058c2ecf20Sopenharmony_ciEX( mov.l r1,@(4,r4) ) 2068c2ecf20Sopenharmony_ci mov #32, r0 2078c2ecf20Sopenharmony_ciEX( mov.l r2,@(8,r4) ) 2088c2ecf20Sopenharmony_ci cmp/gt r6, r0 ! r0 (32) > r6 (len) 2098c2ecf20Sopenharmony_ciEX( mov.l r7,@(12,r4) ) 2108c2ecf20Sopenharmony_ciEX( mov.l r8,@(16,r4) ) 2118c2ecf20Sopenharmony_ciEX( mov.l r9,@(20,r4) ) 2128c2ecf20Sopenharmony_ciEX( mov.l r10,@(24,r4) ) 2138c2ecf20Sopenharmony_ciEX( mov.l r11,@(28,r4) ) 2148c2ecf20Sopenharmony_ci bf/s 2b 2158c2ecf20Sopenharmony_ci add #32,r4 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci1: mov r6, r0 2188c2ecf20Sopenharmony_ci shlr2 r0 2198c2ecf20Sopenharmony_ci tst r0, r0 2208c2ecf20Sopenharmony_ci bt .L_cleanup 2218c2ecf20Sopenharmony_ci1: 2228c2ecf20Sopenharmony_ciEX( mov.l @r5+,r1 ) 2238c2ecf20Sopenharmony_ci dt r0 2248c2ecf20Sopenharmony_ciEX( mov.l r1,@r4 ) 2258c2ecf20Sopenharmony_ci bf/s 1b 2268c2ecf20Sopenharmony_ci add #4,r4 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci bra .L_cleanup 2298c2ecf20Sopenharmony_ci nop 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci! Destination = 10 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci.L_dest10: 2348c2ecf20Sopenharmony_ci mov r2,r7 2358c2ecf20Sopenharmony_ci shlr2 r7 2368c2ecf20Sopenharmony_ci shlr r7 2378c2ecf20Sopenharmony_ci tst r7,r7 2388c2ecf20Sopenharmony_ci mov #7,r0 2398c2ecf20Sopenharmony_ci bt/s 1f 2408c2ecf20Sopenharmony_ci and r0,r2 2418c2ecf20Sopenharmony_ci2: 2428c2ecf20Sopenharmony_ci dt r7 2438c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_LITTLE_ENDIAN 2448c2ecf20Sopenharmony_ciEX( mov.l @r5+,r0 ) 2458c2ecf20Sopenharmony_ciEX( mov.l @r5+,r1 ) 2468c2ecf20Sopenharmony_ciEX( mov.l @r5+,r8 ) 2478c2ecf20Sopenharmony_ciEX( mov.l @r5+,r9 ) 2488c2ecf20Sopenharmony_ciEX( mov.l @r5+,r10 ) 2498c2ecf20Sopenharmony_ciEX( mov.w r0,@r4 ) 2508c2ecf20Sopenharmony_ci add #2,r4 2518c2ecf20Sopenharmony_ci xtrct r1,r0 2528c2ecf20Sopenharmony_ci xtrct r8,r1 2538c2ecf20Sopenharmony_ci xtrct r9,r8 2548c2ecf20Sopenharmony_ci xtrct r10,r9 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ciEX( mov.l r0,@r4 ) 2578c2ecf20Sopenharmony_ciEX( mov.l r1,@(4,r4) ) 2588c2ecf20Sopenharmony_ciEX( mov.l r8,@(8,r4) ) 2598c2ecf20Sopenharmony_ciEX( mov.l r9,@(12,r4) ) 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ciEX( mov.l @r5+,r1 ) 2628c2ecf20Sopenharmony_ciEX( mov.l @r5+,r8 ) 2638c2ecf20Sopenharmony_ciEX( mov.l @r5+,r0 ) 2648c2ecf20Sopenharmony_ci xtrct r1,r10 2658c2ecf20Sopenharmony_ci xtrct r8,r1 2668c2ecf20Sopenharmony_ci xtrct r0,r8 2678c2ecf20Sopenharmony_ci shlr16 r0 2688c2ecf20Sopenharmony_ciEX( mov.l r10,@(16,r4) ) 2698c2ecf20Sopenharmony_ciEX( mov.l r1,@(20,r4) ) 2708c2ecf20Sopenharmony_ciEX( mov.l r8,@(24,r4) ) 2718c2ecf20Sopenharmony_ciEX( mov.w r0,@(28,r4) ) 2728c2ecf20Sopenharmony_ci bf/s 2b 2738c2ecf20Sopenharmony_ci add #30,r4 2748c2ecf20Sopenharmony_ci#else 2758c2ecf20Sopenharmony_ciEX( mov.l @(28,r5),r0 ) 2768c2ecf20Sopenharmony_ciEX( mov.l @(24,r5),r8 ) 2778c2ecf20Sopenharmony_ciEX( mov.l @(20,r5),r9 ) 2788c2ecf20Sopenharmony_ciEX( mov.l @(16,r5),r10 ) 2798c2ecf20Sopenharmony_ciEX( mov.w r0,@(30,r4) ) 2808c2ecf20Sopenharmony_ci add #-2,r4 2818c2ecf20Sopenharmony_ci xtrct r8,r0 2828c2ecf20Sopenharmony_ci xtrct r9,r8 2838c2ecf20Sopenharmony_ci xtrct r10,r9 2848c2ecf20Sopenharmony_ciEX( mov.l r0,@(28,r4) ) 2858c2ecf20Sopenharmony_ciEX( mov.l r8,@(24,r4) ) 2868c2ecf20Sopenharmony_ciEX( mov.l r9,@(20,r4) ) 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ciEX( mov.l @(12,r5),r0 ) 2898c2ecf20Sopenharmony_ciEX( mov.l @(8,r5),r8 ) 2908c2ecf20Sopenharmony_ci xtrct r0,r10 2918c2ecf20Sopenharmony_ciEX( mov.l @(4,r5),r9 ) 2928c2ecf20Sopenharmony_ci mov.l r10,@(16,r4) 2938c2ecf20Sopenharmony_ciEX( mov.l @r5,r10 ) 2948c2ecf20Sopenharmony_ci xtrct r8,r0 2958c2ecf20Sopenharmony_ci xtrct r9,r8 2968c2ecf20Sopenharmony_ci xtrct r10,r9 2978c2ecf20Sopenharmony_ciEX( mov.l r0,@(12,r4) ) 2988c2ecf20Sopenharmony_ciEX( mov.l r8,@(8,r4) ) 2998c2ecf20Sopenharmony_ci swap.w r10,r0 3008c2ecf20Sopenharmony_ciEX( mov.l r9,@(4,r4) ) 3018c2ecf20Sopenharmony_ciEX( mov.w r0,@(2,r4) ) 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci add #32,r5 3048c2ecf20Sopenharmony_ci bf/s 2b 3058c2ecf20Sopenharmony_ci add #34,r4 3068c2ecf20Sopenharmony_ci#endif 3078c2ecf20Sopenharmony_ci tst r2,r2 3088c2ecf20Sopenharmony_ci bt .L_cleanup 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci1: ! Read longword, write two words per iteration 3118c2ecf20Sopenharmony_ciEX( mov.l @r5+,r0 ) 3128c2ecf20Sopenharmony_ci dt r2 3138c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_LITTLE_ENDIAN 3148c2ecf20Sopenharmony_ciEX( mov.w r0,@r4 ) 3158c2ecf20Sopenharmony_ci shlr16 r0 3168c2ecf20Sopenharmony_ciEX( mov.w r0,@(2,r4) ) 3178c2ecf20Sopenharmony_ci#else 3188c2ecf20Sopenharmony_ciEX( mov.w r0,@(2,r4) ) 3198c2ecf20Sopenharmony_ci shlr16 r0 3208c2ecf20Sopenharmony_ciEX( mov.w r0,@r4 ) 3218c2ecf20Sopenharmony_ci#endif 3228c2ecf20Sopenharmony_ci bf/s 1b 3238c2ecf20Sopenharmony_ci add #4,r4 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci bra .L_cleanup 3268c2ecf20Sopenharmony_ci nop 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci! Destination = 01 or 11 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci.L_dest01: 3318c2ecf20Sopenharmony_ci.L_dest11: 3328c2ecf20Sopenharmony_ci ! Read longword, write byte, word, byte per iteration 3338c2ecf20Sopenharmony_ciEX( mov.l @r5+,r0 ) 3348c2ecf20Sopenharmony_ci dt r2 3358c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_LITTLE_ENDIAN 3368c2ecf20Sopenharmony_ciEX( mov.b r0,@r4 ) 3378c2ecf20Sopenharmony_ci shlr8 r0 3388c2ecf20Sopenharmony_ci add #1,r4 3398c2ecf20Sopenharmony_ciEX( mov.w r0,@r4 ) 3408c2ecf20Sopenharmony_ci shlr16 r0 3418c2ecf20Sopenharmony_ciEX( mov.b r0,@(2,r4) ) 3428c2ecf20Sopenharmony_ci bf/s .L_dest01 3438c2ecf20Sopenharmony_ci add #3,r4 3448c2ecf20Sopenharmony_ci#else 3458c2ecf20Sopenharmony_ciEX( mov.b r0,@(3,r4) ) 3468c2ecf20Sopenharmony_ci shlr8 r0 3478c2ecf20Sopenharmony_ci swap.w r0,r7 3488c2ecf20Sopenharmony_ciEX( mov.b r7,@r4 ) 3498c2ecf20Sopenharmony_ci add #1,r4 3508c2ecf20Sopenharmony_ciEX( mov.w r0,@r4 ) 3518c2ecf20Sopenharmony_ci bf/s .L_dest01 3528c2ecf20Sopenharmony_ci add #3,r4 3538c2ecf20Sopenharmony_ci#endif 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci! Cleanup last few bytes 3568c2ecf20Sopenharmony_ci.L_cleanup: 3578c2ecf20Sopenharmony_ci mov r6,r0 3588c2ecf20Sopenharmony_ci and #3,r0 3598c2ecf20Sopenharmony_ci tst r0,r0 3608c2ecf20Sopenharmony_ci bt .L_exit 3618c2ecf20Sopenharmony_ci mov r0,r6 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci.L_cleanup_loop: 3648c2ecf20Sopenharmony_ciEX( mov.b @r5+,r0 ) 3658c2ecf20Sopenharmony_ci dt r6 3668c2ecf20Sopenharmony_ciEX( mov.b r0,@r4 ) 3678c2ecf20Sopenharmony_ci bf/s .L_cleanup_loop 3688c2ecf20Sopenharmony_ci add #1,r4 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci.L_exit: 3718c2ecf20Sopenharmony_ci mov #0,r0 ! normal return 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci5000: 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci# Exception handler: 3768c2ecf20Sopenharmony_ci.section .fixup, "ax" 3778c2ecf20Sopenharmony_ci6000: 3788c2ecf20Sopenharmony_ci mov.l 8000f,r1 3798c2ecf20Sopenharmony_ci mov r3,r0 3808c2ecf20Sopenharmony_ci jmp @r1 3818c2ecf20Sopenharmony_ci sub r4,r0 3828c2ecf20Sopenharmony_ci .align 2 3838c2ecf20Sopenharmony_ci8000: .long 5000b 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci.previous 3868c2ecf20Sopenharmony_ci mov.l @r15+,r8 3878c2ecf20Sopenharmony_ci mov.l @r15+,r9 3888c2ecf20Sopenharmony_ci mov.l @r15+,r10 3898c2ecf20Sopenharmony_ci rts 3908c2ecf20Sopenharmony_ci mov.l @r15+,r11 391