微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 如何将汇编语言与C语言整合至DSP

如何将汇编语言与C语言整合至DSP

时间:06-29 来源: 点击:

图2:从CEVA-X1641手写FFT算法汇编语言实作摘录的一段程序代码。
除了呼叫惯例和缓存器使用惯例(针对每个编译器下定义),一些编译器在人工编写的汇编程序码方面可能会有一些额外的假设。这些假设通常是针对编译器,因此编译器供货商应该提供完善的数据和说明。例如,一些DSP架构会有内存存取对齐限制,用于这些DSP的编译器通常假设堆栈指针以某个宽度(如32位)对齐,这允许编译器最佳化堆栈的读写作业,并使用机器的全部内存频宽;此外亦要求汇编程序设计人员在呼叫C语言函数前确保堆栈对齐,否则会发生对齐错误的存取。
编译器假设的另外一个例子与人工编写的汇编程序码中特殊指令的位置有关。例如,CEVA-X1641编译器假设一个mov acX, rN指令(将累加器移动到地址缓存器)永远不会作为汇编语言函数的第一条指令。当填充呼叫指令(呼叫一个函数)的延迟槽时,这个假设可提供更佳的指令排程。像这样特殊的假设通常可以用专用编译功能覆盖。
连接C/汇编语言的延伸功能
大多数用于嵌入式平台的编译器,特别是用于DSP程序设计上,都具有丰富的C语言和汇编语言连接功能。其中绝大部份功能不属于标准C语言,因此被称为C语言延伸功能。以下列出的是一些对DSP程序设计更有用的功能。
内嵌汇编语言。这个功能可让程序设计人员将汇编语言指令插入C语言程序代码,当必需使用如装置驱动程序等低阶C语言程序代码直接存取机器资源时,会常使用到该功能。由于在大多数使用该功能的实作中,编译器对所要插入的指令信息所知有限,因此对它们的特性会作出最坏的假设,这种假设可能会妨碍许多编译器最佳化作业。例如,在支持某些指令(并非全部指令)平行处理的架构中,编译器不会将插入指令与其它指令作平行处理,因为这种作法很可能会导致非法指令封包。
将硬件缓存器连结到C变量。将一个硬件缓存器连结到一个C变量时,C语言程序代码中的变量值即反映出硬件缓存器的值;反之亦然。每当C变量被读写时,硬件缓存器也相对地被读写。这个功能在低阶程序代码中很常见,时常与汇编语言指令内嵌功能结合在一起,允许内嵌汇编程序码存取C语言层级的变量。图3的例子显示了内嵌汇编语言功能(标示为橙色)和硬件缓存器连结功能(标示为紫色)的常见组合。


图3:结合内嵌汇编语言和硬件缓存器连结的程序代码片段。
内存扇区属性。预设状态下,编译器将全域C变量和函数分配到标准的预定义内存扇区,该扇区属性允许程序设计人员将上述变量和函数分配到特殊的使用者定义内存扇区。在随后的连结阶段,这些内存扇区可以被映像到具体的内存地址。该功能可让程序设计人员将C语言层级单元分配到实际的内存位置,这对DSP应用程序来说至关重要。
使用者定义呼叫惯例。如上所述,编译器有一个汇编程序设计人员必须遵守的预定义呼叫惯例;然而在某些情况下,汇编语言函数可利用不同的呼叫惯例获得更佳的最佳化效果。例如,编译器理论上会在累加器中传递参数。若执行延伸地址计算的函数能接收地址缓存器中的参数,那么它的效率会更高。该功能会依靠附加在函数原型的专用语法,并通知修正后的呼叫惯例编译器。
编译器内嵌函数。意指能够用专用的宏或函数呼叫,触发内建编译器功能的总称。例如,CEVA-X和CEVA-TeakLite-III编译器可为语音编码器中常见的ETSI/ITU基本DSP作业,提供编译器内嵌函数。针对这些作业,编译器可利用其等效高度最佳化汇编语言序列,取代每个基本作业。
相反地,没有内嵌函数支持的编译器必须呼叫使用者定义的函数,这样做会导致两大性能缺陷:首先,使用者定义函数可能会在一个回路里产生函数呼叫和返回(如图4),因此产生了巨额的开销;其次,使用者定义函数将如同其它C语言程序代码一样被编译,这意味着使用者定义函数可能会获得次要的最佳化性能。而另一方面,具有内嵌函数的编译器已经内建了最佳化的实作。

图4:H.264编码器--一个关键的函数性能案例。
图4说明了这个功能的重要性。在图4中,左边的C语言程序代码使用ETSI的mult_r(循环相乘)基本作业,CEVA-TeakLite-III编译器产成了如右边的高效实作结果。mult_r作业在左边的C语言程序代码和右边的汇编程序码中以紫色标示。
汇编语言内嵌函数。汇编语言内嵌函数是将汇编程序码内嵌到C语言程序代码的一种先进方法,详细介绍如下。
汇编语言内嵌函数--将汇编语言指令当作C语句一样编写
上述内嵌汇编语言功能具有显著的缺点:
1. 它会破坏各种编译器的最佳化作业,由于编译器不了解内嵌程序代码的内容,因此会使用最坏的假设。
2. 它可能迫使程序设计人员处理低阶问题,如缓存器分配和指令排程。
汇编语言内嵌函数功能可以帮助程序设计人员实现内嵌汇编程序码,且不会产生上述缺点。从程序设计人员的角度来看,汇编语言内嵌函数就像是C语言宏或函数,它们会在呈现一个单一汇编语言指令时,接收C语言层级变量并返回C语言输出结果。由于涉及该功能的所有程序代码都在C语言层级,因此程序设计人员不必担心缓存器分配、指令排程和其它低级语言问题。汇编语言内嵌函数不仅不会妨碍编译器最佳化作业,还会参与最佳化过程,就好像是编译器固定产生的汇编语言指令一样,这些特性造就了强大的汇编语言内嵌函数功能。
利用汇编语言内嵌函数,程序设计人员可以从特殊汇编语言指令中受益,这些指令不太可能从编译器中产生,且通常是为特定算法量身定做的。在适当的位置采用这些指令可以大幅提高性能;例如,CEVA-X1641的bitrev指令就是为FFT等算法定制的。由于编译器不太可能把一个程序看作FFT而使用bitrev指令,因此程序设计人员只需将bitrev汇编语言内嵌函数嵌入到C语言程序代码中。
结合程序设计人员对应用程序的专业知识,汇编语言内嵌函数功能也相继提升。利用这种专业知识,程序设计人员可将精密的汇编语言序列内嵌函数用在C应用程序中的关键性能区域里。这样一来,程序设计人员便能确保编译器产生的汇编程序码效率就如同手动编写的程序代码一样高。
图5是使用汇编语言内嵌函数与CEVA-X1641编译器的例子。左边的C语言函数使用st(储存,以红色标示)和msu(乘法和减法,以紫色标示)汇编语言内嵌函数。st内嵌函数参与判断(标示为蓝色)和延迟时隙填充(标示为绿色);msu内嵌函数则参与回路解开(标示为橙色)和Quad-Mac(标示为紫色)。汇编语言内嵌函数还受益于由CEVA-X1641编译器处理的所有机械相关问题,如缓存器分配、指令排程和硬件单元分配。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top