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

```asm
<workload>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  lea    -0x148000(%rsp),%r11
L28:
  sub    $0x1000,%rsp
  orq    $0x0,(%rsp)
  cmp    %r11,%rsp
  jne    L28
  sub    $0x828,%rsp
  mov    %rdi,%r13
  mov    %rsi,%r12
  mov    %rdx,%rsi
  mov    %rcx,%rbp
  mov    %fs:0x28,%rax
  mov    %rax,0x148818(%rsp)
  xor    %eax,%eax
  lea    0x810(%rsp),%rdi
  mov    $0x8000,%edx
  call   <memcpy@plt>
  sub    $0x800,%rbp
  mov    $0x0,%ebx
  lea    0x28810(%rsp),%rax
  mov    %rax,0x8(%rsp)
  jmp    L31
L7:
  lea    0xc8810(%rsp),%rsi
  mov    $0x80,%r9d
  mov    %r12,%r8
  mov    0x8(%rsp),%rcx
  mov    %r13,%rdx
  call   <load@plt>
  lea    0x810(%rsp),%rcx
  lea    0x8810(%rsp),%rdx
  lea    0x48810(%rsp),%rsi
  mov    $0x80,%r9d
  lea    0x10(%rsp),%r8
  mov    %r15d,%edi
  call   <compute@plt>
  lea    0x410(%rsp),%rdx
  mov    $0x80,%ecx
  mov    %rbp,%rsi
  mov    %r14d,%edi
  call   <store@plt>
L5:
  add    $0x1,%ebx
  add    $0x80000,%r13
  add    $0x20000,%r12
  add    $0x400,%rbp
  cmp    $0x22,%ebx
  je     L39
L31:
  cmp    $0x1f,%ebx
  setle  %dil
  movzbl %dil,%edi
  lea    -0x1(%rbx),%eax
  cmp    $0x1f,%eax
  setbe  %r15b
  movzbl %r15b,%r15d
  cmp    $0x1,%ebx
  setg   %r14b
  movzbl %r14b,%r14d
  test   $0x1,%bl
  jne    L7
  lea    0x8810(%rsp),%rcx
  lea    0x48810(%rsp),%rsi
  mov    $0x80,%r9d
  mov    %r12,%r8
  mov    %r13,%rdx
  call   <load@plt>
  lea    0x810(%rsp),%rcx
  lea    0xc8810(%rsp),%rsi
  mov    $0x80,%r9d
  lea    0x410(%rsp),%r8
  mov    0x8(%rsp),%rdx
  mov    %r15d,%edi
  call   <compute@plt>
  lea    0x10(%rsp),%rdx
  mov    $0x80,%ecx
  mov    %rbp,%rsi
  mov    %r14d,%edi
  call   <store@plt>
  jmp    L5
L39:
  mov    0x148818(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L56
  add    $0x148828,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L56:
  call   <__stack_chk_fail@plt>
```

assistant: ```c
void workload(double *nzval, short *cols, double *vec, double *out) {
#pragma HLS INTERFACE m_axi port = nzval offset = slave bundle = gmem1
#pragma HLS INTERFACE m_axi port = cols offset = slave bundle = gmem2
#pragma HLS INTERFACE m_axi port = vec offset = slave bundle = gmem1
#pragma HLS INTERFACE m_axi port = out offset = slave bundle = gmem1
#pragma HLS INTERFACE s_axilite port = nzval bundle = control
#pragma HLS INTERFACE s_axilite port = cols bundle = control
#pragma HLS INTERFACE s_axilite port = vec bundle = control
#pragma HLS INTERFACE s_axilite port = out bundle = control
#pragma HLS INTERFACE s_axilite port = return bundle = control
  int num_tiles = ((1 << 12) + 128 - 1) / 128;
  int tail_rows = (1 << 12) % 128;
  if (tail_rows == 0)
    tail_rows = 128;
  double local_nzval_x[4][((128 + 4 - 1) / 4)][(1 << 9)];
#pragma HLS array_partition variable = local_nzval_x dim = 1 complete
  short local_cols_x[4][((128 + 4 - 1) / 4)][(1 << 9)];
#pragma HLS array_partition variable = local_cols_x dim = 1 complete
  double local_nzval_y[4][((128 + 4 - 1) / 4)][(1 << 9)];
#pragma HLS array_partition variable = local_nzval_y dim = 1 complete
  short local_cols_y[4][((128 + 4 - 1) / 4)][(1 << 9)];
#pragma HLS array_partition variable = local_cols_y dim = 1 complete
  double local_vec[(1 << 12)];
  memcpy(local_vec, vec, sizeof(double) * (1 << 12));
  double local_out_x[4][((128 + 4 - 1) / 4)];
#pragma HLS array_partition variable = local_out_x dim = 1 complete
  double local_out_y[4][((128 + 4 - 1) / 4)];
#pragma HLS array_partition variable = local_out_y dim = 1 complete
  int i, j, k;
  for (i = 0; i < num_tiles + 2; i++) {
    int load_flag = i < num_tiles;
    int compute_flag = i > 0 && i < num_tiles + 1;
    int store_flag = i > 1;
    int load_rows = i == num_tiles - 1 ? tail_rows : 128;
    int compute_rows = i == num_tiles ? tail_rows : 128;
    int store_rows = i == num_tiles + 1 ? tail_rows : 128;
    if (i % 2 == 0) {
      load(load_flag, local_nzval_x, nzval + i * 128 * (1 << 9), local_cols_x, cols + i * 128 * (1 << 9), load_rows);
      compute(compute_flag, local_nzval_y, local_cols_y, local_vec, local_out_y, compute_rows);
      store(store_flag, out + (i - 2) * 128, local_out_x, store_rows);
    } else {
      load(load_flag, local_nzval_y, nzval + i * 128 * (1 << 9), local_cols_y, cols + i * 128 * (1 << 9), load_rows);
      compute(compute_flag, local_nzval_x, local_cols_x, local_vec, local_out_x, compute_rows);
      store(store_flag, out + (i - 2) * 128, local_out_y, store_rows);
    }
  }
  return;
}
```