歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> 關於Linux >> uclinux-2008R1-RC8(bf561)到VDSP5的移植(48):__cmpxchg的問題

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

日期:2017/3/3 16:43:28   编辑:關於Linux

在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;
}
Copyright © Linux教程網 All Rights Reserved