root/sys/arch/riscv/riscv/bus_space_generic.S
/*      $NetBSD: bus_space_generic.S,v 1.6 2026/03/29 12:10:50 tls Exp $        */

/*-
 * Copyright (c) 2022 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Nick Hudson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */


#include <riscv/asm.h>
#include "assym.h"

RCSID("$NetBSD: bus_space_generic.S,v 1.6 2026/03/29 12:10:50 tls Exp $")


/* void bs_c_1(a0: tag, a1: src, srcoffset, dst, dstoffset, count); */
/* void bs_c_2(a0: tag, a1: src, srcoffset, dst, dstoffset, count); */
/* void bs_c_4(a0: tag, a1: src, srcoffset, dst, dstoffset, count); */
/* void bs_c_8(a0: tag, a1: src, srcoffset, dst, dstoffset, count); */

/* void bs_sr_1(a0: tag, a1: addr, a2: offset, a3: value, a4: count); */
/* void bs_sr_2(a0: tag, a1: addr, a2: offset, a3: value, a4: count); */
/* void bs_sr_4(a0: tag, a1: addr, a2: offset, a3: value, a4: count); */
/* void bs_sr_8(a0: tag, a1: addr, a2: offset, a3: value, a4: count); */


/* uint8_t bs_r_1(a0: tag, a1: addr, a2: offset); */
ENTRY_NP(generic_bs_r_1)
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
        lbu     a0, 0(a2)               /* load 8-bit */
        ret
END(generic_bs_r_1)


/* uint16_t bs_r_2(a0: tag, a1: addr, a2: offset); */
ENTRY_NP(generic_bs_r_2)
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
        lhu     a0, 0(a2)               /* load 16-bit */
        ret
END(generic_bs_r_2)


/* uint32_t bs_r_4(a0: tag, a1: addr, a2: offset); */
ENTRY_NP(generic_bs_r_4)
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
        lw      a0, 0(a2)               /* load 32-bit */
        ret
END(generic_bs_r_4)


#ifdef _LP64
/* uint64_t bs_r_8(a0: tag, a1: addr, a2: offset); */
ENTRY_NP(generic_bs_r_8)
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
        ld      a0, 0(a2)               /* load 64-bit */
        ret
END(generic_bs_r_8)
#endif


/* void bs_rm_1(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_rm_1)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        lbu     a0, 0(a2)               /* load 8-bit */
        sb      a0, 0(a3)
        add     a3, a3, 1
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_rm_1: count == 0"
        .balign 4, 0
END(generic_bs_rm_1)


/* void bs_rm_2(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_rm_2)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        lhu     a0, 0(a2)               /* load 16-bit */
        sh      a0, 0(a3)               /* store 16-bit */
        add     a3, a3, 2
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_rm_2: count == 0"
        .balign 4, 0
END(generic_bs_rm_2)


/* void bs_rm_4(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_rm_4)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        lw      a0, 0(a2)               /* load 32-bit */
        sw      a0, 0(a3)               /* store 32-bit */
        add     a3, a3, 4
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_rm_4: count == 0"
        .balign 4, 0
END(generic_bs_rm_4)


#ifdef _LP64
/* void bs_rm_8(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_rm_8)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        ld      a0, 0(a2)               /* load 64-bit */
        sd      a0, 0(a3)               /* store 64-bit */
        add     a3, a3, 8
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_rm_8: count == 0"
        .balign 4, 0
END(generic_bs_rm_8)
#endif


/* void bs_rr_1(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_rr_1)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        li      t0, 1
        srl     t0, t0, a5              /* delta = 1 << stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        lbu     a0, 0(a2)               /* load 8-bit */
        sb      a0, 0(a3)               /* *dst = value */
        add     a2, a2, t0              /* src += delta */
        add     a3, a3, 1               /* dst++ */
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_rr_1: count == 0"
        .balign 4, 0
END(generic_bs_rr_1)


/* void bs_rr_2(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_rr_2)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        li      t0, 1
        srl     t0, t0, a5              /* delta = 1 << stride */
// if (delta < 2)
//     delta = 2


        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        lhu     a0, 0(a2)               /* load 16-bit */
        sh      a0, 0(a3)               /* *dst = value */
        add     a2, a2, t0              /* src += delta */
        add     a3, a3, 2               /* dst++ */
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_rr_2: count == 0"
        .balign 4, 0
END(generic_bs_rr_2)


/* void bs_rr_4(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
/* void bs_rr_8(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */



/* void bs_w_1(a0: tag, a1: addr, a2: offset, a3: value); */
ENTRY_NP(generic_bs_w_1)
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
        sb      a3, 0(a2)               /* store 8-bit */
        ret
END(generic_bs_w_1)


/* void bs_w_2(a0: tag, a1: addr, a2: offset, a3: value); */
ENTRY_NP(generic_bs_w_2)
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
        sh      a3, 0(a2)               /* store 16-bit */
        ret
END(generic_bs_w_2)


/* void bs_w_4(a0: tag, a1: addr, a2: offset, a3: value); */
ENTRY_NP(generic_bs_w_4)
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
        sw      a3, 0(a2)               /* store 32-bit */
        ret
END(generic_bs_w_4)


#ifdef _LP64
/* void bs_w_8(a0: tag, a1: addr, a2: offset, a3: value); */
ENTRY_NP(generic_bs_w_8)
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
        sd      a3, 0(a2)               /* store 64-bit */
        ret
END(generic_bs_w_8)
#endif


/* void bs_wm_1(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_wm_1)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        lbu     a0, 0(a3)               /* load 8-bit */
        sb      a0, 0(a2)
        add     a3, a3, 1
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_wm_1: count == 0"
        .balign 4, 0
END(generic_bs_wm_1)


/* void bs_wm_2(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_wm_2)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        lhu     a0, 0(a3)               /* load 16-bit */
        sh      a0, 0(a2)               /* store 16-bit */
        add     a3, a3, 2
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_wm_2: count == 0"
        .balign 4, 0
END(generic_bs_wm_2)


/* void bs_wm_4(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_wm_4)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        lw      a0, 0(a3)               /* load 32-bit */
        sw      a0, 0(a2)               /* store 32-bit */
        add     a3, a3, 4
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_wm_4: count == 0"
        .balign 4, 0
END(generic_bs_wm_4)


#ifdef _LP64
/* void bs_wm_8(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
ENTRY_NP(generic_bs_wm_8)
#ifdef DIAGNOSTIC
        beqz    a4, 2f
#endif
        PTR_L   a5, BS_STRIDE(a0)       /* stride */
        PTR_SLL a2, a2, a5              /* offset <<= stride */
        PTR_ADD a2, a2, a1              /* add to address */
1:
        ld      a0, 0(a3)               /* load 64-bit */
        sd      a0, 0(a2)               /* store 64-bit */
        add     a3, a3, 8
        add     a4, a4, -1              /* count-- */
        bnez    a4, 1b
        ret
2:
        la      a0, 3f
        tail    _C_LABEL(panic)
3:
        .asciz  "_bs_wm_8: count == 0"
        .balign 4, 0
END(generic_bs_wm_8)
#endif

/* void bs_wr_1(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
/* void bs_wr_2(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
/* void bs_wr_4(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */
/* void bs_wr_8(a0: tag, a1: addr, a2: offset, a3: datap, a4: count); */