user: 下面的汇编指令对应的C源代码是什么:

```asm
<memcpy>:
  endbr64
  mov    %rdi,%r8
  test   $0x3,%sil
  je     L138
  test   %rdx,%rdx
  jne    L81
  jmp    L70
  nopw   0x0(%rax,%rax,1)
L86:
  test   %rdx,%rdx
  je     L70
L81:
  movsb  %ds:(%rsi),%es:(%rdi)
  sub    $0x1,%rdx
  test   $0x3,%sil
  jne    L86
L138:
  mov    %rdi,%rax
  and    $0x3,%eax
  je     L281
  push   %r12
  push   %rbp
  push   %rbx
  cmp    $0x1f,%rdx
  jbe    L225
  movzbl (%rsi),%r9d
  mov    (%rsi),%ecx
  cmp    $0x2,%rax
  je     L267
  cmp    $0x3,%rax
  je     L137
  movzbl 0x2(%rsi),%eax
  lea    0x3(%rsi),%r10
  lea    -0x14(%rdx),%rbx
  movzwl (%rsi),%esi
  lea    0x3(%rdi),%r11
  mov    %r10,%r9
  mov    %al,0x2(%rdi)
  mov    %rbx,%rax
  and    $0xfffffffffffffff0,%rbx
  mov    %si,(%rdi)
  shr    $0x4,%rax
  lea    0x13(%rdi,%rbx,1),%rbp
  mov    %r11,%rsi
  nopw   0x0(%rax,%rax,1)
L178:
  mov    0x1(%r9),%edi
  sar    $0x18,%ecx
  add    $0x10,%rsi
  add    $0x10,%r9
  mov    %edi,%r12d
  sar    $0x18,%edi
  shl    $0x8,%r12d
  or     %r12d,%ecx
  mov    %ecx,-0x10(%rsi)
  mov    -0xb(%r9),%ecx
  mov    %ecx,%r12d
  sar    $0x18,%ecx
  shl    $0x8,%r12d
  or     %r12d,%edi
  mov    %edi,-0xc(%rsi)
  mov    -0x7(%r9),%edi
  mov    %edi,%r12d
  sar    $0x18,%edi
  shl    $0x8,%r12d
  or     %r12d,%ecx
  mov    %ecx,-0x8(%rsi)
  mov    -0x3(%r9),%ecx
  mov    %ecx,%r12d
  shl    $0x8,%r12d
  or     %r12d,%edi
  mov    %edi,-0x4(%rsi)
  cmp    %rsi,%rbp
  jne    L178
  sub    $0x13,%rdx
L21:
  add    $0x1,%rax
  sub    %rbx,%rdx
  shl    $0x4,%rax
  lea    (%r11,%rax,1),%rdi
  lea    (%r10,%rax,1),%rsi
L225:
  mov    %rdx,%rcx
  mov    %rdx,%r11
  mov    %rdx,%r10
  mov    %rdx,%r9
  and    $0x8,%ecx
  and    $0x4,%r11d
  and    $0x2,%r10d
  and    $0x1,%r9d
  and    $0x10,%edx
  je     L283
  mov    (%rsi),%rbx
  lea    0x10(%rsi),%rdx
  mov    0x8(%rsi),%rsi
  lea    0x10(%rdi),%rax
  mov    %rbx,(%rdi)
  mov    %rsi,0x8(%rdi)
L115:
  test   %rcx,%rcx
  je     L20
  lea    0x8(%rdx),%rsi
  mov    (%rdx),%rdx
  lea    0x8(%rax),%rcx
  mov    %rdx,(%rax)
L78:
  test   %r11,%r11
  je     L162
  lea    0x4(%rsi),%rdx
  mov    (%rsi),%esi
  lea    0x4(%rcx),%rax
  mov    %esi,(%rcx)
L7:
  test   %r10,%r10
  je     L112
  lea    0x2(%rdx),%rsi
  movzwl (%rdx),%edx
  lea    0x2(%rax),%rcx
  mov    %dx,(%rax)
L105:
  test   %r9,%r9
  je     L296
  movzbl (%rsi),%eax
  mov    %al,(%rcx)
L296:
  pop    %rbx
  mov    %r8,%rax
  pop    %rbp
  pop    %r12
  ret
  nopl   0x0(%rax,%rax,1)
L281:
  cmp    $0xf,%rdx
  jbe    L91
  lea    -0x10(%rdx),%rax
  and    $0xfffffffffffffff0,%rax
  lea    0x10(%rax),%r10
  mov    %rsi,%rax
  lea    (%rdi,%r10,1),%r9
  nopl   (%rax)
L47:
  mov    (%rax),%ecx
  add    $0x10,%rdi
  add    $0x10,%rax
  mov    %ecx,-0x10(%rdi)
  mov    -0xc(%rax),%ecx
  mov    %ecx,-0xc(%rdi)
  mov    -0x8(%rax),%ecx
  mov    %ecx,-0x8(%rdi)
  mov    -0x4(%rax),%ecx
  mov    %ecx,-0x4(%rdi)
  cmp    %r9,%rdi
  jne    L47
  and    $0xf,%edx
  add    %r10,%rsi
L198:
  mov    %rdx,%rdi
  mov    %rdx,%rax
  mov    %rdx,%rcx
  and    $0x4,%edi
  and    $0x2,%eax
  and    $0x1,%ecx
  and    $0x8,%edx
  je     L55
  mov    (%rsi),%rdx
  add    $0x8,%r9
  add    $0x8,%rsi
  mov    %rdx,-0x8(%r9)
L55:
  test   %rdi,%rdi
  je     L46
  mov    (%rsi),%edx
  add    $0x4,%r9
  add    $0x4,%rsi
  mov    %edx,-0x4(%r9)
L46:
  test   %rax,%rax
  je     L134
  lea    0x2(%rsi),%rdx
  movzwl (%rsi),%esi
  lea    0x2(%r9),%rax
  mov    %si,(%r9)
L16:
  test   %rcx,%rcx
  je     L70
  movzbl (%rdx),%edx
  mov    %dl,(%rax)
L70:
  mov    %r8,%rax
  ret
  nopl   0x0(%rax)
L137:
  lea    -0x14(%rdx),%r10
  lea    0x1(%rsi),%r11
  mov    %r9b,(%rdi)
  mov    %r10,%rax
  lea    0x1(%rdi),%rbx
  and    $0xfffffffffffffff0,%r10
  mov    %r11,%r9
  shr    $0x4,%rax
  lea    0x11(%rdi,%r10,1),%rbp
  mov    %rbx,%rsi
  nopl   (%rax)
L257:
  mov    0x3(%r9),%edi
  sar    $0x8,%ecx
  add    $0x10,%rsi
  add    $0x10,%r9
  mov    %edi,%r12d
  sar    $0x8,%edi
  shl    $0x18,%r12d
  or     %r12d,%ecx
  mov    %ecx,-0x10(%rsi)
  mov    -0x9(%r9),%ecx
  mov    %ecx,%r12d
  sar    $0x8,%ecx
  shl    $0x18,%r12d
  or     %r12d,%edi
  mov    %edi,-0xc(%rsi)
  mov    -0x5(%r9),%edi
  mov    %edi,%r12d
  sar    $0x8,%edi
  shl    $0x18,%r12d
  or     %r12d,%ecx
  mov    %ecx,-0x8(%rsi)
  mov    -0x1(%r9),%ecx
  mov    %ecx,%r12d
  shl    $0x18,%r12d
  or     %r12d,%edi
  mov    %edi,-0x4(%rsi)
  cmp    %rbp,%rsi
  jne    L257
  add    $0x1,%rax
  sub    $0x11,%rdx
  shl    $0x4,%rax
  sub    %r10,%rdx
  lea    (%rbx,%rax,1),%rdi
  lea    (%r11,%rax,1),%rsi
  jmp    L225
  nopl   0x0(%rax)
L267:
  movzwl (%rsi),%eax
  lea    -0x14(%rdx),%rbx
  lea    0x2(%rsi),%r10
  lea    0x2(%rdi),%r11
  mov    %r10,%r9
  mov    %ax,(%rdi)
  mov    %rbx,%rax
  and    $0xfffffffffffffff0,%rbx
  mov    %r11,%rsi
  shr    $0x4,%rax
  lea    0x12(%rdi,%rbx,1),%rbp
  nopl   0x0(%rax,%rax,1)
L0:
  mov    0x2(%r9),%edi
  sar    $0x10,%ecx
  add    $0x10,%rsi
  add    $0x10,%r9
  mov    %edi,%r12d
  sar    $0x10,%edi
  shl    $0x10,%r12d
  or     %r12d,%ecx
  mov    %ecx,-0x10(%rsi)
  mov    -0xa(%r9),%ecx
  mov    %ecx,%r12d
  sar    $0x10,%ecx
  shl    $0x10,%r12d
  or     %r12d,%edi
  mov    %edi,-0xc(%rsi)
  mov    -0x6(%r9),%edi
  mov    %edi,%r12d
  sar    $0x10,%edi
  shl    $0x10,%r12d
  or     %r12d,%ecx
  mov    %ecx,-0x8(%rsi)
  mov    -0x2(%r9),%ecx
  mov    %ecx,%r12d
  shl    $0x10,%r12d
  or     %r12d,%edi
  mov    %edi,-0x4(%rsi)
  cmp    %rsi,%rbp
  jne    L0
  sub    $0x12,%rdx
  jmp    L21
L112:
  mov    %rdx,%rsi
  mov    %rax,%rcx
  jmp    L105
L20:
  mov    %rdx,%rsi
  mov    %rax,%rcx
  jmp    L78
L91:
  mov    %rdi,%r9
  jmp    L198
L283:
  mov    %rsi,%rdx
  mov    %rdi,%rax
  jmp    L115
L162:
  mov    %rsi,%rdx
  mov    %rcx,%rax
  jmp    L7
L134:
  mov    %rsi,%rdx
  mov    %r9,%rax
  jmp    L16
```

assistant: ```c
void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
  unsigned char *d = dest;
  const unsigned char *s = src;
  typedef uint32_t __attribute__((__may_alias__)) u32;
  uint32_t w, x;
  for (; (uintptr_t)s % 4 && n; n--)
    *d++ = *s++;
  if ((uintptr_t)d % 4 == 0) {
    for (; n >= 16; s += 16, d += 16, n -= 16) {
      *(u32 *)(d + 0) = *(u32 *)(s + 0);
      *(u32 *)(d + 4) = *(u32 *)(s + 4);
      *(u32 *)(d + 8) = *(u32 *)(s + 8);
      *(u32 *)(d + 12) = *(u32 *)(s + 12);
    }
    if (n & 8) {
      *(u32 *)(d + 0) = *(u32 *)(s + 0);
      *(u32 *)(d + 4) = *(u32 *)(s + 4);
      d += 8;
      s += 8;
    }
    if (n & 4) {
      *(u32 *)(d + 0) = *(u32 *)(s + 0);
      d += 4;
      s += 4;
    }
    if (n & 2) {
      *d++ = *s++;
      *d++ = *s++;
    }
    if (n & 1) {
      *d = *s;
    }
    return dest;
  }
  if (n >= 32)
    switch ((uintptr_t)d % 4) {
    case 1:
      w = *(u32 *)s;
      *d++ = *s++;
      *d++ = *s++;
      *d++ = *s++;
      n -= 3;
      for (; n >= 17; s += 16, d += 16, n -= 16) {
        x = *(u32 *)(s + 1);
        *(u32 *)(d + 0) = (w >> 24) | (x << 8);
        w = *(u32 *)(s + 5);
        *(u32 *)(d + 4) = (x >> 24) | (w << 8);
        x = *(u32 *)(s + 9);
        *(u32 *)(d + 8) = (w >> 24) | (x << 8);
        w = *(u32 *)(s + 13);
        *(u32 *)(d + 12) = (x >> 24) | (w << 8);
      }
      break;
    case 2:
      w = *(u32 *)s;
      *d++ = *s++;
      *d++ = *s++;
      n -= 2;
      for (; n >= 18; s += 16, d += 16, n -= 16) {
        x = *(u32 *)(s + 2);
        *(u32 *)(d + 0) = (w >> 16) | (x << 16);
        w = *(u32 *)(s + 6);
        *(u32 *)(d + 4) = (x >> 16) | (w << 16);
        x = *(u32 *)(s + 10);
        *(u32 *)(d + 8) = (w >> 16) | (x << 16);
        w = *(u32 *)(s + 14);
        *(u32 *)(d + 12) = (x >> 16) | (w << 16);
      }
      break;
    case 3:
      w = *(u32 *)s;
      *d++ = *s++;
      n -= 1;
      for (; n >= 19; s += 16, d += 16, n -= 16) {
        x = *(u32 *)(s + 3);
        *(u32 *)(d + 0) = (w >> 8) | (x << 24);
        w = *(u32 *)(s + 7);
        *(u32 *)(d + 4) = (x >> 8) | (w << 24);
        x = *(u32 *)(s + 11);
        *(u32 *)(d + 8) = (w >> 8) | (x << 24);
        w = *(u32 *)(s + 15);
        *(u32 *)(d + 12) = (x >> 8) | (w << 24);
      }
      break;
    }
  if (n & 16) {
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
  }
  if (n & 8) {
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
  }
  if (n & 4) {
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
    *d++ = *s++;
  }
  if (n & 2) {
    *d++ = *s++;
    *d++ = *s++;
  }
  if (n & 1) {
    *d = *s;
  }
  return dest;
}
```