assembly 用于ARM的memcpy用于ARM64的未缓存内存

gjmwrych  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(246)

我在实现memcpy(src,dst,sz)时遇到问题;适用于 neon
由于ARM SoC的DMA中没有缓存,从DMA中复制的速度会慢很多。

void my_copy(volatile unsigned char *dst, volatile unsigned char *src, int sz)
{
    if (sz & 63) {
        sz = (sz & -64) + 64;
    }
    asm volatile (
        "NEONCopyPLD:                          \n"
        "    VLDM %[src]!,{d0-d7}                 \n"
        "    VSTM %[dst]!,{d0-d7}                 \n"
        "    SUBS %[sz],%[sz],#0x40                 \n"
        "    BGT NEONCopyPLD                  \n"
        : [dst]"+r"(dst), [src]"+r"(src), [sz]"+r"(sz) : : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "cc", "memory");
}

这是一个代码为ARMv7由@蒂莫西米勒ARM/neon memcpy optimized for uncached memory?
由于ARM 64指令集没有VLDM和VSTM,
我使用的是LD和ST。但是,它和C语言中的memcpy()一样慢。

"NEONCopyPLD: \n"
"ld4 {v0.16b, v1.16b, v2.16b, v3.16b}, [%[src]], #64 \n"
"st4 {v0.16b, v1.16b, v2.16b, v3.16b}, [%[dst]], #64 \n"
"SUBS %[sz], %[sz],#0x40\n"
"BGT NEONCopyPLD \n"

在ARM 64中,除了使用LD& ST之外,是否有更好的方法?

camsedfj

camsedfj1#

aarch64具有针对未缓存区域的内存操作。(非临时)
下面是我的建议:

"NEONCopyPLD: \n"
"sub %[dst], %[dst], #64 \n"
"1: \n"
"ldnp q0, q1, [%[src]] \n"
"ldnp q2, q3, [%[src], #32] \n"
"add %[dst], %[dst], #64 \n"
"subs %[sz], %[sz], #64 \n"
"add %[src], %[src], #64 \n"
"stnp q0, q1, [%[dst]] \n"
"stnp q2, q3, [%[dst], #32] \n"
"b.gt 1b \n"

对于缓存区域:

"NEONCopyPLD: \n"
"sub %[src], %[src], #32 \n"
"sub %[dst], %[dst], #32 \n"
"1: \n"
"ldp q0, q1, [%[src], #32] \n"
"ldp q2, q3, [%[src], #64]! \n"
"subs %[sz], %[sz], #64 \n"
"stp q0, q1, [%[dst], #32] \n"
"stp q2, q3, [%[dst], #64]! \n"
"b.gt 1b \n"

相关问题