// File: andrakis[P]alisp/contrib/linenoise-ng/src/ConvertUTF.cpp
// Function: linenoise_ng::ConvertUTF32toUTF16(unsigned int const**, unsigned int const*, char16_t**, char16_t*, linenoise_ng::ConversionFlags)
ConversionResult ConvertUTF32toUTF16 (
        const UTF32** sourceStart, const UTF32* sourceEnd, 
        char16_t** targetStart, char16_t* targetEnd, ConversionFlags flags) {
    ConversionResult result = conversionOK;
    const UTF32* source = *sourceStart;
    char16_t* target = *targetStart;
    while (source < sourceEnd) {
        UTF32 ch;
        if (target >= targetEnd) {
            result = targetExhausted; break;
        }
        ch = *source++;
        if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
            /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
                if (flags == strictConversion) {
                    --source; /* return to the illegal value itself */
                    result = sourceIllegal;
                    break;
                } else {
                    *target++ = UNI_REPLACEMENT_CHAR;
                }
            } else {
                *target++ = (UTF16)ch; /* normal case */
            }
        } else if (ch > UNI_MAX_LEGAL_UTF32) {
            if (flags == strictConversion) {
                result = sourceIllegal;
            } else {
                *target++ = UNI_REPLACEMENT_CHAR;
            }
        } else {
            /* target is a character in range 0xFFFF - 0x10FFFF. */
            if (target + 1 >= targetEnd) {
                --source; /* Back up source pointer! */
                result = targetExhausted; break;
            }
            ch -= halfBase;
            *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
            *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
        }
    }
    *sourceStart = source;
    *targetStart = target;
    return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movl $0x0, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
cmpq -0x10(%rbp), %rax
jae 0x1c32e
movq -0x38(%rbp), %rax
cmpq -0x20(%rbp), %rax
jb 0x1c209
movl $0x2, -0x28(%rbp)
jmp 0x1c32e
movq -0x30(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x30(%rbp)
movl (%rax), %eax
movl %eax, -0x3c(%rbp)
cmpl $0xffff, -0x3c(%rbp)    # imm = 0xFFFF
ja 0x1c289
cmpl $0xd800, -0x3c(%rbp)    # imm = 0xD800
jb 0x1c26c
cmpl $0xdfff, -0x3c(%rbp)    # imm = 0xDFFF
ja 0x1c26c
cmpl $0x0, -0x24(%rbp)
jne 0x1c256
movq -0x30(%rbp), %rax
addq $-0x4, %rax
movq %rax, -0x30(%rbp)
movl $0x3, -0x28(%rbp)
jmp 0x1c32e
movq -0x38(%rbp), %rax
movq %rax, %rcx
addq $0x2, %rcx
movq %rcx, -0x38(%rbp)
movw $0xfffd, (%rax)         # imm = 0xFFFD
jmp 0x1c284
movl -0x3c(%rbp), %eax
movw %ax, %cx
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x2, %rdx
movq %rdx, -0x38(%rbp)
movw %cx, (%rax)
jmp 0x1c329
cmpl $0x10ffff, -0x3c(%rbp)  # imm = 0x10FFFF
jbe 0x1c2b7
cmpl $0x0, -0x24(%rbp)
jne 0x1c2a1
movl $0x3, -0x28(%rbp)
jmp 0x1c2b5
movq -0x38(%rbp), %rax
movq %rax, %rcx
addq $0x2, %rcx
movq %rcx, -0x38(%rbp)
movw $0xfffd, (%rax)         # imm = 0xFFFD
jmp 0x1c327
movq -0x38(%rbp), %rax
addq $0x2, %rax
cmpq -0x20(%rbp), %rax
jb 0x1c2da
movq -0x30(%rbp), %rax
addq $-0x4, %rax
movq %rax, -0x30(%rbp)
movl $0x2, -0x28(%rbp)
jmp 0x1c32e
movl -0x3c(%rbp), %eax
subl $0x10000, %eax          # imm = 0x10000
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
shrl $0xa, %eax
addl $0xd800, %eax           # imm = 0xD800
movw %ax, %cx
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x2, %rdx
movq %rdx, -0x38(%rbp)
movw %cx, (%rax)
movl -0x3c(%rbp), %eax
andl $0x3ff, %eax            # imm = 0x3FF
addl $0xdc00, %eax           # imm = 0xDC00
movw %ax, %cx
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x2, %rdx
movq %rdx, -0x38(%rbp)
movw %cx, (%rax)
jmp 0x1c329
jmp 0x1c1e5
movq -0x30(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, (%rax)
movq -0x38(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movl -0x28(%rbp), %eax
popq %rbp
retq
nopl (%rax)