// File: /workspace/github_c_makefile_star2_O0/mloar[P]charset/utf7.c
// Function: write_utf7
static int write_utf7(charset_spec const *charset, long int input_chr,
		      charset_state *state,
		      void (*emit)(void *ctx, long int output),
		      void *emitctx)
{
    unsigned long hws[2];
    int nhws;
    int i;

    /*
     * For writing: state->s0 contains accumulated base64 data with
     * a 1 in front, and state->s1 indicates how many bits of it we
     * have.
     */

    if ((input_chr >= 0xD800 && input_chr < 0xE000) ||
	input_chr >= 0x110000) {
	/*
	 * We can't output surrogates, or anything above 0x10FFFF.
	 */
	return FALSE;
    }

    /*
     * Look for characters which we output in ASCII mode. A special
     * case here is +, which can be encoded as the empty base64
     * escape sequence `+-': if we're _already_ in ASCII mode we do
     * that, but if we're in base64 mode at the point we see the +
     * then we simply stay in base64 mode and output it as a
     * halfword. (Switching back would cost three bytes, whereas
     * staying in base64 costs only 2 2/3.)
     */
    if (input_chr == -1 || SET_D(input_chr) ||
	(charset->charset == CS_UTF7 && SET_O(input_chr)) ||
	(!state->s0 && input_chr == '+')) {
	if (state->s0) {
	    /*
	     * These characters are output in ASCII mode, so flush any
	     * lingering base64 data.
	     */
	    state->s0 <<= 6 - state->s1;
	    emit(emitctx, base64_chars[state->s0 & 0x3F]);
	    /*
	     * I'm going to arbitrarily decide to always use the
	     * terminating minus sign. It's easier than figuring out
	     * whether to do so or not, and looks prettier besides.
	     */
	    emit(emitctx, '-');
	    state->s0 = state->s1 = 0;
	}

	/*
	 * Now output the character.
	 */
	if (input_chr != -1)	       /* special case: just reset state */
	    emit(emitctx, input_chr);
	if (input_chr == '+')
	    emit(emitctx, '-');	       /* +- encodes + */
	return TRUE;
    }

    /*
     * Now we know we have a character that needs to be output as
     * either one base64-encoded halfword or two. So first figure
     * out how many...
     */
    if (input_chr < 0x10000) {
	nhws = 1;
	hws[0] = input_chr;
    } else {
	input_chr -= 0x10000;
	if (input_chr >= 0x100000) {
	    /* Anything above 0x10FFFF is outside UTF-7 range. */
	    return FALSE;
	}

	nhws = 2;
	hws[0] = 0xD800 | ((input_chr >> 10) & 0x3FF);
	hws[1] = 0xDC00 | (input_chr & 0x3FF);
    }

    /*
     * ... switch into base64 mode if required ...
     */
    if (!state->s0) {
	emit(emitctx, '+');
	state->s0 = 1;
	state->s1 = 0;
    }

    /*
     * ... and do the base64 output.
     */
    for (i = 0; i < nhws; i++) {
	state->s0 = (state->s0 << 16) | hws[i];
	state->s1 += 16;

	while (state->s1 >= 6) {
	    /*
	     * The top set bit must be in position 16, 18 or 20.
	     */
	    unsigned long out, topbit;
	    
	    out = (state->s0 >> (state->s1 - 6)) & 0x3F;
	    state->s1 -= 6;
	    topbit = 1 << state->s1;
	    state->s0 = (state->s0 & (topbit-1)) | topbit;

	    emit(emitctx, base64_chars[out]);
	}
    }
    return TRUE;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
cmpq $0xd800, -0x18(%rbp)    # imm = 0xD800
jl 0xbe80
cmpq $0xe000, -0x18(%rbp)    # imm = 0xE000
jl 0xbe8a
cmpq $0x110000, -0x18(%rbp)  # imm = 0x110000
jl 0xbe96
movl $0x0, -0x4(%rbp)
jmp 0xc13b
cmpq $-0x1, -0x18(%rbp)
je 0xbf0f
cmpq $0x0, -0x18(%rbp)
jl 0xbec5
cmpq $0x80, -0x18(%rbp)
jge 0xbec5
movq -0x18(%rbp), %rcx
leaq 0x99f47(%rip), %rax     # 0xa5e00
movzbl (%rax,%rcx), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0xbf0f
movq -0x10(%rbp), %rax
cmpl $0x3c, (%rax)
jne 0xbef6
cmpq $0x0, -0x18(%rbp)
jl 0xbef6
cmpq $0x80, -0x18(%rbp)
jge 0xbef6
movq -0x18(%rbp), %rcx
leaq 0x99f16(%rip), %rax     # 0xa5e00
movzbl (%rax,%rcx), %eax
andl $0x2, %eax
cmpl $0x0, %eax
jne 0xbf0f
movq -0x20(%rbp), %rax
cmpq $0x0, (%rax)
jne 0xbfb4
cmpq $0x2b, -0x18(%rbp)
jne 0xbfb4
movq -0x20(%rbp), %rax
cmpq $0x0, (%rax)
je 0xbf7d
movq -0x20(%rbp), %rax
movl $0x6, %ecx
subq 0x8(%rax), %rcx
movq -0x20(%rbp), %rax
movq (%rax), %rdx
shlq %cl, %rdx
movq %rdx, %rcx
movq %rcx, (%rax)
movq -0x28(%rbp), %rax
movq -0x30(%rbp), %rdi
movq -0x20(%rbp), %rcx
movq (%rcx), %rdx
andq $0x3f, %rdx
leaq 0x99f30(%rip), %rcx     # 0xa5e80
movsbq (%rcx,%rdx), %rsi
callq *%rax
movq -0x28(%rbp), %rax
movq -0x30(%rbp), %rdi
movl $0x2d, %esi
callq *%rax
movq -0x20(%rbp), %rax
movq $0x0, 0x8(%rax)
movq -0x20(%rbp), %rax
movq $0x0, (%rax)
cmpq $-0x1, -0x18(%rbp)
je 0xbf92
movq -0x28(%rbp), %rax
movq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq *%rax
cmpq $0x2b, -0x18(%rbp)
jne 0xbfa8
movq -0x28(%rbp), %rax
movq -0x30(%rbp), %rdi
movl $0x2d, %esi
callq *%rax
movl $0x1, -0x4(%rbp)
jmp 0xc13b
cmpq $0x10000, -0x18(%rbp)   # imm = 0x10000
jge 0xbfcf
movl $0x1, -0x44(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x40(%rbp)
jmp 0xc026
movq -0x18(%rbp), %rax
subq $0x10000, %rax          # imm = 0x10000
movq %rax, -0x18(%rbp)
cmpq $0x100000, -0x18(%rbp)  # imm = 0x100000
jl 0xbff3
movl $0x0, -0x4(%rbp)
jmp 0xc13b
movl $0x2, -0x44(%rbp)
movq -0x18(%rbp), %rax
sarq $0xa, %rax
andq $0x3ff, %rax            # imm = 0x3FF
orq $0xd800, %rax           # imm = 0xD800
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rax
andq $0x3ff, %rax            # imm = 0x3FF
orq $0xdc00, %rax           # imm = 0xDC00
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rax
cmpq $0x0, (%rax)
jne 0xc056
movq -0x28(%rbp), %rax
movq -0x30(%rbp), %rdi
movl $0x2b, %esi
callq *%rax
movq -0x20(%rbp), %rax
movq $0x1, (%rax)
movq -0x20(%rbp), %rax
movq $0x0, 0x8(%rax)
movl $0x0, -0x48(%rbp)
movl -0x48(%rbp), %eax
cmpl -0x44(%rbp), %eax
jge 0xc134
movq -0x20(%rbp), %rax
movq (%rax), %rcx
shlq $0x10, %rcx
movslq -0x48(%rbp), %rax
orq -0x40(%rbp,%rax,8), %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rcx
addq $0x10, %rcx
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rax
cmpq $0x6, 0x8(%rax)
jb 0xc124
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq -0x20(%rbp), %rcx
movq 0x8(%rcx), %rcx
subq $0x6, %rcx
shrq %cl, %rax
andq $0x3f, %rax
movq %rax, -0x50(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rcx
subq $0x6, %rcx
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movl %eax, %ecx
movl $0x1, %eax
shll %cl, %eax
cltq
movq %rax, -0x58(%rbp)
movq -0x20(%rbp), %rax
movq (%rax), %rcx
movq -0x58(%rbp), %rax
subq $0x1, %rax
andq %rax, %rcx
orq -0x58(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x28(%rbp), %rax
movq -0x30(%rbp), %rdi
movq -0x50(%rbp), %rdx
leaq 0x99d68(%rip), %rcx     # 0xa5e80
movsbq (%rcx,%rdx), %rsi
callq *%rax
jmp 0xc094
jmp 0xc126
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0xc05d
movl $0x1, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nop