2011-05-24 21 views
5

मैं निश्चित बिंदु गुणन के लिए एक विधानसभा (एआरएम) मैक्रो का उपयोग करने की कोशिश कर रहा हूँ: जब कोशिश कर मैं त्रुटि (रों) प्राप्त संकलित करने के लिएजीसीसी एआरएम विधानसभा प्रीप्रोसेसर मैक्रो

#define MULT(a,b) __asm__ __volatile__ (\ 
     "SMULL r2, r3, %0, %1\n\t" \ 
     "ADD r2, r2, #0x8000\n\t" \ 
     "ADC r3, r3, #0\n\t" \ 
     "MOV %0, r2, ASR#16\n\t" \ 
     "ORR %0, %0, r3, ASL#16" \ 
     : "=r" (a) : "0"(a), "1"(b) : "r2", "r3"); 

लेकिन: पहले की उम्मीद अभिव्यक्ति 'एएसएम '

मैं इस कोशिश की (यदि आप अपने समय का महत्व आप इनमें से सब कुछ अनदेखा कर सकते हैं, लेकिन यह अच्छा होगा अगर आप इसे पर एक दृष्टि डाली, यहां मुख्य प्रश्न ऊपर काम करने के लिए कैसे है) :

static inline GLfixed MULT(GLfixed a, GLfixed b){ 
     asm volatile(
     "SMULL r2, r3, %[a], %[b]\n" 
     "ADD r2, r2, #0x8000\n" 
     "ADC r3, r3, #0\n" 
     "MOV %[a], r2, ASR#16\n" 
     "ORR %[a], %[a], r3, ASL#16\n" 
     : "=r" (a) 
     : [a] "r" (a), [b] "r" (b) 
     : "r2", "r3"); 
    return a; } 

यह संकलित लेकिन वहाँ एक समस्या हो सकता है क्योंकि जब मैं स्थिरांक पूर्व का उपयोग लगता है: यह काम करता है MULT (65536,65536) लेकिन यह च ** k अप करने लगता है जब मैं चर का उपयोग:

GLfixed m[16]; 
m[0]=costab[player_ry];//1(65536 integer representation) 
m[5]=costab[player_rx];//1(65536 integer representation) 
m[6]=-sintab[player_rx];//0 
m[8]=-sintab[player_ry];//0 
LOG("%i,%i,%i",m[6],m[8],MULT(m[6],m[8])); 
m[1]=MULT(m[6],m[8]); 
m[2]=MULT(m[5],-m[8]); 
m[9]=MULT(-m[6],m[0]); 
m[10]=MULT(m[5],m[0]); 
m[12]=MULT(m[0],0)+MULT(m[8],0); 
m[13]=MULT(m[1],0)+MULT(m[5],0)+MULT(m[9],0); 
m[14]=MULT(m[2],0)+MULT(m[6],0)+MULT(m[10],0); 
m[15]=0x00010000;//1(65536 integer representation) 

int i=0; 
while(i<16) 
{ 
    LOG("%i,%i,%i,%i",m[i],m[i+1],m[i+2],m[i+3]); 
    i+=4; 
} 

ऊपर कोड प्रिंट होगा (लॉग printf की तरह यहाँ है): जब सही परिणाम होगा (स्पष्ट रूप से कबाड़ की बहुत ऊपर में)

0,0,-1411346156 
65536,65536,65536,440 
-2134820096,65536,0,-1345274311 
0,65536,22,220 
65536,196608,131072,65536 

:

0,0,0 
65536,0,0,0 
0,65536,0,0 
0,0,65536,0 
0,0,0,65536 

उत्तर

3

क्या आपने असेंबली के बजाय सरल सी-कोड की कोशिश की है? जीसीसी के साथ अपने सिस्टम पर 4.5.3 संकलक कोड कम से कम के रूप में अच्छा है कि उत्पन्न करता है अपने हाथ से लिखा कोडांतरक के रूप में:

# input: r0, r1 
mov r3, #32768 
mov r4, #0 
smlal r3, r4, r0, r1 
mov r0, r3, lsr #16 
orr r0, r0, r4, asl #16 
# result in r0 

(समारोह कॉल उपसंहार:

int mul (int a, int b) 
{ 
    long long x = ((long long)a * b + 0x8000); 
    return x>>16; 
} 

निम्नलिखित एएसएम-कोड को संकलित और प्रोलॉग हटा दिया गया)

यदि आपके पास एक ही फ़ंक्शन में एकाधिक गुणाएं हैं तो कोड भी बेहतर हो जाता है क्योंकि संकलक अनावश्यक mov r3, # 32768 निर्देशों को हटा देगा।

5

पहला भाग काफी आसान है: समस्या यह है कि __asm__ ब्लॉक एक कथन है, अभिव्यक्ति नहीं। इनपुट और आउटपुट संकार्य विशिष्टताओं में समस्याओं के कारण

#define MULT(a,b) \ 
    ({ \ 
    __asm__ __volatile__ (\ 
     /* ... asm stuff here ... */ 
    ); \ 
    a; \ 
    }) 

दूसरा हिस्सा है: कुछ इस तरह -

आप प्राप्त करने के लिए आप क्या चाहते हैं जीसीसी के statement expressions एक्सटेंशन का उपयोग कर सकते हैं। आपके यहां दो अलग-अलग संस्करण हैं, और दोनों गलत हैं। मैक्रो संस्करण में, आप जो बोलते हैं उसे:

: "=r" (a) : "0"(a), "1"(b) : "r2", "r3" 

जो

  • उत्पादन a (इस संकार्य 0) एक रजिस्टर तक रोकें;
  • इनपुट a ऑपरेटिंग 0 के समान होने के लिए, यानी एक ही रजिस्टर (यह ऑपरेंड 1 है);
  • इनपुट b इनपुट 1 के समान होने के लिए, यानी वही दोबारा (यह ऑपरेंड 2 है)।

आपको "r"(b) की आवश्यकता है, और इसे %2 के रूप में संदर्भित किया जा सकता है।

इनलाइन संस्करण में, आप जो बोलते हैं उसे:

: "=r" (a) : [a] "r" (a), [b] "r" (b) : "r2", "r3" 

जो उत्पादन a और इनपुट a और b रजिस्टरों तक रोकें, लेकिन

  • यह उन दोनों के बीच किसी भी रिश्ते की घोषणा नहीं करता ;
  • एएसएम कभी भी आउटपुट ऑपरेंड को स्पष्ट रूप से संदर्भित नहीं करता है (आपने आउटपुट ऑपरेंड को नाम नहीं दिया है, और एएसएम कोड %0 का संदर्भ नहीं देता है)।और या तो %0 या %1, और b%2 के रूप में के रूप में a का उल्लेख

    : "=r" (a) : "0" (a), "r" (b) : "r2", "r3" 
    

    :

आप के साथ मूल संस्करण ठीक करने के लिए सक्षम होना चाहिए।

इनलाइन संस्करण इस तरह ठीक किया जा सकता:

: [a] "=r" (a) : "[a]" (a), [b] "r" (b) : "r2", "r3" 

और %[a] और %[b] के रूप में ऑपरेंड देखें।

आप मैक्रो संस्करण में नाम का उपयोग करना चाहते हैं, तो आप

: [arg_a] "=r" (a) : "[arg_a]" (a), [arg_b] "r" (b) : "r2", "r3" 

की तर्ज पर कुछ (और %[arg_a] और %[arg_b] को देखें) की आवश्यकता होगी क्योंकि अन्यथा पूर्वप्रक्रमक अंदर a और b का विस्तार होगा [a] और [b]

नोट

नामित तर्क मामलों में सूक्ष्मता: जब एक नाम एक तर्क को दिया जाता है की जा रही आप [a] बारे में (उत्पादन a के रूप में) - कोई उद्धरण - लेकिन जब आप एक और पहले से ही नाम संकार्य के नाम की बात कर रहे (इनपुट a में) आपको इसे उद्धरण के अंदर रखना होगा: "[a]"

संबंधित मुद्दे