// File: /workspace/github_cpp_makefile_star2_O1/0x6D70[P]chip8_emu/src/cpu.cpp
// Function: Cpu::run(SDL_Renderer*)
void Cpu::run(SDL_Renderer *renderer) {

    bool isFinished = false;
    bool update_video = false;
    uint64_t instruction_count = 0;

    SDL_Event event;

    // variable for keyboard
    bool keys[0x10] = {false};
    

    while (!isFinished) {
        instruction_count++;

        uint16_t opcode = this->mem_read_u16(this->state.pc);
        this->state.pc += 2;

        //  uncomment for single stepping
        // std::cout << "0x" << std::hex << opcode;
        // getchar();

        uint8_t opcode_n3 = opcode & 0xf;
        uint8_t opcode_n2 = (opcode >> 4) & 0xf;
        uint8_t opcode_n1 = (opcode >> 8) & 0xf;
        uint8_t opcode_n0 = (opcode >> 12) & 0xf;

        switch (opcode_n0) {
            case 0x0: {
                if (opcode == 0x00e0) {
                    // cls
                    update_video = true;
                    for (int y = 0; y < VIDEO_HEIGHT; y++) {
                        for (int x = 0; x < VIDEO_WIDTH; x++) {
                            this->state.video[x][y] = false;
                        }
                    }
                } else if (opcode == 0x00ee) {
                    // ret
                    this->state.pc = this->state.call_stack.top();
                    this->state.call_stack.pop();
                } else {
                    // sys addr
                    // this instruction is ignored
                    // http://devernay.free.fr/hacks/chip8/C8TECH10.HTM#0nnn
                }
                break;
            }
            case 0x1: {
                // JP addr
                this->state.pc = opcode & 0xfff;
                break;
            }
            case 0x2: {
                // CALL addr
                this->state.call_stack.push(this->state.pc);
                this->state.pc = opcode & 0xfff;
                break;
            }
            case 0x3: {
                // SE Vx, byte
                if (this->state.regs[opcode_n1] == (uint8_t)(opcode & 0xff)) {
                    // skip instruction
                    this->state.pc += 2;
                }
                break;
            }
            case 0x4: {
                // SNE Vx, byte
                if (this->state.regs[opcode_n1] != (uint8_t)(opcode & 0xff)) {
                    // skip instruction
                    this->state.pc += 2;
                }
                break;
            }
            case 0x5: {
                // SE Vx, Vy
                if (this->state.regs[opcode_n1] == this->state.regs[opcode_n2]) {
                    // skip instruction
                    this->state.pc += 2;
                }
                break;
            }
            case 0x6: {
                // ld vx,byte
                this->state.regs[opcode_n1] = (uint8_t)(opcode & 0xff);
                break;
            }
            case 0x7: {
                // ADD Vx, byte
                this->state.regs[opcode_n1] += (opcode & 0xff);
                break;
            }
            case 0x8: {
                // logical and arithmetic instruction
                switch (opcode_n3) {
                    case 0x0: {
                        this->state.regs[opcode_n1] = this->state.regs[opcode_n2];
                        break;
                    }
                    case 0x1: {
                        this->state.regs[opcode_n1] |= this->state.regs[opcode_n2];
                        break;
                    }
                    case 0x2: {
                        this->state.regs[opcode_n1] &= this->state.regs[opcode_n2];
                        break;
                    }
                    case 0x3: {
                        this->state.regs[opcode_n1] ^= this->state.regs[opcode_n2];
                        break;
                    }
                    case 0x4: {
                        // check overflow
                        if ((uint16_t)this->state.regs[opcode_n1] + (uint16_t)this->state.regs[opcode_n2] > 0xff) {
                            this->state.regs[0xf] = 1;
                        } else {
                            this->state.regs[0xf] = 0;
                        }

                        this->state.regs[opcode_n1] += this->state.regs[opcode_n2];
                        break;
                    }
                    case 0x5: {
                        if (this->state.regs[opcode_n1] > this->state.regs[opcode_n2]) {
                            this->state.regs[0xf] = 1;
                        } else {
                            this->state.regs[0xf] = 0;
                        }

                        this->state.regs[opcode_n1] -= this->state.regs[opcode_n2];
                        break;
                    }
                    case 0x6: {
                        this->state.regs[opcode_n1] = this->state.regs[opcode_n2];
                        // shift right

                        this->state.regs[0xf] = this->state.regs[opcode_n1] & 1;
                        this->state.regs[opcode_n1] >>= 1;

                        break;
                    }
                    case 0x7: {
                        if (this->state.regs[opcode_n2] > this->state.regs[opcode_n1]) {
                            this->state.regs[0xf] = 1;
                        } else {
                            this->state.regs[0xf] = 0;
                        }
                        
                        this->state.regs[opcode_n1] = this->state.regs[opcode_n2] - this->state.regs[opcode_n1];
                        break;
                    }
                    case 0xe: {
                        this->state.regs[opcode_n1] = this->state.regs[opcode_n2];
                        // shift left

                        this->state.regs[0xf] = (this->state.regs[opcode_n1] >> 7) & 1;
                        this->state.regs[opcode_n1] <<= 1;

                        break;
                    }
                }
                break;
            }
            case 0x9: {
                // SNE Vx, Vy
                if (this->state.regs[opcode_n1] != this->state.regs[opcode_n2]) {
                    // skip instruction
                    this->state.pc += 2;
                }
                break;
            }
            case 0xa: {
                // ld l, addr
                this->state.l = opcode & 0xfff;
                break;
            }
            case 0xb: {
                // Bnnn - JP V0, addr
                this->state.pc = (opcode & 0xfff) + this->state.regs[0x0];
                break;
            }
            case 0xc: {
                // Cxkk - RND Vx, byte
                this->state.regs[opcode_n1] = (uint8_t)(rand() & (opcode & 0xff));
                break;
            }
            case 0xd: {
                // DXYN
                uint8_t x_base = this->state.regs[opcode_n1] % 64;
                uint8_t y_base = this->state.regs[opcode_n2] % 32;
                this->state.regs[0xf] = 0;
                update_video = true;

                for (int n = 0; n < opcode_n3; n++) {
                    uint8_t pixels = this->state.ram[this->state.l + n];

                    for (int x = 0; x < 8; x++) {
                        if (pixels & (0x80 >> x)) {
                            // current bit is one

                            if (this->state.video[x_base + x][y_base + n]) {
                                this->state.regs[0xf] = 1;
                                // flip bit
                                this->state.video[x_base + x][y_base + n] = false;
                            } else {
                                this->state.video[x_base + x][y_base + n] = true;
                            }
                        }
                    }

                }

                break;
            }
            case 0xe: {
                switch (opcode & 0xff) {
                    case 0x9e: {
                        // Ex9E - SKP Vx
                        uint8_t index = this->state.regs[opcode_n1] & 0xf;
                        if (keys[index])
                            this->state.pc += 2;
                        break;
                    }
                    case 0xa1: {
                        // ExA1 - SKNP Vx
                        uint8_t index = this->state.regs[opcode_n1] & 0xf;
                        if (!keys[index])
                            this->state.pc += 2;
                        break;
                    }
                }
                break;
            }
            case 0xf: {

                switch (opcode & 0xff) { 
                    case 0x7: {
                        // LD Vx, DT
                        this->state.regs[opcode_n1] = this->state.delay_timer;
                        break;
                    }
                    case 0xa: {
                        // LD Vx, K
                        // wait until key is pressed
                        // when the key is pressed, put it into Vx

                        if (isKeyPressed(keys)) {
                            for (int i = 0; i < 0x10; i++) {
                                if (keys[i]) {
                                    this->state.regs[opcode_n1] = i;
                                }
                            }
                        } else {
                            // decrement pc to hit this instruction again
                            this->state.pc -= 2;
                        }
                        break;
                    }
                    case 0x15: {
                        // LD DT, Vx
                        this->state.delay_timer = this->state.regs[opcode_n1];
                        break;
                    }
                    case 0x18: {
                        // LD ST, Vx
                        this->state.sound_timer = this->state.regs[opcode_n1];
                        break;
                    }
                    case 0x1e: {
                        // ADD I, Vx
                        this->state.l += this->state.regs[opcode_n1];

                        if (this->state.l > 0xfff) {
                            this->state.regs[0xf] = 1;
                        } else {
                            this->state.regs[0xf] = 0;
                        }

                        this->state.l &= 0xfff;
                        break;
                    }
                    case 0x29: {
                        // LD F, Vx
                        this->state.l = 0x50 + (opcode & 0xff) * 5;
                        break;
                    }
                    case 0x33: {
                        // Fx33 - LD B, Vx
                        // Binary-coded decimal conversion

                        this->state.ram[this->state.l + 0] = this->state.regs[opcode_n1] / 100;
                        this->state.ram[this->state.l + 1] = (this->state.regs[opcode_n1] / 10) % 10;
                        this->state.ram[this->state.l + 2] = this->state.regs[opcode_n1] % 10;

                        break;
                    }
                    case 0x55: {
                        // LD [I], Vx

                        for (int i = 0; i <= opcode_n1; i++) {
                            this->state.ram[this->state.l + i] = this->state.regs[i];
                        }

                        break;
                    }
                    case 0x65: {
                        // LD Vx, [I]

                        for (int i = 0; i <= opcode_n1; i++) {
                            this->state.regs[i] = this->state.ram[this->state.l + i];
                        }

                        break;
                    }
                }
                break;
            }
            default:
                std::cout << "missing instruction 0x" << std::hex << (int)opcode_n0 << std::endl;
                isFinished = true;
        }

        // update timers

        if (instruction_count % 10  == 0) {
            // ownly decrease every 10 instructions which should be a rate of about ~60 times a second

            if (this->state.delay_timer > 0)
                this->state.delay_timer--;
            if (this->state.sound_timer > 0)
                this->state.sound_timer--;
        }

        if (update_video || instruction_count % 0x100 == 0) {
            // video array has changed => update window

            SDL_RenderClear(renderer);

            for (int y = 0; y < VIDEO_HEIGHT; y++) {
                for (int x = 0; x < VIDEO_WIDTH; x++) {
                    if (this->state.video[x][y]) {
                        // white
                        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
                    } else {
                        // black
                        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
                    }

                    SDL_Rect rect;
                    rect.h = VIDEO_MULTI;
                    rect.w = VIDEO_MULTI;
                    rect.x = x * VIDEO_MULTI;
                    rect.y = y * VIDEO_MULTI;

                    SDL_RenderFillRect(renderer, &rect);
                }
            }

            SDL_RenderPresent(renderer);

            update_video = false;
        }

        while(SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    isFinished = true;
                    break;
                case SDL_KEYDOWN: {
                    uint8_t index = keysym_to_index(event.key.keysym);

                    if (index < 0x10) {
                        keys[index] = true;
                    }
                    
                    break;
                }
                case SDL_KEYUP: {
                    uint8_t index = keysym_to_index(event.key.keysym);

                    if (index < 0x10) {
                        keys[index] = false;
                    }

                    break;
                }
            }
        }

        SDL_Delay(1);
    }

    std::cout << "Exited after 0x" << std::hex << (long)instruction_count << " instructions\n";
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %rsi, -0xa0(%rbp)
movq %rdi, %r15
xorps %xmm0, %xmm0
movaps %xmm0, -0x80(%rbp)
leaq 0x1860(%rdi), %rax
movq %rax, -0x38(%rbp)
leaq 0x1000(%rdi), %rax
movq %rax, -0x90(%rbp)
leaq 0x1810(%rdi), %rax
movq %rax, -0x98(%rbp)
leaq 0x1010(%rdi), %rax
movq %rax, -0x88(%rbp)
xorl %r14d, %r14d
xorl %ebx, %ebx
xorl %r13d, %r13d
movq %rdi, -0xa8(%rbp)
movq %r14, -0x30(%rbp)
movzwl 0x1860(%r15), %eax
movzbl (%r15,%rax), %esi
movl %esi, %r14d
shll $0x8, %r14d
leal 0x1(%rax), %ecx
movzwl %cx, %ecx
movzbl (%r15,%rcx), %r12d
orl %r12d, %r14d
leal 0x2(%rax), %edi
movw %di, 0x1860(%r15)
movl %r12d, %edx
andl $0xf, %edx
movl %r12d, %ecx
shrl $0x4, %ecx
movl %esi, %r9d
andl $0xf, %r9d
shrl $0x4, %esi
leaq 0x194b(%rip), %r8       # 0x4088
movslq (%r8,%rsi,4), %rsi
addq %r8, %rsi
jmpq *%rsi
cmpl $0xee, %r14d
je 0x2c74
cmpl $0xe0, %r14d
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
jne 0x2a8e
movq -0x88(%rbp), %rax
xorl %ecx, %ecx
xorl %edx, %edx
movb $0x0, (%rax,%rdx)
addq $0x20, %rdx
cmpq $0x800, %rdx            # imm = 0x800
jne 0x2773
incq %rcx
incq %rax
movb $0x1, %bl
cmpq $0x20, %rcx
jne 0x2771
jmp 0x2a8e
cmpl $0xa1, %r12d
je 0x2c46
cmpl $0x9e, %r12d
jne 0x2a86
movzbl 0x1000(%r15,%r9), %ecx
andl $0xf, %ecx
cmpb $0x1, -0x80(%rbp,%rcx)
jmp 0x2c57
andl $0xfff, %r14d           # imm = 0xFFF
movzbl 0x1000(%r15), %eax
addl %r14d, %eax
movw %ax, 0x1860(%r15)
jmp 0x2a86
cmpb %r12b, 0x1000(%r15,%r9)
jne 0x290a
jmp 0x2a86
movq %r9, %r14
callq 0x20b0
andb %r12b, %al
movb %al, 0x1000(%r15,%r14)
jmp 0x2a86
movb 0x1000(%r15,%r9), %dl
cmpb 0x1000(%r15,%rcx), %dl
jne 0x290a
jmp 0x2a86
movq 0x1840(%r15), %rax
movq 0x1850(%r15), %rcx
addq $-0x2, %rcx
cmpq %rcx, %rax
je 0x2a67
movw %di, (%rax)
addq $0x2, %rax
movq %rax, 0x1840(%r15)
movq -0x38(%rbp), %r12
jmp 0x2a7a
cmpl $0x1d, %r12d
jle 0x2a03
cmpl $0x32, %r12d
jle 0x2cdf
cmpl $0x33, %r12d
je 0x2d62
cmpl $0x55, %r12d
je 0x2e71
cmpl $0x65, %r12d
jne 0x2a86
incb %r9b
movzbl %r9b, %eax
movq -0x90(%rbp), %rcx
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
movzwl 0x1862(%r15), %edx
movb -0x1000(%rcx,%rdx), %dl
movb %dl, (%rcx)
incq %rcx
decq %rax
jne 0x28a6
jmp 0x2a8e
cmpb %r12b, 0x1000(%r15,%r9)
je 0x290a
jmp 0x2a86
addb %r12b, 0x1000(%r15,%r9)
jmp 0x2a86
andl $0xfff, %r14d           # imm = 0xFFF
movq -0x38(%rbp), %rax
movw %r14w, (%rax)
jmp 0x2a86
movb 0x1000(%r15,%r9), %dl
cmpb 0x1000(%r15,%rcx), %dl
jne 0x2a86
addl $0x4, %eax
movq -0x38(%rbp), %rcx
movw %ax, (%rcx)
jmp 0x2a86
movzbl 0x1000(%r15,%r9), %eax
movzbl 0x1000(%r15,%rcx), %ecx
movb $0x0, 0x100f(%r15)
movb $0x1, %bl
testb %dl, %dl
je 0x2a86
andl $0x1f, %ecx
andl $0x3f, %eax
movzwl 0x1862(%r15), %esi
shll $0x5, %eax
orq %rcx, %rax
addq -0x88(%rbp), %rax
xorl %edi, %edi
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
leaq (%rdi,%rsi), %rcx
movzbl (%r15,%rcx), %r8d
movq %rax, %r9
xorl %ecx, %ecx
movl %r8d, %r10d
shll %cl, %r10d
testb %r10b, %r10b
jns 0x2992
movb $0x1, %r10b
cmpb $0x1, (%r9)
jne 0x298f
movb $0x1, 0x100f(%r15)
xorl %r10d, %r10d
movb %r10b, (%r9)
incq %rcx
addq $0x20, %r9
cmpq $0x8, %rcx
jne 0x2970
incq %rdi
incq %rax
cmpq %rdx, %rdi
jne 0x2962
movb $0x1, %bl
jmp 0x2a8e
movb %r12b, 0x1000(%r15,%r9)
jmp 0x2a86
andl $0xfff, %r14d           # imm = 0xFFF
movw %r14w, 0x1862(%r15)
jmp 0x2a86
cmpb $0xe, %dl
ja 0x2a86
movzbl %dl, %eax
leaq 0x16e3(%rip), %rdx      # 0x40c8
movslq (%rdx,%rax,4), %rax
addq %rdx, %rax
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
jmpq *%rax
movb 0x1000(%r15,%rcx), %al
jmp 0x2f65
cmpl $0x14, %r12d
jg 0x2cbb
cmpl $0x7, %r12d
je 0x2d17
cmpl $0xa, %r12d
jne 0x2a86
cmpb $0x0, -0x80(%rbp)
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
jne 0x2a4b
xorl %edx, %edx
movq %rdx, %rcx
cmpq $0xf, %rdx
je 0x2a41
leaq 0x1(%rcx), %rdx
cmpb $0x1, -0x7f(%rbp,%rcx)
jne 0x2a2d
cmpq $0xe, %rcx
ja 0x2f8f
xorl %eax, %eax
cmpb $0x1, -0x80(%rbp,%rax)
jne 0x2a5c
movb %al, 0x1000(%r15,%r9)
incq %rax
cmpq $0x10, %rax
jne 0x2a4d
jmp 0x2a8e
movq -0x98(%rbp), %rdi
movq -0x38(%rbp), %r12
movq %r12, %rsi
callq 0x3352
andl $0xfff, %r14d           # imm = 0xFFF
movw %r14w, (%r12)
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
incq %r13
movq %r13, %rax
movabsq $-0x3333333333333333, %rcx # imm = 0xCCCCCCCCCCCCCCCD
imulq %rcx, %rax
rorq %rax
movabsq $0x1999999999999999, %rcx # imm = 0x1999999999999999
cmpq %rcx, %rax
ja 0x2adc
movb 0x1864(%r15), %al
testb %al, %al
je 0x2ac8
decb %al
movb %al, 0x1864(%r15)
movb 0x1865(%r15), %al
testb %al, %al
je 0x2adc
decb %al
movb %al, 0x1865(%r15)
testb %r13b, %r13b
sete %al
orb %bl, %al
testb $0x1, %al
je 0x2c21
movq %r13, -0xb0(%rbp)
movq -0xa0(%rbp), %rdi
movq %rdi, %r12
callq 0x21d0
movq -0x88(%rbp), %r14
xorl %eax, %eax
movq %rax, -0xb8(%rbp)
leal (,%rax,4), %eax
leal (%rax,%rax,4), %r15d
movq %r14, -0xc0(%rbp)
xorl %ebx, %ebx
cmpb $0x1, (%r14)
jne 0x2b43
movq %r12, %r13
movq %r12, %rdi
movl $0xff, %esi
movl $0xff, %edx
movl $0xff, %ecx
jmp 0x2b4f
movq %r12, %r13
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
movl $0xff, %r8d
callq 0x2260
movabsq $0x1400000014, %rax     # imm = 0x1400000014
movq %rax, -0xc8(%rbp)
movl %ebx, -0xd0(%rbp)
movl %r15d, -0xcc(%rbp)
movq %r13, %rdi
leaq -0xd0(%rbp), %rsi
callq 0x2100
addq $0x14, %rbx
addq $0x20, %r14
cmpq $0x500, %rbx            # imm = 0x500
jne 0x2b26
movq -0xb8(%rbp), %rax
incq %rax
movq -0xc0(%rbp), %r14
incq %r14
cmpq $0x20, %rax
jne 0x2b0b
movq %r12, %rdi
callq 0x2080
xorl %ebx, %ebx
movq -0xa8(%rbp), %r15
movq -0xb0(%rbp), %r13
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
jmp 0x2c21
movl -0x70(%rbp), %eax
cmpl $0x301, %eax            # imm = 0x301
je 0x2c0c
cmpl $0x300, %eax            # imm = 0x300
je 0x2bf5
cmpl $0x100, %eax            # imm = 0x100
jne 0x2c21
movb $0x1, %r14b
jmp 0x2c21
movq -0x60(%rbp), %rdi
callq 0x25e0
cmpb $0xf, %al
ja 0x2c21
movzbl %al, %eax
movb $0x1, -0x80(%rbp,%rax)
jmp 0x2c21
movq -0x60(%rbp), %rdi
callq 0x25e0
cmpb $0xf, %al
ja 0x2c21
movzbl %al, %eax
movb $0x0, -0x80(%rbp,%rax)
movq %r12, %rdi
callq 0x2130
testl %eax, %eax
jne 0x2bd8
movl $0x1, %edi
callq 0x2160
testb $0x1, %r14b
je 0x26ef
jmp 0x2f9b
movzbl 0x1000(%r15,%r9), %ecx
andl $0xf, %ecx
cmpb $0x0, -0x80(%rbp,%rcx)
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
jne 0x2a8e
addl $0x4, %eax
movq -0x38(%rbp), %rcx
movw %ax, (%rcx)
jmp 0x2a8e
movq 0x1840(%r15), %rax
cmpq 0x1848(%r15), %rax
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
jne 0x2c9f
movq 0x1858(%r15), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movzwl -0x2(%rax), %eax
movq -0x38(%rbp), %rcx
movw %ax, (%rcx)
movq -0x98(%rbp), %rdi
callq 0x32fc
jmp 0x2a8e
cmpl $0x15, %r12d
je 0x2d2b
cmpl $0x18, %r12d
jne 0x2a86
movb 0x1000(%r15,%r9), %al
movb %al, 0x1865(%r15)
jmp 0x2a86
cmpl $0x1e, %r12d
je 0x2dde
cmpl $0x29, %r12d
jne 0x2a86
movw $0x11d, 0x1862(%r15)    # imm = 0x11D
jmp 0x2a86
movb 0x1000(%r15,%rcx), %al
andb %al, 0x1000(%r15,%r9)
jmp 0x2a8e
movb 0x1864(%r15), %al
movb %al, 0x1000(%r15,%r9)
jmp 0x2a86
movb 0x1000(%r15,%r9), %al
movb %al, 0x1864(%r15)
jmp 0x2a86
movb 0x1000(%r15,%r9), %al
cmpb 0x1000(%r15,%rcx), %al
jbe 0x2f0e
movb $0x1, 0x100f(%r15)
jmp 0x2f16
movzbl 0x1000(%r15,%r9), %eax
leal (%rax,%rax,4), %ecx
leal (%rax,%rcx,8), %eax
shrl $0xc, %eax
movzwl 0x1862(%r15), %ecx
movb %al, (%r15,%rcx)
movzbl 0x1000(%r15,%r9), %eax
imull $0xcd, %eax, %eax
shrl $0xb, %eax
leal (%rax,%rax,4), %ecx
leal (%rcx,%rcx,4), %ecx
addl %eax, %ecx
shrl $0x7, %ecx
andl $0x6, %ecx
leal (%rcx,%rcx,4), %ecx
subb %cl, %al
movzwl 0x1862(%r15), %ecx
movb %al, 0x1(%rcx,%r15)
movzbl 0x1000(%r15,%r9), %eax
imull $0xcd, %eax, %ecx
shrl $0xa, %ecx
andl $-0x2, %ecx
leal (%rcx,%rcx,4), %ecx
subb %cl, %al
movzwl 0x1862(%r15), %ecx
movb %al, 0x2(%rcx,%r15)
jmp 0x2a86
movzbl 0x1000(%r15,%r9), %eax
addw 0x1862(%r15), %ax
movw %ax, 0x1862(%r15)
movzwl %ax, %ecx
cmpl $0x1000, %ecx           # imm = 0x1000
jb 0x2f2b
movb $0x1, 0x100f(%r15)
jmp 0x2f33
movb 0x1000(%r15,%rcx), %al
orb %al, 0x1000(%r15,%r9)
jmp 0x2a8e
movb 0x1000(%r15,%rcx), %al
movb %al, 0x1000(%r15,%r9)
andb $0x1, %al
movb %al, 0x100f(%r15)
shrb 0x1000(%r15,%r9)
jmp 0x2a8e
movb 0x1000(%r15,%rcx), %al
cmpb 0x1000(%r15,%r9), %al
jbe 0x2f4d
movb $0x1, 0x100f(%r15)
jmp 0x2f55
incb %r9b
movzbl %r9b, %eax
movq -0x90(%rbp), %rcx
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
movb (%rcx), %dl
movzwl 0x1862(%r15), %esi
movb %dl, -0x1000(%rcx,%rsi)
incq %rcx
decq %rax
jne 0x2e87
jmp 0x2a8e
movb 0x1000(%r15,%rcx), %al
xorb %al, 0x1000(%r15,%r9)
jmp 0x2a8e
movzbl 0x1000(%r15,%r9), %eax
movzbl 0x1000(%r15,%rcx), %edx
addl %eax, %edx
cmpl $0x100, %edx            # imm = 0x100
jb 0x2f72
movb $0x1, 0x100f(%r15)
jmp 0x2f7a
movb 0x1000(%r15,%rcx), %al
movb %al, 0x1000(%r15,%r9)
shrb $0x7, %al
movb %al, 0x100f(%r15)
shlb 0x1000(%r15,%r9)
jmp 0x2a8e
movb $0x0, 0x100f(%r15)
movb 0x1000(%r15,%rcx), %al
subb %al, 0x1000(%r15,%r9)
jmp 0x2a8e
movb $0x0, 0x100f(%r15)
movq -0x30(%rbp), %r14
leaq -0x70(%rbp), %r12
andl $0xfff, %eax            # imm = 0xFFF
movw %ax, 0x1862(%r15)
jmp 0x2a8e
movb $0x0, 0x100f(%r15)
movb 0x1000(%r15,%rcx), %al
subb 0x1000(%r15,%r9), %al
movb %al, 0x1000(%r15,%r9)
jmp 0x2a8e
movb $0x0, 0x100f(%r15)
movb 0x1000(%r15,%rcx), %al
addb %al, 0x1000(%r15,%r9)
jmp 0x2a8e
movq -0x38(%rbp), %rcx
movw %ax, (%rcx)
jmp 0x2a8e
movq 0x3036(%rip), %rbx      # 0x5fd8
leaq 0x11ba(%rip), %rsi      # 0x4163
movl $0xf, %edx
movq %rbx, %rdi
callq 0x2230
movq (%rbx), %rax
movq -0x18(%rax), %rax
movl 0x18(%rbx,%rax), %ecx
andl $-0x4b, %ecx
orl $0x8, %ecx
movl %ecx, 0x18(%rbx,%rax)
movq %rbx, %rdi
movq %r13, %rsi
callq 0x21e0
leaq 0x1196(%rip), %rsi      # 0x4173
movl $0xe, %edx
movq %rax, %rdi
callq 0x2230
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq