// File: ke6jjj[P]r-dat/ECC_C1.cc
// Function: ECC_C1::Correct()
ECC_C1::Status
ECC_C1::Correct()
{
  uint8_t result_vector[kTwoT];
  uint8_t dummy_erasures_vector[kTwoT];
  size_t erasures;
  
  bool ok = true;
  bool corrected = false;
  
  //
  // Scan the input to determine how many erasures there are.
  //
  // Since this is the first level of error checking and the two
  // levels of error correction in DAT work best if the first level
  // corrects errors with 100% confidence, we will not use our known
  // erasure locations when it comes to processing this vector.
  //
  // Every erasure position we add reduces the error checking capability
  // of the code and we would rather have assurance that all bytes are
  // either correct or unknown when it comes to the C1 checking because
  // we are going to run the C2 check in erasures-only mode; it will have
  // no error detection at all.
  //
  erasures = 0;
  for (size_t i = 0; i < kN; i++) {
    if (!mDataIsValid[i]) {
      if (erasures >= kTwoT) {
        //
        // Too many erasures encountered. This vector will not be
        // correctable.
        //
        ok = false;
        break;
      }
      erasures++;
    }
  }
  
  if (ok) {
    //
    // The known erasures (if any) are under control.
    // Compute the syndrome of the current vector.
    //
    ok = ComputeSyndrome(result_vector);

    if (!ok) {
      //
      // There's a non-zero syndrome. Attempt to correct the errors.
      //
      ok = HandleSyndrome(result_vector, dummy_erasures_vector, 0);
      if (ok)
        corrected = true;
    } else {
      mCorrectionCount = 0;
    }
  }
  
  if (ok) {
    if (erasures || corrected) {
      //
      // The data entered with some erasures. It has now been fully
      // validated, so mark every byte as good.
      //
      for (size_t j = 0; j < kN; j++)
        //
        // If the code corrects two errors then it is much safer to assume
        // that there are further uncorrected errors. If not, then it
        // is safe to mark the whole vector good.
        //
        mDataIsValid[j] = mCorrectionCount < kTwoT;

      return CORRECTED;
    }
    //
    // Everything came in good. No modifications necessary.
    //
    return NO_ERRORS;
  } else {
    //
    // There are uncorrectable errors. Mark the whole vector as
    // invalid.
    //
    for (size_t j = 0; j < kN; j++)
      mDataIsValid[j] = false;

    return UNCORRECTABLE;
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x48(%rbp)
movb $0x1, -0x21(%rbp)
movb $0x0, -0x22(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x30(%rbp)
cmpq $0x20, -0x30(%rbp)
jae 0x838b
movq -0x48(%rbp), %rax
movq -0x30(%rbp), %rcx
testb $0x1, 0x20(%rax,%rcx)
jne 0x837b
cmpq $0x4, -0x20(%rbp)
jb 0x836f
movb $0x0, -0x21(%rbp)
jmp 0x838b
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x837d
movq -0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
jmp 0x834c
testb $0x1, -0x21(%rbp)
je 0x83dc
movq -0x48(%rbp), %rdi
leaq -0x14(%rbp), %rsi
callq 0x8240
andb $0x1, %al
movb %al, -0x21(%rbp)
testb $0x1, -0x21(%rbp)
jne 0x83cf
movq -0x48(%rbp), %rdi
leaq -0x14(%rbp), %rsi
leaq -0x18(%rbp), %rdx
xorl %eax, %eax
movl %eax, %ecx
callq 0x8470
andb $0x1, %al
movb %al, -0x21(%rbp)
testb $0x1, -0x21(%rbp)
je 0x83cd
movb $0x1, -0x22(%rbp)
jmp 0x83da
movq -0x48(%rbp), %rax
movl $0x0, 0x40(%rax)
jmp 0x83dc
testb $0x1, -0x21(%rbp)
je 0x8434
cmpq $0x0, -0x20(%rbp)
jne 0x83ef
testb $0x1, -0x22(%rbp)
je 0x842b
movq $0x0, -0x38(%rbp)
cmpq $0x20, -0x38(%rbp)
jae 0x8422
movq -0x48(%rbp), %rax
cmpl $0x4, 0x40(%rax)
setb %dl
movq -0x38(%rbp), %rcx
andb $0x1, %dl
movb %dl, 0x20(%rax,%rcx)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x83f7
movl $0x1, -0x4(%rbp)
jmp 0x8465
movl $0x0, -0x4(%rbp)
jmp 0x8465
movq $0x0, -0x40(%rbp)
cmpq $0x20, -0x40(%rbp)
jae 0x845e
movq -0x48(%rbp), %rax
movq -0x40(%rbp), %rcx
movb $0x0, 0x20(%rax,%rcx)
movq -0x40(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x40(%rbp)
jmp 0x843c
movl $0x2, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nop