root/sys/arch/mac68k/mac68k/bus_space.c
/*      $NetBSD: bus_space.c,v 1.34 2026/04/26 10:52:15 thorpej Exp $   */

/*-
 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * 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.
 */

/*
 * Implementation of bus_space mapping for mac68k.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.34 2026/04/26 10:52:15 thorpej Exp $");

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/extent.h>

#include <machine/bus.h>
#include <machine/cpu.h>
#include <m68k/cacheops.h>

#include <uvm/uvm_extern.h>

int     bus_mem_add_mapping(bus_addr_t, bus_size_t, int, bus_space_handle_t *);

extern struct extent *iomem_ex;
extern int iomem_malloc_safe;

int
bus_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int flags,
                    bus_space_handle_t *hp)
{
        u_long pa, endpa;
        vaddr_t va;

        pa = m68k_trunc_page(bpa);
        endpa = m68k_round_page((bpa + size) - 1);

#ifdef DIAGNOSTIC
        if (endpa <= pa)
                panic("bus_mem_add_mapping: overflow");
#endif

        va = uvm_km_alloc(kernel_map, endpa - pa, 0,
            UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
        if (va == 0)
                return (ENOMEM);

        hp->base = (u_long)(va + m68k_page_offset(bpa));
        hp->swapped = 0;
        hp->stride = 1;
        hp->bsr1 = mac68k_bsr1;
        hp->bsr2 = mac68k_bsr2;
        hp->bsr4 = mac68k_bsr4;
        hp->bsrs1 = mac68k_bsr1;
        hp->bsrs2 = mac68k_bsr2;
        hp->bsrs4 = mac68k_bsr4;
        hp->bsrm1 = mac68k_bsrm1;
        hp->bsrm2 = mac68k_bsrm2;
        hp->bsrm4 = mac68k_bsrm4;
        hp->bsrms1 = mac68k_bsrm1;
        hp->bsrms2 = mac68k_bsrm2;
        hp->bsrms4 = mac68k_bsrm4;
        hp->bsrr1 = mac68k_bsrr1;
        hp->bsrr2 = mac68k_bsrr2;
        hp->bsrr4 = mac68k_bsrr4;
        hp->bsrrs1 = mac68k_bsrr1;
        hp->bsrrs2 = mac68k_bsrr2;
        hp->bsrrs4 = mac68k_bsrr4;
        hp->bsw1 = mac68k_bsw1;
        hp->bsw2 = mac68k_bsw2;
        hp->bsw4 = mac68k_bsw4;
        hp->bsws1 = mac68k_bsw1;
        hp->bsws2 = mac68k_bsw2;
        hp->bsws4 = mac68k_bsw4;
        hp->bswm1 = mac68k_bswm1;
        hp->bswm2 = mac68k_bswm2;
        hp->bswm4 = mac68k_bswm4;
        hp->bswms1 = mac68k_bswm1;
        hp->bswms2 = mac68k_bswm2;
        hp->bswms4 = mac68k_bswm4;
        hp->bswr1 = mac68k_bswr1;
        hp->bswr2 = mac68k_bswr2;
        hp->bswr4 = mac68k_bswr4;
        hp->bswrs1 = mac68k_bswr1;
        hp->bswrs2 = mac68k_bswr2;
        hp->bswrs4 = mac68k_bswr4;
        hp->bssm1 = mac68k_bssm1;
        hp->bssm2 = mac68k_bssm2;
        hp->bssm4 = mac68k_bssm4;
        hp->bssr1 = mac68k_bssr1;
        hp->bssr2 = mac68k_bssr2;
        hp->bssr4 = mac68k_bssr4;

        const int pmap_flags =
            (flags & BUS_SPACE_MAP_CACHEABLE) ? PMAP_WIRED
                                              : (PMAP_WIRED | PMAP_NOCACHE);

        for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
                pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE,
                    pmap_flags);
        }
        pmap_update(pmap_kernel());
 
        return 0;
}

int
bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
              bus_space_handle_t *hp)
{
#ifdef DIAGNOSTIC
        paddr_t pa, endpa;
#endif
        int error;

        /*
         * Before we go any further, let's make sure that this
         * region is available.
         */
        error = extent_alloc_region(iomem_ex, bpa, size,
            EX_NOWAIT | (iomem_malloc_safe ? EX_MALLOCOK : 0));
        if (error)
                return (error);

#ifdef DIAGNOSTIC
        pa = m68k_trunc_page(bpa + t);
        endpa = m68k_round_page((bpa + t + size) - 1);

        if (endpa <= pa)
                panic("bus_space_map: overflow");
#endif

        error = bus_mem_add_mapping(bpa, size, flags, hp);
        if (error) {
                if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
                    (iomem_malloc_safe ? EX_MALLOCOK : 0))) {
                        printf("bus_space_map: pa 0x%lx, size 0x%lx\n",
                            bpa, size);
                        printf("bus_space_map: can't free region\n");
                }
        }

        return (error);
}

int
bus_space_alloc(bus_space_tag_t t,
                bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
                bus_size_t alignment, bus_size_t boundary, int flags,
                bus_addr_t *bpap, bus_space_handle_t *hp)
{
        u_long bpa;
        int error;

        /*
         * Sanity check the allocation against the extent's boundaries.
         */
        if (rstart < iomem_ex->ex_start || rend > iomem_ex->ex_end)
                panic("bus_space_alloc: bad region start/end");

        /*
         * Do the requested allocation.
         */
        error = extent_alloc_subregion(iomem_ex, rstart, rend, size, alignment,
            boundary,
            EX_FAST | EX_NOWAIT | (iomem_malloc_safe ?  EX_MALLOCOK : 0),
            &bpa);

        if (error)
                return (error);

        /*
         * For memory space, map the bus physical address to
         * a kernel virtual address.
         */
        error = bus_mem_add_mapping(bpa, size, flags, hp);
        if (error) {
                if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
                    (iomem_malloc_safe ? EX_MALLOCOK : 0))) {
                        printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n",
                            bpa, size);
                        printf("bus_space_alloc: can't free region\n");
                }
        }

        *bpap = bpa;

        return (error);
}

void
bus_space_unmap(bus_space_tag_t t, bus_space_handle_t h, bus_size_t size)
{
        vaddr_t va, endva;
        bus_addr_t bpa;

        va = m68k_trunc_page(h.base);
        endva = m68k_round_page((h.base + size) - 1);

#ifdef DIAGNOSTIC
        if (endva <= va)
                panic("bus_space_unmap: overflow");
#endif

        (void) pmap_extract(pmap_kernel(), va, &bpa);
        bpa += m68k_page_offset(h.base);

        /*
         * Free the kernel virtual mapping.
         */
        pmap_kremove(va, endva - va);
        uvm_km_free(kernel_map, va, endva - va, UVM_KMF_VAONLY);

        if (extent_free(iomem_ex, bpa, size,
            EX_NOWAIT | (iomem_malloc_safe ? EX_MALLOCOK : 0))) {
                printf("bus_space_unmap: pa 0x%lx, size 0x%lx\n",
                    bpa, size);
                printf("bus_space_unmap: can't free region\n");
        }
}

void    
bus_space_free(bus_space_tag_t t, bus_space_handle_t h, bus_size_t size)
{
        /* bus_space_unmap() does all that we need to do. */
        bus_space_unmap(t, h, size);
}

int
bus_space_subregion(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset,
                    bus_size_t size, bus_space_handle_t *nhp)
{

        *nhp = h;
        nhp->base += offset;
        return (0);
}

int
mac68k_bus_space_probe(bus_space_tag_t t, bus_space_handle_t h,
                       bus_size_t offset, int size)
{
        label_t faultbuf;

        nofault = &faultbuf;
        if (setjmp(nofault)) {
                nofault = NULL;
                return (0);
        }

        switch (size) {
        case 1:
                bus_space_read_1(t, h, offset);
                break;
        case 2:
                bus_space_read_2(t, h, offset);
                break;
        case 4:
                bus_space_read_4(t, h, offset);
                break;
        case 8:
        default:
                panic("bus_space_probe: unsupported data size %d", size);
                /* NOTREACHED */
        }

        nofault = NULL;
        return (1);
}

void
mac68k_bus_space_handle_swapped(bus_space_tag_t t, bus_space_handle_t *h)
{
        h->swapped = 1;
        if (h->stride == 1) {
                h->bsr2 = mac68k_bsr2_swap;
                h->bsr4 = mac68k_bsr4_swap;
                h->bsrm2 = mac68k_bsrm2_swap;
                h->bsrm4 = mac68k_bsrm4_swap;
                h->bsrr2 = mac68k_bsrr2_swap;
                h->bsrr4 = mac68k_bsrr4_swap;
                h->bsw2 = mac68k_bsw2_swap;
                h->bsw4 = mac68k_bsw4_swap;
                h->bswm2 = mac68k_bswm2_swap;
                h->bswm4 = mac68k_bswm4_swap;
                h->bswr2 = mac68k_bswr2_swap;
                h->bswr4 = mac68k_bswr4_swap;
                h->bssm2 = mac68k_bssm2_swap;
                h->bssm4 = mac68k_bssm4_swap;
                h->bssr2 = mac68k_bssr2_swap;
                h->bssr4 = mac68k_bssr4_swap;
        }
}

void
mac68k_bus_space_handle_set_stride(bus_space_tag_t t, bus_space_handle_t *h,
                                   int stride)
{
        h->stride = stride;
        h->bsr1 = mac68k_bsr1_gen;
        h->bsr2 = mac68k_bsr2_gen;
        h->bsr4 = mac68k_bsr4_gen;
        h->bsrs2 = mac68k_bsrs2_gen;
        h->bsrs4 = mac68k_bsrs4_gen;
        h->bsrm1 = mac68k_bsrm1_gen;
        h->bsrm2 = mac68k_bsrm2_gen;
        h->bsrm4 = mac68k_bsrm4_gen;
        h->bsrms2 = mac68k_bsrms2_gen;
        h->bsrms4 = mac68k_bsrms4_gen;
        h->bsrr1 = mac68k_bsrr1_gen;
        h->bsrr2 = mac68k_bsrr2_gen;
        h->bsrr4 = mac68k_bsrr4_gen;
        h->bsrrs2 = mac68k_bsrrs2_gen;
        h->bsrrs4 = mac68k_bsrrs4_gen;
        h->bsw1 = mac68k_bsw1_gen;
        h->bsw2 = mac68k_bsw2_gen;
        h->bsw4 = mac68k_bsw4_gen;
        h->bsws2 = mac68k_bsws2_gen;
        h->bsws4 = mac68k_bsws4_gen;
        h->bswm2 = mac68k_bswm2_gen;
        h->bswm4 = mac68k_bswm4_gen;
        h->bswms2 = mac68k_bswms2_gen;
        h->bswms4 = mac68k_bswms4_gen;
        h->bswr1 = mac68k_bswr1_gen;
        h->bswr2 = mac68k_bswr2_gen;
        h->bswr4 = mac68k_bswr4_gen;
        h->bswrs2 = mac68k_bswrs2_gen;
        h->bswrs4 = mac68k_bswrs4_gen;
        h->bssm1 = mac68k_bssm1_gen;
        h->bssm2 = mac68k_bssm2_gen;
        h->bssm4 = mac68k_bssm4_gen;
        h->bssr1 = mac68k_bssr1_gen;
        h->bssr2 = mac68k_bssr2_gen;
        h->bssr4 = mac68k_bssr4_gen;
}

u_int8_t
mac68k_bsr1(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset)
{
        return (*(volatile u_int8_t *)(h->base + offset));
}

u_int8_t
mac68k_bsr1_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset)
{
        return (*(volatile u_int8_t *)(h->base + offset * h->stride));
}

u_int16_t
mac68k_bsr2(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset)
{
        return (*(volatile u_int16_t *)(h->base + offset));
}

u_int16_t
mac68k_bsr2_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset)
{
        u_int16_t       v;

        v = (*(volatile u_int16_t *)(h->base + offset));
        return bswap16(v);
}

u_int16_t
mac68k_bsrs2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset)
{
        u_int16_t       v;

        v = (*(volatile u_int8_t *)(h->base + offset++ * h->stride)) << 8;
        v |= (*(volatile u_int8_t *)(h->base + offset * h->stride));
        return v;
}

u_int16_t
mac68k_bsr2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset)
{
        u_int16_t       v;

        v = mac68k_bsrs2_gen(t, h, offset);
        if (h->swapped) {
                v = bswap16(v);
        }
        return v;
}

u_int32_t
mac68k_bsr4(bus_space_tag_t tag, bus_space_handle_t *h, bus_size_t offset)
{
        return (*(volatile u_int32_t *)(h->base + offset));
}

u_int32_t
mac68k_bsr4_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset)
{
        u_int32_t       v;

        v = (*(volatile u_int32_t *)(h->base + offset));
        return bswap32(v);
}

u_int32_t
mac68k_bsrs4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset)
{
        u_int32_t       v;

        v = (*(volatile u_int8_t *)(h->base + offset++ * h->stride));
        v <<= 8;
        v |= (*(volatile u_int8_t *)(h->base + offset++ * h->stride));
        v <<= 8;
        v |= (*(volatile u_int8_t *)(h->base + offset++ * h->stride));
        v <<= 8;
        v |= (*(volatile u_int8_t *)(h->base + offset++ * h->stride));
        return v;
}

u_int32_t
mac68k_bsr4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset)
{
        u_int32_t       v;

        v = mac68k_bsrs4_gen(t, h, offset);
        if (h->swapped) {
                v = bswap32(v);
        }
        return v;
}

void
mac68k_bsrm1(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int8_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movb    %%a0@,%%a1@+    ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bsrm1_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int8_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_1(t, *h, offset);
        }
}

void
mac68k_bsrm2(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int16_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%a0@,%%a1@+    ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bsrm2_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int16_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%a0@,%%d1      ;"
        "       rolw    #8,%%d1         ;"
        "       movw    %%d1,%%a1@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0","d1");
}

void
mac68k_bsrm2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int16_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_2(t, *h, offset);
        }
}

void
mac68k_bsrms2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int16_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_stream_2(t, *h, offset);
        }
}

void
mac68k_bsrm4(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int32_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%a0@,%%a1@+    ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bsrm4_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int32_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%a0@,%%d1      ;"
        "       rolw    #8,%%d1         ;"
        "       swap    %%d1            ;"
        "       rolw    #8,%%d1         ;"
        "       movl    %%d1,%%a1@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0","d1");
}

void
mac68k_bsrm4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int32_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_4(t, *h, offset);
        }
}

void
mac68k_bsrms4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int32_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_stream_4(t, *h, offset);
        }
}

void
mac68k_bsrr1(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int8_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movb    %%a0@+,%%a1@+   ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bsrr1_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int8_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_1(t, *h, offset);
                offset++;
        }
}

void
mac68k_bsrr2(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int16_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%a0@+,%%a1@+   ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bsrr2_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int16_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%a0@+,%%d1     ;"
        "       rolw    #8,%%d1         ;"
        "       movw    %%d1,%%a1@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0","d1");
}

void
mac68k_bsrr2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int16_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_2(t, *h, offset);
                offset += 2;
        }
}

void
mac68k_bsrrs2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int16_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_stream_2(t, *h, offset);
                offset += 2;
        }
}

void
mac68k_bsrr4(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int32_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%a0@+,%%a1@+   ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bsrr4_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int32_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%a0@+,%%d1     ;"
        "       rolw    #8,%%d1         ;"
        "       swap    %%d1            ;"
        "       rolw    #8,%%d1         ;"
        "       movl    %%d1,%%a1@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bsrr4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int32_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_4(t, *h, offset);
                offset += 4;
        }
}

void
mac68k_bsrrs4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int32_t *a, size_t c)
{
        while (c--) {
                *a++ = bus_space_read_stream_4(t, *h, offset);
                offset += 4;
        }
}

void
mac68k_bsw1(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
            u_int8_t v)
{
        (*(volatile u_int8_t *)(h->base + offset)) = v;
}

void
mac68k_bsw1_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                u_int8_t v)
{
        (*(volatile u_int8_t *)(h->base + offset * h->stride)) = v;
}

void
mac68k_bsw2(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
            u_int16_t v)
{
        (*(volatile u_int16_t *)(h->base + offset)) = v;
}

void
mac68k_bsw2_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int16_t v)
{
        v = bswap16(v);
        (*(volatile u_int16_t *)(h->base + offset)) = v;
}

void
mac68k_bsws2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int16_t v)
{
        u_int8_t        v1;

        v1 = (v & 0xff00) >> 8;
        (*(volatile u_int8_t *)(h->base + offset++ * h->stride)) = v1;
        (*(volatile u_int8_t *)(h->base + offset * h->stride)) = v & 0xff;
}

void
mac68k_bsw2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                u_int16_t v)
{
        if (h->swapped) {
                v = bswap16(v);
        }
        mac68k_bsws2_gen(t, h, offset, v);
}

void
mac68k_bsw4(bus_space_tag_t tag, bus_space_handle_t *h, bus_size_t offset,
            u_int32_t v)
{
        (*(volatile u_int32_t *)(h->base + offset)) = v;
}

void
mac68k_bsw4_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int32_t v)
{
        v = bswap32(v);
        (*(volatile u_int32_t *)(h->base + offset)) = v;
}

void
mac68k_bsws4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int32_t v)
{
        u_int8_t        v1,v2,v3;

        v1 = (v & 0xff000000) >> 24;
        v2 = (v & 0x00ff0000) >> 16;
        v3 = (v & 0x0000ff00) >> 8;
        (*(volatile u_int8_t *)(h->base + offset++ * h->stride)) = v1;
        (*(volatile u_int8_t *)(h->base + offset++ * h->stride)) = v2;
        (*(volatile u_int8_t *)(h->base + offset++ * h->stride)) = v3;
        (*(volatile u_int8_t *)(h->base + offset * h->stride)) = v & 0xff;
}

void
mac68k_bsw4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int32_t v)
{
        if (h->swapped) {
                v = bswap32(v);
        }
        mac68k_bsws4_gen(t, h, offset, v);
}

void
mac68k_bswm1(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             const u_int8_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movb    %%a1@+,%%a0@    ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bswm1_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 const u_int8_t *a, size_t c)
{
        while (c--) {
                bus_space_write_1(t, *h, offset, *a++);
        }
}

void
mac68k_bswm2(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             const u_int16_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%a1@+,%%a0@    ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bswm2_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  const u_int16_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%a1@+,%%d1     ;"
        "       rolw    #8,%%d1         ;"
        "       movw    %%d1,%%a0@      ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0","d1");
}

void
mac68k_bswm2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 const u_int16_t *a, size_t c)
{
        while (c--) {
                bus_space_write_2(t, *h, offset, *a++);
        }
}

void
mac68k_bswms2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  const u_int16_t *a, size_t c)
{
        while (c--) {
                bus_space_write_stream_2(t, *h, offset, *a++);
        }
}

void
mac68k_bswm4(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             const u_int32_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%a1@+,%%a0@    ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bswm4_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  const u_int32_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%a1@+,%%d1     ;"
        "       rolw    #8,%%d1         ;"
        "       swap    %%d1            ;"
        "       rolw    #8,%%d1         ;"
        "       movl    %%d1,%%a0@      ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0","d1");
}

void
mac68k_bswm4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 const u_int32_t *a, size_t c)
{
        while (c--) {
                bus_space_write_4(t, *h, offset, *a++);
        }
}

void
mac68k_bswms4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  const u_int32_t *a, size_t c)
{
        while (c--) {
                bus_space_write_stream_4(t, *h, offset, *a++);
        }
}

void
mac68k_bswr1(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             const u_int8_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movb    %%a1@+,%%a0@+   ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bswr1_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 const u_int8_t *a, size_t c)
{
        while (c--) {
                bus_space_write_1(t, *h, offset, *a++);
                offset++;
        }
}

void
mac68k_bswr2(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             const u_int16_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%a1@+,%%a0@+   ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bswr2_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  const u_int16_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%a1@+,%%d1     ;"
        "       rolw    #8,%%d1         ;"
        "       movw    %%d1,%%a0@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0","d1");
}

void
mac68k_bswr2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 const u_int16_t *a, size_t c)
{
        while (c--) {
                bus_space_write_2(t, *h, offset, *a++);
                offset += 2;
        }
}

void
mac68k_bswrs2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  const u_int16_t *a, size_t c)
{
        while (c--) {
                bus_space_write_stream_2(t, *h, offset, *a++);
                offset += 2;
        }
}

void
mac68k_bswr4(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             const u_int32_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%a1@+,%%a0@+   ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0");
}

void
mac68k_bswr4_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  const u_int32_t *a, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%a1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%a1@+,%%d1     ;"
        "       rolw    #8,%%d1         ;"
        "       swap    %%d1            ;"
        "       rolw    #8,%%d1         ;"
        "       movl    %%d1,%%a0@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                     :
                                                                :
                    "r" (h->base + offset), "g" (a), "g" (c)    :
                    "a0","a1","d0","d1");
}

void
mac68k_bswr4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 const u_int32_t *a, size_t c)
{
        while (c--) {
                bus_space_write_4(t, *h, offset, *a++);
                offset += 4;
        }
}

void
mac68k_bswrs4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  const u_int32_t *a, size_t c)
{
        while (c--) {
                bus_space_write_4(t, *h, offset, *a++);
                offset += 4;
        }
}

void
mac68k_bssm1(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int8_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movb    %%d1,%%a0@      ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssm1_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int8_t v, size_t c)
{
        while (c--) {
                bus_space_write_1(t, *h, offset, v);
        }
}

void
mac68k_bssm2(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int16_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%d1,%%a0@      ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssm2_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int16_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       rolw    #8,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%d1,%%a0@      ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssm2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int16_t v, size_t c)
{
        while (c--) {
                bus_space_write_2(t, *h, offset, v);
        }
}

void
mac68k_bssm4(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int32_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%d1,%%a0@      ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssm4_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int32_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       rolw    #8,%%d1         ;"
        "       swap    %%d1            ;"
        "       rolw    #8,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%d1,%%a0@      ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssm4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int32_t v, size_t c)
{
        while (c--) {
                bus_space_write_4(t, *h, offset, v);
        }
}

void
mac68k_bssr1(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int8_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movb    %%d1,%%a0@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssr1_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int8_t v, size_t c)
{
        while (c--) {
                bus_space_write_1(t, *h, offset, v);
                offset++;
        }
}

void
mac68k_bssr2(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int16_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%d1,%%a0@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssr2_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int16_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       rolw    #8,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movw    %%d1,%%a0@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssr2_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int16_t v, size_t c)
{
        while (c--) {
                bus_space_write_2(t, *h, offset, v);
                offset += 2;
        }
}

void
mac68k_bssr4(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
             u_int32_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%d1,%%a0@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssr4_swap(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                  u_int32_t v, size_t c)
{
        __asm volatile (
        "       movl    %0,%%a0         ;"
        "       movl    %1,%%d1         ;"
        "       rolw    #8,%%d1         ;"
        "       swap    %%d1            ;"
        "       rolw    #8,%%d1         ;"
        "       movl    %2,%%d0         ;"
        "1:     movl    %%d1,%%a0@+     ;"
        "       subql   #1,%%d0         ;"
        "       jne     1b"                                             :
                                                                        :
                    "r" (h->base + offset), "g" ((u_long)v), "g" (c)    :
                    "a0","d0","d1");
}

void
mac68k_bssr4_gen(bus_space_tag_t t, bus_space_handle_t *h, bus_size_t offset,
                 u_int32_t v, size_t c)
{
        while (c--) {
                bus_space_write_4(t, *h, offset, v);
                offset += 4;
        }
}