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

```asm
<spi_read>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  mov    %rdi,-0x38(%rbp)
  mov    %rsi,-0x40(%rbp)
  mov    %rdx,-0x48(%rbp)
  mov    -0x48(%rbp),%rax
  mov    %rax,-0x20(%rbp)
  mov    $0xd4035010,%eax
  mov    %rax,-0x18(%rbp)
  mov    $0xd4035008,%eax
  mov    %rax,-0x10(%rbp)
  mov    $0xd4035000,%eax
  movq   $0x10000f,(%rax)
  mov    $0xd4035000,%eax
  movq   $0x10008f,(%rax)
  jmp    L19
L34:
  mov    -0x38(%rbp),%rax
  or     $0x3000000,%rax
  mov    %rax,%rdx
  mov    -0x18(%rbp),%rax
  mov    %rdx,(%rax)
  cmpq   $0x3b,-0x40(%rbp)
  jg     L47
  mov    -0x40(%rbp),%rax
  lea    0x3(%rax),%rdx
  test   %rax,%rax
  cmovs  %rdx,%rax
  sar    $0x2,%rax
  jmp    L37
L47:
  mov    $0xf,%eax
L37:
  mov    %eax,-0x24(%rbp)
  mov    -0x24(%rbp),%eax
  mov    %eax,-0x28(%rbp)
  jmp    L78
L12:
  mov    -0x18(%rbp),%rax
  movq   $0x0,(%rax)
  subl   $0x1,-0x28(%rbp)
L78:
  cmpl   $0x0,-0x28(%rbp)
  jne    L12
  nop
L23:
  mov    -0x10(%rbp),%rax
  mov    (%rax),%rax
  and    $0x8,%eax
  test   %rax,%rax
  je     L23
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  mov    %rax,-0x8(%rbp)
  mov    -0x24(%rbp),%eax
  mov    %eax,-0x28(%rbp)
  jmp    L79
L93:
  nop
L11:
  mov    -0x10(%rbp),%rax
  mov    (%rax),%rax
  and    $0x8,%eax
  test   %rax,%rax
  je     L11
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  mov    %rax,-0x8(%rbp)
  mov    -0x8(%rbp),%rax
  shr    $0x18,%rax
  mov    %rax,%rcx
  mov    -0x20(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x20(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0x8(%rbp),%rax
  shr    $0x10,%rax
  mov    %rax,%rcx
  mov    -0x20(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x20(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0x8(%rbp),%rax
  shr    $0x8,%rax
  mov    %rax,%rcx
  mov    -0x20(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x20(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0x20(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x20(%rbp)
  mov    -0x8(%rbp),%rdx
  mov    %dl,(%rax)
  subl   $0x1,-0x28(%rbp)
L79:
  cmpl   $0x0,-0x28(%rbp)
  jne    L93
  mov    -0x24(%rbp),%eax
  shl    $0x2,%eax
  cltq
  sub    %rax,-0x40(%rbp)
  mov    -0x24(%rbp),%eax
  shl    $0x2,%eax
  cltq
  add    %rax,-0x38(%rbp)
L19:
  cmpq   $0x0,-0x40(%rbp)
  jg     L34
  mov    $0xd4035000,%eax
  movq   $0x7,(%rax)
  mov    $0xd4035000,%eax
  movq   $0x87,(%rax)
  nop
  pop    %rbp
  ret
```

assistant: ```c
void spi_read(long offset, long len, long adr) {
  unsigned char *p = (unsigned char *)adr;
  int cansend, i;
  volatile unsigned long *fifo = (volatile unsigned long *)0xd4035010;
  volatile unsigned long *stat = (volatile unsigned long *)0xd4035008;
  unsigned long regval;
  *(volatile unsigned long *)0xd4035000 = 0x0010000f;
  *(volatile unsigned long *)0xd4035000 = 0x0010008f;
  while (len > 0) {
    *fifo = (0x03 << 24) | offset;
    cansend = (len < (15 * 4)) ? (len / 4) : 15;
    for (i = cansend; i; i--) {
      *fifo = 0;
    }
    while ((*stat & 8) == 0)
      ;
    regval = *fifo;
    for (i = cansend; i; i--) {
      while ((*stat & 8) == 0)
        ;
      regval = *fifo;
      *p++ = (regval >> 24) & 0xff;
      *p++ = (regval >> 16) & 0xff;
      *p++ = (regval >> 8) & 0xff;
      *p++ = regval & 0xff;
    }
    len -= (cansend * 4);
    offset += (cansend * 4);
  }
  *(volatile unsigned long *)0xd4035000 = 0x00000007;
  *(volatile unsigned long *)0xd4035000 = 0x00000087;
}
```