| ! Copyright (C) 2008-2012 Imagination Technologies Ltd. | |
| .text | |
| .global _memmove | |
| .type _memmove,function | |
| ! D1Ar1 dst | |
| ! D0Ar2 src | |
| ! D1Ar3 cnt | |
| ! D0Re0 dst | |
| _memmove: | |
| CMP D1Ar3, #0 | |
| MOV D0Re0, D1Ar1 | |
| BZ $LEND2 | |
| MSETL [A0StP], D0.5, D0.6, D0.7 | |
| MOV D1Ar5, D0Ar2 | |
| CMP D1Ar1, D1Ar5 | |
| BLT $Lforwards_copy | |
| SUB D0Ar4, D1Ar1, D1Ar3 | |
| ADD D0Ar4, D0Ar4, #1 | |
| CMP D0Ar2, D0Ar4 | |
| BLT $Lforwards_copy | |
| ! should copy backwards | |
| MOV D1Re0, D0Ar2 | |
| ! adjust pointer to the end of mem | |
| ADD D0Ar2, D1Re0, D1Ar3 | |
| ADD D1Ar1, D1Ar1, D1Ar3 | |
| MOV A1.2, D0Ar2 | |
| MOV A0.2, D1Ar1 | |
| CMP D1Ar3, #8 | |
| BLT $Lbbyte_loop | |
| MOV D0Ar4, D0Ar2 | |
| MOV D1Ar5, D1Ar1 | |
| ! test 8 byte alignment | |
| ANDS D1Ar5, D1Ar5, #7 | |
| BNE $Lbdest_unaligned | |
| ANDS D0Ar4, D0Ar4, #7 | |
| BNE $Lbsrc_unaligned | |
| LSR D1Ar5, D1Ar3, #3 | |
| $Lbaligned_loop: | |
| GETL D0Re0, D1Re0, [--A1.2] | |
| SETL [--A0.2], D0Re0, D1Re0 | |
| SUBS D1Ar5, D1Ar5, #1 | |
| BNE $Lbaligned_loop | |
| ANDS D1Ar3, D1Ar3, #7 | |
| BZ $Lbbyte_loop_exit | |
| $Lbbyte_loop: | |
| GETB D1Re0, [--A1.2] | |
| SETB [--A0.2], D1Re0 | |
| SUBS D1Ar3, D1Ar3, #1 | |
| BNE $Lbbyte_loop | |
| $Lbbyte_loop_exit: | |
| MOV D0Re0, A0.2 | |
| $LEND: | |
| SUB A0.2, A0StP, #24 | |
| MGETL D0.5, D0.6, D0.7, [A0.2] | |
| SUB A0StP, A0StP, #24 | |
| $LEND2: | |
| MOV PC, D1RtP | |
| $Lbdest_unaligned: | |
| GETB D0Re0, [--A1.2] | |
| SETB [--A0.2], D0Re0 | |
| SUBS D1Ar5, D1Ar5, #1 | |
| SUB D1Ar3, D1Ar3, #1 | |
| BNE $Lbdest_unaligned | |
| CMP D1Ar3, #8 | |
| BLT $Lbbyte_loop | |
| $Lbsrc_unaligned: | |
| LSR D1Ar5, D1Ar3, #3 | |
| ! adjust A1.2 | |
| MOV D0Ar4, A1.2 | |
| ! save original address | |
| MOV D0Ar6, A1.2 | |
| ADD D0Ar4, D0Ar4, #7 | |
| ANDMB D0Ar4, D0Ar4, #0xfff8 | |
| ! new address is the 8-byte aligned one above the original | |
| MOV A1.2, D0Ar4 | |
| ! A0.2 dst 64-bit is aligned | |
| ! measure the gap size | |
| SUB D0Ar6, D0Ar4, D0Ar6 | |
| MOVS D0Ar4, D0Ar6 | |
| ! keep this information for the later adjustment | |
| ! both aligned | |
| BZ $Lbaligned_loop | |
| ! prefetch | |
| GETL D0Re0, D1Re0, [--A1.2] | |
| CMP D0Ar6, #4 | |
| BLT $Lbunaligned_1_2_3 | |
| ! 32-bit aligned | |
| BZ $Lbaligned_4 | |
| SUB D0Ar6, D0Ar6, #4 | |
| ! D1.6 stores the gap size in bits | |
| MULW D1.6, D0Ar6, #8 | |
| MOV D0.6, #32 | |
| ! D0.6 stores the complement of the gap size | |
| SUB D0.6, D0.6, D1.6 | |
| $Lbunaligned_5_6_7: | |
| GETL D0.7, D1.7, [--A1.2] | |
| ! form 64-bit data in D0Re0, D1Re0 | |
| MOV D1Re0, D0Re0 | |
| ! D1Re0 << gap-size | |
| LSL D1Re0, D1Re0, D1.6 | |
| MOV D0Re0, D1.7 | |
| ! D0Re0 >> complement | |
| LSR D0Re0, D0Re0, D0.6 | |
| MOV D1.5, D0Re0 | |
| ! combine the both | |
| ADD D1Re0, D1Re0, D1.5 | |
| MOV D1.5, D1.7 | |
| LSL D1.5, D1.5, D1.6 | |
| MOV D0Re0, D0.7 | |
| LSR D0Re0, D0Re0, D0.6 | |
| MOV D0.5, D1.5 | |
| ADD D0Re0, D0Re0, D0.5 | |
| SETL [--A0.2], D0Re0, D1Re0 | |
| MOV D0Re0, D0.7 | |
| MOV D1Re0, D1.7 | |
| SUBS D1Ar5, D1Ar5, #1 | |
| BNE $Lbunaligned_5_6_7 | |
| ANDS D1Ar3, D1Ar3, #7 | |
| BZ $Lbbyte_loop_exit | |
| ! Adjust A1.2 | |
| ! A1.2 <- A1.2 +8 - gapsize | |
| ADD A1.2, A1.2, #8 | |
| SUB A1.2, A1.2, D0Ar4 | |
| B $Lbbyte_loop | |
| $Lbunaligned_1_2_3: | |
| MULW D1.6, D0Ar6, #8 | |
| MOV D0.6, #32 | |
| SUB D0.6, D0.6, D1.6 | |
| $Lbunaligned_1_2_3_loop: | |
| GETL D0.7, D1.7, [--A1.2] | |
| ! form 64-bit data in D0Re0, D1Re0 | |
| LSL D1Re0, D1Re0, D1.6 | |
| ! save D0Re0 for later use | |
| MOV D0.5, D0Re0 | |
| LSR D0Re0, D0Re0, D0.6 | |
| MOV D1.5, D0Re0 | |
| ADD D1Re0, D1Re0, D1.5 | |
| ! orignal data in D0Re0 | |
| MOV D1.5, D0.5 | |
| LSL D1.5, D1.5, D1.6 | |
| MOV D0Re0, D1.7 | |
| LSR D0Re0, D0Re0, D0.6 | |
| MOV D0.5, D1.5 | |
| ADD D0Re0, D0Re0, D0.5 | |
| SETL [--A0.2], D0Re0, D1Re0 | |
| MOV D0Re0, D0.7 | |
| MOV D1Re0, D1.7 | |
| SUBS D1Ar5, D1Ar5, #1 | |
| BNE $Lbunaligned_1_2_3_loop | |
| ANDS D1Ar3, D1Ar3, #7 | |
| BZ $Lbbyte_loop_exit | |
| ! Adjust A1.2 | |
| ADD A1.2, A1.2, #8 | |
| SUB A1.2, A1.2, D0Ar4 | |
| B $Lbbyte_loop | |
| $Lbaligned_4: | |
| GETL D0.7, D1.7, [--A1.2] | |
| MOV D1Re0, D0Re0 | |
| MOV D0Re0, D1.7 | |
| SETL [--A0.2], D0Re0, D1Re0 | |
| MOV D0Re0, D0.7 | |
| MOV D1Re0, D1.7 | |
| SUBS D1Ar5, D1Ar5, #1 | |
| BNE $Lbaligned_4 | |
| ANDS D1Ar3, D1Ar3, #7 | |
| BZ $Lbbyte_loop_exit | |
| ! Adjust A1.2 | |
| ADD A1.2, A1.2, #8 | |
| SUB A1.2, A1.2, D0Ar4 | |
| B $Lbbyte_loop | |
| $Lforwards_copy: | |
| MOV A1.2, D0Ar2 | |
| MOV A0.2, D1Ar1 | |
| CMP D1Ar3, #8 | |
| BLT $Lfbyte_loop | |
| MOV D0Ar4, D0Ar2 | |
| MOV D1Ar5, D1Ar1 | |
| ANDS D1Ar5, D1Ar5, #7 | |
| BNE $Lfdest_unaligned | |
| ANDS D0Ar4, D0Ar4, #7 | |
| BNE $Lfsrc_unaligned | |
| LSR D1Ar5, D1Ar3, #3 | |
| $Lfaligned_loop: | |
| GETL D0Re0, D1Re0, [A1.2++] | |
| SUBS D1Ar5, D1Ar5, #1 | |
| SETL [A0.2++], D0Re0, D1Re0 | |
| BNE $Lfaligned_loop | |
| ANDS D1Ar3, D1Ar3, #7 | |
| BZ $Lfbyte_loop_exit | |
| $Lfbyte_loop: | |
| GETB D1Re0, [A1.2++] | |
| SETB [A0.2++], D1Re0 | |
| SUBS D1Ar3, D1Ar3, #1 | |
| BNE $Lfbyte_loop | |
| $Lfbyte_loop_exit: | |
| MOV D0Re0, D1Ar1 | |
| B $LEND | |
| $Lfdest_unaligned: | |
| GETB D0Re0, [A1.2++] | |
| ADD D1Ar5, D1Ar5, #1 | |
| SUB D1Ar3, D1Ar3, #1 | |
| SETB [A0.2++], D0Re0 | |
| CMP D1Ar5, #8 | |
| BNE $Lfdest_unaligned | |
| CMP D1Ar3, #8 | |
| BLT $Lfbyte_loop | |
| $Lfsrc_unaligned: | |
| ! adjust A1.2 | |
| LSR D1Ar5, D1Ar3, #3 | |
| MOV D0Ar4, A1.2 | |
| MOV D0Ar6, A1.2 | |
| ANDMB D0Ar4, D0Ar4, #0xfff8 | |
| MOV A1.2, D0Ar4 | |
| ! A0.2 dst 64-bit is aligned | |
| SUB D0Ar6, D0Ar6, D0Ar4 | |
| ! keep the information for the later adjustment | |
| MOVS D0Ar4, D0Ar6 | |
| ! both aligned | |
| BZ $Lfaligned_loop | |
| ! prefetch | |
| GETL D0Re0, D1Re0, [A1.2] | |
| CMP D0Ar6, #4 | |
| BLT $Lfunaligned_1_2_3 | |
| BZ $Lfaligned_4 | |
| SUB D0Ar6, D0Ar6, #4 | |
| MULW D0.6, D0Ar6, #8 | |
| MOV D1.6, #32 | |
| SUB D1.6, D1.6, D0.6 | |
| $Lfunaligned_5_6_7: | |
| GETL D0.7, D1.7, [++A1.2] | |
| ! form 64-bit data in D0Re0, D1Re0 | |
| MOV D0Re0, D1Re0 | |
| LSR D0Re0, D0Re0, D0.6 | |
| MOV D1Re0, D0.7 | |
| LSL D1Re0, D1Re0, D1.6 | |
| MOV D0.5, D1Re0 | |
| ADD D0Re0, D0Re0, D0.5 | |
| MOV D0.5, D0.7 | |
| LSR D0.5, D0.5, D0.6 | |
| MOV D1Re0, D1.7 | |
| LSL D1Re0, D1Re0, D1.6 | |
| MOV D1.5, D0.5 | |
| ADD D1Re0, D1Re0, D1.5 | |
| SETL [A0.2++], D0Re0, D1Re0 | |
| MOV D0Re0, D0.7 | |
| MOV D1Re0, D1.7 | |
| SUBS D1Ar5, D1Ar5, #1 | |
| BNE $Lfunaligned_5_6_7 | |
| ANDS D1Ar3, D1Ar3, #7 | |
| BZ $Lfbyte_loop_exit | |
| ! Adjust A1.2 | |
| ADD A1.2, A1.2, D0Ar4 | |
| B $Lfbyte_loop | |
| $Lfunaligned_1_2_3: | |
| MULW D0.6, D0Ar6, #8 | |
| MOV D1.6, #32 | |
| SUB D1.6, D1.6, D0.6 | |
| $Lfunaligned_1_2_3_loop: | |
| GETL D0.7, D1.7, [++A1.2] | |
| ! form 64-bit data in D0Re0, D1Re0 | |
| LSR D0Re0, D0Re0, D0.6 | |
| MOV D1.5, D1Re0 | |
| LSL D1Re0, D1Re0, D1.6 | |
| MOV D0.5, D1Re0 | |
| ADD D0Re0, D0Re0, D0.5 | |
| MOV D0.5, D1.5 | |
| LSR D0.5, D0.5, D0.6 | |
| MOV D1Re0, D0.7 | |
| LSL D1Re0, D1Re0, D1.6 | |
| MOV D1.5, D0.5 | |
| ADD D1Re0, D1Re0, D1.5 | |
| SETL [A0.2++], D0Re0, D1Re0 | |
| MOV D0Re0, D0.7 | |
| MOV D1Re0, D1.7 | |
| SUBS D1Ar5, D1Ar5, #1 | |
| BNE $Lfunaligned_1_2_3_loop | |
| ANDS D1Ar3, D1Ar3, #7 | |
| BZ $Lfbyte_loop_exit | |
| ! Adjust A1.2 | |
| ADD A1.2, A1.2, D0Ar4 | |
| B $Lfbyte_loop | |
| $Lfaligned_4: | |
| GETL D0.7, D1.7, [++A1.2] | |
| MOV D0Re0, D1Re0 | |
| MOV D1Re0, D0.7 | |
| SETL [A0.2++], D0Re0, D1Re0 | |
| MOV D0Re0, D0.7 | |
| MOV D1Re0, D1.7 | |
| SUBS D1Ar5, D1Ar5, #1 | |
| BNE $Lfaligned_4 | |
| ANDS D1Ar3, D1Ar3, #7 | |
| BZ $Lfbyte_loop_exit | |
| ! Adjust A1.2 | |
| ADD A1.2, A1.2, D0Ar4 | |
| B $Lfbyte_loop | |
| .size _memmove,.-_memmove |