root/usr/src/uts/intel/ml/ddi_i86_asm.S
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Copyright 2019 Joyent, Inc.
 */

#include <sys/asm_linkage.h>
#include <sys/asm_misc.h>
#include "assym.h"

        ENTRY(ddi_get8)
        ALTENTRY(ddi_mem_get8)
        ALTENTRY(ddi_io_get8)
        movl    ACC_ATTR(%rdi), %edx
        cmpl    $_CONST(DDI_ACCATTR_IO_SPACE|DDI_ACCATTR_DIRECT), %edx
        jne     1f
        movq    %rsi, %rdx
        xorq    %rax, %rax
        inb     (%dx)
        ret
1:
        cmpl    $_CONST(DDI_ACCATTR_CPU_VADDR|DDI_ACCATTR_DIRECT), %edx
        jne     2f
        movzbq  (%rsi), %rax
        ret
2:
        movq    ACC_GETB(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_get8)
        SET_SIZE(ddi_mem_get8)
        SET_SIZE(ddi_io_get8)


        ENTRY(ddi_get16)
        ALTENTRY(ddi_mem_get16)
        ALTENTRY(ddi_io_get16)
        movl    ACC_ATTR(%rdi), %edx
        cmpl    $_CONST(DDI_ACCATTR_IO_SPACE|DDI_ACCATTR_DIRECT), %edx
        jne     3f
        movq    %rsi, %rdx
        xorq    %rax, %rax
        inw     (%dx)
        ret
3:
        cmpl    $_CONST(DDI_ACCATTR_CPU_VADDR|DDI_ACCATTR_DIRECT), %edx
        jne     4f
        movzwq  (%rsi), %rax
        ret
4:
        movq    ACC_GETW(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_get16)
        SET_SIZE(ddi_mem_get16)
        SET_SIZE(ddi_io_get16)


        ENTRY(ddi_get32)
        ALTENTRY(ddi_mem_get32)
        ALTENTRY(ddi_io_get32)
        movl    ACC_ATTR(%rdi), %edx
        cmpl    $_CONST(DDI_ACCATTR_IO_SPACE|DDI_ACCATTR_DIRECT), %edx
        jne     5f
        movq    %rsi, %rdx
        inl     (%dx)
        ret
5:
        cmpl    $_CONST(DDI_ACCATTR_CPU_VADDR|DDI_ACCATTR_DIRECT), %edx
        jne     6f
        movl    (%rsi), %eax
        ret
6:
        movq    ACC_GETL(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_get32)
        SET_SIZE(ddi_mem_get32)
        SET_SIZE(ddi_io_get32)


        ENTRY(ddi_get64)
        ALTENTRY(ddi_mem_get64)
        movq    ACC_GETLL(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_get64)
        SET_SIZE(ddi_mem_get64)


        ENTRY(ddi_put8)
        ALTENTRY(ddi_mem_put8)
        ALTENTRY(ddi_io_put8)
        movl    ACC_ATTR(%rdi), %ecx
        cmpl    $_CONST(DDI_ACCATTR_IO_SPACE|DDI_ACCATTR_DIRECT), %ecx
        jne     7f
        movq    %rdx, %rax
        movq    %rsi, %rdx
        outb    (%dx)
        ret
7:
        cmpl    $_CONST(DDI_ACCATTR_CPU_VADDR|DDI_ACCATTR_DIRECT), %ecx
        jne     8f
        movb    %dl, (%rsi)
        ret
8:
        movq    ACC_PUTB(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_put8)
        SET_SIZE(ddi_mem_put8)
        SET_SIZE(ddi_io_put8)


        ENTRY(ddi_put16)
        ALTENTRY(ddi_mem_put16)
        ALTENTRY(ddi_io_put16)
        movl    ACC_ATTR(%rdi), %ecx
        cmpl    $_CONST(DDI_ACCATTR_IO_SPACE|DDI_ACCATTR_DIRECT), %ecx
        jne     8f
        movq    %rdx, %rax
        movq    %rsi, %rdx
        outw    (%dx)
        ret
8:
        cmpl    $_CONST(DDI_ACCATTR_CPU_VADDR|DDI_ACCATTR_DIRECT), %ecx
        jne     9f
        movw    %dx, (%rsi)
        ret
9:
        movq    ACC_PUTW(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_put16)
        SET_SIZE(ddi_mem_put16)
        SET_SIZE(ddi_io_put16)


        ENTRY(ddi_put32)
        ALTENTRY(ddi_mem_put32)
        ALTENTRY(ddi_io_put32)
        movl    ACC_ATTR(%rdi), %ecx
        cmpl    $_CONST(DDI_ACCATTR_IO_SPACE|DDI_ACCATTR_DIRECT), %ecx
        jne     8f
        movq    %rdx, %rax
        movq    %rsi, %rdx
        outl    (%dx)
        ret
8:
        cmpl    $_CONST(DDI_ACCATTR_CPU_VADDR|DDI_ACCATTR_DIRECT), %ecx
        jne     9f
        movl    %edx, (%rsi)
        ret
9:
        movq    ACC_PUTL(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_put32)
        SET_SIZE(ddi_mem_put32)
        SET_SIZE(ddi_io_put32)


        ENTRY(ddi_put64)
        ALTENTRY(ddi_mem_put64)
        movq    ACC_PUTLL(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_put64)
        SET_SIZE(ddi_mem_put64)


        ENTRY(ddi_rep_get8)
        ALTENTRY(ddi_mem_rep_get8)
        movq    ACC_REP_GETB(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_rep_get8)
        SET_SIZE(ddi_mem_rep_get8)


        ENTRY(ddi_rep_get16)
        ALTENTRY(ddi_mem_rep_get16)
        movq    ACC_REP_GETW(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_rep_get16)
        SET_SIZE(ddi_mem_rep_get16)


        ENTRY(ddi_rep_get32)
        ALTENTRY(ddi_mem_rep_get32)
        movq    ACC_REP_GETL(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_rep_get32)
        SET_SIZE(ddi_mem_rep_get32)


        ENTRY(ddi_rep_get64)
        ALTENTRY(ddi_mem_rep_get64)
        movq    ACC_REP_GETLL(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_rep_get64)
        SET_SIZE(ddi_mem_rep_get64)


        ENTRY(ddi_rep_put8)
        ALTENTRY(ddi_mem_rep_put8)
        movq    ACC_REP_PUTB(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_rep_put8)
        SET_SIZE(ddi_mem_rep_put8)


        ENTRY(ddi_rep_put16)
        ALTENTRY(ddi_mem_rep_put16)
        movq    ACC_REP_PUTW(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_rep_put16)
        SET_SIZE(ddi_mem_rep_put16)


        ENTRY(ddi_rep_put32)
        ALTENTRY(ddi_mem_rep_put32)
        movq    ACC_REP_PUTL(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_rep_put32)
        SET_SIZE(ddi_mem_rep_put32)


        ENTRY(ddi_rep_put64)
        ALTENTRY(ddi_mem_rep_put64)
        movq    ACC_REP_PUTLL(%rdi), %rax
        INDIRECT_JMP_REG(rax)
        SET_SIZE(ddi_rep_put64)
        SET_SIZE(ddi_mem_rep_put64)

        ENTRY(i_ddi_vaddr_get8)
        movzbq  (%rsi), %rax
        ret
        SET_SIZE(i_ddi_vaddr_get8)

        ENTRY(i_ddi_vaddr_get16)
        movzwq  (%rsi), %rax
        ret
        SET_SIZE(i_ddi_vaddr_get16)


        ENTRY(i_ddi_vaddr_get32)
        movl    (%rsi), %eax
        ret
        SET_SIZE(i_ddi_vaddr_get32)


        ENTRY(i_ddi_vaddr_get64)
        movq    (%rsi), %rax
        ret
        SET_SIZE(i_ddi_vaddr_get64)


        ENTRY(i_ddi_io_get8)
        movq    %rsi, %rdx
        inb     (%dx)
        movzbq  %al, %rax
        ret
        SET_SIZE(i_ddi_io_get8)


        ENTRY(i_ddi_io_get16)
        movq    %rsi, %rdx
        inw     (%dx)
        movzwq  %ax, %rax
        ret
        SET_SIZE(i_ddi_io_get16)


        ENTRY(i_ddi_io_get32)
        movq    %rsi, %rdx
        inl     (%dx)
        ret
        SET_SIZE(i_ddi_io_get32)

        ENTRY(i_ddi_vaddr_put8)
        movb    %dl, (%rsi)
        ret
        SET_SIZE(i_ddi_vaddr_put8)


        ENTRY(i_ddi_vaddr_put16)
        movw    %dx, (%rsi)
        ret
        SET_SIZE(i_ddi_vaddr_put16)


        ENTRY(i_ddi_vaddr_put32)
        movl    %edx, (%rsi)
        ret
        SET_SIZE(i_ddi_vaddr_put32)


        ENTRY(i_ddi_vaddr_put64)
        movq    %rdx, (%rsi)
        ret
        SET_SIZE(i_ddi_vaddr_put64)

        ENTRY(i_ddi_io_put8)
        movq    %rdx, %rax
        movq    %rsi, %rdx
        outb    (%dx)
        ret
        SET_SIZE(i_ddi_io_put8)


        ENTRY(i_ddi_io_put16)
        movq    %rdx, %rax
        movq    %rsi, %rdx
        outw    (%dx)
        ret
        SET_SIZE(i_ddi_io_put16)


        ENTRY(i_ddi_io_put32)
        movq    %rdx, %rax
        movq    %rsi, %rdx
        outl    (%dx)
        ret
        SET_SIZE(i_ddi_io_put32)

        /*
         * Incoming arguments
         *
         * %rdi : hdlp
         * %rsi : host_addr
         * %rdx : dev_addr
         * %rcx : repcount
         * %r8  : flags
         *
         * This routine will destroy values in %rdx, %rsi, %rcx.
         */
        ENTRY(i_ddi_io_rep_get8)

        cmpq    $DDI_DEV_AUTOINCR, %r8
        je      gb_ioadv
        movq    %rsi, %rdi
        rep
        insb
        ret

gb_ioadv:
        andq    %rcx, %rcx
        jz      gb_ioadv_done
gb_ioadv2:
        inb     (%dx)
        movb    %al, (%rsi)
        incq    %rdx
        incq    %rsi
        decq    %rcx
        jg      gb_ioadv2

gb_ioadv_done:
        rep;    ret     /* use 2 byte return instruction when branch target */
                        /* AMD Software Optimization Guide - Section 6.2 */

        SET_SIZE(i_ddi_io_rep_get8)


        ENTRY(i_ddi_io_rep_get16)

        cmpq    $DDI_DEV_AUTOINCR, %r8
        je      gw_ioadv

        movq    %rsi, %rdi
        rep
        insw
        ret

gw_ioadv:
        andq    %rcx, %rcx
        jz      gw_ioadv_done
gw_ioadv2:
        inw     (%dx)
        movw    %ax,(%rsi)
        addq    $2, %rsi
        addq    $2, %rdx
        decq    %rcx
        jg      gw_ioadv2

gw_ioadv_done:
        rep;    ret     /* use 2 byte return instruction when branch target */
                        /* AMD Software Optimization Guide - Section 6.2 */
        SET_SIZE(i_ddi_io_rep_get16)


        ENTRY(i_ddi_io_rep_get32)

        cmpq    $DDI_DEV_AUTOINCR, %r8
        je      gl_ioadv

        movq    %rsi, %rdi
        rep
        insl
        ret

gl_ioadv:
        andq    %rcx, %rcx
        jz      gl_ioadv_done
gl_ioadv2:
        inl     (%dx)
        movl    %eax,(%rsi)
        addq    $4, %rsi
        addq    $4, %rdx
        decq    %rcx
        jg      gl_ioadv2

gl_ioadv_done:
        rep;    ret     /* use 2 byte return instruction when branch target */
                        /* AMD Software Optimization Guide - Section 6.2 */

        SET_SIZE(i_ddi_io_rep_get32)

        /*
         * Incoming arguments
         *
         * %rdi : hdlp
         * %rsi : host_addr
         * %rdx : dev_addr
         * %rcx : repcount
         * %r8  : flags
         *
         * This routine will destroy values in %rdx, %rsi, %rcx.
         */
        ENTRY(i_ddi_io_rep_put8)

        cmpq    $DDI_DEV_AUTOINCR, %r8
        je      pb_ioadv

        movq    %rsi, %rdi
        rep
        outsb
        ret

pb_ioadv:
        andq    %rcx, %rcx
        jz      pb_ioadv_done
pb_ioadv2:
        movb    (%rsi), %al
        outb    (%dx)
        incq    %rsi
        incq    %rdx
        decq    %rcx
        jg      pb_ioadv2

pb_ioadv_done:
        rep;    ret     /* use 2 byte return instruction when branch target */
                        /* AMD Software Optimization Guide - Section 6.2 */
        SET_SIZE(i_ddi_io_rep_put8)

        ENTRY(i_ddi_io_rep_put16)

        cmpq    $DDI_DEV_AUTOINCR, %r8
        je      pw_ioadv

        movq    %rsi, %rdi
        rep
        outsw
        ret

pw_ioadv:
        andq    %rcx, %rcx
        jz      pw_ioadv_done
pw_ioadv2:
        movw    (%rsi), %ax
        outw    (%dx)
        addq    $2, %rsi
        addq    $2, %rdx
        decq    %rcx
        jg      pw_ioadv2

pw_ioadv_done:
        rep;    ret     /* use 2 byte return instruction when branch target */
                        /* AMD Software Optimization Guide - Section 6.2 */
        SET_SIZE(i_ddi_io_rep_put16)


        ENTRY(i_ddi_io_rep_put32)

        cmpq    $DDI_DEV_AUTOINCR, %r8
        je      pl_ioadv

        movq    %rsi, %rdi
        rep
        outsl
        ret

pl_ioadv:
        andq    %rcx, %rcx
        jz      pl_ioadv_done
pl_ioadv2:
        movl    (%rsi), %eax
        outl    (%dx)
        addq    $4, %rsi
        addq    $4, %rdx
        decq    %rcx
        jg      pl_ioadv2

pl_ioadv_done:
        rep;    ret     /* use 2 byte return instruction when branch target */
                        /* AMD Software Optimization Guide - Section 6.2 */
        SET_SIZE(i_ddi_io_rep_put32)