// File: /workspace/github_c_makefile_star2_O0/canboat[P]canboat/analyzer/print.c
// Function: extractNumber
bool extractNumber(const Field   *field,
                   const uint8_t *data,
                   size_t         dataLen,
                   size_t         startBit,
                   size_t         bits,
                   int64_t       *value,
                   int64_t       *maxValue)
{
  const bool  hasSign = field ? field->hasSign : false;
  const char *name    = field ? field->name : "<bits>";

  size_t   firstBit;
  size_t   bitsRemaining = bits;
  size_t   magnitude     = 0;
  size_t   bitsInThisByte;
  uint64_t bitMask;
  uint64_t allOnes;
  uint64_t valueInThisByte;
  uint64_t maxv;

  logDebug("extractNumber <%s> startBit=%zu bits=%zu\n", name, startBit, bits);

  if (!adjustDataLenStart(&data, &dataLen, &startBit))
  {
    return false;
  }

  firstBit = startBit;
  *value   = 0;
  maxv     = 0;

  while (bitsRemaining > 0 && dataLen > 0)
  {
    bitsInThisByte = min(8 - firstBit, bitsRemaining);
    allOnes        = (uint64_t) ((((uint64_t) 1) << bitsInThisByte) - 1);

    // How are bits ordered in bytes for bit fields? There are two ways, first field at LSB or first
    // field as MSB.
    // Experimentation, using the 129026 PGN, has shown that the most likely candidate is LSB.
    bitMask         = allOnes << firstBit;
    valueInThisByte = (*data & bitMask) >> firstBit;

    *value |= valueInThisByte << magnitude;
    maxv |= allOnes << magnitude;

    magnitude += bitsInThisByte;
    bitsRemaining -= bitsInThisByte;
    firstBit += bitsInThisByte;
    if (firstBit >= 8)
    {
      firstBit -= 8;
      data++;
      dataLen--;
    }
  }
  if (bitsRemaining > 0)
  {
    logDebug("Insufficient length in PGN to fill field '%s'\n", name);
    return false;
  }

  if (hasSign)
  {
    maxv >>= 1;

    if (field && field->offset) /* J1939 Excess-K notation */
    {
      *value += field->offset;
      maxv += field->offset;
    }
    else
    {
      bool negative = (*value & (((uint64_t) 1) << (bits - 1))) > 0;

      if (negative)
      {
        /* Sign extend value for cases where bits < 64 */
        /* Assume we have bits = 16 and value = -2 then we do: */
        /* 0000.0000.0000.0000.0111.1111.1111.1101 value    */
        /* 0000.0000.0000.0000.0111.1111.1111.1111 maxvalue */
        /* 1111.1111.1111.1111.1000.0000.0000.0000 ~maxvalue */
        *value |= ~maxv;
      }
    }
  }
  else
  {
    if (field && field->offset) /* J1939 Excess-K notation */
    {
      *value += field->offset;
      maxv += field->offset;
    }
  }

  *maxValue = (int64_t) maxv;

  logDebug("extractNumber <%s> startBit=%zu bits=%zu value=%" PRId64 " (%" PRIx64 ") max=%" PRId64 "\n",
           name,
           startBit,
           bits,
           *value,
           *value,
           *maxValue);

  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x1b192
movq -0x10(%rbp), %rax
movb 0x49(%rax), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x90(%rbp)
jmp 0x1b19c
xorl %eax, %eax
movl %eax, -0x90(%rbp)
jmp 0x1b19c
movl -0x90(%rbp), %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x39(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x1b1c4
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x98(%rbp)
jmp 0x1b1d4
leaq 0x1597e(%rip), %rax     # 0x30b49
movq %rax, -0x98(%rbp)
jmp 0x1b1d4
movq -0x98(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x58(%rbp)
movq $0x0, -0x60(%rbp)
movq -0x48(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
leaq 0x1594e(%rip), %rdi     # 0x30b50
movb $0x0, %al
callq 0x1f670
leaq -0x18(%rbp), %rdi
leaq -0x20(%rbp), %rsi
leaq -0x28(%rbp), %rdx
callq 0x1b0e0
testb $0x1, %al
jne 0x1b227
movb $0x0, -0x1(%rbp)
jmp 0x1b4af
movq -0x28(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x38(%rbp), %rax
movq $0x0, (%rax)
movq $0x0, -0x88(%rbp)
xorl %eax, %eax
cmpq $0x0, -0x58(%rbp)
movb %al, -0x99(%rbp)
jbe 0x1b262
cmpq $0x0, -0x20(%rbp)
seta %al
movb %al, -0x99(%rbp)
movb -0x99(%rbp), %al
testb $0x1, %al
jne 0x1b271
jmp 0x1b369
movl $0x8, %eax
subq -0x50(%rbp), %rax
cmpq -0x58(%rbp), %rax
ja 0x1b292
movl $0x8, %eax
subq -0x50(%rbp), %rax
movq %rax, -0xa8(%rbp)
jmp 0x1b29d
movq -0x58(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rcx
movl $0x1, %eax
shlq %cl, %rax
subq $0x1, %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq -0x50(%rbp), %rcx
shlq %cl, %rax
movq %rax, -0x70(%rbp)
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
andq -0x70(%rbp), %rax
movq -0x50(%rbp), %rcx
shrq %cl, %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movq -0x60(%rbp), %rcx
shlq %cl, %rax
movq %rax, %rcx
movq -0x38(%rbp), %rax
orq (%rax), %rcx
movq %rcx, (%rax)
movq -0x78(%rbp), %rax
movq -0x60(%rbp), %rcx
shlq %cl, %rax
orq -0x88(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x68(%rbp), %rax
addq -0x60(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x68(%rbp), %rcx
movq -0x58(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x68(%rbp), %rax
addq -0x50(%rbp), %rax
movq %rax, -0x50(%rbp)
cmpq $0x8, -0x50(%rbp)
jb 0x1b364
movq -0x50(%rbp), %rax
subq $0x8, %rax
movq %rax, -0x50(%rbp)
movq -0x18(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x1b245
cmpq $0x0, -0x58(%rbp)
jbe 0x1b38b
movq -0x48(%rbp), %rsi
leaq 0x157ff(%rip), %rdi     # 0x30b7a
movb $0x0, %al
callq 0x1f670
movb $0x0, -0x1(%rbp)
jmp 0x1b4af
testb $0x1, -0x39(%rbp)
je 0x1b42f
movq -0x88(%rbp), %rax
shrq %rax
movq %rax, -0x88(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x1b3e1
movq -0x10(%rbp), %rax
cmpl $0x0, 0x28(%rax)
je 0x1b3e1
movq -0x10(%rbp), %rax
movslq 0x28(%rax), %rcx
movq -0x38(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
movq -0x10(%rbp), %rax
movslq 0x28(%rax), %rax
addq -0x88(%rbp), %rax
movq %rax, -0x88(%rbp)
jmp 0x1b42d
movq -0x38(%rbp), %rax
movq (%rax), %rax
movq -0x30(%rbp), %rcx
subq $0x1, %rcx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
seta %al
andb $0x1, %al
movb %al, -0x89(%rbp)
testb $0x1, -0x89(%rbp)
je 0x1b42b
movq -0x88(%rbp), %rcx
xorq $-0x1, %rcx
movq -0x38(%rbp), %rax
orq (%rax), %rcx
movq %rcx, (%rax)
jmp 0x1b42d
jmp 0x1b46a
cmpq $0x0, -0x10(%rbp)
je 0x1b468
movq -0x10(%rbp), %rax
cmpl $0x0, 0x28(%rax)
je 0x1b468
movq -0x10(%rbp), %rax
movslq 0x28(%rax), %rcx
movq -0x38(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
movq -0x10(%rbp), %rax
movslq 0x28(%rax), %rax
addq -0x88(%rbp), %rax
movq %rax, -0x88(%rbp)
jmp 0x1b46a
movq -0x88(%rbp), %rcx
movq 0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x48(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
movq -0x38(%rbp), %rax
movq (%rax), %r8
movq -0x38(%rbp), %rax
movq (%rax), %r9
movq 0x10(%rbp), %rax
movq (%rax), %rax
leaq 0x15709(%rip), %rdi     # 0x30ba9
movq %rax, (%rsp)
movb $0x0, %al
callq 0x1f670
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xb0, %rsp
popq %rbp
retq
nopl (%rax)