James Hogan | 086e9dc | 2012-10-05 17:02:09 +0100 | [diff] [blame] | 1 | ! Copyright (C) 2008-2012 Imagination Technologies Ltd. |
| 2 | |
| 3 | .text |
| 4 | .global _memmove |
| 5 | .type _memmove,function |
| 6 | ! D1Ar1 dst |
| 7 | ! D0Ar2 src |
| 8 | ! D1Ar3 cnt |
| 9 | ! D0Re0 dst |
| 10 | _memmove: |
| 11 | CMP D1Ar3, #0 |
| 12 | MOV D0Re0, D1Ar1 |
| 13 | BZ $LEND2 |
| 14 | MSETL [A0StP], D0.5, D0.6, D0.7 |
| 15 | MOV D1Ar5, D0Ar2 |
| 16 | CMP D1Ar1, D1Ar5 |
| 17 | BLT $Lforwards_copy |
| 18 | SUB D0Ar4, D1Ar1, D1Ar3 |
| 19 | ADD D0Ar4, D0Ar4, #1 |
| 20 | CMP D0Ar2, D0Ar4 |
| 21 | BLT $Lforwards_copy |
| 22 | ! should copy backwards |
| 23 | MOV D1Re0, D0Ar2 |
| 24 | ! adjust pointer to the end of mem |
| 25 | ADD D0Ar2, D1Re0, D1Ar3 |
| 26 | ADD D1Ar1, D1Ar1, D1Ar3 |
| 27 | |
| 28 | MOV A1.2, D0Ar2 |
| 29 | MOV A0.2, D1Ar1 |
| 30 | CMP D1Ar3, #8 |
| 31 | BLT $Lbbyte_loop |
| 32 | |
| 33 | MOV D0Ar4, D0Ar2 |
| 34 | MOV D1Ar5, D1Ar1 |
| 35 | |
| 36 | ! test 8 byte alignment |
| 37 | ANDS D1Ar5, D1Ar5, #7 |
| 38 | BNE $Lbdest_unaligned |
| 39 | |
| 40 | ANDS D0Ar4, D0Ar4, #7 |
| 41 | BNE $Lbsrc_unaligned |
| 42 | |
| 43 | LSR D1Ar5, D1Ar3, #3 |
| 44 | |
| 45 | $Lbaligned_loop: |
| 46 | GETL D0Re0, D1Re0, [--A1.2] |
| 47 | SETL [--A0.2], D0Re0, D1Re0 |
| 48 | SUBS D1Ar5, D1Ar5, #1 |
| 49 | BNE $Lbaligned_loop |
| 50 | |
| 51 | ANDS D1Ar3, D1Ar3, #7 |
| 52 | BZ $Lbbyte_loop_exit |
| 53 | $Lbbyte_loop: |
| 54 | GETB D1Re0, [--A1.2] |
| 55 | SETB [--A0.2], D1Re0 |
| 56 | SUBS D1Ar3, D1Ar3, #1 |
| 57 | BNE $Lbbyte_loop |
| 58 | $Lbbyte_loop_exit: |
| 59 | MOV D0Re0, A0.2 |
| 60 | $LEND: |
| 61 | SUB A0.2, A0StP, #24 |
| 62 | MGETL D0.5, D0.6, D0.7, [A0.2] |
| 63 | SUB A0StP, A0StP, #24 |
| 64 | $LEND2: |
| 65 | MOV PC, D1RtP |
| 66 | |
| 67 | $Lbdest_unaligned: |
| 68 | GETB D0Re0, [--A1.2] |
| 69 | SETB [--A0.2], D0Re0 |
| 70 | SUBS D1Ar5, D1Ar5, #1 |
| 71 | SUB D1Ar3, D1Ar3, #1 |
| 72 | BNE $Lbdest_unaligned |
| 73 | CMP D1Ar3, #8 |
| 74 | BLT $Lbbyte_loop |
| 75 | $Lbsrc_unaligned: |
| 76 | LSR D1Ar5, D1Ar3, #3 |
| 77 | ! adjust A1.2 |
| 78 | MOV D0Ar4, A1.2 |
| 79 | ! save original address |
| 80 | MOV D0Ar6, A1.2 |
| 81 | |
| 82 | ADD D0Ar4, D0Ar4, #7 |
| 83 | ANDMB D0Ar4, D0Ar4, #0xfff8 |
| 84 | ! new address is the 8-byte aligned one above the original |
| 85 | MOV A1.2, D0Ar4 |
| 86 | |
| 87 | ! A0.2 dst 64-bit is aligned |
| 88 | ! measure the gap size |
| 89 | SUB D0Ar6, D0Ar4, D0Ar6 |
| 90 | MOVS D0Ar4, D0Ar6 |
| 91 | ! keep this information for the later adjustment |
| 92 | ! both aligned |
| 93 | BZ $Lbaligned_loop |
| 94 | |
| 95 | ! prefetch |
| 96 | GETL D0Re0, D1Re0, [--A1.2] |
| 97 | |
| 98 | CMP D0Ar6, #4 |
| 99 | BLT $Lbunaligned_1_2_3 |
| 100 | ! 32-bit aligned |
| 101 | BZ $Lbaligned_4 |
| 102 | |
| 103 | SUB D0Ar6, D0Ar6, #4 |
| 104 | ! D1.6 stores the gap size in bits |
| 105 | MULW D1.6, D0Ar6, #8 |
| 106 | MOV D0.6, #32 |
| 107 | ! D0.6 stores the complement of the gap size |
| 108 | SUB D0.6, D0.6, D1.6 |
| 109 | |
| 110 | $Lbunaligned_5_6_7: |
| 111 | GETL D0.7, D1.7, [--A1.2] |
| 112 | ! form 64-bit data in D0Re0, D1Re0 |
| 113 | MOV D1Re0, D0Re0 |
| 114 | ! D1Re0 << gap-size |
| 115 | LSL D1Re0, D1Re0, D1.6 |
| 116 | MOV D0Re0, D1.7 |
| 117 | ! D0Re0 >> complement |
| 118 | LSR D0Re0, D0Re0, D0.6 |
| 119 | MOV D1.5, D0Re0 |
| 120 | ! combine the both |
| 121 | ADD D1Re0, D1Re0, D1.5 |
| 122 | |
| 123 | MOV D1.5, D1.7 |
| 124 | LSL D1.5, D1.5, D1.6 |
| 125 | MOV D0Re0, D0.7 |
| 126 | LSR D0Re0, D0Re0, D0.6 |
| 127 | MOV D0.5, D1.5 |
| 128 | ADD D0Re0, D0Re0, D0.5 |
| 129 | |
| 130 | SETL [--A0.2], D0Re0, D1Re0 |
| 131 | MOV D0Re0, D0.7 |
| 132 | MOV D1Re0, D1.7 |
| 133 | SUBS D1Ar5, D1Ar5, #1 |
| 134 | BNE $Lbunaligned_5_6_7 |
| 135 | |
| 136 | ANDS D1Ar3, D1Ar3, #7 |
| 137 | BZ $Lbbyte_loop_exit |
| 138 | ! Adjust A1.2 |
| 139 | ! A1.2 <- A1.2 +8 - gapsize |
| 140 | ADD A1.2, A1.2, #8 |
| 141 | SUB A1.2, A1.2, D0Ar4 |
| 142 | B $Lbbyte_loop |
| 143 | |
| 144 | $Lbunaligned_1_2_3: |
| 145 | MULW D1.6, D0Ar6, #8 |
| 146 | MOV D0.6, #32 |
| 147 | SUB D0.6, D0.6, D1.6 |
| 148 | |
| 149 | $Lbunaligned_1_2_3_loop: |
| 150 | GETL D0.7, D1.7, [--A1.2] |
| 151 | ! form 64-bit data in D0Re0, D1Re0 |
| 152 | LSL D1Re0, D1Re0, D1.6 |
| 153 | ! save D0Re0 for later use |
| 154 | MOV D0.5, D0Re0 |
| 155 | LSR D0Re0, D0Re0, D0.6 |
| 156 | MOV D1.5, D0Re0 |
| 157 | ADD D1Re0, D1Re0, D1.5 |
| 158 | |
| 159 | ! orignal data in D0Re0 |
| 160 | MOV D1.5, D0.5 |
| 161 | LSL D1.5, D1.5, D1.6 |
| 162 | MOV D0Re0, D1.7 |
| 163 | LSR D0Re0, D0Re0, D0.6 |
| 164 | MOV D0.5, D1.5 |
| 165 | ADD D0Re0, D0Re0, D0.5 |
| 166 | |
| 167 | SETL [--A0.2], D0Re0, D1Re0 |
| 168 | MOV D0Re0, D0.7 |
| 169 | MOV D1Re0, D1.7 |
| 170 | SUBS D1Ar5, D1Ar5, #1 |
| 171 | BNE $Lbunaligned_1_2_3_loop |
| 172 | |
| 173 | ANDS D1Ar3, D1Ar3, #7 |
| 174 | BZ $Lbbyte_loop_exit |
| 175 | ! Adjust A1.2 |
| 176 | ADD A1.2, A1.2, #8 |
| 177 | SUB A1.2, A1.2, D0Ar4 |
| 178 | B $Lbbyte_loop |
| 179 | |
| 180 | $Lbaligned_4: |
| 181 | GETL D0.7, D1.7, [--A1.2] |
| 182 | MOV D1Re0, D0Re0 |
| 183 | MOV D0Re0, D1.7 |
| 184 | SETL [--A0.2], D0Re0, D1Re0 |
| 185 | MOV D0Re0, D0.7 |
| 186 | MOV D1Re0, D1.7 |
| 187 | SUBS D1Ar5, D1Ar5, #1 |
| 188 | BNE $Lbaligned_4 |
| 189 | ANDS D1Ar3, D1Ar3, #7 |
| 190 | BZ $Lbbyte_loop_exit |
| 191 | ! Adjust A1.2 |
| 192 | ADD A1.2, A1.2, #8 |
| 193 | SUB A1.2, A1.2, D0Ar4 |
| 194 | B $Lbbyte_loop |
| 195 | |
| 196 | $Lforwards_copy: |
| 197 | MOV A1.2, D0Ar2 |
| 198 | MOV A0.2, D1Ar1 |
| 199 | CMP D1Ar3, #8 |
| 200 | BLT $Lfbyte_loop |
| 201 | |
| 202 | MOV D0Ar4, D0Ar2 |
| 203 | MOV D1Ar5, D1Ar1 |
| 204 | |
| 205 | ANDS D1Ar5, D1Ar5, #7 |
| 206 | BNE $Lfdest_unaligned |
| 207 | |
| 208 | ANDS D0Ar4, D0Ar4, #7 |
| 209 | BNE $Lfsrc_unaligned |
| 210 | |
| 211 | LSR D1Ar5, D1Ar3, #3 |
| 212 | |
| 213 | $Lfaligned_loop: |
| 214 | GETL D0Re0, D1Re0, [A1.2++] |
| 215 | SUBS D1Ar5, D1Ar5, #1 |
| 216 | SETL [A0.2++], D0Re0, D1Re0 |
| 217 | BNE $Lfaligned_loop |
| 218 | |
| 219 | ANDS D1Ar3, D1Ar3, #7 |
| 220 | BZ $Lfbyte_loop_exit |
| 221 | $Lfbyte_loop: |
| 222 | GETB D1Re0, [A1.2++] |
| 223 | SETB [A0.2++], D1Re0 |
| 224 | SUBS D1Ar3, D1Ar3, #1 |
| 225 | BNE $Lfbyte_loop |
| 226 | $Lfbyte_loop_exit: |
| 227 | MOV D0Re0, D1Ar1 |
| 228 | B $LEND |
| 229 | |
| 230 | $Lfdest_unaligned: |
| 231 | GETB D0Re0, [A1.2++] |
| 232 | ADD D1Ar5, D1Ar5, #1 |
| 233 | SUB D1Ar3, D1Ar3, #1 |
| 234 | SETB [A0.2++], D0Re0 |
| 235 | CMP D1Ar5, #8 |
| 236 | BNE $Lfdest_unaligned |
| 237 | CMP D1Ar3, #8 |
| 238 | BLT $Lfbyte_loop |
| 239 | $Lfsrc_unaligned: |
| 240 | ! adjust A1.2 |
| 241 | LSR D1Ar5, D1Ar3, #3 |
| 242 | |
| 243 | MOV D0Ar4, A1.2 |
| 244 | MOV D0Ar6, A1.2 |
| 245 | ANDMB D0Ar4, D0Ar4, #0xfff8 |
| 246 | MOV A1.2, D0Ar4 |
| 247 | |
| 248 | ! A0.2 dst 64-bit is aligned |
| 249 | SUB D0Ar6, D0Ar6, D0Ar4 |
| 250 | ! keep the information for the later adjustment |
| 251 | MOVS D0Ar4, D0Ar6 |
| 252 | |
| 253 | ! both aligned |
| 254 | BZ $Lfaligned_loop |
| 255 | |
| 256 | ! prefetch |
| 257 | GETL D0Re0, D1Re0, [A1.2] |
| 258 | |
| 259 | CMP D0Ar6, #4 |
| 260 | BLT $Lfunaligned_1_2_3 |
| 261 | BZ $Lfaligned_4 |
| 262 | |
| 263 | SUB D0Ar6, D0Ar6, #4 |
| 264 | MULW D0.6, D0Ar6, #8 |
| 265 | MOV D1.6, #32 |
| 266 | SUB D1.6, D1.6, D0.6 |
| 267 | |
| 268 | $Lfunaligned_5_6_7: |
| 269 | GETL D0.7, D1.7, [++A1.2] |
| 270 | ! form 64-bit data in D0Re0, D1Re0 |
| 271 | MOV D0Re0, D1Re0 |
| 272 | LSR D0Re0, D0Re0, D0.6 |
| 273 | MOV D1Re0, D0.7 |
| 274 | LSL D1Re0, D1Re0, D1.6 |
| 275 | MOV D0.5, D1Re0 |
| 276 | ADD D0Re0, D0Re0, D0.5 |
| 277 | |
| 278 | MOV D0.5, D0.7 |
| 279 | LSR D0.5, D0.5, D0.6 |
| 280 | MOV D1Re0, D1.7 |
| 281 | LSL D1Re0, D1Re0, D1.6 |
| 282 | MOV D1.5, D0.5 |
| 283 | ADD D1Re0, D1Re0, D1.5 |
| 284 | |
| 285 | SETL [A0.2++], D0Re0, D1Re0 |
| 286 | MOV D0Re0, D0.7 |
| 287 | MOV D1Re0, D1.7 |
| 288 | SUBS D1Ar5, D1Ar5, #1 |
| 289 | BNE $Lfunaligned_5_6_7 |
| 290 | |
| 291 | ANDS D1Ar3, D1Ar3, #7 |
| 292 | BZ $Lfbyte_loop_exit |
| 293 | ! Adjust A1.2 |
| 294 | ADD A1.2, A1.2, D0Ar4 |
| 295 | B $Lfbyte_loop |
| 296 | |
| 297 | $Lfunaligned_1_2_3: |
| 298 | MULW D0.6, D0Ar6, #8 |
| 299 | MOV D1.6, #32 |
| 300 | SUB D1.6, D1.6, D0.6 |
| 301 | |
| 302 | $Lfunaligned_1_2_3_loop: |
| 303 | GETL D0.7, D1.7, [++A1.2] |
| 304 | ! form 64-bit data in D0Re0, D1Re0 |
| 305 | LSR D0Re0, D0Re0, D0.6 |
| 306 | MOV D1.5, D1Re0 |
| 307 | LSL D1Re0, D1Re0, D1.6 |
| 308 | MOV D0.5, D1Re0 |
| 309 | ADD D0Re0, D0Re0, D0.5 |
| 310 | |
| 311 | MOV D0.5, D1.5 |
| 312 | LSR D0.5, D0.5, D0.6 |
| 313 | MOV D1Re0, D0.7 |
| 314 | LSL D1Re0, D1Re0, D1.6 |
| 315 | MOV D1.5, D0.5 |
| 316 | ADD D1Re0, D1Re0, D1.5 |
| 317 | |
| 318 | SETL [A0.2++], D0Re0, D1Re0 |
| 319 | MOV D0Re0, D0.7 |
| 320 | MOV D1Re0, D1.7 |
| 321 | SUBS D1Ar5, D1Ar5, #1 |
| 322 | BNE $Lfunaligned_1_2_3_loop |
| 323 | |
| 324 | ANDS D1Ar3, D1Ar3, #7 |
| 325 | BZ $Lfbyte_loop_exit |
| 326 | ! Adjust A1.2 |
| 327 | ADD A1.2, A1.2, D0Ar4 |
| 328 | B $Lfbyte_loop |
| 329 | |
| 330 | $Lfaligned_4: |
| 331 | GETL D0.7, D1.7, [++A1.2] |
| 332 | MOV D0Re0, D1Re0 |
| 333 | MOV D1Re0, D0.7 |
| 334 | SETL [A0.2++], D0Re0, D1Re0 |
| 335 | MOV D0Re0, D0.7 |
| 336 | MOV D1Re0, D1.7 |
| 337 | SUBS D1Ar5, D1Ar5, #1 |
| 338 | BNE $Lfaligned_4 |
| 339 | ANDS D1Ar3, D1Ar3, #7 |
| 340 | BZ $Lfbyte_loop_exit |
| 341 | ! Adjust A1.2 |
| 342 | ADD A1.2, A1.2, D0Ar4 |
| 343 | B $Lfbyte_loop |
| 344 | |
| 345 | .size _memmove,.-_memmove |