// File: sbingner[P]kerneldec/lzfse/src/lzfse_encode_base.c
// Function: lzfse_push_match
static int lzfse_push_match(lzfse_encoder_state *s, const lzfse_match *match) {
  // Save the initial n_matches, n_literals, src_literal
  uint32_t n_matches0 = s->n_matches;
  uint32_t n_literals0 = s->n_literals;
  lzfse_offset src_literals0 = s->src_literal;

  // L,M,D
  uint32_t L = (uint32_t)(match->pos - s->src_literal); // literal count
  uint32_t M = match->length;                           // match length
  uint32_t D = (uint32_t)(match->pos - match->ref);     // match distance
  int ok = 1;

  // Split L if too large
  while (L > LZFSE_ENCODE_MAX_L_VALUE) {
    if (lzfse_push_lmd(s, LZFSE_ENCODE_MAX_L_VALUE, 0, 1) != 0) {
      ok = 0;
      goto END;
    } // take D=1 because most frequent, but not actually used
    L -= LZFSE_ENCODE_MAX_L_VALUE;
  }

  // Split if M too large
  while (M > LZFSE_ENCODE_MAX_M_VALUE) {
    if (lzfse_push_lmd(s, L, LZFSE_ENCODE_MAX_M_VALUE, D) != 0) {
      ok = 0;
      goto END;
    }
    L = 0;
    M -= LZFSE_ENCODE_MAX_M_VALUE;
  }

  // L,M in range
  if (L > 0 || M > 0) {
    if (lzfse_push_lmd(s, L, M, D) != 0) {
      ok = 0;
      goto END;
    }
    L = M = 0;
    (void)L;
    (void)M; // dead stores
  }

END:
  if (!ok) {
    // Revert state
    s->n_matches = n_matches0;
    s->n_literals = n_literals0;
    s->src_literal = src_literals0;

    return LZFSE_STATUS_DST_FULL; // state tables full
  }

  return LZFSE_STATUS_OK; // OK
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rax
movl 0x58(%rax), %eax
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movl 0x5c(%rax), %eax
movl %eax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x10(%rbp), %rcx
subq 0x10(%rcx), %rax
movl %eax, -0x2c(%rbp)
movq -0x18(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
subq 0x8(%rcx), %rax
movl %eax, -0x34(%rbp)
movl $0x1, -0x38(%rbp)
cmpl $0x13b, -0x2c(%rbp)     # imm = 0x13B
jbe 0x4e91
movq -0x10(%rbp), %rdi
movl $0x13b, %esi            # imm = 0x13B
xorl %edx, %edx
movl $0x1, %ecx
callq 0x6e50
cmpl $0x0, %eax
je 0x4e84
movl $0x0, -0x38(%rbp)
jmp 0x4f0e
movl -0x2c(%rbp), %eax
subl $0x13b, %eax            # imm = 0x13B
movl %eax, -0x2c(%rbp)
jmp 0x4e55
jmp 0x4e93
cmpl $0x937, -0x30(%rbp)     # imm = 0x937
jbe 0x4ed2
movq -0x10(%rbp), %rdi
movl -0x2c(%rbp), %esi
movl -0x34(%rbp), %ecx
movl $0x937, %edx            # imm = 0x937
callq 0x6e50
cmpl $0x0, %eax
je 0x4ebe
movl $0x0, -0x38(%rbp)
jmp 0x4f0e
movl $0x0, -0x2c(%rbp)
movl -0x30(%rbp), %eax
subl $0x937, %eax            # imm = 0x937
movl %eax, -0x30(%rbp)
jmp 0x4e93
cmpl $0x0, -0x2c(%rbp)
ja 0x4ede
cmpl $0x0, -0x30(%rbp)
jbe 0x4f0c
movq -0x10(%rbp), %rdi
movl -0x2c(%rbp), %esi
movl -0x30(%rbp), %edx
movl -0x34(%rbp), %ecx
callq 0x6e50
cmpl $0x0, %eax
je 0x4efe
movl $0x0, -0x38(%rbp)
jmp 0x4f0e
movl $0x0, -0x30(%rbp)
movl $0x0, -0x2c(%rbp)
jmp 0x4f0e
cmpl $0x0, -0x38(%rbp)
jne 0x4f3d
movl -0x1c(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x58(%rax)
movl -0x20(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x5c(%rax)
movq -0x28(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x10(%rax)
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
jmp 0x4f44
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax)