user: Please show me the C implementation that matches the assembly code listed below:

```asm
<png_predict>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  push   %rbx
  sub    $0x68,%rsp
  mov    %rdi,-0x58(%rbp)
  mov    %esi,-0x5c(%rbp)
  mov    %edx,-0x60(%rbp)
  mov    %ecx,-0x64(%rbp)
  mov    %r8d,-0x68(%rbp)
  mov    -0x5c(%rbp),%eax
  imul   -0x64(%rbp),%eax
  imul   -0x68(%rbp),%eax
  add    $0x7,%eax
  shr    $0x3,%eax
  mov    %eax,-0x40(%rbp)
  mov    -0x64(%rbp),%eax
  imul   -0x68(%rbp),%eax
  add    $0x7,%eax
  shr    $0x3,%eax
  mov    %eax,-0x3c(%rbp)
  movl   $0x0,-0x44(%rbp)
  jmp    L52
L240:
  mov    -0x40(%rbp),%eax
  add    $0x1,%eax
  imul   -0x44(%rbp),%eax
  mov    %eax,%edx
  mov    -0x58(%rbp),%rax
  add    %rdx,%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x40(%rbp),%eax
  imul   -0x44(%rbp),%eax
  mov    %eax,%edx
  mov    -0x58(%rbp),%rax
  add    %rdx,%rax
  mov    %rax,-0x30(%rbp)
  mov    -0x30(%rbp),%rax
  mov    %rax,-0x28(%rbp)
  mov    -0x40(%rbp),%eax
  neg    %rax
  mov    %rax,%rdx
  mov    -0x30(%rbp),%rax
  add    %rdx,%rax
  mov    %rax,-0x20(%rbp)
  mov    -0x40(%rbp),%eax
  neg    %rax
  mov    %rax,%rdx
  mov    -0x30(%rbp),%rax
  add    %rdx,%rax
  mov    %rax,-0x18(%rbp)
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%eax
  movzbl %al,%eax
  cmp    $0x4,%eax
  je     L362
  cmp    $0x4,%eax
  jg     L5
  cmp    $0x3,%eax
  je     L367
  cmp    $0x3,%eax
  jg     L5
  cmp    $0x1,%eax
  je     L121
  cmp    $0x2,%eax
  je     L141
L5:
  movl   $0x0,-0x48(%rbp)
  jmp    L100
L393:
  mov    -0x38(%rbp),%rdx
  lea    0x1(%rdx),%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rcx
  mov    %rcx,-0x30(%rbp)
  movzbl (%rdx),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L100:
  mov    -0x48(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jb     L393
  jmp    L48
L121:
  movl   $0x0,-0x48(%rbp)
  jmp    L203
L435:
  mov    -0x38(%rbp),%rdx
  lea    0x1(%rdx),%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rcx
  mov    %rcx,-0x30(%rbp)
  movzbl (%rdx),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L203:
  mov    -0x48(%rbp),%eax
  cmp    -0x3c(%rbp),%eax
  jb     L435
  mov    -0x3c(%rbp),%eax
  mov    %eax,-0x48(%rbp)
  jmp    L404
L327:
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%esi
  mov    -0x28(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x28(%rbp)
  movzbl (%rax),%ecx
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  lea    (%rsi,%rcx,1),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L404:
  mov    -0x48(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jb     L327
  jmp    L48
L141:
  cmpl   $0x0,-0x44(%rbp)
  jne    L287
  movl   $0x0,-0x48(%rbp)
  jmp    L165
L4:
  mov    -0x38(%rbp),%rdx
  lea    0x1(%rdx),%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rcx
  mov    %rcx,-0x30(%rbp)
  movzbl (%rdx),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L165:
  mov    -0x48(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jb     L4
  jmp    L48
L287:
  movl   $0x0,-0x48(%rbp)
  jmp    L104
L353:
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%esi
  mov    -0x20(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x20(%rbp)
  movzbl (%rax),%ecx
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  lea    (%rsi,%rcx,1),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L104:
  mov    -0x48(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jb     L353
  jmp    L48
L367:
  cmpl   $0x0,-0x44(%rbp)
  jne    L47
  movl   $0x0,-0x48(%rbp)
  jmp    L298
L415:
  mov    -0x38(%rbp),%rdx
  lea    0x1(%rdx),%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rcx
  mov    %rcx,-0x30(%rbp)
  movzbl (%rdx),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L298:
  mov    -0x48(%rbp),%eax
  cmp    -0x3c(%rbp),%eax
  jb     L415
  mov    -0x3c(%rbp),%eax
  mov    %eax,-0x48(%rbp)
  jmp    L274
L146:
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%ecx
  mov    -0x28(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x28(%rbp)
  movzbl (%rax),%eax
  shr    %al
  mov    %eax,%esi
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  lea    (%rcx,%rsi,1),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L274:
  mov    -0x48(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jb     L146
  jmp    L48
L47:
  movl   $0x0,-0x48(%rbp)
  jmp    L207
L338:
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%ecx
  mov    -0x20(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x20(%rbp)
  movzbl (%rax),%eax
  shr    %al
  mov    %eax,%esi
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  lea    (%rcx,%rsi,1),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L207:
  mov    -0x48(%rbp),%eax
  cmp    -0x3c(%rbp),%eax
  jb     L338
  mov    -0x3c(%rbp),%eax
  mov    %eax,-0x48(%rbp)
  jmp    L140
L169:
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%ecx
  mov    -0x20(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x20(%rbp)
  movzbl (%rax),%eax
  movzbl %al,%esi
  mov    -0x28(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x28(%rbp)
  movzbl (%rax),%eax
  movzbl %al,%eax
  add    %esi,%eax
  sar    %eax
  mov    %eax,%esi
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  lea    (%rcx,%rsi,1),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L140:
  mov    -0x48(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jb     L169
  jmp    L48
L362:
  cmpl   $0x0,-0x44(%rbp)
  jne    L355
  movl   $0x0,-0x48(%rbp)
  jmp    L95
L51:
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%ebx
  mov    $0x0,%edx
  mov    $0x0,%esi
  mov    $0x0,%edi
  mov    $0x0,%eax
  call   <paeth@plt>
  mov    %eax,%ecx
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  lea    (%rbx,%rcx,1),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L95:
  mov    -0x48(%rbp),%eax
  cmp    -0x3c(%rbp),%eax
  jb     L51
  mov    -0x3c(%rbp),%eax
  mov    %eax,-0x48(%rbp)
  jmp    L57
L125:
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%ebx
  mov    -0x28(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x28(%rbp)
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    $0x0,%edx
  mov    $0x0,%esi
  mov    %eax,%edi
  mov    $0x0,%eax
  call   <paeth@plt>
  mov    %eax,%ecx
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  lea    (%rbx,%rcx,1),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L57:
  mov    -0x48(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jb     L125
  jmp    L78
L355:
  movl   $0x0,-0x48(%rbp)
  jmp    L89
L174:
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%ebx
  mov    -0x20(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x20(%rbp)
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    $0x0,%edx
  mov    %eax,%esi
  mov    $0x0,%edi
  mov    $0x0,%eax
  call   <paeth@plt>
  mov    %eax,%ecx
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  lea    (%rbx,%rcx,1),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L89:
  mov    -0x48(%rbp),%eax
  cmp    -0x3c(%rbp),%eax
  jb     L174
  mov    -0x3c(%rbp),%eax
  mov    %eax,-0x48(%rbp)
  jmp    L35
L323:
  mov    -0x38(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x38(%rbp)
  movzbl (%rax),%ebx
  mov    -0x18(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x18(%rbp)
  movzbl (%rax),%eax
  movzbl %al,%edx
  mov    -0x20(%rbp),%rax
  lea    0x1(%rax),%rcx
  mov    %rcx,-0x20(%rbp)
  movzbl (%rax),%eax
  movzbl %al,%ecx
  mov    -0x28(%rbp),%rax
  lea    0x1(%rax),%rsi
  mov    %rsi,-0x28(%rbp)
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %ecx,%esi
  mov    %eax,%edi
  mov    $0x0,%eax
  call   <paeth@plt>
  mov    %eax,%ecx
  mov    -0x30(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  lea    (%rbx,%rcx,1),%edx
  mov    %dl,(%rax)
  addl   $0x1,-0x48(%rbp)
L35:
  mov    -0x48(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jb     L323
L78:
  nop
L48:
  addl   $0x1,-0x44(%rbp)
L52:
  mov    -0x44(%rbp),%eax
  cmp    -0x60(%rbp),%eax
  jb     L240
  nop
  nop
  mov    -0x8(%rbp),%rbx
  leave
  ret
```

assistant: ```c
void png_predict(unsigned char *samples, unsigned int width, unsigned int height, unsigned int n, unsigned int depth) {
  unsigned int stride = (width * n * depth + 7) / 8;
  unsigned int bpp = (n * depth + 7) / 8;
  unsigned int i, row;
  for (row = 0; row < height; row++) {
    unsigned char *src = samples + (unsigned int)((stride + 1) * row);
    unsigned char *dst = samples + (unsigned int)(stride * row);
    unsigned char *a = dst;
    unsigned char *b = dst - stride;
    unsigned char *c = dst - stride;
    switch (*src++) {
    default:
    case 0:
      for (i = 0; i < stride; i++)
        *dst++ = *src++;
      break;
    case 1:
      for (i = 0; i < bpp; i++)
        *dst++ = *src++;
      for (i = bpp; i < stride; i++)
        *dst++ = *src++ + *a++;
      break;
    case 2:
      if (row == 0)
        for (i = 0; i < stride; i++)
          *dst++ = *src++;
      else
        for (i = 0; i < stride; i++)
          *dst++ = *src++ + *b++;
      break;
    case 3:
      if (row == 0) {
        for (i = 0; i < bpp; i++)
          *dst++ = *src++;
        for (i = bpp; i < stride; i++)
          *dst++ = *src++ + (*a++ >> 1);
      } else {
        for (i = 0; i < bpp; i++)
          *dst++ = *src++ + (*b++ >> 1);
        for (i = bpp; i < stride; i++)
          *dst++ = *src++ + ((*b++ + *a++) >> 1);
      }
      break;
    case 4:
      if (row == 0) {
        for (i = 0; i < bpp; i++)
          *dst++ = *src++ + paeth(0, 0, 0);
        for (i = bpp; i < stride; i++)
          *dst++ = *src++ + paeth(*a++, 0, 0);
      } else {
        for (i = 0; i < bpp; i++)
          *dst++ = *src++ + paeth(0, *b++, 0);
        for (i = bpp; i < stride; i++)
          *dst++ = *src++ + paeth(*a++, *b++, *c++);
      }
      break;
    }
  }
}
```