/* * void bcopy64(uint64_t src, uint64_t dst, uint64_t len) * * Layout on stack: * len 32,36 * dst 24,28 * src 16,20 * retaddr 12 * %ebx 8 * %esi 4 * %edi 0 */ .globl bcopy64 .type bcopy64,@function .size bcopy64,ebcopy64-bcopy64 /* arrive here in 32 bit mode */ bcopy64: pushl %ebx pushl %esi pushl %edi call base base: popl %esi /* relocatable address of "base" */ /* Set up for inter-segment jump to 64 bit code mode */ movl %esi,%edx addl $to64-base,%edx pushl $43 /* $GSEL(GUCODE_SEL, SEL_UPL) */ pushl %edx lretl .code64 .p2align 4 to64: movq %rsi,%r9 addq $to32-base,%r9 movq 16(%rsp),%rsi /* src */ movq 24(%rsp),%rdi /* dst */ movq 32(%rsp),%rdx /* len */ movq %rdx,%rcx movq %rdi,%r8 subq %rsi,%r8 cmpq %rcx,%r8 /* overlapping? */ jb 1f cld /* nope, copy forwards. */ shrq $3,%rcx /* copy by 64 bit words */ rep movsq movq %rdx,%rcx andq $7,%rcx /* any bytes left? */ rep movsb jmp 2f 1: addq %rcx,%rdi /* copy backwards. */ addq %rcx,%rsi std andq $7,%rcx /* any fractional bytes? */ decq %rdi decq %rsi rep movsb movq %rdx,%rcx /* copy remainder by words */ shrq $3,%rcx subq $7,%rsi subq $7,%rdi rep movsq cld 2: /* Jump back to 32 bit code segment */ pushq $27 /* GSEL(GUCODE32_UPL, SEL_UPL) */ pushq %r9 lretq .code32 .p2align 4 to32: popl %edi popl %esi popl %ebx ret ebcopy64: