一个细节问题——__builtin_compose_128还是memcpy还是强制类型转换

 为了学习ADSP--TigerSHARC的C语言编程,我找了一个TS101的C程序,来学习。
      看到DMA的部分,发现函数中定义了一个这样的结构体变量t:
      struct tcb{
            void * DI;
            int DX;
            int DY;
            int DP;
      }t;
      我查阅了相关的文档,知道在TS101中,有这样一些名为TCB的寄存器,它们的功能是设置DMA的一些参数,它们的结构如下:
      一个TCB寄存器有128位,分成四块,每块32位,即每块4个字节。
      这四个32位单元从低到高排列,名字分别是DI、DX、DY、DP。
      根据文档,各个单元的作用是:
      DI:The DI register is the 32-bit Index register for the DMA. This contains the source or destination of the data to be transmitted or received and can point to internal, external memory, or the link ports.
      DI用来存放地址,所以在C中该域定义为一个指针;
      DX:The DX register contains a 16-bit count value and a 16-bit modify value. The count value is stored in the upper 16 bits (16-31) and the modify in the lower (0-15). If a two-dimensional DMA is enabled, then this register contains the modify and count values for the X dimension only. The value of X count must always be the number of normal (32-bit) words to be transferred. Likewise, the modify value is the number of normal words to modify the count.
      大概是说DX在做一维DMA时,高十六位存放欲传送的单元个数,低十六位存放地址增量(?modify value大概是这个意思吧),二维的DMA我暂时不关心;
      DY:The DY register is used in conjunction with the DX. This register contains the 16-bit modify and 16-bit count values for the DMA in the Y dimension. If two-dimensional DMA is not selected, then this register is not used and the contents are irrelevant.
      DY与二维DMA有关,而我现在不关心二维DMA,所以该域对我而言没有作用;
      DP:The DP register contains all the control information for the DMA. This register is split into two main fields. The first contains all the control information and the second the chaining information.
      DP域主要是一些控制位,详细说明参阅文档。
      上面这些中英文混合的文字就是对TCB结构和功能的介绍,现在回头看看那个C程序,定义的struct tcb变量t并不是一个TCB寄存器,仅仅是一个位于内存中的普通结构体变量,即使你给它取名为tcb它也仍然是平凡的内存中的平凡变量,不具备任何寄存器的功能。在程序中,定义了变量t之后,先把t的各个域设置好相应的数值,然后利用函数__builtin_compose_128,将变量t赋值给一个__builtin_quad类型的变量qvalue;再利用函数__builtin_sysreg_write4将qvalue写入一个TCB寄存器DCS1中。
      我觉得这样写有点让人费解。因为结构体变量t,实际上与TCB寄存器的结构是一样的,t有四个域,每个域32位。为什么不能直接将t写入TCB寄存器,而是先要转换成一个__builtin_quad类型的变量,再写TCB寄存器呢?而且,用__builtin_compose_128来构造__builtin_quad类型也是很麻烦的,既要转换类型又要移位还要按位或。
      我试着直接将t利用__builtin_sysreg_write4写入TCB中,但是编译失败了,原因是不能把t转换成__builtin_quad类型。于是我就将t强制类型转换成__builtin_quad,可是编译仍然失败。
      用__builtin_compose_128将t构建成一个__builtin_quad确实麻烦,强制类型转换又不行,这时我想起了C的库函数memcpy,这个函数对于参数的类型可没有要求,我试验了一下,将t直接copy到qvalue中,然后写寄存器,成功了。
      为什么原来没有使用memcpy呢?我想起来,曾经有一次看别人写89C52的C程序,因为使用了一个库函数,程序体积暴增,以至于内部程序存储器放不下了。
      使用库函数会增加程序的体积,而且库函数的调用也有一定的开销,比如参数压栈,现场保护等等。因为这些原因所以不愿意用memcpy吧。
      但是用__builtin_compose_128(虽然__builtin_compose_128本身类似inline函数)将t变成qvalue也有开销:移位,按位或什么的。
      后来我想起一种手法,使强制类型转换可行,那是以前在别人的C++程序中看到的。只要这样进行强制类型转换,编译就不会报错:
__builtin_sysreg_write4(__DCS1,*(__builtin_quad*)&t);


(2010年4月16日补充)但是使用这种手法要注意对齐的问题,__builtin_quad是四字对齐的,而根据TS C编译器结构体对齐方式,struct tcb则不一定会四字对齐。所以为了使struct tcb和__builtin_quad使用相同的对齐方式,最好这样定义struct tcb:
struct tcb
{
    #pragma align 4
    int * DI;
    int DX;
    int DY;
    int DP;
};


           将t的地址转换成__builtin_quad*类型,然后再加个*,其实又变回了t,只是它的类型已经是__builtin_quad了(窃笑)。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值