user: 请从给定的汇编指令推导出C源代码:

```asm
<memcpy>:
  endbr64
  mov    %rdi,%r9
  mov    %rsi,%rcx
  test   $0x3,%sil
  je     L205
  test   %rdx,%rdx
  je     L205
  mov    %rdi,%rax
L246:
  add    $0x1,%rcx
  add    $0x1,%rax
  movzbl -0x1(%rcx),%esi
  mov    %sil,-0x1(%rax)
  sub    $0x1,%rdx
  test   $0x3,%cl
  je     L212
  test   %rdx,%rdx
  jne    L246
L212:
  mov    %rax,%rsi
  and    $0x3,%esi
  je     L250
  push   %rbp
  push   %rbx
  cmp    $0x1f,%rdx
  jbe    L130
  cmp    $0x2,%rsi
  je     L188
  cmp    $0x3,%rsi
  je     L54
  cmp    $0x1,%rsi
  je     L5
L130:
  test   $0x10,%dl
  je     L64
  movzbl (%rcx),%esi
  mov    %sil,(%rax)
  movzbl 0x1(%rcx),%esi
  mov    %sil,0x1(%rax)
  movzbl 0x2(%rcx),%esi
  mov    %sil,0x2(%rax)
  movzbl 0x3(%rcx),%esi
  mov    %sil,0x3(%rax)
  movzbl 0x4(%rcx),%esi
  mov    %sil,0x4(%rax)
  movzbl 0x5(%rcx),%esi
  mov    %sil,0x5(%rax)
  movzbl 0x6(%rcx),%esi
  mov    %sil,0x6(%rax)
  movzbl 0x7(%rcx),%esi
  mov    %sil,0x7(%rax)
  movzbl 0x8(%rcx),%esi
  mov    %sil,0x8(%rax)
  movzbl 0x9(%rcx),%esi
  mov    %sil,0x9(%rax)
  movzbl 0xa(%rcx),%esi
  mov    %sil,0xa(%rax)
  movzbl 0xb(%rcx),%esi
  mov    %sil,0xb(%rax)
  movzbl 0xc(%rcx),%esi
  mov    %sil,0xc(%rax)
  movzbl 0xd(%rcx),%esi
  mov    %sil,0xd(%rax)
  movzbl 0xe(%rcx),%esi
  mov    %sil,0xe(%rax)
  movzbl 0xf(%rcx),%esi
  mov    %sil,0xf(%rax)
  lea    0x10(%rcx),%rcx
  lea    0x10(%rax),%rax
L64:
  test   $0x8,%dl
  je     L91
  movzbl (%rcx),%esi
  mov    %sil,(%rax)
  movzbl 0x1(%rcx),%esi
  mov    %sil,0x1(%rax)
  movzbl 0x2(%rcx),%esi
  mov    %sil,0x2(%rax)
  movzbl 0x3(%rcx),%esi
  mov    %sil,0x3(%rax)
  movzbl 0x4(%rcx),%esi
  mov    %sil,0x4(%rax)
  movzbl 0x5(%rcx),%esi
  mov    %sil,0x5(%rax)
  movzbl 0x6(%rcx),%esi
  mov    %sil,0x6(%rax)
  movzbl 0x7(%rcx),%esi
  mov    %sil,0x7(%rax)
  lea    0x8(%rcx),%rcx
  lea    0x8(%rax),%rax
L91:
  test   $0x4,%dl
  je     L270
  movzbl (%rcx),%esi
  mov    %sil,(%rax)
  movzbl 0x1(%rcx),%esi
  mov    %sil,0x1(%rax)
  movzbl 0x2(%rcx),%esi
  mov    %sil,0x2(%rax)
  movzbl 0x3(%rcx),%esi
  mov    %sil,0x3(%rax)
  lea    0x4(%rcx),%rcx
  lea    0x4(%rax),%rax
L270:
  test   $0x2,%dl
  je     L2
  movzbl (%rcx),%esi
  mov    %sil,(%rax)
  movzbl 0x1(%rcx),%esi
  mov    %sil,0x1(%rax)
  lea    0x2(%rcx),%rcx
  lea    0x2(%rax),%rax
L2:
  test   $0x1,%dl
  je     L216
  movzbl (%rcx),%edx
  mov    %dl,(%rax)
L216:
  mov    %r9,%rax
  pop    %rbx
  pop    %rbp
  ret
L205:
  mov    %r9,%rax
  jmp    L212
L250:
  cmp    $0xf,%rdx
  jbe    L16
  lea    -0x10(%rdx),%rsi
  and    $0xfffffffffffffff0,%rsi
  lea    0x10(%rsi),%r10
  lea    (%rax,%r10,1),%r8
  mov    %rcx,%rsi
L143:
  mov    (%rsi),%edi
  mov    %edi,(%rax)
  mov    0x4(%rsi),%edi
  mov    %edi,0x4(%rax)
  mov    0x8(%rsi),%edi
  mov    %edi,0x8(%rax)
  mov    0xc(%rsi),%edi
  mov    %edi,0xc(%rax)
  add    $0x10,%rsi
  add    $0x10,%rax
  cmp    %r8,%rax
  jne    L143
  add    %r10,%rcx
  and    $0xf,%edx
L244:
  test   $0x8,%dl
  je     L1
  mov    (%rcx),%eax
  mov    %eax,(%r8)
  mov    0x4(%rcx),%eax
  mov    %eax,0x4(%r8)
  add    $0x8,%r8
  add    $0x8,%rcx
L1:
  test   $0x4,%dl
  je     L42
  mov    (%rcx),%eax
  mov    %eax,(%r8)
  add    $0x4,%r8
  add    $0x4,%rcx
L42:
  test   $0x2,%dl
  je     L235
  movzbl (%rcx),%eax
  mov    %al,(%r8)
  movzbl 0x1(%rcx),%eax
  mov    %al,0x1(%r8)
  lea    0x2(%rcx),%rcx
  lea    0x2(%r8),%r8
L235:
  test   $0x1,%dl
  je     L102
  movzbl (%rcx),%eax
  mov    %al,(%r8)
L102:
  mov    %r9,%rax
  ret
L16:
  mov    %rax,%r8
  jmp    L244
L5:
  mov    (%rcx),%esi
  movzbl (%rcx),%edi
  mov    %dil,(%rax)
  movzbl 0x1(%rcx),%edi
  mov    %dil,0x1(%rax)
  lea    0x3(%rcx),%r10
  lea    0x3(%rax),%r8
  movzbl 0x2(%rcx),%ecx
  mov    %cl,0x2(%rax)
  lea    -0x14(%rdx),%rcx
  mov    %rcx,%rdi
  shr    $0x4,%rdi
  and    $0xfffffffffffffff0,%rcx
  lea    0x13(%rax,%rcx,1),%rbx
  mov    %r10,%r11
  mov    %r8,%rax
L33:
  mov    0x1(%r11),%ecx
  sar    $0x18,%esi
  mov    %ecx,%ebp
  shl    $0x8,%ebp
  or     %ebp,%esi
  mov    %esi,(%rax)
  mov    0x5(%r11),%esi
  sar    $0x18,%ecx
  mov    %esi,%ebp
  shl    $0x8,%ebp
  or     %ebp,%ecx
  mov    %ecx,0x4(%rax)
  mov    0x9(%r11),%ecx
  sar    $0x18,%esi
  mov    %ecx,%ebp
  shl    $0x8,%ebp
  or     %ebp,%esi
  mov    %esi,0x8(%rax)
  mov    0xd(%r11),%esi
  sar    $0x18,%ecx
  mov    %esi,%ebp
  shl    $0x8,%ebp
  or     %ebp,%ecx
  mov    %ecx,0xc(%rax)
  add    $0x10,%r11
  add    $0x10,%rax
  cmp    %rbx,%rax
  jne    L33
  lea    0x1(%rdi),%rax
  shl    $0x4,%rax
  lea    (%r10,%rax,1),%rcx
  add    %r8,%rax
  neg    %rdi
  shl    $0x4,%rdi
  lea    -0x13(%rdx,%rdi,1),%rdx
  jmp    L130
L188:
  mov    (%rcx),%esi
  movzbl (%rcx),%edi
  mov    %dil,(%rax)
  lea    0x2(%rcx),%r10
  lea    0x2(%rax),%r8
  movzbl 0x1(%rcx),%ecx
  mov    %cl,0x1(%rax)
  lea    -0x14(%rdx),%rcx
  mov    %rcx,%rdi
  shr    $0x4,%rdi
  and    $0xfffffffffffffff0,%rcx
  lea    0x12(%rax,%rcx,1),%rbx
  mov    %r10,%r11
  mov    %r8,%rax
L66:
  mov    0x2(%r11),%ecx
  sar    $0x10,%esi
  mov    %ecx,%ebp
  shl    $0x10,%ebp
  or     %ebp,%esi
  mov    %esi,(%rax)
  mov    0x6(%r11),%esi
  sar    $0x10,%ecx
  mov    %esi,%ebp
  shl    $0x10,%ebp
  or     %ebp,%ecx
  mov    %ecx,0x4(%rax)
  mov    0xa(%r11),%ecx
  sar    $0x10,%esi
  mov    %ecx,%ebp
  shl    $0x10,%ebp
  or     %ebp,%esi
  mov    %esi,0x8(%rax)
  mov    0xe(%r11),%esi
  sar    $0x10,%ecx
  mov    %esi,%ebp
  shl    $0x10,%ebp
  or     %ebp,%ecx
  mov    %ecx,0xc(%rax)
  add    $0x10,%r11
  add    $0x10,%rax
  cmp    %rbx,%rax
  jne    L66
  lea    0x1(%rdi),%rax
  shl    $0x4,%rax
  lea    (%r10,%rax,1),%rcx
  add    %r8,%rax
  neg    %rdi
  shl    $0x4,%rdi
  lea    -0x12(%rdx,%rdi,1),%rdx
  jmp    L130
L54:
  mov    (%rcx),%esi
  lea    0x1(%rcx),%r10
  lea    0x1(%rax),%r8
  movzbl (%rcx),%ecx
  mov    %cl,(%rax)
  lea    -0x14(%rdx),%rcx
  mov    %rcx,%rdi
  shr    $0x4,%rdi
  and    $0xfffffffffffffff0,%rcx
  lea    0x11(%rax,%rcx,1),%rbx
  mov    %r10,%r11
  mov    %r8,%rax
L70:
  mov    0x3(%r11),%ecx
  sar    $0x8,%esi
  mov    %ecx,%ebp
  shl    $0x18,%ebp
  or     %ebp,%esi
  mov    %esi,(%rax)
  mov    0x7(%r11),%esi
  sar    $0x8,%ecx
  mov    %esi,%ebp
  shl    $0x18,%ebp
  or     %ebp,%ecx
  mov    %ecx,0x4(%rax)
  mov    0xb(%r11),%ecx
  sar    $0x8,%esi
  mov    %ecx,%ebp
  shl    $0x18,%ebp
  or     %ebp,%esi
  mov    %esi,0x8(%rax)
  mov    0xf(%r11),%esi
  sar    $0x8,%ecx
  mov    %esi,%ebp
  shl    $0x18,%ebp
  or     %ebp,%ecx
  mov    %ecx,0xc(%rax)
  add    $0x10,%r11
  add    $0x10,%rax
  cmp    %rbx,%rax
  jne    L70
  lea    0x1(%rdi),%rax
  shl    $0x4,%rax
  lea    (%r10,%rax,1),%rcx
  add    %r8,%rax
  neg    %rdi
  shl    $0x4,%rdi
  lea    -0x11(%rdx,%rdi,1),%rdx
  jmp    L130
```

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;
}
```