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

```asm
<bn_add_part_words>:
  endbr64
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  mov    %rdi,%r14
  mov    %rsi,%r12
  mov    %rdx,%r13
  mov    %ecx,%ebx
  mov    %r8d,%ebp
  mov    %ecx,%edi
  not    %edi
  shr    $0x1f,%edi
  call   <assert@plt>
  mov    %ebx,%ecx
  mov    %r13,%rdx
  mov    %r12,%rsi
  mov    %r14,%rdi
  call   <bn_add_words@plt>
  mov    %eax,%edx
  test   %ebp,%ebp
  je     L435
  movslq %ebx,%rax
  shl    $0x2,%rax
  lea    (%r14,%rax,1),%rcx
  test   %ebp,%ebp
  js     L100
  add    %r12,%rax
  test   %edx,%edx
  je     L250
  add    (%rax),%edx
  mov    %edx,%esi
  setb   %dl
  movzbl %dl,%edx
  mov    %esi,(%rcx)
  cmp    $0x1,%ebp
  jle    L435
  mov    %edx,%esi
  add    0x4(%rax),%esi
  setb   %dl
  movzbl %dl,%edx
  mov    %esi,0x4(%rcx)
  cmp    $0x2,%ebp
  jle    L435
  mov    %ebp,%r10d
  and    $0x3,%r10d
  lea    -0x4(%rbp),%r9d
  lea    -0x3(%rbp),%esi
  and    $0xfffffffc,%esi
  mov    %r9d,%ebx
  sub    %esi,%ebx
  lea    -0x2(%rbp),%esi
  and    $0xfffffffc,%esi
  mov    %r9d,%r11d
  sub    %esi,%r11d
  lea    -0x1(%rbp),%esi
  and    $0xfffffffc,%esi
  sub    %esi,%r9d
L342:
  add    0x8(%rax),%edx
  mov    %edx,%esi
  setb   %dl
  movzbl %dl,%edx
  mov    %esi,0x8(%rcx)
  lea    -0x3(%rbp),%esi
  cmp    %r10d,%ebp
  je     L186
  mov    %edx,%edi
  add    0xc(%rax),%edi
  mov    %edi,0xc(%rcx)
  lea    -0x4(%rbp),%esi
  cmp    %r9d,%esi
  je     L421
  add    $0x10,%rax
  add    $0x10,%rcx
  cmp    %edi,%edx
  jbe    L47
  mov    (%rax),%edi
  add    $0x1,%edi
  sete   %dl
  movzbl %dl,%edx
  mov    %edi,(%rcx)
  lea    -0x5(%rbp),%edi
  cmp    %r11d,%esi
  je     L460
  add    0x4(%rax),%edx
  mov    %edx,%edi
  setb   %dl
  movzbl %dl,%edx
  mov    %edi,0x4(%rcx)
  lea    -0x6(%rbp),%r8d
  cmp    %ebx,%esi
  je     L378
  mov    %esi,%ebp
  jmp    L342
L100:
  add    %r13,%rax
  test   %edx,%edx
  je     L232
  add    (%rax),%edx
  mov    %edx,%esi
  setb   %dl
  movzbl %dl,%edx
  mov    %esi,(%rcx)
  cmp    $0xffffffff,%ebp
  jge    L435
  mov    %edx,%esi
  add    0x4(%rax),%esi
  setb   %dl
  movzbl %dl,%edx
  mov    %esi,0x4(%rcx)
  cmp    $0xfffffffe,%ebp
  jge    L435
  mov    %ebp,%r11d
  neg    %r11d
  and    $0xfffffffc,%r11d
  add    %ebp,%r11d
  lea    0x4(%rbp),%esi
  mov    $0xfffffffd,%r10d
  sub    %ebp,%r10d
  and    $0xfffffffc,%r10d
  add    %esi,%r10d
  mov    $0xfffffffe,%r9d
  sub    %ebp,%r9d
  and    $0xfffffffc,%r9d
  add    %esi,%r9d
  mov    %ebp,%ebx
  not    %ebx
  and    $0xfffffffc,%ebx
  add    %esi,%ebx
L211:
  add    0x8(%rax),%edx
  mov    %edx,%esi
  setb   %dl
  movzbl %dl,%edx
  mov    %esi,0x8(%rcx)
  lea    0x3(%rbp),%esi
  cmp    %ebp,%r11d
  je     L91
  mov    %edx,%edi
  add    0xc(%rax),%edi
  mov    %edi,0xc(%rcx)
  lea    0x4(%rbp),%esi
  cmp    %ebx,%esi
  je     L311
  add    $0x10,%rax
  add    $0x10,%rcx
  cmp    %edi,%edx
  jbe    L287
  mov    (%rax),%edi
  add    $0x1,%edi
  sete   %dl
  movzbl %dl,%edx
  mov    %edi,(%rcx)
  lea    0x5(%rbp),%edi
  cmp    %esi,%r9d
  je     L3
  add    0x4(%rax),%edx
  mov    %edx,%edi
  setb   %dl
  movzbl %dl,%edx
  mov    %edi,0x4(%rcx)
  lea    0x6(%rbp),%r8d
  cmp    %esi,%r10d
  je     L350
  mov    %esi,%ebp
  jmp    L211
L311:
  cmp    %edi,%edx
  seta   %dl
  movzbl %dl,%edx
L91:
  test   %esi,%esi
  js     L441
L435:
  mov    %edx,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  ret
L287:
  mov    $0x0,%edx
  jmp    L91
L232:
  mov    %ebp,%esi
L441:
  mov    (%rax),%edi
  mov    %edi,(%rcx)
  cmp    $0xffffffff,%esi
  jge    L435
  mov    0x4(%rax),%edi
  mov    %edi,0x4(%rcx)
  cmp    $0xfffffffe,%esi
  jge    L435
  mov    0x8(%rax),%edi
  mov    %edi,0x8(%rcx)
  cmp    $0xfffffffd,%esi
  jge    L435
  mov    0xc(%rax),%edi
  mov    %edi,0xc(%rcx)
  mov    %esi,%edi
  add    $0x4,%edi
  jns    L435
  mov    $0xfffffffb,%r8d
  sub    %esi,%r8d
  and    $0xfffffffc,%r8d
  lea    0x8(%rsi,%r8,1),%r8d
L131:
  add    $0x10,%rax
  add    $0x10,%rcx
  mov    (%rax),%esi
  mov    %esi,(%rcx)
  cmp    $0xffffffff,%edi
  jge    L435
  mov    0x4(%rax),%esi
  mov    %esi,0x4(%rcx)
  cmp    $0xfffffffe,%edi
  jge    L435
  mov    0x8(%rax),%esi
  mov    %esi,0x8(%rcx)
  cmp    $0xfffffffd,%edi
  jge    L435
  mov    0xc(%rax),%esi
  mov    %esi,0xc(%rcx)
  add    $0x4,%edi
  cmp    %edi,%r8d
  jne    L131
  jmp    L435
L421:
  cmp    %edi,%edx
  seta   %dl
  movzbl %dl,%edx
L186:
  test   %esi,%esi
  jle    L435
L411:
  mov    (%rax),%edi
  mov    %edi,(%rcx)
  cmp    $0x1,%esi
  jle    L435
  mov    0x4(%rax),%edi
  mov    %edi,0x4(%rcx)
  cmp    $0x2,%esi
  jle    L435
  mov    0x8(%rax),%edi
  mov    %edi,0x8(%rcx)
  cmp    $0x3,%esi
  jle    L435
  mov    0xc(%rax),%edi
  mov    %edi,0xc(%rcx)
  lea    -0x4(%rsi),%edi
  test   %edi,%edi
  jle    L435
  lea    -0x8(%rsi),%r8d
  sub    $0x5,%esi
  and    $0xfffffffc,%esi
  sub    %esi,%r8d
L386:
  add    $0x10,%rax
  add    $0x10,%rcx
  mov    (%rax),%esi
  mov    %esi,(%rcx)
  cmp    $0x1,%edi
  jle    L435
  mov    0x4(%rax),%esi
  mov    %esi,0x4(%rcx)
  cmp    $0x2,%edi
  jle    L435
  mov    0x8(%rax),%esi
  mov    %esi,0x8(%rcx)
  cmp    $0x3,%edi
  jle    L435
  mov    0xc(%rax),%esi
  mov    %esi,0xc(%rcx)
  sub    $0x4,%edi
  cmp    %r8d,%edi
  jne    L386
  jmp    L435
L47:
  mov    $0x0,%edx
  jmp    L186
L250:
  mov    %ebp,%esi
  jmp    L411
L3:
  mov    %edi,%esi
  jmp    L91
L350:
  mov    %r8d,%esi
  jmp    L91
L460:
  mov    %edi,%esi
  jmp    L186
L378:
  mov    %r8d,%esi
  jmp    L186
```

assistant: ```c
unsigned int bn_add_part_words(unsigned int *r, const unsigned int *a, const unsigned int *b, int cl, int dl) {
  unsigned int c, l, t;
  assert(cl >= 0);
  c = bn_add_words(r, a, b, cl);
  if (dl == 0)
    return c;
  r += cl;
  a += cl;
  b += cl;
  if (dl < 0) {
    int save_dl = dl;
    while (c) {
      l = (c + b[0]) & (0xffffffffL);
      c = (l < c);
      r[0] = l;
      if (++dl >= 0)
        break;
      l = (c + b[1]) & (0xffffffffL);
      c = (l < c);
      r[1] = l;
      if (++dl >= 0)
        break;
      l = (c + b[2]) & (0xffffffffL);
      c = (l < c);
      r[2] = l;
      if (++dl >= 0)
        break;
      l = (c + b[3]) & (0xffffffffL);
      c = (l < c);
      r[3] = l;
      if (++dl >= 0)
        break;
      save_dl = dl;
      b += 4;
      r += 4;
    }
    if (dl < 0) {
      if (save_dl < dl) {
        switch (dl - save_dl) {
        case 1:
          r[1] = b[1];
          if (++dl >= 0)
            break;
        case 2:
          r[2] = b[2];
          if (++dl >= 0)
            break;
        case 3:
          r[3] = b[3];
          if (++dl >= 0)
            break;
        }
        b += 4;
        r += 4;
      }
    }
    if (dl < 0) {
      for (;;) {
        r[0] = b[0];
        if (++dl >= 0)
          break;
        r[1] = b[1];
        if (++dl >= 0)
          break;
        r[2] = b[2];
        if (++dl >= 0)
          break;
        r[3] = b[3];
        if (++dl >= 0)
          break;
        b += 4;
        r += 4;
      }
    }
  } else {
    int save_dl = dl;
    while (c) {
      t = (a[0] + c) & (0xffffffffL);
      c = (t < c);
      r[0] = t;
      if (--dl <= 0)
        break;
      t = (a[1] + c) & (0xffffffffL);
      c = (t < c);
      r[1] = t;
      if (--dl <= 0)
        break;
      t = (a[2] + c) & (0xffffffffL);
      c = (t < c);
      r[2] = t;
      if (--dl <= 0)
        break;
      t = (a[3] + c) & (0xffffffffL);
      c = (t < c);
      r[3] = t;
      if (--dl <= 0)
        break;
      save_dl = dl;
      a += 4;
      r += 4;
    }
    if (dl > 0)
      if (save_dl > dl) {
        switch (save_dl - dl) {
        case 1:
          r[1] = a[1];
          if (--dl <= 0)
            break;
        case 2:
          r[2] = a[2];
          if (--dl <= 0)
            break;
        case 3:
          r[3] = a[3];
          if (--dl <= 0)
            break;
        }
        a += 4;
        r += 4;
      }
    if (dl > 0) {
      for (;;) {
        r[0] = a[0];
        if (--dl <= 0)
          break;
        r[1] = a[1];
        if (--dl <= 0)
          break;
        r[2] = a[2];
        if (--dl <= 0)
          break;
        r[3] = a[3];
        if (--dl <= 0)
          break;
        a += 4;
        r += 4;
      }
    }
  }
  return c;
}
```