// File: /workspace/github_c_makefile_star2_O3/leiradel[P]zx48k-libretro/src/zx.h
// Function: zx_tick
static uint64_t _zx_tick(int num_ticks, uint64_t pins, void* user_data) {
    zx_t* sys = (zx_t*) user_data;
    /* video decoding and vblank interrupt */
    sys->scanline_counter -= num_ticks;
    if (sys->scanline_counter <= 0) {
        sys->scanline_counter += sys->scanline_period;
        /* decode next video scanline */
        if (_zx_decode_scanline(sys)) {
            /* request vblank interrupt */
            pins |= Z80_INT;
        }
    }

    /* tick audio systems */
    for (int i = 0; i < num_ticks; i++) {
        sys->tick_count++;
        bool sample_ready = beeper_tick(&sys->beeper);
        /* the AY-3-8912 chip runs at half CPU frequency */
        if (sys->type == ZX_TYPE_128) {
            if (sys->tick_count & 1) {
                ay38910_tick(&sys->ay);
            }
        }
        if (sample_ready) {
            float sample = sys->beeper.sample;
            if (sys->type == ZX_TYPE_128) {
                sample += sys->ay.sample;
            }
            sys->sample_buffer[sys->sample_pos++] = sample;
            if (sys->sample_pos == sys->num_samples) {
                if (sys->audio_cb) {
                    sys->audio_cb(sys->sample_buffer, sys->num_samples, sys->user_data);
                }
                sys->sample_pos = 0;
            }
        }
    }

    /* memory and IO requests */
    if (pins & Z80_MREQ) {
        /* a memory request machine cycle
            FIXME: 'contended memory' accesses should inject wait states
        */
        const uint16_t addr = Z80_GET_ADDR(pins);
        if (pins & Z80_RD) {
            Z80_SET_DATA(pins, mem_rd(&sys->mem, addr));
        }
        else if (pins & Z80_WR) {
            mem_wr(&sys->mem, addr, Z80_GET_DATA(pins));
        }
    }
    else if (pins & Z80_IORQ) {
        /* an IO request machine cycle
            see http://problemkaputt.de/zxdocs.htm#zxspectrum for address decoding
        */
        if (pins & Z80_RD) {
            /* an IO read
                FIXME: reading from port xxFF should return 'current VRAM data'
            */
            if ((pins & Z80_A0) == 0) {
                /* Spectrum ULA (...............0)
                    Bits 5 and 7 as read by INning from Port 0xfe are always one
                */
                uint8_t data = (1<<7)|(1<<5);
                /* MIC/EAR flags -> bit 6 */
                if (sys->last_fe_out & (1<<3|1<<4)) {
                    data |= (1<<6);
                }
                /* keyboard matrix bits are encoded in the upper 8 bit of the port address */
                uint16_t column_mask = (~(Z80_GET_ADDR(pins)>>8)) & 0x00FF;
                const uint16_t kbd_lines = kbd_test_lines(&sys->kbd, column_mask);
                data |= (~kbd_lines) & 0x1F;
                Z80_SET_DATA(pins, data);
            }
            else if ((pins & (Z80_A7|Z80_A6|Z80_A5)) == 0) {
                /* Kempston Joystick (........000.....) */
                Z80_SET_DATA(pins, sys->kbd_joymask | sys->joy_joymask);
            }
            else if (sys->type == ZX_TYPE_128){
                /* read from AY-3-8912 (11............0.) */
                if ((pins & (Z80_A15|Z80_A14|Z80_A1)) == (Z80_A15|Z80_A14)) {
                    pins = ay38910_iorq(&sys->ay, AY38910_BC1|pins) & Z80_PIN_MASK;
                }
            }
        }
        else if (pins & Z80_WR) {
            // an IO write
            const uint8_t data = Z80_GET_DATA(pins);
            if ((pins & Z80_A0) == 0) {
                /* Spectrum ULA (...............0)
                    "every even IO port addresses the ULA but to avoid
                    problems with other I/O devices, only FE should be used"
                    FIXME:
                        bit 3: MIC output (CAS SAVE, 0=On, 1=Off)
                */
                sys->border_color = _zx_palette[data & 7] & 0xFFD7D7D7;
                sys->last_fe_out = data;
                beeper_set(&sys->beeper, 0 != (data & (1<<4)));
            }
            else if (sys->type == ZX_TYPE_128) {
                /* Spectrum 128 memory control (0.............0.)
                    http://8bit.yarek.pl/computer/zx.128/
                */
                if ((pins & (Z80_A15|Z80_A1)) == 0) {
                    if (!sys->memory_paging_disabled) {
                        sys->last_mem_config = data;
                        /* bit 3 defines the video scanout memory bank (5 or 7) */
                        sys->display_ram_bank = (data & (1<<3)) ? 7 : 5;
                        /* only last memory bank is mappable */
                        mem_map_ram(&sys->mem, 0, 0xC000, 0x4000, sys->ram[data & 0x7]);

                        /* ROM0 or ROM1 */
                        if (data & (1<<4)) {
                            /* bit 4 set: ROM1 */
                            mem_map_rom(&sys->mem, 0, 0x0000, 0x4000, sys->rom[1]);
                        }
                        else {
                            /* bit 4 clear: ROM0 */
                            mem_map_rom(&sys->mem, 0, 0x0000, 0x4000, sys->rom[0]);
                        }
                    }
                    if (data & (1<<5)) {
                        /* bit 5 prevents further changes to memory pages
                            until computer is reset, this is used when switching
                            to the 48k ROM
                        */
                        sys->memory_paging_disabled = true;
                    }
                }
                else if ((pins & (Z80_A15|Z80_A14|Z80_A1)) == (Z80_A15|Z80_A14)) {
                    /* select AY-3-8912 register (11............0.) */
                    ay38910_iorq(&sys->ay, AY38910_BDIR|AY38910_BC1|pins);
                }
                else if ((pins & (Z80_A15|Z80_A14|Z80_A1)) == Z80_A15) {
                    /* write to AY-3-8912 (10............0.) */
                    ay38910_iorq(&sys->ay, AY38910_BDIR|pins);
                }
            }
        }
    }
    return pins;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdx, %r14
movl %edi, %r15d
movl 0x1134(%rdx), %eax
subl %edi, %eax
movl %eax, 0x1134(%rdx)
jg 0x10ca0
addl 0x1130(%r14), %eax
movl %eax, 0x1134(%r14)
movl 0x112c(%r14), %eax
movl 0x1138(%r14), %ecx
leal -0x20(%rax), %edx
movl %ecx, %r8d
subl %edx, %r8d
setge %dl
addl $0xe0, %eax
cmpl %eax, %ecx
setl %al
andb %dl, %al
cmpb $0x1, %al
jne 0x10c62
movzwl %r8w, %ecx
movl %ecx, %eax
shll $0x8, %eax
leal (%rax,%rax,4), %eax
addq 0x3210(%r14), %rax
addl $0xffffff20, %ecx       # imm = 0xFFFFFF20
cmpl $0xffffff3f, %ecx       # imm = 0xFFFFFF3F
ja 0x10b26
movl 0x1140(%r14), %ecx
xorl %edx, %edx
movl %ecx, (%rax,%rdx,4)
incq %rdx
cmpl $0x140, %edx            # imm = 0x140
jne 0x10b13
jmp 0x10c62
movq %rsi, -0x38(%rbp)
movl 0x113c(%r14), %ecx
shlq $0xe, %rcx
addq %r14, %rcx
addq $0x4230, %rcx           # imm = 0x4230
movq %rcx, -0x40(%rbp)
movb 0x1126(%r14), %cl
movb %cl, -0x29(%rbp)
leal 0xffe0(%r8), %esi
movl %r8d, %edi
shll $0x8, %r8d
leal 0x3ff80(,%rdi,4), %r10d
movl 0x1140(%r14), %edi
xorl %r9d, %r9d
movl %edi, (%rax,%r9)
addq $0x4, %r9
cmpl $0x80, %r9d
jne 0x10b6d
movl %esi, %edi
shll $0x5, %edi
andl $0x700, %r8d            # imm = 0x700
andl $0xe0, %r10d
movl $0x1800, %r11d          # imm = 0x1800
andl %r11d, %edi
orl %r8d, %edi
orl %r10d, %edi
shll $0x2, %esi
addl %r11d, %esi
andl $0xffe0, %esi           # imm = 0xFFE0
addq -0x40(%rbp), %rsi
addq %r9, %rax
xorl %r8d, %r8d
leaq 0x3a23(%rip), %r9       # 0x145e0
movl $0xffd7d7d7, %r10d      # imm = 0xFFD7D7D7
testb $0x10, -0x29(%rbp)
sete %bl
movq %r8, %r11
orq %rdi, %r11
movzbl (%rsi,%r8), %r13d
testb %r13b, %r13b
setns %r12b
orb %bl, %r12b
movl %r13d, %ebx
shrl $0x3, %ebx
testb %r12b, %r12b
movl %r13d, %r12d
cmovnel %ebx, %r12d
cmovnel %r13d, %ebx
andl $0x7, %ebx
movl (%r9,%rbx,4), %edx
andl $0x7, %r12d
movl (%r9,%r12,4), %ecx
movl %edx, %ebx
andl %r10d, %ebx
movl %ecx, %r12d
andl %r10d, %r12d
testb $0x40, %r13b
cmovnel %ecx, %r12d
movq -0x40(%rbp), %rcx
movzbl (%rcx,%r11), %r11d
cmovnel %edx, %ebx
movl $0x7, %r13d
btl %r13d, %r11d
movl %ebx, %ecx
cmovael %r12d, %ecx
movl %ecx, (%rax)
addq $0x4, %rax
addl $-0x1, %r13d
jb 0x10c27
incq %r8
cmpq $0x20, %r8
jne 0x10bc3
movl 0x1140(%r14), %ecx
xorl %edx, %edx
movq -0x38(%rbp), %rsi
movl %ecx, (%rax,%rdx,4)
incq %rdx
cmpl $0x20, %edx
jne 0x10c57
movl 0x1128(%r14), %eax
movl 0x1138(%r14), %ecx
leal 0x1(%rcx), %edx
movl %edx, 0x1138(%r14)
cmpl %eax, %ecx
jl 0x10c90
movl $0x0, 0x1138(%r14)
incb 0x1126(%r14)
movq %rsi, %rdx
orq $0x40000000, %rdx       # imm = 0x40000000
cmpl %eax, %ecx
cmovgeq %rdx, %rsi
movq %rsi, -0x38(%rbp)
testl %r15d, %r15d
jle 0x10d5e
leaq 0x50(%r14), %r12
leaq 0x870(%r14), %r13
leaq 0x3230(%r14), %rax
movq %rax, -0x40(%rbp)
incl 0x1120(%r14)
movq %r12, %rdi
callq 0x3170
movl %eax, %ebx
cmpl $0x1, 0x1114(%r14)
jne 0x10cf0
testb $0x1, 0x1120(%r14)
je 0x10cf0
movq %r13, %rdi
callq 0x30c0
testb %bl, %bl
je 0x10d55
movss 0x60(%r14), %xmm0
cmpl $0x1, 0x1114(%r14)
jne 0x10d0d
addss 0x904(%r14), %xmm0
movslq 0x322c(%r14), %rax
leal 0x1(%rax), %esi
movl %esi, 0x322c(%r14)
movss %xmm0, 0x3230(%r14,%rax,4)
cmpl 0x3228(%r14), %esi
jne 0x10d55
movq 0x3220(%r14), %rax
testq %rax, %rax
je 0x10d4a
movq 0x3218(%r14), %rdx
movq -0x40(%rbp), %rdi
callq *%rax
movl $0x0, 0x322c(%r14)
decl %r15d
jne 0x10cc3
movq -0x38(%rbp), %r12
btl $0x19, %r12d
jb 0x10dcd
btl $0x1a, %r12d
jae 0x10e33
btl $0x1b, %r12d
jb 0x10e45
btl $0x1c, %r12d
jae 0x10e33
movq %r12, %r15
shrq $0x10, %r15
testb $0x1, %r12b
jne 0x10ed0
movl %r15d, %eax
andl $0x7, %eax
leaq 0x3838(%rip), %rcx      # 0x145e0
movl $0xffd7d7d7, %edx       # imm = 0xFFD7D7D7
andl (%rcx,%rax,4), %edx
movl %edx, 0x1140(%r14)
movb %r15b, 0x1125(%r14)
movl %r12d, %eax
shrl $0x14, %eax
andl $0x1, %eax
movl %eax, 0x50(%r14)
jmp 0x10e33
btl $0x1b, %r12d
jb 0x10e03
btl $0x1c, %r12d
jae 0x10e33
movl %r12d, %eax
shrl $0x10, %eax
movl %r12d, %ecx
shrl $0x6, %ecx
andl $0x3f0, %ecx            # imm = 0x3F0
movq 0x2618(%r14,%rcx), %rcx
movl %r12d, %edx
andl $0x3ff, %edx            # imm = 0x3FF
movb %al, (%rcx,%rdx)
jmp 0x10e33
movq %r12, %rax
andq $-0xff0001, %rax        # imm = 0xFF00FFFF
movl %r12d, %ecx
shrl $0x6, %ecx
andl $0x3f0, %ecx            # imm = 0x3F0
movq 0x2610(%r14,%rcx), %rcx
andl $0x3ff, %r12d           # imm = 0x3FF
movzbl (%rcx,%r12), %r12d
shll $0x10, %r12d
orq %rax, %r12
movq %r12, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testb $0x1, %r12b
jne 0x10e84
xorl %eax, %eax
testb $0x18, 0x1125(%r14)
setne %al
shll $0x6, %eax
orq $0xa0, %rax
movl %r12d, %ecx
notl %ecx
movzbl %ch, %edx
cmpw %dx, 0x1608(%r14)
jne 0x10f1f
movzwl 0x160a(%r14), %ecx
jmp 0x10f54
testb $-0x20, %r12b
je 0x10f74
movl %r12d, %eax
andl $0xc002, %eax           # imm = 0xC002
cmpl $0xc000, %eax           # imm = 0xC000
jne 0x10e33
cmpl $0x1, 0x1114(%r14)
jne 0x10e33
addq $0x870, %r14            # imm = 0x870
btsq $0x29, %r12
movq %r14, %rdi
movq %r12, %rsi
callq 0x3090
movabsq $0xffffffffff, %r12     # imm = 0xFFFFFFFFFF
andq %rax, %r12
jmp 0x10e33
cmpl $0x1, 0x1114(%r14)
jne 0x10e33
testl $0x8002, %r12d          # imm = 0x8002
je 0x10f94
movl %r12d, %eax
andl $0xc002, %eax           # imm = 0xC002
movl %eax, %ecx
negw %cx
jo 0x11029
cmpl $0xc000, %eax           # imm = 0xC000
jne 0x10e33
addq $0x870, %r14            # imm = 0x870
movabsq $0x30000000000, %rsi    # imm = 0x30000000000
jmp 0x1103d
movw %dx, 0x1608(%r14)
movw $0x0, 0x160a(%r14)
xorl %ecx, %ecx
xorl %esi, %esi
btl %esi, %edx
jae 0x10f4b
orw 0x15f0(%r14,%rsi,2), %cx
movw %cx, 0x160a(%r14)
incq %rsi
cmpq $0xc, %rsi
jne 0x10f35
andl $0x1f, %ecx
orl %ecx, %eax
andq $-0x2ff0002, %r12       # imm = 0xFD00FFFE
shll $0x10, %eax
orq %r12, %rax
xorq $0x1f0000, %rax         # imm = 0x1F0000
movq %rax, %r12
jmp 0x10e33
movb 0x111e(%r14), %al
orb 0x111d(%r14), %al
andq $-0x2ff00e1, %r12       # imm = 0xFD00FF1F
movzbl %al, %eax
shll $0x10, %eax
jmp 0x10e30
cmpb $0x0, 0x111c(%r14)
jne 0x11011
movb %r15b, 0x1124(%r14)
movl %r15d, %eax
andl $0x8, %eax
shrl $0x2, %eax
orl $0x5, %eax
movl %eax, 0x113c(%r14)
leaq 0x1610(%r14), %rbx
movl %r15d, %eax
andl $0x7, %eax
shll $0xe, %eax
leaq (%r14,%rax), %r8
addq $0x4230, %r8            # imm = 0x4230
movq %rbx, %rdi
xorl %esi, %esi
movl $0xc000, %edx           # imm = 0xC000
movl $0x4000, %ecx           # imm = 0x4000
movq %r8, %r9
callq 0x418a
andl $0x10, %r15d
shll $0xa, %r15d
leaq (%r15,%r14), %r8
addq $0x24230, %r8           # imm = 0x24230
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
movl $0x4000, %ecx           # imm = 0x4000
xorl %r9d, %r9d
callq 0x418a
btl $0x15, %r12d
jae 0x10e33
movb $0x1, 0x111c(%r14)
jmp 0x10e33
addq $0x870, %r14            # imm = 0x870
movabsq $0xffffffffff, %rsi     # imm = 0xFFFFFFFFFF
incq %rsi
orq %r12, %rsi
movq %r14, %rdi
callq 0x3090
jmp 0x10e33