// File: splatlab[P]debgr/threadsafe-gqf/gqf.c
// Function: insert1(quotient_filter*, unsigned __int128, bool, bool)
static inline bool insert1(QF *qf, __uint128_t hash, bool lock, bool spin)
{
	uint64_t hash_remainder           = hash & BITMASK(qf->metadata->bits_per_slot);
	uint64_t hash_bucket_index        = hash >> qf->metadata->bits_per_slot;
	uint64_t hash_bucket_block_offset = hash_bucket_index % SLOTS_PER_BLOCK;
	uint64_t hash_bucket_lock_offset  = hash_bucket_index % NUM_SLOTS_TO_LOCK;

	if (lock) {
#ifdef LOG_WAIT_TIME
		if (!qf_spin_lock(qf, &qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK],
											hash_bucket_index/NUM_SLOTS_TO_LOCK, spin))
			return false;
		if (hash_bucket_lock_offset > (NUM_SLOTS_TO_LOCK - CLUSTER_SIZE)) {
			if (!qf_spin_lock(qf, &qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK+1],
												hash_bucket_index/NUM_SLOTS_TO_LOCK+1, spin)) {
				qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK]);
				return false;
			}
		}
#else
		if (!qf_spin_lock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK], spin))
			return false;
		if (hash_bucket_lock_offset > (NUM_SLOTS_TO_LOCK - CLUSTER_SIZE)) {
			if (!qf_spin_lock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK+1],
												spin)) {
				qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK]);
				return false;
			}
		}
#endif
	}
	if (is_empty(qf, hash_bucket_index) /* might_be_empty(qf, hash_bucket_index) && runend_index == hash_bucket_index */) {
		METADATA_WORD(qf, runends, hash_bucket_index) |= 1ULL <<
			(hash_bucket_block_offset % 64);
		set_slot(qf, hash_bucket_index, hash_remainder);
		METADATA_WORD(qf, occupieds, hash_bucket_index) |= 1ULL <<
			(hash_bucket_block_offset % 64);

		/*modify_metadata(qf, &qf->metadata->ndistinct_elts, 1);*/
		/*modify_metadata(qf, &qf->metadata->noccupied_slots, 1);*/
		/*modify_metadata(qf, &qf->metadata->nelts, 1);*/
	} else {
		uint64_t runend_index              = run_end(qf, hash_bucket_index);
		int operation = 0; /* Insert into empty bucket */
		uint64_t insert_index = runend_index + 1;
		uint64_t new_value = hash_remainder;

		/* printf("RUNSTART: %02lx RUNEND: %02lx\n", runstart_index, runend_index); */

		uint64_t runstart_index = hash_bucket_index == 0 ? 0 : run_end(qf,
																																	 hash_bucket_index
																																	 - 1) + 1;

		if (is_occupied(qf, hash_bucket_index)) {

			/* Find the counter for this remainder if it exists. */
			uint64_t current_remainder = get_slot(qf, runstart_index);
			uint64_t zero_terminator = runstart_index;

			/* The counter for 0 is special. */
			if (current_remainder == 0) {
				uint64_t t = runstart_index + 1;
				while (t < runend_index && get_slot(qf, t) != 0)
					t++;
				if (t < runend_index && get_slot(qf, t+1) == 0)
					zero_terminator = t+1; /* Three or more 0s */
				else if (runstart_index < runend_index && get_slot(qf, runstart_index
																													 + 1) == 0)
					zero_terminator = runstart_index + 1; /* Exactly two 0s */
				/* Otherwise, exactly one 0 (i.e. zero_terminator == runstart_index) */

				/* May read past end of run, but that's OK because loop below
					 can handle that */
				if (hash_remainder != 0) {
					runstart_index = zero_terminator + 1;
					current_remainder = get_slot(qf, runstart_index);
				}
			}

			/* Skip over counters for other remainders. */
			while (current_remainder < hash_remainder && runstart_index <=
						 runend_index) {
				/* If this remainder has an extended counter, skip over it. */
				if (runstart_index < runend_index && 
						get_slot(qf, runstart_index + 1) < current_remainder) {
					runstart_index = runstart_index + 2;
					while (runstart_index < runend_index &&
								 get_slot(qf, runstart_index) != current_remainder)
						runstart_index++;
					runstart_index++;

					/* This remainder has a simple counter. */
				} else {
					runstart_index++;
				}

				/* This may read past the end of the run, but the while loop
					 condition will prevent us from using the invalid result in
					 that case. */
				current_remainder = get_slot(qf, runstart_index);
			}

			/* If this is the first time we've inserted the new remainder,
				 and it is larger than any remainder in the run. */
			if (runstart_index > runend_index) {
				operation = 1;
				insert_index = runstart_index;
				new_value = hash_remainder;
				/*modify_metadata(qf, &qf->metadata->ndistinct_elts, 1);*/

				/* This is the first time we're inserting this remainder, but
					 there are larger remainders already in the run. */
			} else if (current_remainder != hash_remainder) {
				operation = 2; /* Inserting */
				insert_index = runstart_index;
				new_value = hash_remainder;
				/*modify_metadata(qf, &qf->metadata->ndistinct_elts, 1);*/

				/* Cases below here: we're incrementing the (simple or
					 extended) counter for this remainder. */

				/* If there's exactly one instance of this remainder. */
			} else if (runstart_index == runend_index || 
								 (hash_remainder > 0 && get_slot(qf, runstart_index + 1) >
									hash_remainder) ||
								 (hash_remainder == 0 && zero_terminator == runstart_index)) {
				operation = 2; /* Insert */
				insert_index = runstart_index;
				new_value = hash_remainder;

				/* If there are exactly two instances of this remainder. */
			} else if ((hash_remainder > 0 && get_slot(qf, runstart_index + 1) ==
									hash_remainder) ||
								 (hash_remainder == 0 && zero_terminator == runstart_index + 1)) {
				operation = 2; /* Insert */
				insert_index = runstart_index + 1;
				new_value = 0;

				/* Special case for three 0s */
			} else if (hash_remainder == 0 && zero_terminator == runstart_index + 2) {
				operation = 2; /* Insert */
				insert_index = runstart_index + 1;
				new_value = 1;

				/* There is an extended counter for this remainder. */
			} else {

				/* Move to the LSD of the counter. */
				insert_index = runstart_index + 1;
				while (get_slot(qf, insert_index+1) != hash_remainder)
					insert_index++;

				/* Increment the counter. */
				uint64_t digit, carry;
				do {
					carry = 0;
					digit = get_slot(qf, insert_index);
					// Convert a leading 0 (which is special) to a normal encoded digit
					if (digit == 0) {
						digit++;
						if (digit == current_remainder)
							digit++;
					}

					// Increment the digit
					digit = (digit + 1) & BITMASK(qf->metadata->bits_per_slot);

					// Ensure digit meets our encoding requirements
					if (digit == 0) {
						digit++;
						carry = 1;
					}
					if (digit == current_remainder)
						digit = (digit + 1) & BITMASK(qf->metadata->bits_per_slot);
					if (digit == 0) {
						digit++;
						carry = 1;
					}

					set_slot(qf, insert_index, digit);
					insert_index--;
				} while(insert_index > runstart_index && carry);

				/* If the counter needs to be expanded. */
				if (insert_index == runstart_index && (carry > 0 || (current_remainder
																														 != 0 && digit >=
																														 current_remainder)))
				{
					operation = 2; /* insert */
					insert_index = runstart_index + 1;
					if (!carry)						/* To prepend a 0 before the counter if the MSD is greater than the rem */
						new_value = 0;
					else if (carry) {			/* Increment the new value because we don't use 0 to encode counters */
						new_value = 2;
						/* If the rem is greater than or equal to the new_value then fail*/
						if (current_remainder)
							assert(new_value < current_remainder);
					}
				} else {
					operation = -1;
				}
			}
		}

		if (operation >= 0) {
			uint64_t empty_slot_index = find_first_empty_slot(qf, runend_index+1);

			shift_remainders(qf, insert_index, empty_slot_index);

			set_slot(qf, insert_index, new_value);

			shift_runends(qf, insert_index, empty_slot_index-1, 1);
			switch (operation) {
				case 0:
					METADATA_WORD(qf, runends, insert_index)   |= 1ULL << ((insert_index
																																	%
																																	SLOTS_PER_BLOCK)
																																 % 64);
					break;
				case 1:
					METADATA_WORD(qf, runends, insert_index-1) &= ~(1ULL <<
																													(((insert_index-1) %
																														SLOTS_PER_BLOCK) %
																													 64));
					METADATA_WORD(qf, runends, insert_index)   |= 1ULL << ((insert_index
																																	%
																																	SLOTS_PER_BLOCK)
																																 % 64);
					break;
				case 2:
					METADATA_WORD(qf, runends, insert_index)   &= ~(1ULL <<
																													((insert_index %
																														SLOTS_PER_BLOCK) %
																													 64));
					break;
				default:
					fprintf(stderr, "Invalid operation %d\n", operation);
					abort();
			}
			/* 
			 * Increment the offset for each block between the hash bucket index
			 * and block of the empty slot  
			 * */
			uint64_t i;
			for (i = hash_bucket_index / SLOTS_PER_BLOCK + 1; i <=
					 empty_slot_index/SLOTS_PER_BLOCK; i++) {
				if (get_block(qf, i)->offset < BITMASK(8*sizeof(qf->blocks[0].offset)))
					get_block(qf, i)->offset++;
				//assert(get_block(qf, i)->offset != 0);
			}
			/*modify_metadata(qf, &qf->metadata->noccupied_slots, 1);*/
		}
		/*modify_metadata(qf, &qf->metadata->nelts, 1);*/
		METADATA_WORD(qf, occupieds, hash_bucket_index) |= 1ULL <<
			(hash_bucket_block_offset % 64);
	}

	if (lock) {
		qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK]);
		if (hash_bucket_lock_offset > (NUM_SLOTS_TO_LOCK - CLUSTER_SIZE))
			qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK+1]);
	}

	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x150, %rsp            # imm = 0x150
movb %r8b, %al
movq %rsi, -0x20(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x20(%rbp), %rdx
movq -0x18(%rbp), %rsi
movq %rdi, -0x28(%rbp)
movq %rsi, -0x38(%rbp)
movq %rdx, -0x40(%rbp)
andb $0x1, %cl
movb %cl, -0x41(%rbp)
andb $0x1, %al
movb %al, -0x42(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0x38(%rbp), %rax
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
cmpq $0x40, 0x38(%rax)
jne 0x254c3
movq $-0x1, %rax
movq %rax, -0xd8(%rbp)
jmp 0x254e2
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rcx
movl $0x1, %eax
shlq %cl, %rax
subq $0x1, %rax
movq %rax, -0xd8(%rbp)
movq -0xd0(%rbp), %rax
movq -0xd8(%rbp), %rcx
andq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rsi
movq -0x28(%rbp), %rcx
movq 0x8(%rcx), %rcx
movb 0x38(%rcx), %dl
movb %dl, %cl
movq %rsi, %rdi
shrq %cl, %rdi
movq %rdi, -0xe0(%rbp)
movb %dl, %cl
shrdq %cl, %rsi, %rax
movq -0xe0(%rbp), %rcx
testb $0x40, %dl
cmovneq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
andq $0x3f, %rax
movq %rax, -0x60(%rbp)
movq -0x58(%rbp), %rax
andq $0xfff, %rax            # imm = 0xFFF
movq %rax, -0x68(%rbp)
testb $0x1, -0x41(%rbp)
je 0x255ee
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x58(%rbp), %rax
shrq $0xc, %rax
shlq $0x2, %rax
addq %rax, %rdi
movb -0x42(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x27ff0
testb $0x1, %al
jne 0x25589
movb $0x0, -0x1(%rbp)
jmp 0x26099
cmpq $0xf00, -0x68(%rbp)     # imm = 0xF00
jbe 0x255ec
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x58(%rbp), %rax
shrq $0xc, %rax
addq $0x1, %rax
shlq $0x2, %rax
addq %rax, %rdi
movb -0x42(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x27ff0
testb $0x1, %al
jne 0x255ea
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x58(%rbp), %rax
shrq $0xc, %rax
shlq $0x2, %rax
addq %rax, %rdi
callq 0x28050
movb $0x0, -0x1(%rbp)
jmp 0x26099
jmp 0x255ec
jmp 0x255ee
movq -0x28(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x28070
cmpl $0x0, %eax
je 0x256a4
movq -0x60(%rbp), %rcx
andq $0x3f, %rcx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, -0xf0(%rbp)
movq -0x28(%rbp), %rdi
movq -0x58(%rbp), %rsi
shrq $0x6, %rsi
callq 0x27590
movq -0xf0(%rbp), %rdx
movq -0x58(%rbp), %rcx
andq $0x3f, %rcx
shrq $0x6, %rcx
orq 0x9(%rax,%rcx,8), %rdx
movq %rdx, 0x9(%rax,%rcx,8)
movq -0x28(%rbp), %rdi
movq -0x58(%rbp), %rsi
movq -0x50(%rbp), %rdx
callq 0x280a0
movq -0x60(%rbp), %rcx
andq $0x3f, %rcx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, -0xe8(%rbp)
movq -0x28(%rbp), %rdi
movq -0x58(%rbp), %rsi
shrq $0x6, %rsi
callq 0x27590
movq -0xe8(%rbp), %rdx
movq -0x58(%rbp), %rcx
andq $0x3f, %rcx
shrq $0x6, %rcx
orq 0x1(%rax,%rcx,8), %rdx
movq %rdx, 0x1(%rax,%rcx,8)
jmp 0x26041
movq -0x28(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x26ea0
movq %rax, -0x70(%rbp)
movl $0x0, -0x74(%rbp)
movq -0x70(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x88(%rbp)
cmpq $0x0, -0x58(%rbp)
jne 0x256e5
xorl %eax, %eax
movq %rax, -0xf8(%rbp)
jmp 0x25701
movq -0x28(%rbp), %rdi
movq -0x58(%rbp), %rsi
subq $0x1, %rsi
callq 0x26ea0
addq $0x1, %rax
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x28(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x26e50
cmpl $0x0, %eax
je 0x25d92
movq -0x28(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x281b0
movq %rax, -0x98(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0xa0(%rbp)
cmpq $0x0, -0x98(%rbp)
jne 0x25864
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rcx
xorl %eax, %eax
cmpq -0x70(%rbp), %rcx
movb %al, -0xf9(%rbp)
jae 0x2579c
movq -0x28(%rbp), %rdi
movq -0xa8(%rbp), %rsi
callq 0x281b0
cmpq $0x0, %rax
setne %al
movb %al, -0xf9(%rbp)
movb -0xf9(%rbp), %al
testb $0x1, %al
jne 0x257a8
jmp 0x257bc
movq -0xa8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa8(%rbp)
jmp 0x2576a
movq -0xa8(%rbp), %rax
cmpq -0x70(%rbp), %rax
jae 0x257f7
movq -0x28(%rbp), %rdi
movq -0xa8(%rbp), %rsi
addq $0x1, %rsi
callq 0x281b0
cmpq $0x0, %rax
jne 0x257f7
movq -0xa8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
jmp 0x25832
movq -0x90(%rbp), %rax
cmpq -0x70(%rbp), %rax
jae 0x25830
movq -0x28(%rbp), %rdi
movq -0x90(%rbp), %rsi
addq $0x1, %rsi
callq 0x281b0
cmpq $0x0, %rax
jne 0x25830
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
jmp 0x25832
cmpq $0x0, -0x50(%rbp)
je 0x25862
movq -0xa0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x90(%rbp)
movq -0x28(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x281b0
movq %rax, -0x98(%rbp)
jmp 0x25864
jmp 0x25866
movq -0x98(%rbp), %rcx
xorl %eax, %eax
cmpq -0x50(%rbp), %rcx
movb %al, -0xfa(%rbp)
jae 0x2588f
movq -0x90(%rbp), %rax
cmpq -0x70(%rbp), %rax
setbe %al
movb %al, -0xfa(%rbp)
movb -0xfa(%rbp), %al
testb $0x1, %al
jne 0x2589e
jmp 0x25975
movq -0x90(%rbp), %rax
cmpq -0x70(%rbp), %rax
jae 0x25947
movq -0x28(%rbp), %rdi
movq -0x90(%rbp), %rsi
addq $0x1, %rsi
callq 0x281b0
cmpq -0x98(%rbp), %rax
jae 0x25947
movq -0x90(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rcx
xorl %eax, %eax
cmpq -0x70(%rbp), %rcx
movb %al, -0xfb(%rbp)
jae 0x25913
movq -0x28(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x281b0
cmpq -0x98(%rbp), %rax
setne %al
movb %al, -0xfb(%rbp)
movb -0xfb(%rbp), %al
testb $0x1, %al
jne 0x2591f
jmp 0x25933
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x90(%rbp)
jmp 0x258de
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x90(%rbp)
jmp 0x25959
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x90(%rbp)
movq -0x28(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x281b0
movq %rax, -0x98(%rbp)
jmp 0x25866
movq -0x90(%rbp), %rax
cmpq -0x70(%rbp), %rax
jbe 0x259a4
movl $0x1, -0x74(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x88(%rbp)
jmp 0x25d90
movq -0x98(%rbp), %rax
cmpq -0x50(%rbp), %rax
je 0x259d3
movl $0x2, -0x74(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x88(%rbp)
jmp 0x25d8e
movq -0x90(%rbp), %rax
cmpq -0x70(%rbp), %rax
je 0x25a18
cmpq $0x0, -0x50(%rbp)
jbe 0x25a01
movq -0x28(%rbp), %rdi
movq -0x90(%rbp), %rsi
addq $0x1, %rsi
callq 0x281b0
cmpq -0x50(%rbp), %rax
ja 0x25a18
cmpq $0x0, -0x50(%rbp)
jne 0x25a3a
movq -0xa0(%rbp), %rax
cmpq -0x90(%rbp), %rax
jne 0x25a3a
movl $0x2, -0x74(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x88(%rbp)
jmp 0x25d8c
cmpq $0x0, -0x50(%rbp)
jbe 0x25a5b
movq -0x28(%rbp), %rdi
movq -0x90(%rbp), %rsi
addq $0x1, %rsi
callq 0x281b0
cmpq -0x50(%rbp), %rax
je 0x25a79
cmpq $0x0, -0x50(%rbp)
jne 0x25a9f
movq -0xa0(%rbp), %rax
movq -0x90(%rbp), %rcx
addq $0x1, %rcx
cmpq %rcx, %rax
jne 0x25a9f
movl $0x2, -0x74(%rbp)
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
movq $0x0, -0x88(%rbp)
jmp 0x25d8a
cmpq $0x0, -0x50(%rbp)
jne 0x25ae3
movq -0xa0(%rbp), %rax
movq -0x90(%rbp), %rcx
addq $0x2, %rcx
cmpq %rcx, %rax
jne 0x25ae3
movl $0x2, -0x74(%rbp)
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
movq $0x1, -0x88(%rbp)
jmp 0x25d88
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
addq $0x1, %rsi
callq 0x281b0
cmpq -0x50(%rbp), %rax
je 0x25b17
movq -0x80(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
jmp 0x25af2
jmp 0x25b19
movq $0x0, -0xb8(%rbp)
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
callq 0x281b0
movq %rax, -0xb0(%rbp)
cmpq $0x0, -0xb0(%rbp)
jne 0x25b78
movq -0xb0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
cmpq -0x98(%rbp), %rax
jne 0x25b76
movq -0xb0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb0(%rbp)
jmp 0x25b78
movq -0xb0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x108(%rbp)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
cmpq $0x40, 0x38(%rax)
jne 0x25ba9
movq $-0x1, %rax
movq %rax, -0x110(%rbp)
jmp 0x25bc8
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rcx
movl $0x1, %eax
shlq %cl, %rax
subq $0x1, %rax
movq %rax, -0x110(%rbp)
movq -0x108(%rbp), %rax
movq -0x110(%rbp), %rcx
andq %rcx, %rax
movq %rax, -0xb0(%rbp)
cmpq $0x0, -0xb0(%rbp)
jne 0x25c07
movq -0xb0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb0(%rbp)
movq $0x1, -0xb8(%rbp)
movq -0xb0(%rbp), %rax
cmpq -0x98(%rbp), %rax
jne 0x25c7f
movq -0xb0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x118(%rbp)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
cmpq $0x40, 0x38(%rax)
jne 0x25c48
movq $-0x1, %rax
movq %rax, -0x120(%rbp)
jmp 0x25c67
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rcx
movl $0x1, %eax
shlq %cl, %rax
subq $0x1, %rax
movq %rax, -0x120(%rbp)
movq -0x118(%rbp), %rax
movq -0x120(%rbp), %rcx
andq %rcx, %rax
movq %rax, -0xb0(%rbp)
cmpq $0x0, -0xb0(%rbp)
jne 0x25ca6
movq -0xb0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb0(%rbp)
movq $0x1, -0xb8(%rbp)
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0xb0(%rbp), %rdx
callq 0x280a0
movq -0x80(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rcx
xorl %eax, %eax
cmpq -0x90(%rbp), %rcx
movb %al, -0x121(%rbp)
jbe 0x25cec
cmpq $0x0, -0xb8(%rbp)
setne %al
movb %al, -0x121(%rbp)
movb -0x121(%rbp), %al
testb $0x1, %al
jne 0x25b19
movq -0x80(%rbp), %rax
cmpq -0x90(%rbp), %rax
jne 0x25d7f
cmpq $0x0, -0xb8(%rbp)
ja 0x25d2b
cmpq $0x0, -0x98(%rbp)
je 0x25d7f
movq -0xb0(%rbp), %rax
cmpq -0x98(%rbp), %rax
jb 0x25d7f
movl $0x2, -0x74(%rbp)
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
cmpq $0x0, -0xb8(%rbp)
jne 0x25d58
movq $0x0, -0x88(%rbp)
jmp 0x25d7d
cmpq $0x0, -0xb8(%rbp)
je 0x25d7b
movq $0x2, -0x88(%rbp)
cmpq $0x0, -0x98(%rbp)
je 0x25d79
jmp 0x25d79
jmp 0x25d7b
jmp 0x25d7d
jmp 0x25d86
movl $0xffffffff, -0x74(%rbp) # imm = 0xFFFFFFFF
jmp 0x25d88
jmp 0x25d8a
jmp 0x25d8c
jmp 0x25d8e
jmp 0x25d90
jmp 0x25d92
cmpl $0x0, -0x74(%rbp)
jl 0x25ffc
movq -0x28(%rbp), %rdi
movq -0x70(%rbp), %rsi
incq %rsi
callq 0x28270
movq %rax, -0xc0(%rbp)
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0xc0(%rbp), %rdx
callq 0x282c0
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0x88(%rbp), %rdx
callq 0x280a0
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0xc0(%rbp), %rdx
decq %rdx
movl $0x1, %ecx
callq 0x28510
movl -0x74(%rbp), %eax
movl %eax, -0x128(%rbp)
testl %eax, %eax
je 0x25e27
jmp 0x25e06
movl -0x128(%rbp), %eax
subl $0x1, %eax
je 0x25e75
jmp 0x25e13
movl -0x128(%rbp), %eax
subl $0x2, %eax
je 0x25f19
jmp 0x25f68
movq -0x80(%rbp), %rcx
andq $0x3f, %rcx
andq $0x3f, %rcx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, -0x130(%rbp)
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
shrq $0x6, %rsi
callq 0x27590
movq -0x130(%rbp), %rdx
movq -0x80(%rbp), %rcx
andq $0x3f, %rcx
shrq $0x6, %rcx
orq 0x9(%rax,%rcx,8), %rdx
movq %rdx, 0x9(%rax,%rcx,8)
jmp 0x25f88
movq -0x80(%rbp), %rcx
subq $0x1, %rcx
andq $0x3f, %rcx
andq $0x3f, %rcx
movl $0x1, %eax
shlq %cl, %rax
xorq $-0x1, %rax
movq %rax, -0x140(%rbp)
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
subq $0x1, %rsi
shrq $0x6, %rsi
callq 0x27590
movq -0x140(%rbp), %rdx
movq -0x80(%rbp), %rcx
subq $0x1, %rcx
andq $0x3f, %rcx
shrq $0x6, %rcx
andq 0x9(%rax,%rcx,8), %rdx
movq %rdx, 0x9(%rax,%rcx,8)
movq -0x80(%rbp), %rcx
andq $0x3f, %rcx
andq $0x3f, %rcx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, -0x138(%rbp)
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
shrq $0x6, %rsi
callq 0x27590
movq -0x138(%rbp), %rdx
movq -0x80(%rbp), %rcx
andq $0x3f, %rcx
shrq $0x6, %rcx
orq 0x9(%rax,%rcx,8), %rdx
movq %rdx, 0x9(%rax,%rcx,8)
jmp 0x25f88
movq -0x80(%rbp), %rcx
andq $0x3f, %rcx
andq $0x3f, %rcx
movl $0x1, %eax
shlq %cl, %rax
xorq $-0x1, %rax
movq %rax, -0x148(%rbp)
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
shrq $0x6, %rsi
callq 0x27590
movq -0x148(%rbp), %rdx
movq -0x80(%rbp), %rcx
andq $0x3f, %rcx
shrq $0x6, %rcx
andq 0x9(%rax,%rcx,8), %rdx
movq %rdx, 0x9(%rax,%rcx,8)
jmp 0x25f88
movq 0x14069(%rip), %rax     # 0x39fd8
movq (%rax), %rdi
movl -0x74(%rbp), %edx
leaq 0x4bb2(%rip), %rsi      # 0x2ab2e
movb $0x0, %al
callq 0x33d0
callq 0x3110
movq -0x58(%rbp), %rax
shrq $0x6, %rax
addq $0x1, %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movq -0xc0(%rbp), %rcx
shrq $0x6, %rcx
cmpq %rcx, %rax
ja 0x25ffa
movq -0x28(%rbp), %rdi
movq -0xc8(%rbp), %rsi
callq 0x27590
movzbl (%rax), %eax
cmpq $0xff, %rax
jae 0x25fe4
movq -0x28(%rbp), %rdi
movq -0xc8(%rbp), %rsi
callq 0x27590
movb (%rax), %cl
addb $0x1, %cl
movb %cl, (%rax)
jmp 0x25fe6
movq -0xc8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xc8(%rbp)
jmp 0x25f9b
jmp 0x25ffc
movq -0x60(%rbp), %rcx
andq $0x3f, %rcx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, -0x150(%rbp)
movq -0x28(%rbp), %rdi
movq -0x58(%rbp), %rsi
shrq $0x6, %rsi
callq 0x27590
movq -0x150(%rbp), %rdx
movq -0x58(%rbp), %rcx
andq $0x3f, %rcx
shrq $0x6, %rcx
orq 0x1(%rax,%rcx,8), %rdx
movq %rdx, 0x1(%rax,%rcx,8)
testb $0x1, -0x41(%rbp)
je 0x26095
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x58(%rbp), %rax
shrq $0xc, %rax
shlq $0x2, %rax
addq %rax, %rdi
callq 0x28050
cmpq $0xf00, -0x68(%rbp)     # imm = 0xF00
jbe 0x26093
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x58(%rbp), %rax
shrq $0xc, %rax
addq $0x1, %rax
shlq $0x2, %rax
addq %rax, %rdi
callq 0x28050
jmp 0x26095
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
nopw (%rax,%rax)