// File: /workspace/github_c_makefile_star2_O3/leiradel[P]zx48k-libretro/src/ay38910.h
// Function: ay38910_iorq
uint64_t ay38910_iorq(ay38910_t* ay, uint64_t pins) {
    if (pins & (AY38910_BDIR|AY38910_BC1)) {
        if (pins & AY38910_BDIR) {
            const uint8_t data = AY38910_DATA(pins);
            if (pins & AY38910_BC1) {
                /* latch address */
                ay->addr = data;
            }
            else {
                /* Write to register using the currently latched address.
                   The whole 8-bit address is considered, the low 4 bits
                   are the register index, and the upper bits are burned
                   into the chip as a 'chip select' and are usually 0
                   (this emulator assumes they are 0, so addresses greater
                   are ignored for reading and writing)
                */
                if (ay->addr < AY38910_NUM_REGISTERS) {
                    /* write register content, and update dependent values */
                    ay->reg[ay->addr] = data & _ay38910_reg_mask[ay->addr];
                    _ay38910_update_values(ay);
                    if (ay->addr == AY38910_REG_ENV_SHAPE_CYCLE) {
                        _ay38910_restart_env_shape(ay);
                    }
                    /* Handle port output:

                        If port A or B is in output mode, call the
                        port output callback to notify the outer world
                        about the new register value.

                        input/output mode is defined by bits 6 and 7 of
                        the 'enable' register
                            bit6 = 1: port A in output mode
                            bit7 = 1: port B in output mode
                    */
                    else if (ay->addr == AY38910_REG_IO_PORT_A) {
                        if (ay->enable & (1<<6)) {
                            if (ay->out_cb) {
                                ay->out_cb(AY38910_PORT_A, ay->port_a, ay->user_data);
                            }
                        }
                    }
                    else if (ay->addr == AY38910_REG_IO_PORT_B) {
                        if (ay->enable & (1<<7)) {
                            if (ay->out_cb) {
                                ay->out_cb(AY38910_PORT_B, ay->port_b, ay->user_data);
                            }
                        }
                    }
                }
            }
        }
        else {
            /* Read from register using the currently latched address.
               See 'write' for why the latched address must be in the
               valid register range to have an effect.
            */
            if (ay->addr < AY38910_NUM_REGISTERS) {
                /* Handle port input:

                    If port A or B is in input mode, first call the port
                    input callback to update the port register content.

                    input/output mode is defined by bits 6 and 7 of
                    the 'enable' register:
                        bit6 = 0: port A in input mode
                        bit7 = 0: port B in input mode
                */
                if (ay->addr == AY38910_REG_IO_PORT_A) {
                    if ((ay->enable & (1<<6)) == 0) {
                        if (ay->in_cb) {
                            ay->port_a = ay->in_cb(AY38910_PORT_A, ay->user_data);
                        }
                        else {
                            ay->port_a = 0xFF;
                        }
                    }
                }
                else if (ay->addr == AY38910_REG_IO_PORT_B) {
                    if ((ay->enable & (1<<7)) == 0) {
                        if (ay->in_cb) {
                            ay->port_b = ay->in_cb(AY38910_PORT_B, ay->user_data);
                        }
                        else {
                            ay->port_b = 0xFF;
                        }
                    }
                }
                /* read register content into data pins */
                const uint8_t data = ay->reg[ay->addr];
                AY38910_SET_DATA(pins, data);
            }
        }
        AY38910_SET_PA(pins, ay->port_a);
        AY38910_SET_PB(pins, ay->port_b);
        ay->pins = pins;
    }
    return pins;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %rbx
movabsq $0x30000000000, %rax    # imm = 0x30000000000
testq %rax, %rsi
je 0x3768
movq %rdi, %r14
btq $0x28, %rbx
jb 0x3686
movzbl 0x24(%r14), %eax
cmpl $0xf, %eax
ja 0x373c
je 0x36f5
cmpl $0xe, %eax
jne 0x371e
testb $0x40, 0x2c(%r14)
jne 0x371e
movq 0x8(%r14), %rax
movl $0x33, %r15d
testq %rax, %rax
je 0x3718
movq 0x18(%r14), %rsi
xorl %edi, %edi
jmp 0x3714
movq %rbx, %rax
shrq $0x10, %rax
btq $0x29, %rbx
jb 0x36ef
movzbl 0x24(%r14), %ecx
cmpq $0xf, %rcx
ja 0x373c
leaq 0x104d6(%rip), %rdx     # 0x13b80
andb (%rcx,%rdx), %al
movb %al, 0x25(%r14,%rcx)
movq %r14, %rdi
callq 0x33a0
movzbl 0x24(%r14), %eax
cmpl $0xf, %eax
je 0x3793
cmpl $0xe, %eax
je 0x3776
cmpl $0xd, %eax
jne 0x373c
xorl %eax, %eax
movb %al, 0x78(%r14)
movb %al, 0x7a(%r14)
movb 0x32(%r14), %al
andb $0x9, %al
cmpb $0x8, %al
setne 0x79(%r14)
jmp 0x373c
movb %al, 0x24(%r14)
jmp 0x373c
cmpb $0x0, 0x2c(%r14)
js 0x371e
movq 0x8(%r14), %rax
movl $0x34, %r15d
testq %rax, %rax
je 0x3718
movq 0x18(%r14), %rsi
movl $0x1, %edi
callq *%rax
jmp 0x371a
movb $-0x1, %al
movb %al, (%r14,%r15)
movzbl 0x24(%r14), %eax
movzbl 0x25(%r14,%rax), %eax
movabsq $-0x10000ff0001, %rcx   # imm = 0xFFFFFEFFFF00FFFF
andq %rcx, %rbx
shll $0x10, %eax
orq %rax, %rbx
movabsq $0xffffffffffff, %rax   # imm = 0xFFFFFFFFFFFF
andq %rbx, %rax
movzbl 0x33(%r14), %ecx
shlq $0x30, %rcx
orq %rax, %rcx
movzbl 0x34(%r14), %ebx
shlq $0x38, %rbx
orq %rcx, %rbx
movq %rbx, 0x80(%r14)
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
testb $0x40, 0x2c(%r14)
je 0x373c
movq 0x10(%r14), %rax
testq %rax, %rax
je 0x373c
movzbl 0x33(%r14), %esi
movq 0x18(%r14), %rdx
xorl %edi, %edi
jmp 0x37b1
cmpb $0x0, 0x2c(%r14)
jns 0x373c
movq 0x10(%r14), %rax
testq %rax, %rax
je 0x373c
movzbl 0x34(%r14), %esi
movq 0x18(%r14), %rdx
movl $0x1, %edi
callq *%rax
jmp 0x373c