// File: /workspace/github_c_makefile_star2_O0/ebiggers[P]xpack/lib/xpack_compress.c
// Function: build_fse_encoding_tables
static void
build_fse_encoding_tables(struct xpack_compressor *c,
			  struct fse_symbol_encoding_info sym_encinfo[],
			  u16 next_statesx[],
			  const u16 state_counts[],
			  const unsigned alphabet_size,
			  const unsigned log2_num_states)
{
	const unsigned num_states = 1 << log2_num_states;
	const unsigned state_generator = get_state_generator(num_states);
	const unsigned state_mask = num_states - 1;
	unsigned cumul_total;
	unsigned sym;
	unsigned state;
	unsigned count;
	unsigned max_bits;

	/*
	 * Build sym_encinfo[], which provides encoding information for each
	 * used symbol.  At the same time, build cumul_state_counts[], which for
	 * each symbol provides the total state count of the symbols that
	 * numerically precede it.
	 */
	cumul_total = 0;
	for (sym = 0; sym < alphabet_size; sym++) {

		count = state_counts[sym];

		if (count == 0) /* Unused symbol? */
			continue;

		c->cumul_state_counts[sym] = cumul_total;

		/*
		 * Each encoding of this symbol requires either 'min_bits' or
		 * 'max_bits = min_bits + 1' bits, where 'min_bits' is the
		 * entropy of this symbol rounded down to the nearest integer:
		 *
		 *	min_bits = floor(log2(1/probability))
		 *	min_bits = floor(log2(1/(count/num_states)))
		 *	min_bits = floor(log2(num_states/count))
		 *	min_bits = floor(log2(num_states) - log2(count))
		 *	min_bits = log2(num_states) - ceil(log2(count))
		 */
		max_bits = log2_num_states - ilog2_ceil(count) + 1;

		/*
		 * Save a value that makes it possible to branchlessly find the
		 * num_bits for a given state.  See encode_symbol() for details.
		 */
		sym_encinfo[sym].adjusted_num_states_in_big_ranges =
			((u32)max_bits << MAX_LOG2_NUM_STATES) -
			((u32)count << max_bits);

		/*
		 * When we need to encode an instance of this symbol, we'll have
		 * a "current state".  We'll need to find which destination
		 * range the current state is in, and which state --- the "next
		 * state" from the encoder's point of view but the "previous
		 * state" from the decoder's point of view --- maps to that
		 * destination range.  How can we do this efficiently?
		 *
		 * The solution relies on these facts:
		 *
		 *   - We'll know the number of bits to use.  Consequently,
		 *     we'll know the length of the destination range.
		 *   - The 'min_bits' destination ranges all precede the
		 *     'max_bits' destination ranges.
		 *
		 * What we'll do is maintain the state adjusted upwards by
		 * 'num_states'.  Then, we'll right-shift it by the number of
		 * bits that need to be used.  If 'min_bits' were required, then
		 * the result will be 'num_states >> min_bits' plus the index of
		 * the destination range in the list of 'min_bits' destination
		 * ranges.  But if 'max_bits' were required, then the result
		 * will be 'num_states >> min_bits' minus the number of
		 * 'max_bits' destination ranges, plus the index of the
		 * destination range in the list of 'max_bits' destination
		 * ranges.  Result: we map states to consecutive integers, each
		 * of which identifies a destination range.  We can use these
		 * integers as indices into a lookup table for the next state.
		 *
		 * Below, 'cumul_total' is the index at which the entries will
		 * actually begin in 'next_statesx[]'.  'count' is the beginning
		 * of the sequence of destination range identifiers.  This is
		 * 'num_states >> min_bits' minus the number of 'max_bits'
		 * destination ranges, which is also the same as the number of
		 * states (or destination ranges).  Note that the result of the
		 * subtraction may be a negative number.
		 */
		sym_encinfo[sym].next_states_begin = (s32)cumul_total - (s32)count;

		cumul_total += count;
	}

	/* Assign states to symbols. */
	state = 0;
	for (sym = 0; sym < alphabet_size; sym++) {
		count = state_counts[sym];
		while (count--) {
			c->state_to_symbol[state] = sym;
			state = (state + state_generator) & state_mask;
		}
	}

	/*
	 * Build next_statesx[].  This array maps symbol occurrences in the
	 * state table, ordered primarily by increasing symbol value and
	 * secondarily by increasing state, to their states, adjusted upwards by
	 * num_states.
	 */
	for (state = 0; state < num_states; state++) {
		unsigned symbol = c->state_to_symbol[state];
		unsigned position = c->cumul_state_counts[symbol]++;
		next_statesx[position] = num_states + state;
	}
}

// Assembly:
movq %rdi, -0x18(%rsp)
movq %rsi, -0x20(%rsp)
movq %rdx, -0x28(%rsp)
movq %rcx, -0x30(%rsp)
movl %r8d, -0x34(%rsp)
movl %r9d, -0x38(%rsp)
movl -0x38(%rsp), %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, -0x3c(%rsp)
movl -0x3c(%rsp), %eax
movl %eax, -0x4(%rsp)
movl -0x4(%rsp), %eax
shrl %eax
movl -0x4(%rsp), %ecx
shrl $0x3, %ecx
orl %ecx, %eax
orl $0x3, %eax
movl %eax, -0x40(%rsp)
movl -0x3c(%rsp), %eax
subl $0x1, %eax
movl %eax, -0x44(%rsp)
movl $0x0, -0x48(%rsp)
movl $0x0, -0x4c(%rsp)
movl -0x4c(%rsp), %eax
cmpl -0x34(%rsp), %eax
jae 0x6800
movq -0x30(%rsp), %rax
movl -0x4c(%rsp), %ecx
movzwl (%rax,%rcx,2), %eax
movl %eax, -0x54(%rsp)
cmpl $0x0, -0x54(%rsp)
jne 0x6751
jmp 0x67f0
movl -0x48(%rsp), %edx
movq -0x18(%rsp), %rax
movl -0x4c(%rsp), %ecx
movl %edx, 0x2a24(%rax,%rcx,4)
movl -0x38(%rsp), %eax
movl %eax, -0x64(%rsp)
movl -0x54(%rsp), %eax
movl %eax, -0xc(%rsp)
cmpl $0x1, -0xc(%rsp)
ja 0x6786
movl $0x0, -0x8(%rsp)
jmp 0x67a1
movl -0xc(%rsp), %eax
subl $0x1, %eax
bsrl %eax, %ecx
xorl $0x1f, %ecx
movl $0x1f, %eax
subl %ecx, %eax
addl $0x1, %eax
movl %eax, -0x8(%rsp)
movl -0x64(%rsp), %eax
subl -0x8(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x58(%rsp)
movl -0x58(%rsp), %edx
shll $0xa, %edx
movl -0x54(%rsp), %eax
movl -0x58(%rsp), %ecx
shll %cl, %eax
subl %eax, %edx
movq -0x20(%rsp), %rax
movl -0x4c(%rsp), %ecx
movl %edx, (%rax,%rcx,8)
movl -0x48(%rsp), %edx
subl -0x54(%rsp), %edx
movq -0x20(%rsp), %rax
movl -0x4c(%rsp), %ecx
movl %edx, 0x4(%rax,%rcx,8)
movl -0x54(%rsp), %eax
addl -0x48(%rsp), %eax
movl %eax, -0x48(%rsp)
movl -0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rsp)
jmp 0x6726
movl $0x0, -0x50(%rsp)
movl $0x0, -0x4c(%rsp)
movl -0x4c(%rsp), %eax
cmpl -0x34(%rsp), %eax
jae 0x6874
movq -0x30(%rsp), %rax
movl -0x4c(%rsp), %ecx
movzwl (%rax,%rcx,2), %eax
movl %eax, -0x54(%rsp)
movl -0x54(%rsp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x54(%rsp)
cmpl $0x0, %eax
je 0x6865
movl -0x4c(%rsp), %eax
movb %al, %dl
movq -0x18(%rsp), %rax
movl -0x50(%rsp), %ecx
movb %dl, 0x2e24(%rax,%rcx)
movl -0x50(%rsp), %eax
addl -0x40(%rsp), %eax
andl -0x44(%rsp), %eax
movl %eax, -0x50(%rsp)
jmp 0x682b
jmp 0x6867
movl -0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rsp)
jmp 0x6810
movl $0x0, -0x50(%rsp)
movl -0x50(%rsp), %eax
cmpl -0x3c(%rsp), %eax
jae 0x68e2
movq -0x18(%rsp), %rax
movl -0x50(%rsp), %ecx
movzbl 0x2e24(%rax,%rcx), %eax
movl %eax, -0x5c(%rsp)
movq -0x18(%rsp), %rcx
movl -0x5c(%rsp), %eax
movl %eax, %edx
movl 0x2a24(%rcx,%rdx,4), %eax
movl %eax, %esi
addl $0x1, %esi
movl %esi, 0x2a24(%rcx,%rdx,4)
movl %eax, -0x60(%rsp)
movl -0x3c(%rsp), %eax
addl -0x50(%rsp), %eax
movw %ax, %dx
movq -0x28(%rsp), %rax
movl -0x60(%rsp), %ecx
movw %dx, (%rax,%rcx,2)
movl -0x50(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rsp)
jmp 0x687c
retq
nopw %cs:(%rax,%rax)