2013-06-19 65 views
3

您好我目前正在處理一個程序,我需要處理一個包含一系列可能未對齊(有時也是)未對齊的浮動的數據blob。 我正在爲gcc 4.6.2編譯ARM cortex-a8。 我不得不生成的彙編代碼的一個問題:GCC爲ARM上的未對齊浮動訪問生成彙編

作爲例子我寫了一個最小的例子:下面的測試代碼

float aligned[2]; 
float *unaligned = (float*)(((char*)aligned)+2); 

int main(int argc, char **argv) 
{ 
    float f = unaligned[0]; 
    return (int)f; 
} 

的編譯器(gcc 4.6.2 - 與優化-O3)產生

00008634 <main>: 
    8634: e30038ec   movw   r3, #2284  ; 0x8ec 
    8638: e3403001   movt   r3, #1 
    863c: e5933000   ldr   r3, [r3] 
    8640: edd37a00   vldr   s15, [r3] 
    8644: eefd7ae7   vcvt.s32.f32 s15, s15 
    8648: ee170a90   vmov   r0, s15 
    864c: e12fff1e   bx   lr 

此處的編譯器無法知道數據是否對齊,但從來沒有使用過的VLDR需要對齊的數據,否則程序將因總線錯誤而崩潰。

現在這裏是我的實際問題:這是從編譯器是否正確,我需要照顧我的C++代碼對齊還是這是編譯器中的錯誤?

我也可以添加我當前的解決方法,它可以在訪問該值之前使gcc進行復制。訣竅是定義一個只包含一個帶有gcc packed屬性的float的結構,並通過一個結構指針訪問數據。代碼片段:

struct FloatWrapper { float f; } __attribute__((packed)); 
const FloatWrapper *x = reinterpret_cast<const FloatWrapper *>(rawX.data()); 
const FloatWrapper *y = reinterpret_cast<const FloatWrapper *>(rawY.data()); 

for (size_t i = 0; i < vertexCount; ++i) { 
    vertices[i].x = x[i].f; 
    vertices[i].y = y[i].f; 
} 
+3

C99標準包含這個腳註:「在由一元運算符取消引用指針的無效值中,有一個是空指針,一個地址與所指向的對象的類型不恰當對齊......」。我毫不懷疑C++標準包含一個類似的警告。所以你的程序在技術上是未定義的,編譯器可以自由地產生任何它喜歡的指令序列,而不會成爲一個錯誤。 –

回答

3

正如你所指出的,無論SCTLR.A價值ARM ARM A3.2.1狀態,VLDR產生Alignment fault

我測試過上的Cortex-A9你的榜樣,我得到了

# float_align             
[1] + Stopped (signal)  float_align 

不過,我由ARM Cortex-A8 TRM 4.2.1也困惑,它指出

如果對齊方式限定符沒有指定,並且A = 1,如果未對齊元素大小,則會採用對齊錯誤。

如果未指定對齊限定符,並且A = 0,則將其視爲未對齊訪問

這大概是一個半烤解釋,因爲ARM ARM與一個詳細的表格給出的指令的詳細信息。

所以我認爲答案是,你需要照顧好自己的定位,因爲編譯器無法找出解決您加載在所有情況下,如地址可能鏈接等後可用

+0

嗨auselen,謝謝你的回覆。正如我從「ARM體系結構參考手冊ARMv7-A和ARMv7-R第A3.2章節對齊支持/ A3.2.1」中收集的,有一些不支持未對齊訪問的指令(VLDR和其他指令)。[鏈接到參考手冊](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0406c/index.html) – Jahn

+0

@Jahn更新了我的答案。 – auselen

+0

感謝auselen查看它,我還會進一步查看有關C(++)標準的評論Pascal,並在此處發佈結果。 – Jahn