// File: /workspace/github_c_makefile_star2_O3/mloar[P]charset/euc.c
// Function: read_euc
static void read_euc(charset_spec const *charset, long int input_chr,
		     charset_state *state,
		     void (*emit)(void *ctx, long int output), void *emitctx)
{
    struct euc const *euc = (struct euc *)charset->data;

    /*
     * For EUC input, our state variable divides into three parts:
     * 
     * 	- Topmost nibble (bits 31:28) is nonzero if we're
     * 	  accumulating a multibyte character, and it indicates
     * 	  which section we're in: 1 for GR chars, 2 for things
     * 	  beginning with SS2, 3 for things beginning with SS3.
     * 
     * 	- Next nibble (bits 27:24) indicates how many bytes of the
     * 	  character we've accumulated so far.
     * 
     * 	- The rest (bits 23:0) are those bytes in full, accumulated
     * 	  as a large integer (so that seeing A1 A2 A3, in a
     * 	  hypothetical EUC whose GR encoding is three-byte, runs
     * 	  our state variable from 0 -> 0x110000A1 -> 0x1200A1A2 ->
     * 	  0x13A1A2A3, at which point it gets translated and output
     * 	  and resets to zero).
     */

    if (state->s0 != 0) {

	/*
	 * At this point, no matter whether we had an SS2 or SS3
	 * introducer or not, we _always_ expect a GR character.
	 * Anything else causes us to emit ERROR for an incomplete
	 * character, and then reset to state 0 to process the
	 * character in its own way.
	 */
	if (input_chr < 0xA1 || input_chr == 0xFF) {
	    emit(emitctx, ERROR);
	    state->s0 = 0;
	} else
	    state->s0 = (((state->s0 & 0xFF000000) + 0x01000000) |
			 ((state->s0 & 0x0000FFFF) << 8) | input_chr);

    }

    if (state->s0 == 0) {
	/*
	 * The input character determines which of the four
	 * possible charsets we're going to be in.
	 */
	if (input_chr < 0x80) {	       /* this is always ASCII */
	    emit(emitctx, input_chr);
	} else if (input_chr == 0x8E) {/* SS2 means charset 2 */
	    state->s0 = 0x20000000;
	} else if (input_chr == 0x8F) {/* SS3 means charset 3 */
	    state->s0 = 0x30000000;
	} else if (input_chr < 0xA1 || input_chr == 0xFF) {   /* errors */
	    emit(emitctx, ERROR);
	} else {		       /* A1-FE means charset 1 */
	    state->s0 = 0x11000000 | input_chr;
	}
    }

    /*
     * Finally, if we have accumulated a complete character, output
     * it.
     */
    if (state->s0 != 0 &&
	((state->s0 & 0x0F000000) >> 24) >=
	(unsigned)euc->nchars[(state->s0 >> 28)-1]) {
	emit(emitctx, euc->to_ucs(state->s0));
	state->s0 = 0;
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq %r8, %r15
movq %rcx, %r14
movq %rdx, %rbx
movq %rsi, %r12
movq 0x18(%rdi), %r13
movq (%rdx), %rax
testq %rax, %rax
je 0x6947
cmpq $0xa1, %r12
setge %cl
cmpq $0xff, %r12
setne %dl
testb %dl, %cl
jne 0x697f
movl $0xffff, %esi           # imm = 0xFFFF
movq %r15, %rdi
callq *%r14
movq $0x0, (%rbx)
cmpq $0x80, %r12
jge 0x6966
movq %r12, %rsi
movq %r15, %rdi
callq *%r14
movq (%rbx), %rdi
testq %rdi, %rdi
jne 0x69ce
jmp 0x69f8
cmpq $0x8e, %r12
je 0x699d
cmpq $0x8f, %r12
jne 0x69a4
movl $0x30000000, %edi       # imm = 0x30000000
jmp 0x69cb
movl %eax, %ecx
andl $0xff000000, %ecx       # imm = 0xFF000000
movzwl %ax, %eax
shll $0x8, %eax
leaq (%rcx,%rax), %rdi
addq $0x1000000, %rdi        # imm = 0x1000000
orq %r12, %rdi
jmp 0x69cb
movl $0x20000000, %edi       # imm = 0x20000000
jmp 0x69cb
cmpq $0xa1, %r12
setb %al
cmpq $0xff, %r12
sete %cl
orb %al, %cl
movl $0xffff, %esi           # imm = 0xFFFF
jne 0x6953
orq $0x11000000, %r12       # imm = 0x11000000
movq %r12, %rdi
movq %rdi, (%rbx)
movl %edi, %eax
shrl $0x18, %eax
andl $0xf, %eax
movq %rdi, %rcx
shrq $0x1c, %rcx
cmpl -0x4(%r13,%rcx,4), %eax
jb 0x69f8
callq *0x10(%r13)
movq %r15, %rdi
movq %rax, %rsi
callq *%r14
movq $0x0, (%rbx)
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq