252 lines
5.7 KiB
ArmAsm
Raw Normal View History

2001-01-01 00:00:00 +01:00
// TITLE("memcpy")
//++
//
// Copyright (c) 1995 IBM Corporation
//
// Module Name:
//
// memcpyp.s
//
// Author:
//
// John Morgan (jpm) 13-Oct-1995
//
// Environment:
//
// User or Kernel mode.
//
// Revision History:
//
.globl memmove
.globl ..memmove
.globl memcpy
.globl ..memcpy
// code table
.pdata
.align 2
.long ..memmove, memmove.e, 0,0,memmove.b
.long ..memcpy, memcpy.e, 0,0,memcpy.b
// function descriptors
.rdata
.align 2
memmove:
.long ..memmove,.toc
memcpy:
.long ..memcpy,.toc
// function code
.text
.align 6
//
// void * memmove(
// void * dest,
// void const * src,
// size_t count )
//
// Routine Description:
//
// Copies count bytes from src to dest. Even when the source and
// destination blocks overlap the source block is correctly copied
// to the destination.
//
// Arguments:
//
// dest (r3) - pointer to the memory destination
//
// src (r4) - pointer to the memory source
//
// count (r5) - number of bytes to move
//
// Return Value:
//
// dest (r3) - original pointer to destination
//
..memmove:
.function ..memmove
memmove.b:
cmpw r3,r4
beqlr- // exit if source and destination same
blt- ..memcpy // use memcpy() if source > destination
addi r0,r5,1
// move from end of blocks (backwards)
add r3,r3,r5 // adjust destination pointer to end of block
add r4,r4,r5 // adjust source pointer to end of block
// make sure destination is aligned.
mtctr r0
b mm.2
mm.1:
// move last byte and try again
addi r5,r5,-1
lbz r0,-1(r4)
addi r4,r4,-1
stb r0,-1(r3)
addi r3,r3,-1
mm.2:
// check alignment and exit if aligned or entire block copied
andi. r0,r3,3
bdnzf- eq,mm.1
// copy block by words
srwi. r0,r5,2 // get number of words
beq- mm.4 // skip word copy if length < 4
mtctr r0
andi. r0,r4,3 // check for aligned source
bne- mm.6
// copy with both source and destination word aligned
mm.3:
lwz r7,-4(r4)
addi r4,r4,-4
stw r7,-4(r3)
addi r3,r3,-4
bdnz+ mm.3
mm.4:
// copy last bytes (if any)
andi. r0,r5,3
mtctr r0
beqlr+ // exit if no remaining bytes
mm.5:
lbz r0,-1(r4)
addi r4,r4,-1
stb r0,-1(r3)
addi r3,r3,-1
bdnz+ mm.5
blr
// word copy with unaligned source
mm.6:
lbz r7,-4(r4)
addi r3,r3,-4
lbz r8,-3(r4)
rlwimi r7,r8,8,16,23 // combine first two bytes
lbz r9,-2(r4)
rlwimi r7,r9,16,8,15 // combine with next byte
lbz r10,-1(r4)
rlwimi r7,r10,24,0,7 // combine with last byte
addi r4,r4,-4
stw r7,0(r3)
bdnz mm.6
b mm.4
memmove.e:
//
// void * memcpy(
// void * dest,
// void const * src,
// size_t count )
//
// Routine Description:
//
// Copies count bytes from src to dest. If the source and destination
// blocks overlap the behavior of memcpy is undefined.
//
// Arguments:
//
// dest (r3) - pointer to the memory destination
//
// src (r4) - pointer to the memory source
//
// count (r5) - number of bytes to move
//
// Return Value:
//
// dest (r3) - original pointer to destination
//
..memcpy:
.function ..memcpy
memcpy.b:
// make sure destination is aligned.
addi r0,r5,1
ori r6,r3,0
mtctr r0
b mc.2
mc.1:
// move last byte and try again
addi r5,r5,-1
lbz r0,0(r4)
addi r4,r4,1
stb r0,0(r6)
addi r6,r6,1
// check alignment and exit if aligned or entire block copied
mc.2:
andi. r0,r6,3
bdnzf- eq,mc.1
// copy block by words
srwi. r0,r5,2 // get number of words
beq- mc.4 // skip word copy if length < 4
mtctr r0
andi. r0,r4,3 // check for aligned source
bne- mc.6
// copy with both source and destination word aligned
mc.3:
lwz r7,0(r4)
addi r4,r4,4
stw r7,0(r6)
addi r6,r6,4
bdnz+ mc.3
mc.4:
// copy last bytes (if any)
andi. r0,r5,3
mtctr r0
beqlr+ // exit if no remaining bytes
mc.5:
lbz r0,0(r4)
addi r4,r4,1
stb r0,0(r6)
addi r6,r6,1
bdnz+ mc.5
blr
// word copy with unaligned source
mc.6:
lbz r7,0(r4)
lbz r8,1(r4)
rlwimi r7,r8,8,16,23 // combine first two bytes
lbz r9,2(r4)
rlwimi r7,r9,16,8,15 // combine with next byte
lbz r10,3(r4)
rlwimi r7,r10,24,0,7 // combine with last byte
addi r4,r4,4
stw r7,0(r6)
addi r6,r6,4
bdnz mc.6
b mc.4
memcpy.e:
.debug$S
.ualong 1
.uashort 18
.uashort 0x9 # S_OBJNAME
.ualong 0
.byte 11, "memcpyp.obj"
.uashort 24
.uashort 0x1 # S_COMPILE
.byte 0x42 # Target processor = PPC 604
.byte 3 # Language = ASM
.byte 0
.byte 0
.byte 17, "PowerPC Assembler"