DSP汇编中的循环问题

2019-03-26 16:36发布

  我的板子是c6740,编写测试程序想把两个数组对应的数相乘存到第三个数组中,主文件是:
#include <stdio.h> int MPY_1(int *m, int *n, int *result, int count); void main()
{
 int n[10] = {1,2,3,4,5,6,7,8,9,10};
 int m[10] = {11,12,13,14,15,16,17,18,19,20};
 int tmp,i;
 int *result;
 result = (int *)malloc(10*sizeof(int));
 tmp = MPY_1(m,n,result,10);
 for(i=0;i<10;i++)
  printf("m=%d,n=%d,result=%d,d=%d ",m,n,result,tmp); }
/**************调用汇编函数文件****************/
 .text
 .global _MPY_1
_MPY_1:     .asg A4, p_m
  .asg B4, p_n
  .asg A6, p_result
  .asg B6, B_count
  .asg A1, A_m
  .asg B1, B_n
  .asg A3, A_loopcount
  .asg A7, A_s
* ================= LOOP PROLOG ============================ *
   MV .S1 B6, A_loopcount    || MV .L1 A4,B4   || MV .L2 A5,B5
 SUB .S1 A_loopcount, 1,A_loopcount
* ===================== LOOP KERNEL ============================== *
loop:
    LDW .D1 *A5++[1], A_m ;A_m = *m
  ||  LDW .D2 *B5++[1], B_n ;A_n = *n
   MPY .M1 A_m,B_n,A_s ; A_S = m * n 
    NOP 1
 STW .D1 A_s,*A6++[1]  ; result = A_S
  
 ||[A_loopcount] B .S2 loop    ; branch ,Illegal register for conditional
    ||[A_loopcount]SUB .S1 A_loopcount, 1,A_loopcount
 
* ===================== LOOP EPILOG ============================== *
 B .S2 B3   ;return
 MVK .S1 1,A4 ;return 1
 nop 1
 .end   这程序编译没通过,在||[A_loopcount] B .S2 loop   这条语句下报错Illegal register for conditional。
第一次写汇编循环,请大侠帮看下这个程序哪些地方出错了?需要怎么改才能实现所想要的功能,谢谢! [ 本帖最后由 breeze505 于 2012-4-27 14:35 编辑 ] 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
18条回答
carrotchen
1楼-- · 2019-03-27 11:09
1. 由于中间结果会超过255,那么就不能使用ADD4指令了,但是可以利用C64的打包指令和并行运算指令来实现一次处理两个数据。

2. 对于pSrcRGB的存储方式有一定要求:像素的R G B分量存储在一个32位的数据中,且高8-bit为0。如下所示,
| 0x00 | R1 | G1 | B1 | 0x00 | R2 | G2 | B2 | ......

3. 下面说一下实现的思路,供参考(非最优code,根据实际情况改写)
1) 用两个LDW指令读取两个像素的RGB值到寄存器RGB1_reg和RGB2_reg
RGB1_reg: 0x00 | R1 | G1 | B1
RGB2_reg: 0x00 | R2 | G2 | B2

2) 用打包指令对R G B分量进行打包
需要一个寄存器保存mask
MVKL 0x00ff00ff, mask_reg
MVKH 0x00ff00ff, mask_reg; mask_reg = 0x00ff00ff,可以放在循环外,值保持不变

打包
PACKH2 RGB1_reg, RGB2_reg, R12_reg ;R12_reg = 0x00 | R1 | 0x00 | R2
PACKH4 RGB1_reg, RGB2_reg, G12_reg ;G12_reg = 0x00 | G1 | 0x00 | G2
PACKL4 RGB1_reg, RGB2_reg, B12_reg ;B12_reg = R1 | B1 | R2 | B2
AND B12_reg, mask_reg, B12_reg    ;B12_reg = 0x00 | B1 | 0x00 | B2

3) 使用ADD2 SUB2 SHR2做并行16位的运算,高8-bit的0x00保证中间结果不会溢出

4) 将运算结果限定不超过255
MIN2 R12_reg, max_reg, R12_reg; max_reg的值等于mask_reg,可以复用
MIN2 G12_reg, max_reg, G12_reg
MIN2 B12_reg, max_reg, B12_reg
MAX2 R12_reg, min_reg, R12_reg; min_reg = 0
MAX2 G12_reg, min_reg, G12_reg
MAX2 B12_reg, min_reg, B12_reg

运算结果是:
R12_reg: 0x00 | R1_r | 0x00 | R2_r
B12_reg: 0x00 | B1_r | 0x00 | B2_r
G12_reg: 0x00 | G1_r | 0x00 | G2_r

5) 解包,也是用打包指令
PACKH2 R12_reg, B12_reg, dst1_reg ;dst1_reg = 0x00 | R1_r | 0x00 | B1_r
PACK2 R12_reg, B12_reg, dst2_reg  ;dst2_reg = 0x00 | R2_r | 0x00 | B2_r

把G12_reg并入dst reg会比较麻烦,可以用以下方法:
需要另外一个寄存器保存mask
MVKL 0x0000ff00, mask2_reg ;
MVKH 0x0000ff00, mask2_reg; mask2_reg = 0x0000ff00,可以放在循环外,值保持不变

    SHRMB G12_reg, G12_reg, tmp1_reg; tmp1_reg = G2_r | 0x00 | G1_r | 0x00
    AND tmp1_reg, mask2_reg, tmp1_reg; tmp1_reg = 0x00 | 0x00 | G1_r | 0x00
    SHLMB G12_reg, G12_reg, tmp2_reg; tmp2_reg = G1_r | 0x00 | G2_r | 0x00
    AND tmp2_reg, mask2_reg, tmp2_reg; tmp2_reg = 0x00 | 0x00 | G2_r | 0x00

    OR dst1_reg, tmp1_reg, dst1_reg; dst1_reg = 0x00 | R1_r | G1_r | B1_r ; dst1_reg是像素1的运算结果
    OR dst2_reg, tmp2_reg, dst2_reg; dst2_reg = 0x00 | R2_r | G2_r | B2_r ; dst2_reg是像素2的运算结果

6) STW

[ 本帖最后由 carrotchen 于 2012-4-28 16:31 编辑 ]
breeze505
2楼-- · 2019-03-27 11:40
(1)我要计算的数据是RGB24格式,依照B1,G1,R1,B2,G2,R2..存储,这样它就是非32位对齐,用LDW就不好读进去算了吧?
(2)根据你的指导,打包指令看起来很强大,我需对照指令集文档再详细看下。
(3)还得麻烦你帮看下我在7楼所描述的双层循环问题,为什么我只能执行单层 的
求教,感谢!
carrotchen
3楼-- · 2019-03-27 12:03
1. RGB数据需存储成| 0x00 | R1 | G1 | B1 | 0x00 | R2 | G2 | B2 | ......,否则不方便处理。
2. 你的代码中
[!A_loopheight]  B .S1 loop ; <--- A_loopheight为0时跳转到loop,第一次执行到该指令处,A_loopheight=2,那么就跳出循环了,与预想不符合吧?
breeze505
4楼-- · 2019-03-27 16:44

(1)那这样的话,需要在主函数进入汇编前把数据流处理成0RGB0RGB格式的,这样需要遍历64*64,还要写操作,这些耗费的时间应该也不会少,所以我觉得这样的话,总体的效率应该不会比直接单字节高吧?我写了单字节处理的RGB-YCbCr位移的汇编程序,发现瓶颈都集中在.S单元,因为位移运算只有用到.S单元,所以一次只能并行2条指令。所以,我想是否有可以采取某种数据打包方式+提高并行处理度,来提高总体的程序性能?

(2)嗯,我想错了,但是那应该怎么去跳转才能实现双循环功能呢

[ 本帖最后由 breeze505 于 2012-5-2 09:07 编辑 ]
carrotchen
5楼-- · 2019-03-27 20:45
 精彩回答 2  元偷偷看……
breeze505
6楼-- · 2019-03-28 00:16
 精彩回答 2  元偷偷看……

一周热门 更多>