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

    /*
     * For reading ISO-2022 subsets, we divide up our state
     * variables as follows:
     * 
     * 	- The top byte of s0 (bits 31:24) indicates, if nonzero,
     * 	  that we are part-way through a recognised ISO-2022 escape
     * 	  sequence. Five of those bits (31:27) give the index of
     * 	  the first member of the escapes list matching what we
     * 	  have so far; the remaining three (26:24) give the number
     * 	  of characters we have seen so far.
     * 
     * 	- The top bit of s1 (bit 31) is non-zero at all times, to
     * 	  indicate that we have performed any necessary
     * 	  initialisation. When we start, we detect a zero s1 and
     * 	  respond to it by initialising the default container
     * 	  contents.
     * 
     * 	- The next three bits of s1 (bits 30:28) indicate which
     * 	  _container_ is currently selected. This isn't quite as
     * 	  simple as it sounds, since we have to preserve memory of
     * 	  which of the SI/SO containers we came from when we're
     * 	  temporarily in SS2/SS3. Hence, what happens is:
     *     + bit 28 indicates SI/SO.
     * 	   + if we're in an SS2/SS3 container, that's indicated by
     * 	     the two bits above that being nonzero and holding
     * 	     either 2 or 3.
     * 	   + Hence: 0 is SI, 1 is SO, 4 is SS2-from-SI, 5 is
     * 	     SS2-from-SO, 6 is SS3-from-SI, 7 is SS3-from-SO.
     * 	   + For added fun: in an _8-bit_ ISO 2022 subset, we have
     * 	     the further special value 2, which means that we're
     * 	     theoretically in SI but the current character being
     * 	     accumulated is composed of 8-bit characters and will
     * 	     therefore be interpreted as if in SO.
     * 
     * 	- The next nibble of s1 (27:24) indicates how many bytes
     * 	  have been accumulated in the current character.
     * 
     * 	- The remaining three bytes of s1 are divided into four
     * 	  six-bit sections, and each section gives the current
     * 	  sub-charset selected in one of the possible containers.
     * 	  (Those containers are SI, SO, SS2 and SS3, respectively
     * 	  and in order from the bottom of s0 to the top.)
     * 
     * 	- The bottom 24 bits of s0 give the accumulated character
     * 	  data so far.
     * 
     * (Note that this means s1 contains all the parts of the state
     * which might need to be operated on by escape sequences.
     * Cunning, eh?)
     */

    if (!(state->s1 & 0x80000000)) {
	state->s1 = iso->s1;
    }

    /*
     * So. Firstly, we process escape sequences, if we're in the
     * middle of one or if we see a possible introducer (SI, SO,
     * ESC).
     */
    if ((state->s0 >> 24) ||
	(input_chr == SO || input_chr == SI || input_chr == ESC)) {
	int n = (state->s0 >> 24) & 7, i = (state->s0 >> 27), oi = i, j;

	/*
	 * If this is the start of an escape sequence, we might be
	 * in mid-character. If so, clear the character state and
	 * emit an error token for the incomplete character.
	 */
	if (state->s1 & 0x0F000000) {
	    state->s1 &= ~0x0F000000;
	    state->s0 &= 0xFF000000;
	    /*
	     * If we were in the SS2 or SS3 container, we
	     * automatically exit it.
	     */
	    if (state->s1 & 0x60000000)
		state->s1 &= 0x9FFFFFFF;
	    emit(emitctx, ERROR);
	}

	j = i;
	while (j < iso->nescapes &&
	       !memcmp(iso->escapes[j].sequence,
		       iso->escapes[oi].sequence, n)) {
	    if (iso->escapes[j].sequence[n] < input_chr)
		i = ++j;
	    else
		break;
	}
	if (i >= iso->nescapes ||
	    memcmp(iso->escapes[i].sequence,
		   iso->escapes[oi].sequence, n) ||
	    iso->escapes[i].sequence[n] != input_chr) {
	    /*
	     * This character does not appear in any valid escape
	     * sequence. Therefore, we must emit all the characters
	     * we had previously swallowed, plus this one, and
	     * return to non-escape-sequence state.
	     */
	    for (j = 0; j < n; j++)
		emit(emitctx, iso->escapes[oi].sequence[j]);
	    emit(emitctx, input_chr);
	    state->s0 = 0;
	    return;
	}

	/*
	 * Otherwise, we have found an additional character in our
	 * escape sequence. See if we have reached the _end_ of our
	 * sequence (and therefore must process the sequence).
	 */
	n++;
	if (!iso->escapes[i].sequence[n]) {
	    state->s0 = 0;
	    state->s1 &= iso->escapes[i].andbits;
	    state->s1 ^= iso->escapes[i].xorbits;
	    return;
	}

	/*
	 * Failing _that_, we simply update our escape-sequence-
	 * tracking state.
	 */
	assert(i < 32 && n < 8);
	state->s0 = (i << 27) | (n << 24);
	return;
    }

    /*
     * If this isn't an escape sequence, it must be part of a
     * character. One possibility is that it's a control character
     * (00-20 or 7F-9F; also in non-8-bit ISO 2022 subsets I'm
     * going to treat all top-half characters as controls), in
     * which case we output it verbatim.
     */
    if (input_chr < 0x21 ||
	(input_chr > 0x7E && (!iso->eightbit || input_chr < 0xA0))) {
	/*
	 * We might be in mid-multibyte-character. If so, clear the
	 * character state and emit an error token for the
	 * incomplete character.
	 */
	if (state->s1 & 0x0F000000) {
	    state->s1 &= ~0x0F000000;
	    state->s0 &= 0xFF000000;
	    emit(emitctx, ERROR);
	    /*
	     * If we were in the SS2 or SS3 container, we
	     * automatically exit it.
	     */
	    if (state->s1 & 0x60000000)
		state->s1 &= 0x9FFFFFFF;
	}

	emit(emitctx, input_chr);
	return;
    }

    /*
     * Otherwise, accumulate character data.
     */
    {
	unsigned long chr;
	int chrlen, cont, subcharset, bytes;

	/*
	 * Verify that we've seen the right kind of character for
	 * what we're currently doing. This only matters in 8-bit
	 * subsets.
	 */
	if (iso->eightbit) {
	    cont = (state->s1 >> 28) & 7;
	    /*
	     * If cont==0, we're entitled to see either GL or GR
	     * characters. If cont==2, we expect only GR; otherwise
	     * we expect only GL.
	     * 
	     * If we see a GR character while cont==0, we set
	     * cont=2 immediately.
	     */
	    if ((cont == 2 && !(input_chr & 0x80)) ||
		(cont != 0 && cont != 2 && (input_chr & 0x80))) {
		/*
		 * Clear the previous character; it was prematurely
		 * terminated by this error.
		 */
		state->s1 &= ~0x0F000000;
		state->s0 &= 0xFF000000;
		emit(emitctx, ERROR);
		/*
		 * If we were in the SS2 or SS3 container, we
		 * automatically exit it.
		 */
		if (state->s1 & 0x60000000)
		    state->s1 &= 0x9FFFFFFF;
	    }

	    if (cont == 0 && (input_chr & 0x80)) {
		state->s1 |= 0x20000000;
	    }
	}

	/* The current character and its length. */
	chr = ((state->s0 & 0x00FFFFFF) << 8) | (input_chr & 0x7F);
	chrlen = ((state->s1 >> 24) & 0xF) + 1;
	/* The current sub-charset. */
	cont = (state->s1 >> 28) & 7;
	if (cont > 1) cont >>= 1;
	subcharset = (state->s1 >> (6*cont)) & 0x3F;
	/* The number of bytes-per-character in that sub-charset. */
	bytes = iso->nbytes[subcharset];

	/*
	 * If this character is now complete, we convert and emit
	 * it. Otherwise, we simply update the state and return.
	 */
	if (chrlen >= bytes) {
	    emit(emitctx, iso->to_ucs(subcharset, chr));
	    chr = chrlen = 0;
	    /*
	     * If we were in the SS2 or SS3 container, we
	     * automatically exit it.
	     */
	    if (state->s1 & 0x60000000)
		state->s1 &= 0x9FFFFFFF;
	}
	state->s0 = (state->s0 & 0xFF000000) | chr;
	state->s1 = (state->s1 & 0xF0FFFFFF) | (chrlen << 24);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rcx
movabsq $0x80000000, %rax       # imm = 0x80000000
andq 0x8(%rcx), %rax
cmpq $0x0, %rax
jne 0x9c40
movq -0x30(%rbp), %rax
movq 0x20(%rax), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movq (%rax), %rax
shrq $0x18, %rax
cmpq $0x0, %rax
jne 0x9c6a
cmpq $0xe, -0x10(%rbp)
je 0x9c6a
cmpq $0xf, -0x10(%rbp)
je 0x9c6a
cmpq $0x1b, -0x10(%rbp)
jne 0x9f29
movq -0x18(%rbp), %rax
movq (%rax), %rax
shrq $0x18, %rax
andq $0x7, %rax
movl %eax, -0x34(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
shrq $0x1b, %rax
movl %eax, -0x38(%rbp)
movl -0x38(%rbp), %eax
movl %eax, -0x3c(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
andq $0xf000000, %rax        # imm = 0xF000000
cmpq $0x0, %rax
je 0x9d04
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rcx
andq $-0xf000001, %rcx       # imm = 0xF0FFFFFF
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movabsq $0xff000000, %rcx       # imm = 0xFF000000
andq (%rax), %rcx
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
andq $0x60000000, %rax       # imm = 0x60000000
cmpq $0x0, %rax
je 0x9cf5
movq -0x18(%rbp), %rax
movabsq $0x9fffffff, %rcx       # imm = 0x9FFFFFFF
andq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq *%rax
movl -0x38(%rbp), %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %ecx
movq -0x30(%rbp), %rdx
xorl %eax, %eax
cmpl 0x8(%rdx), %ecx
movb %al, -0x59(%rbp)
jge 0x9d59
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x40(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq (%rax), %rdi
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x3c(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq (%rax), %rsi
movslq -0x34(%rbp), %rdx
callq 0x6060
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
movb %al, -0x59(%rbp)
movb -0x59(%rbp), %al
testb $0x1, %al
jne 0x9d62
jmp 0x9d9b
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x40(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq (%rax), %rax
movslq -0x34(%rbp), %rcx
movsbq (%rax,%rcx), %rax
cmpq -0x10(%rbp), %rax
jge 0x9d94
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
movl %eax, -0x38(%rbp)
jmp 0x9d96
jmp 0x9d9b
jmp 0x9d0a
movl -0x38(%rbp), %eax
movq -0x30(%rbp), %rcx
cmpl 0x8(%rcx), %eax
jge 0x9e03
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x38(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq (%rax), %rdi
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x3c(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq (%rax), %rsi
movslq -0x34(%rbp), %rdx
callq 0x6060
cmpl $0x0, %eax
jne 0x9e03
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x38(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq (%rax), %rax
movslq -0x34(%rbp), %rcx
movsbq (%rax,%rcx), %rax
cmpq -0x10(%rbp), %rax
je 0x9e63
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x9e45
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rcx
movq (%rcx), %rcx
movslq -0x3c(%rbp), %rdx
shlq $0x5, %rdx
addq %rdx, %rcx
movq (%rcx), %rcx
movslq -0x40(%rbp), %rdx
movsbq (%rcx,%rdx), %rsi
callq *%rax
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x9e0a
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq *%rax
movq -0x18(%rbp), %rax
movq $0x0, (%rax)
jmp 0xa1f1
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x38(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq (%rax), %rax
movslq -0x34(%rbp), %rcx
cmpb $0x0, (%rax,%rcx)
jne 0x9edf
movq -0x18(%rbp), %rax
movq $0x0, (%rax)
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x38(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rcx
movq -0x18(%rbp), %rax
andq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
movq -0x30(%rbp), %rax
movq (%rax), %rax
movslq -0x38(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq 0x10(%rax), %rcx
movq -0x18(%rbp), %rax
xorq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
jmp 0xa1f1
cmpl $0x20, -0x38(%rbp)
jge 0x9eed
cmpl $0x8, -0x34(%rbp)
jge 0x9eed
jmp 0x9f0c
leaq 0x54e22(%rip), %rdi     # 0x5ed16
leaq 0x54e2b(%rip), %rsi     # 0x5ed26
movl $0xdd, %edx
leaq 0x54e2a(%rip), %rcx     # 0x5ed31
callq 0x6050
movl -0x38(%rbp), %eax
shll $0x1b, %eax
movl -0x34(%rbp), %ecx
shll $0x18, %ecx
orl %ecx, %eax
movslq %eax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
jmp 0xa1f1
cmpq $0x21, -0x10(%rbp)
jl 0x9f53
cmpq $0x7e, -0x10(%rbp)
jle 0x9fdc
movq -0x30(%rbp), %rax
cmpl $0x0, 0x30(%rax)
je 0x9f53
cmpq $0xa0, -0x10(%rbp)
jge 0x9fdc
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
andq $0xf000000, %rax        # imm = 0xF000000
cmpq $0x0, %rax
je 0x9fc9
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rcx
andq $-0xf000001, %rcx       # imm = 0xF0FFFFFF
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movabsq $0xff000000, %rcx       # imm = 0xFF000000
andq (%rax), %rcx
movq %rcx, (%rax)
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq *%rax
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
andq $0x60000000, %rax       # imm = 0x60000000
cmpq $0x0, %rax
je 0x9fc7
movq -0x18(%rbp), %rax
movabsq $0x9fffffff, %rcx       # imm = 0x9FFFFFFF
andq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
jmp 0x9fc9
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq *%rax
jmp 0xa1f1
movq -0x30(%rbp), %rax
cmpl $0x0, 0x30(%rax)
je 0xa0bc
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
shrq $0x1c, %rax
andq $0x7, %rax
movl %eax, -0x50(%rbp)
cmpl $0x2, -0x50(%rbp)
jne 0xa013
movq -0x10(%rbp), %rax
andq $0x80, %rax
cmpq $0x0, %rax
je 0xa02f
cmpl $0x0, -0x50(%rbp)
je 0xa091
cmpl $0x2, -0x50(%rbp)
je 0xa091
movq -0x10(%rbp), %rax
andq $0x80, %rax
cmpq $0x0, %rax
je 0xa091
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rcx
andq $-0xf000001, %rcx       # imm = 0xF0FFFFFF
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movabsq $0xff000000, %rcx       # imm = 0xFF000000
andq (%rax), %rcx
movq %rcx, (%rax)
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq *%rax
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
andq $0x60000000, %rax       # imm = 0x60000000
cmpq $0x0, %rax
je 0xa08f
movq -0x18(%rbp), %rax
movabsq $0x9fffffff, %rcx       # imm = 0x9FFFFFFF
andq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
jmp 0xa091
cmpl $0x0, -0x50(%rbp)
jne 0xa0ba
movq -0x10(%rbp), %rax
andq $0x80, %rax
cmpq $0x0, %rax
je 0xa0ba
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rcx
orq $0x20000000, %rcx       # imm = 0x20000000
movq %rcx, 0x8(%rax)
jmp 0xa0bc
movq -0x18(%rbp), %rax
movq (%rax), %rax
andq $0xffffff, %rax         # imm = 0xFFFFFF
shlq $0x8, %rax
movq -0x10(%rbp), %rcx
andq $0x7f, %rcx
orq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
shrq $0x18, %rax
andq $0xf, %rax
addq $0x1, %rax
movl %eax, -0x4c(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
shrq $0x1c, %rax
andq $0x7, %rax
movl %eax, -0x50(%rbp)
cmpl $0x1, -0x50(%rbp)
jle 0xa114
movl -0x50(%rbp), %eax
sarl %eax
movl %eax, -0x50(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
imull $0x6, -0x50(%rbp), %ecx
movl %ecx, %ecx
shrq %cl, %rax
andq $0x3f, %rax
movl %eax, -0x54(%rbp)
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0x54(%rbp), %rcx
movsbl (%rax,%rcx), %eax
movl %eax, -0x58(%rbp)
movl -0x4c(%rbp), %eax
cmpl -0x58(%rbp), %eax
jl 0xa1b0
movq -0x20(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x30(%rbp), %rax
movq 0x38(%rax), %rax
movl -0x54(%rbp), %edi
movq -0x48(%rbp), %rsi
callq *%rax
movq -0x70(%rbp), %rdi
movq %rax, %rsi
movq -0x68(%rbp), %rax
callq *%rax
movl $0x0, -0x4c(%rbp)
movq $0x0, -0x48(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
andq $0x60000000, %rax       # imm = 0x60000000
cmpq $0x0, %rax
je 0xa1ae
movq -0x18(%rbp), %rax
movabsq $0x9fffffff, %rcx       # imm = 0x9FFFFFFF
andq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
jmp 0xa1b0
movq -0x18(%rbp), %rax
movabsq $0xff000000, %rcx       # imm = 0xFF000000
andq (%rax), %rcx
orq -0x48(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
movabsq $0xf0ffffff, %rcx       # imm = 0xF0FFFFFF
andq 0x8(%rax), %rcx
movl -0x4c(%rbp), %eax
shll $0x18, %eax
cltq
orq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
addq $0x70, %rsp
popq %rbp
retq
nopw (%rax,%rax)