Sub8x8_dct8_neon 函数分析

news/2024/10/23 19:54:25/

static void sub8x8_dct8dctcoef dct[64], pixel *pix1pixel *pix2 )

// 定义一个函数 sub8x8_dct8_neon,设置导出属性为 1

function sub8x8_dct8_neon, export=1

// 将 x3 寄存器设置为 FENC_STRIDE 的值 16

mov         x3, #FENC_STRIDE

// 将 x4 寄存器设置为 FDEC_STRIDE 的值 32 因为涉及deblocking 所以pading32x32

mov         x4, #FDEC_STRIDE

// 从地址 x1 加载 8 个字节到 v16

ld1        {v16.8b}, [x1], x3

// 从地址 x2 加载 8 个字节到 v17

ld1        {v17.8b}, [x2], x4

// 从地址 x1 加载 8 个字节到 v18

ld1        {v18.8b}, [x1], x3

// 从地址 x2 加载 8 个字节到 v19

ld1        {v19.8b}, [x2], x4

// 执行无符号减法,将 v16 和 v17 相减的结果保存到 v0

usubl       v0.8h,  v16.8b, v17.8b

// 从地址 x1 加载 8 个字节到 v20

ld1        {v20.8b}, [x1], x3

// 从地址 x2 加载 8 个字节到 v21

ld1        {v21.8b}, [x2], x4

// 执行无符号减法,将 v18 和 v19 相减的结果保存到 v1

usubl       v1.8h,  v18.8b, v19.8b

// 从地址 x1 加载 8 个字节到 v22

ld1        {v22.8b}, [x1], x3

// 从地址 x2 加载 8 个字节到 v23

ld1        {v23.8b}, [x2], x4

// 执行无符号减法,将 v20 和 v21 相减的结果保存到 v2

usubl       v2.8h,  v20.8b, v21.8b

// 从地址 x1 加载 8 个字节到 v24

ld1        {v24.8b}, [x1], x3

// 从地址 x2 加载 8 个字节到 v25

ld1        {v25.8b}, [x2], x4

// 执行无符号减法,将 v22 和 v23 相减的结果保存到 v3

usubl       v3.8h,  v22.8b, v23.8b

// 从地址 x1 加载 8 个字节到 v26

ld1        {v26.8b}, [x1], x3

// 从地址 x2 加载 8 个字节到 v27

ld1        {v27.8b}, [x2], x4

// 执行无符号减法,将 v24 和 v25 相减的结果保存到 v4

usubl       v4.8h,  v24.8b, v25.8b

// 从地址 x1 加载 8 个字节到 v28

ld1        {v28.8b}, [x1], x3

// 从地址 x2 加载 8 个字节到 v29

ld1        {v29.8b}, [x2], x4

// 执行无符号减法,将 v26 和 v27 相减的结果保存到 v5

usubl       v5.8h,  v26.8b, v27.8b

// 从地址 x1 加载 8 个字节到 v30

ld1        {v30.8b}, [x1], x3

// 从地址 x2 加载 8 个字节到 v31

ld1        {v31.8b}, [x2], x4

// 执行无符号减法,将 v28 和 v29 相减的结果保存到 v6

usubl       v6.8h,  v28.8b, v29.8b

// 执行无符号减法,将 v30 和 v31 相减的结果保存到 v7

usubl       v7.8h,  v30.8b, v31.8b

    DCT8_1D row //乘以正交矩阵

    transpose8x8.h v0, v1, v2, v3, v4, v5, v6, v7, v30, v31 //矩阵转秩一下

    DCT8_1D col //乘以一次正交矩阵

    st1        {v0.8h,v1.8h,v2.8h,v3.8h}, [x0], #64 //存入内存

    st1        {v4.8h,v5.8h,v6.8h,v7.8h}, [x0], #64 //存入内存

    ret

endfunc

//详细看看乘以矩阵的函数实现

.macro SUMSUB_AB   sum, sub, a, b

    add        \sum,  \a,  \b

    sub        \sub,  \a,  \b

.endm

里面相减相加参数需要\转义一下

.macro DCT8_1D type

// 对 v17.8h 和 v3.8h 进行 SUMSUB_AB 操作,结果存储在 v18.8h

    SUMSUB_AB   v18.8h, v17.8h, v3.8h,  v4.8h   

// 对 v16.8h 和 v2.8h 进行 SUMSUB_AB 操作,结果存储在 v19.8h

    SUMSUB_AB   v19.8h, v16.8h, v2.8h,  v5.8h   

// 对 v21.8h 和 v1.8h 进行 SUMSUB_AB 操作,结果存储在 v22.8h

    SUMSUB_AB   v22.8h, v21.8h, v1.8h,  v6.8h   

// 对 v20.8h 和 v0.8h 进行 SUMSUB_AB 操作,结果存储在 v23.8h

    SUMSUB_AB   v23.8h, v20.8h, v0.8h,  v7.8h   

// 对 v26.8h 和 v23.8h 进行 SUMSUB_AB 操作,结果存储在 v24.8h

    SUMSUB_AB   v24.8h, v26.8h,  v23.8h, v18.8h  

// 对 v27.8h 和 v22.8h 进行 SUMSUB_AB 操作,结果存储在 v25.8h

    SUMSUB_AB   v25.8h, v27.8h,  v22.8h, v19.8h  

// 对 v29.8h 和 v20.8h 进行 SUMSUB_AB 操作,结果存储在 v30.8h

    SUMSUB_AB   v30.8h, v29.8h,  v20.8h, v17.8h  

// 将 v21.8h 右移一位

    sshr        v23.8h, v21.8h, #1

// 将 v16.8h 右移一位

    sshr        v18.8h, v16.8h, #1

// 将 v23.8h 和 v21.8h 相加

    add         v23.8h, v23.8h, v21.8h

// 将 v18.8h 和 v16.8h 相加

    add         v18.8h, v18.8h, v16.8h

// 从 v30.8h 中减去 v23.8h

    sub         v30.8h, v30.8h, v23.8h

// 从 v29.8h 中减去 v18.8h

    sub         v29.8h, v29.8h, v18.8h

// 对 v31.8h 和 v21.8h 进行 SUMSUB_AB 操作,结果存储在 v28.8h

    SUMSUB_AB   v28.8h, v31.8h,  v21.8h, v16.8h  

// 将 v20.8h 右移一位

    sshr        v22.8h, v20.8h, #1

// 将 v17.8h 右移一位

    sshr        v19.8h, v17.8h, #1

// 将 v22.8h 和 v20.8h 相加

    add         v22.8h, v22.8h, v20.8h

// 将 v19.8h 和 v17.8h 相加

    add         v19.8h, v19.8h, v17.8h

// 将 v28.8h 和 v22.8h 相加

    add         v22.8h, v28.8h, v22.8h

// 将 v31.8h 和 v19.8h 相加

    add         v31.8h, v31.8h, v19.8h

// 对 v0.8h、v4.8h、v24.8h 和 v25.8h 进行 SUMSUB_AB 操作,结果存储在 v0.8h

    SUMSUB_AB      v0.8h,  v4.8h,  v24.8h, v25.8h

// 对 v1.8h、v7.8h、v22.8h、v31.8h、v16.8h 和 v17.8h 进行 SUMSUB_SHR 操作,结果存储在 v1.8h

    SUMSUB_SHR  2, v1.8h,  v7.8h,  v22.8h, v31.8h, v16.8h, v17.8h

// 对 v2.8h、v6.8h、v26.8h、v27.8h、v18.8h 和 v19.8h 进行 SUMSUB_SHR 操作,结果存储在 v2.8h

    SUMSUB_SHR  1, v2.8h,  v6.8h,  v26.8h, v27.8h, v18.8h, v19.8h

// 对 v3.8h、v5.8h、v30.8h、v29.8h、v20.8h 和 v21.8h 进行 SUMSUB_SHR2 操作,结果存储在 v3.8h

    SUMSUB_SHR2 2, v3.8h,  v5.8h,  v30.8h, v29.8h, v20.8h, v21.8h

.endm

这段代码是一个宏定义,用于执行离散余弦变换(DCT)的 1D 版本。它包含了一系列算术操作,主要是加法(SUMSUB_AB)和右移(sshr)操作。

以下是对代码中各部分的详细解释:

  1. SUMSUB_AB 操作:这是一种二元运算,对两个操作数进行求和和减法操作。
  2. shsr 操作:右移操作,将操作数向右移动指定的位数。
  3. add 和 sub 操作:加法和减法操作,用于执行数值计算。
  4. 宏定义的参数 type:可能用于表示数据类型或其他特定的配置。

总体而言,这段代码的目的是通过一系列的算术操作来计算离散余弦变换的 1D 版本。这些操作可能用于图像、音频或其他数字信号处理任务中,以对数据进行频域分析或变换。具体的计算细节和用途可能取决于上下文和应用程序的需求。如果你需要更详细的解释,可能需要参考相关的文档、算法说明或代码的其他部分。

函数注释

展开之后

.macro transpose8x8.h r0, r1, r2, r3, r4, r5, r6, r7, r8, r9

    trn1        v30().8H,  v0().8H,  v1().8H //

/*

trn1 v30().8H, v0().8H, v1().8H这句汇编指令可能是想表达trn1 v30.8H, v0.8H, v1.8H,如果是这样的话,它的含义为:将寄存器v30的高8位与寄存器v0v1的高8位进行转置( Transpose )操作,并将结果存储在寄存器v30中。

具体来说,转置操作是一种将数据的行和列进行交换的操作,在这个例子中,就是将寄存器v0v1的高8位进行交换,并将交换后的结果存储在寄存器v30的高8位中。

*/

    trn2        v31().8H,  v0().8H,  v1().8H

    trn1        v1().8H,  v2().8H,  v3().8H

    trn2        v3().8H,  v2().8H,  v3().8H

    trn1        v0().8H,  v4().8H,  v5().8H

    trn2        v5().8H,  v4().8H,  v5().8H

    trn1        v2().8H,  v6().8H,  v7().8H

    trn2        v7().8H,  v6().8H,  v7().8H

    trn1        v4().4S,  v0().4S,  v2().4S

    trn2        v2().4S,  v0().4S,  v2().4S

    trn1        v6().4S,  v5().4S,  v7().4S

    trn2        v7().4S,  v5().4S,  v7().4S

    trn1        v5().4S,  v31().4S,  v3().4S

    trn2        v31().4S,  v31().4S,  v3().4S

    trn1        v3().4S,  v30().4S,  v1().4S

    trn2        v30().4S,  v30().4S,  v1().4S

    trn1        v0().2D,  v3().2D,  v4().2D

    trn2        v4().2D,  v3().2D,  v4().2D

    trn1        v1().2D,  v5().2D,  v6().2D

    trn2        v5().2D,  v5().2D,  v6().2D

    trn2        v6().2D,  v30().2D,  v2().2D

    trn1        v2().2D,  v30().2D,  v2().2D

    trn1        v3().2D,  v31().2D,  v7().2D

    trn2        v7().2D,  v31().2D,  v7().2D

.endm


http://www.ppmy.cn/news/1400554.html

相关文章

【Springboot整合系列】SpringBoot整合WebService

目录 Web服务介绍Web服务的两种类型Web服务架构Web服务的主要特点Web服务使用场景Web服务标准和技术 WebService介绍WebService的作用适用场景不适用场景 WebService的原理三个角色相关概念 WebService开发框架代码实现服务端1.引入依赖2.实体类3.业务层接口接口实现类 4.配置类…

通俗易懂:volatile关键字在内存模型中起到什么作用?

在计算机编程语言中,尤其是在Java语言中,volatile关键字对于内存模型的影响至关重要,它主要用于解决多线程环境下的内存可见性和禁止指令重排序问题,以确保并发编程的正确性。以下是volatile关键字在Java内存模型(JMM&…

图像颜色空间转换算法

图像颜色空间转换算法主要包括RGB到灰度图像的转换、RGB到CMYK的转换、RGB到HSV的转换以及RGB到Lab的转换。下面我将详细介绍每种算法的实现原理: RGB到灰度图像的转换: 对于RGB图像,可以将每个像素点的红、绿、蓝三个通道的值按照一定权重进…

RabbitMQ 延时消息实现

1. 实现方式 1. 设置队列过期时间:延迟队列消息过期 死信队列,所有消息过期时间一致 2. 设置消息的过期时间:此种方式下有缺陷,MQ只会判断队列第一条消息是否过期,会导致消息的阻塞需要额外安装 rabbitmq_delayed_me…

Linux内核之debugfs_create_dir与debugfs_create_file实例与调用栈流程(三十二)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

选择全球直播专线考虑的因素有哪些?

当你需要选择全球直播专线时,有一些关键因素需要考虑,以确保你的直播服务能够稳定、低延迟且高质量。以下是一些建议,帮助你选择合适的全球直播专线: 地理位置:选择距离你目标观众较近的直播专线,以减少网络…

Go程序设计语言 学习笔记 第五章 函数

5.1 函数声明 每个函数声明都包含一个名字、一个形参列表、一个可选的返回列表以及函数体: func name(parameter-list) (result-list) {body }形参列表指定了一组变量的参数名和参数类型,这些局部变量由调用者提供的实参传递而来。返回列表则指定了函数…

图论- 最小生成树

一、最小生成树-prim算法 1.1 最小生成树概念 一幅图可以有很多不同的生成树,比如下面这幅图,红色的边就组成了两棵不同的生成树: 对于加权图,每条边都有权重(用最小生成树算法的现实场景中,图的边权重…