DSP

uclinux-2008R1-RC8(bf561)到VDSP5的移植(48): __cmpxchg

2019-07-13 16:42发布

  快乐虾 http://blog.csdn.net/lights_joy/ lights@hb165.com      本文适用于 ADI bf561 DSP 优视科技BV561EVB开发板 uclinux-2008r1-rc8(移植到vdsp5) Visual DSP++ 5.0    欢迎转载,但请保留作者信息   在include/asm/system.h下有一个__cmpxchg函数: /*  * 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;        local_irq_save(flags);        switch (size) {      case 1:          __asm__ __volatile__               ("%0 = b%3 (z);/n/t"                "CC = %1 == %0;/n/t"                "IF !CC JUMP 1f;/n/t"                "b%3 = %2;/n/t"                "1:/n/t"                : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");          break;      case 2:          __asm__ __volatile__               ("%0 = w%3 (z);/n/t"                "CC = %1 == %0;/n/t"                "IF !CC JUMP 1f;/n/t"                "w%3 = %2;/n/t"                "1:/n/t"                : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");          break;      case 4:          __asm__ __volatile__               ("%0 = %3;/n/t"                "CC = %1 == %0;/n/t"                "IF !CC JUMP 1f;/n/t"                "%3 = %2;/n/t"                "1:/n/t"                : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");          break;      }      local_irq_restore(flags);      return tmp; } 在VDSP下编译将产生如下语法错误: "../../include/asm/system.h", line 209: cc1101: error: invalid constraint in           asm statement    : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");                                          ^   "../../include/asm/system.h", line 209: cc1155: error: gnu asm operand           requires integral or pointer type    : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");                                               ^   "../../include/asm/system.h", line 218: cc1101: error: invalid constraint in           asm statement    : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");                                          ^   "../../include/asm/system.h", line 218: cc1155: error: gnu asm operand           requires integral or pointer type    : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");                                               ^   "../../include/asm/system.h", line 227: cc1101: error: invalid constraint in           asm statement    : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");                                          ^   "../../include/asm/system.h", line 227: cc1155: error: gnu asm operand           requires integral or pointer type    : "=&d" (tmp) : "d" (old), "d" (new), "m" (*__xg(ptr)) : "memory");                                               ^   6 errors detected in the compilation of "../../fs/sysfs/dir.c". cc3089: fatal error: Compilation failed 首先,VDSP的嵌入汇编不支持”m”这个constraint,但是可以用”a”来替换。 其次,VDSP的嵌入汇编不支持"a" (*__xg(ptr))结构体的传递,可以直接使用"a" (ptr),所得到的结果和GCC的相一致。 在改正完上面两个错误后,还有更奇怪的问题: [Error ea5003] "c:/temp/acc01786adb000/acc01786adb001.s":138 Semantic Error in instruction : IF !CC JUMP 1f; Operands don't fit instruction template 'IF BANG CC JUMP expr'. Check for an out of range immediate value or an illegal register.   [Error ea5004] "c:/temp/acc01786adb000/acc01786adb001.s":138 Syntax Error in : IF !CC JUMP 1f; syntax error is at or near text 'f'. Attempting error recovery by ignoring text until the ';'   [Error ea5004] "c:/temp/acc01786adb000/acc01786adb001.s":139 Syntax Error in : wP1 = R1; syntax error is at or near text '='. Attempting error recovery by ignoring text until the ';'   [Error ea5007] "c:/temp/acc01786adb000/acc01786adb001.s":140 The label "1:" is illegal because it begins with a digit. If this is GNU assembly source, rewrite to a local temporary name of your choosing. If the GNU assembly code was generated from a macro, the VisualDSP++ preprocessing label auto-generation feature ("?") can be used to generate a unique local label.   [Error ea5003] "c:/temp/acc01786adb000/acc01786adb001.s":158 Semantic Error in instruction : IF !CC JUMP 1f; Operands don't fit instruction template 'IF BANG CC JUMP expr'. Check for an out of range immediate value or an illegal register.   [Error ea5004] "c:/temp/acc01786adb000/acc01786adb001.s":158 Syntax Error in : IF !CC JUMP 1f; syntax error is at or near text 'f'. Attempting error recovery by ignoring text until the ';'   [Error ea5007] "c:/temp/acc01786adb000/acc01786adb001.s":160 The label "1:" is illegal because it begins with a digit. If this is GNU assembly source, rewrite to a local temporary name of your choosing. If the GNU assembly code was generated from a macro, the VisualDSP++ preprocessing label auto-generation feature ("?") can be used to generate a unique local label.    Previous errors prevent assembly   Assembler totals: 7 error(s) and 0 warning(s) cc3089: fatal error: Assembler failed 如果不是刚改完此函数,几乎无法知道错误的来源在哪里! 根据提示检查上述汇编代码,修改jump 1f之类的跳转后OK。 而对于wP1 = R1;这样的错误则改为w[%3]之类的。 修改完后的函数如下: /*  * 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;        local_irq_save(flags);        switch (size) {      case 1:          __asm__ __volatile__               ("%0 = b[%3] (z);/n/t"                "CC = %1 == %0;/n/t"                "IF !CC JUMP __cmpxchg_size_1;/n/t"                "b[%3] = %2;/n/t"                "__cmpxchg_size_1:/n/t"                : "=&d" (tmp) : "d" (old), "d" (new), "a" (ptr) : "memory");          break;      case 2:          __asm__ __volatile__               ("%0 = w[%3] (z);/n/t"                "CC = %1 == %0;/n/t"                "IF !CC JUMP __cmpxchg_size_2;/n/t"                "w[%3] = %2;/n/t"                "__cmpxchg_size_2:/n/t"                : "=&d" (tmp) : "d" (old), "d" (new), "a" (ptr) : "memory");          break;      case 4:          __asm__ __volatile__               ("%0 = %3;/n/t"                "CC = %1 == %0;/n/t"                "IF !CC JUMP __cmpxchg_size_4;/n/t"                "%3 = %2;/n/t"                "__cmpxchg_size_4:/n/t"                : "=&d" (tmp) : "d" (old), "d" (new), "a" (ptr) : "memory");          break;      }      local_irq_restore(flags);      return tmp; }