<% dim ModuleName,InfoID,ChannelShortName,CorrelativeArticle,InstallDir,ChannelDir,Keyword,PageTitle,ArticleIntro,Articlecontent Keyword=stripHTML("uclinux编译器,VDSP中编译") PageTitle=stripHTML("VDSP中编译uclinux编译器的差异") ArticleIntro=stripHTML("") Articlecontent=stripHTML("虽然VDSP和GCC3.2有很好的兼容性,但是还是有一些差异的,以下列出已经碰到的一些差异及处理办法:  1、__builtin_expect(exp, val…") ModuleName = stripHTML("programme") InfoID = stripHTML("115094") ChannelShortName=stripHTML("编程") InstallDir=stripHTML("http://www.77169.com/") ChannelDir=stripHTML("programme") %> VDSP中编译uclinux编译器的差异 - 华盟网 - http://www.77169.com
您现在的位置: 华盟网 >> 编程 >> Vc >> 正文

uclinux编译器的差异

2012/6/7 作者:不详 来源: 华盟收集
导读 <% if len(ArticleIntro)<3 then Response.Write Articlecontent 'Response.Write "Articlecontent" else Response.Write ArticleIntro 'Response.Write "ArticleIntro" end if %>

  虽然VDSP和GCC3.2有很好的兼容性,但是还是有一些差异的,以下列出已经碰到的一些差异及处理办法:

  1、__builtin_expect(exp, val):这是GCC的一个内建函数,而VDSP无此函数,它用于为编译器提供分支预测信息,其返回值是整数表达式exp的值,val的值必须是编译时常数。这个内建函数的语义是 exp 的预期值是 val,编译器可以根据这个信息适当地重排语句块的顺序,使程序在预期的情况下有更高的执行效率。因此在移植时直接用:

  #define __builtin_expect(exp, val) (exp)

  2、__builtin_constant_p(EXP):此内建函数用于判断一个值是否为编译时常数,如果参数EXP 的值是常数,函数返回 1,否则返回 0.很多计算或操作在参数为常数时有更优化的实现,在 GNU C 中用上面的方法可以根据参数是否为常数,只编译常数版本或非常数版本,这样既不失通用性,又能在参数是常数时编译出最优化的代码。在移植时使用:

  #define __builtin_constant_p(x) (0)

  3、__builtin_return_address (LEVEL):此内建函数返回当前函数或其调用者的返回地址,参数LEVEL 指定在栈上搜索框架的个数,0 表示当前函数的返回地址,1 表示当前函数的调用者的返回地址,依此类推。在VDSP中,仅能取得当前函数的返回地址:

  #define __builtin_return_address(level) ({void* addr;

  asm("%0 = rets;" : "=a"(addr)); addr;})

  4、汇编中的jump 1f或者jump 1b之类的跳转语句:在VDSP中不支持这种方式的跳转,只能将其中的标号改为绝对标号,并修改相应的jump语句。

  5、汇编中的。macro:VDSP不支持。macro,必须将其改为#define语句,如果在。macro的中间出现了条件汇编#ifdef之类的东西,必须将这些条件移到#define语句之外。

  6、汇编中的。rept:世间最痛苦的事情莫过于此,无奈,使用最原始的方法,Copy/Paste.

  7、__cmpxchg函数:这个函数是用嵌入汇编写的,但在VDSP下无法编译,因此用C重写,虽然效率有所降低,但我们的目标是首先有一个可以运行的版本,不是吗?

  /*

  * Atomic compare and exchange. Compare OLD with MEM, if identical,

  * store NEW in MEM. Return the initial value in MEM. Success is

  * indicated by comparing RETURN with OLD.

  */

  static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,

  unsigned long new, int size)

  {

  unsigned long tmp = 0;

  unsigned long flags = 0;

  unsigned long* p = (unsigned long*)ptr;

  local_irq_save(flags);

  switch (size) {

  case 1:

  tmp = (*p) & 0x000000ff;

  if(old != new)

  (*p) = ((*p) & 0xffffff00) | (new & 0x000000ff);

  //__asm__ __volatile__

  // ("%0 = b%3 (z);nt"

  // "CC = %1 == %0;nt"

  // "IF !CC JUMP f1;nt"

  // "B%3 = %2;nt"

  // "f1:nt"

  // : "=&d" (tmp) : "d" (old), "d" (new), "d" (*(unsigned char*)__xg(ptr)) : "memory");

  break;

  case 2:

  tmp = (*p) & 0x0000ffff;

  if(old != new)

  (*p) = ((*p) & 0xffff0000) | (new & 0x0000ffff);

  //__asm__ __volatile__

  // ("%0 = w%3 (z);nt"

  // "CC = %1 == %0;nt"

  // "IF !CC JUMP f2;nt"

  // "S%3 = %2;nt"

  // "f2:nt"

  // : "=&d" (tmp) : "d" (old), "d" (new), "d" (*(unsigned short*)__xg(ptr)) : "memory");

  break;

  case 4:

  tmp = *p;

  if(old != new)

  (*p) = new;

  //__asm__ __volatile__

  // ("%0 = %3;nt"

  // "CC = %1 == %0;nt"

  // "IF !CC JUMP f3;nt"

  // "%3 = %2;nt"

  // "f3:nt"

  // : "=&d" (tmp) : "d" (old), "d" (new), "d" (*(unsigned int*)__xg(ptr)) : "memory");

  break;

  }

  local_irq_restore(flags);

  return tmp;

  }

  8、jiffies_64的定义问题:在uclinux中,jiffies_64的定义为:

  #define __jiffy_data __attribute__((section(".data")))

  extern u64 __jiffy_data jiffies_64;

  这样的定义本身没有问题,但是在编译kernel/timer.c时却造成了其它地方代码的编译失败,这是一个非常奇怪的问题,出错提示为:

  [Error ea1008] "e:tempacc08143dff000acc08143dff001.s":3601 '.epcdata':

  The symbol has already been defined and cannot be redefined.

  [Error ea1008] "e:tempacc08143dff000acc08143dff001.s":3608 '.epcdata.end':

  The symbol has already been defined and cannot be redefined.

  但是如果将定义改为:

  extern u64 /*__jiffy_data*/ jiffies_64;

  则没有问题。

  还有一些其它的问题,但是没有及时记录下来,以后再补上。



  • 上一篇编程:

  • 下一篇编程:
  • 编程栏目相关内容

      没有相关编程