2009-11-17 23:54:20 -07:00
|
|
|
// Inferno's libkern/memmove-arm.s
|
|
|
|
// http://code.google.com/p/inferno-os/source/browse/libkern/memmove-arm.s
|
|
|
|
//
|
|
|
|
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
|
|
|
// Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
|
|
|
|
// Portions Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
// THE SOFTWARE.
|
|
|
|
|
2014-09-04 21:05:18 -06:00
|
|
|
#include "textflag.h"
|
2013-08-07 13:20:05 -06:00
|
|
|
|
2012-06-24 16:28:30 -06:00
|
|
|
// TE or TS are spilled to the stack during bulk register moves.
|
2015-02-13 15:21:18 -07:00
|
|
|
#define TS R0
|
|
|
|
#define TE R8
|
2012-06-24 16:28:30 -06:00
|
|
|
|
|
|
|
// Warning: the linker will use R11 to synthesize certain instructions. Please
|
|
|
|
// take care and double check with objdump.
|
2015-02-13 15:21:18 -07:00
|
|
|
#define FROM R11
|
|
|
|
#define N R12
|
|
|
|
#define TMP R12 /* N and TMP don't overlap */
|
|
|
|
#define TMP1 R5
|
|
|
|
|
|
|
|
#define RSHIFT R5
|
|
|
|
#define LSHIFT R6
|
|
|
|
#define OFFSET R7
|
|
|
|
|
|
|
|
#define BR0 R0 /* shared with TS */
|
|
|
|
#define BW0 R1
|
|
|
|
#define BR1 R1
|
|
|
|
#define BW1 R2
|
|
|
|
#define BR2 R2
|
|
|
|
#define BW2 R3
|
|
|
|
#define BR3 R3
|
|
|
|
#define BW3 R4
|
|
|
|
|
|
|
|
#define FW0 R1
|
|
|
|
#define FR0 R2
|
|
|
|
#define FW1 R2
|
|
|
|
#define FR1 R3
|
|
|
|
#define FW2 R3
|
|
|
|
#define FR2 R4
|
|
|
|
#define FW3 R4
|
|
|
|
#define FR3 R8 /* shared with TE */
|
2012-06-24 16:28:30 -06:00
|
|
|
|
2013-08-07 13:20:05 -06:00
|
|
|
TEXT runtime·memmove(SB), NOSPLIT, $4-12
|
2009-11-17 23:54:20 -07:00
|
|
|
_memmove:
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW to+0(FP), TS
|
|
|
|
MOVW from+4(FP), FROM
|
|
|
|
MOVW n+8(FP), N
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
ADD N, TS, TE /* to end pointer */
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP FROM, TS
|
2009-11-17 23:54:20 -07:00
|
|
|
BLS _forward
|
|
|
|
|
|
|
|
_back:
|
2015-02-13 15:21:18 -07:00
|
|
|
ADD N, FROM /* from end pointer */
|
|
|
|
CMP $4, N /* need at least 4 bytes to copy */
|
2009-11-17 23:54:20 -07:00
|
|
|
BLT _b1tail
|
|
|
|
|
|
|
|
_b4align: /* align destination on 4 */
|
2015-02-13 15:21:18 -07:00
|
|
|
AND.S $3, TE, TMP
|
2009-11-17 23:54:20 -07:00
|
|
|
BEQ _b4aligned
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVBU.W -1(FROM), TMP /* pre-indexed */
|
|
|
|
MOVBU.W TMP, -1(TE) /* pre-indexed */
|
2009-11-17 23:54:20 -07:00
|
|
|
B _b4align
|
|
|
|
|
|
|
|
_b4aligned: /* is source now aligned? */
|
2015-02-13 15:21:18 -07:00
|
|
|
AND.S $3, FROM, TMP
|
2009-11-17 23:54:20 -07:00
|
|
|
BNE _bunaligned
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
ADD $31, TS, TMP /* do 32-byte chunks if possible */
|
|
|
|
MOVW TS, savedts-4(SP)
|
2009-11-17 23:54:20 -07:00
|
|
|
_b32loop:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP TMP, TE
|
2009-11-17 23:54:20 -07:00
|
|
|
BLS _b4tail
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVM.DB.W (FROM), [R0-R7]
|
|
|
|
MOVM.DB.W [R0-R7], (TE)
|
2009-11-17 23:54:20 -07:00
|
|
|
B _b32loop
|
|
|
|
|
|
|
|
_b4tail: /* do remaining words if possible */
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW savedts-4(SP), TS
|
|
|
|
ADD $3, TS, TMP
|
2009-11-17 23:54:20 -07:00
|
|
|
_b4loop:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP TMP, TE
|
2009-11-17 23:54:20 -07:00
|
|
|
BLS _b1tail
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW.W -4(FROM), TMP1 /* pre-indexed */
|
|
|
|
MOVW.W TMP1, -4(TE) /* pre-indexed */
|
2009-11-17 23:54:20 -07:00
|
|
|
B _b4loop
|
|
|
|
|
|
|
|
_b1tail: /* remaining bytes */
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP TE, TS
|
2009-11-17 23:54:20 -07:00
|
|
|
BEQ _return
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVBU.W -1(FROM), TMP /* pre-indexed */
|
|
|
|
MOVBU.W TMP, -1(TE) /* pre-indexed */
|
2009-11-17 23:54:20 -07:00
|
|
|
B _b1tail
|
|
|
|
|
|
|
|
_forward:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP $4, N /* need at least 4 bytes to copy */
|
2009-11-17 23:54:20 -07:00
|
|
|
BLT _f1tail
|
|
|
|
|
|
|
|
_f4align: /* align destination on 4 */
|
2015-02-13 15:21:18 -07:00
|
|
|
AND.S $3, TS, TMP
|
2009-11-17 23:54:20 -07:00
|
|
|
BEQ _f4aligned
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVBU.P 1(FROM), TMP /* implicit write back */
|
|
|
|
MOVBU.P TMP, 1(TS) /* implicit write back */
|
2009-11-17 23:54:20 -07:00
|
|
|
B _f4align
|
|
|
|
|
|
|
|
_f4aligned: /* is source now aligned? */
|
2015-02-13 15:21:18 -07:00
|
|
|
AND.S $3, FROM, TMP
|
2009-11-17 23:54:20 -07:00
|
|
|
BNE _funaligned
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
SUB $31, TE, TMP /* do 32-byte chunks if possible */
|
|
|
|
MOVW TE, savedte-4(SP)
|
2009-11-17 23:54:20 -07:00
|
|
|
_f32loop:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP TMP, TS
|
2009-11-17 23:54:20 -07:00
|
|
|
BHS _f4tail
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVM.IA.W (FROM), [R1-R8]
|
|
|
|
MOVM.IA.W [R1-R8], (TS)
|
2009-11-17 23:54:20 -07:00
|
|
|
B _f32loop
|
|
|
|
|
|
|
|
_f4tail:
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW savedte-4(SP), TE
|
|
|
|
SUB $3, TE, TMP /* do remaining words if possible */
|
2009-11-17 23:54:20 -07:00
|
|
|
_f4loop:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP TMP, TS
|
2009-11-17 23:54:20 -07:00
|
|
|
BHS _f1tail
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW.P 4(FROM), TMP1 /* implicit write back */
|
|
|
|
MOVW.P TMP1, 4(TS) /* implicit write back */
|
2009-11-17 23:54:20 -07:00
|
|
|
B _f4loop
|
|
|
|
|
|
|
|
_f1tail:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP TS, TE
|
2009-11-17 23:54:20 -07:00
|
|
|
BEQ _return
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVBU.P 1(FROM), TMP /* implicit write back */
|
|
|
|
MOVBU.P TMP, 1(TS) /* implicit write back */
|
2009-11-17 23:54:20 -07:00
|
|
|
B _f1tail
|
|
|
|
|
|
|
|
_return:
|
|
|
|
MOVW to+0(FP), R0
|
|
|
|
RET
|
|
|
|
|
|
|
|
_bunaligned:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP $2, TMP /* is TMP < 2 ? */
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW.LT $8, RSHIFT /* (R(n)<<24)|(R(n-1)>>8) */
|
|
|
|
MOVW.LT $24, LSHIFT
|
|
|
|
MOVW.LT $1, OFFSET
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW.EQ $16, RSHIFT /* (R(n)<<16)|(R(n-1)>>16) */
|
|
|
|
MOVW.EQ $16, LSHIFT
|
|
|
|
MOVW.EQ $2, OFFSET
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW.GT $24, RSHIFT /* (R(n)<<8)|(R(n-1)>>24) */
|
|
|
|
MOVW.GT $8, LSHIFT
|
|
|
|
MOVW.GT $3, OFFSET
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
ADD $16, TS, TMP /* do 16-byte chunks if possible */
|
|
|
|
CMP TMP, TE
|
2009-11-17 23:54:20 -07:00
|
|
|
BLS _b1tail
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
BIC $3, FROM /* align source */
|
|
|
|
MOVW TS, savedts-4(SP)
|
|
|
|
MOVW (FROM), BR0 /* prime first block register */
|
2009-11-17 23:54:20 -07:00
|
|
|
|
|
|
|
_bu16loop:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP TMP, TE
|
2009-11-17 23:54:20 -07:00
|
|
|
BLS _bu1tail
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW BR0<<LSHIFT, BW3
|
|
|
|
MOVM.DB.W (FROM), [BR0-BR3]
|
|
|
|
ORR BR3>>RSHIFT, BW3
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW BR3<<LSHIFT, BW2
|
|
|
|
ORR BR2>>RSHIFT, BW2
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW BR2<<LSHIFT, BW1
|
|
|
|
ORR BR1>>RSHIFT, BW1
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW BR1<<LSHIFT, BW0
|
|
|
|
ORR BR0>>RSHIFT, BW0
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVM.DB.W [BW0-BW3], (TE)
|
2009-11-17 23:54:20 -07:00
|
|
|
B _bu16loop
|
|
|
|
|
|
|
|
_bu1tail:
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW savedts-4(SP), TS
|
|
|
|
ADD OFFSET, FROM
|
2009-11-17 23:54:20 -07:00
|
|
|
B _b1tail
|
|
|
|
|
|
|
|
_funaligned:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP $2, TMP
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW.LT $8, RSHIFT /* (R(n+1)<<24)|(R(n)>>8) */
|
|
|
|
MOVW.LT $24, LSHIFT
|
|
|
|
MOVW.LT $3, OFFSET
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW.EQ $16, RSHIFT /* (R(n+1)<<16)|(R(n)>>16) */
|
|
|
|
MOVW.EQ $16, LSHIFT
|
|
|
|
MOVW.EQ $2, OFFSET
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW.GT $24, RSHIFT /* (R(n+1)<<8)|(R(n)>>24) */
|
|
|
|
MOVW.GT $8, LSHIFT
|
|
|
|
MOVW.GT $1, OFFSET
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
SUB $16, TE, TMP /* do 16-byte chunks if possible */
|
|
|
|
CMP TMP, TS
|
2009-11-17 23:54:20 -07:00
|
|
|
BHS _f1tail
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
BIC $3, FROM /* align source */
|
|
|
|
MOVW TE, savedte-4(SP)
|
|
|
|
MOVW.P 4(FROM), FR3 /* prime last block register, implicit write back */
|
2009-11-17 23:54:20 -07:00
|
|
|
|
|
|
|
_fu16loop:
|
2015-02-13 15:21:18 -07:00
|
|
|
CMP TMP, TS
|
2009-11-17 23:54:20 -07:00
|
|
|
BHS _fu1tail
|
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW FR3>>RSHIFT, FW0
|
|
|
|
MOVM.IA.W (FROM), [FR0,FR1,FR2,FR3]
|
|
|
|
ORR FR0<<LSHIFT, FW0
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW FR0>>RSHIFT, FW1
|
|
|
|
ORR FR1<<LSHIFT, FW1
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW FR1>>RSHIFT, FW2
|
|
|
|
ORR FR2<<LSHIFT, FW2
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW FR2>>RSHIFT, FW3
|
|
|
|
ORR FR3<<LSHIFT, FW3
|
2009-11-17 23:54:20 -07:00
|
|
|
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVM.IA.W [FW0,FW1,FW2,FW3], (TS)
|
2009-11-17 23:54:20 -07:00
|
|
|
B _fu16loop
|
|
|
|
|
|
|
|
_fu1tail:
|
2015-02-13 15:21:18 -07:00
|
|
|
MOVW savedte-4(SP), TE
|
|
|
|
SUB OFFSET, FROM
|
2009-11-17 23:54:20 -07:00
|
|
|
B _f1tail
|