2011-12-03 18 views
8

के साथ फिक्स्ड पॉइंट गणित मैं फ्रीस्केल किनेटिस के 60 का उपयोग कर रहा हूं और कोडवायरियर आईडीई का उपयोग कर रहा हूं (जो मुझे लगता है कि शिकायतकर्ता के लिए जीसीसी का उपयोग करता है)।एआरएम कॉर्टेक्स-एम 4 और जीसीसी कंपाइलर

मैं दो 32 बिट संख्याओं को गुणा करना चाहता हूं (जिसके परिणामस्वरूप 64 बिट संख्या होती है) और केवल ऊपरी 32 बिट्स को बनाए रखना है।

मुझे लगता है कि एआरएम कॉर्टेक्स-एम 4 के लिए सही असेंबली निर्देश SMMUL निर्देश है। मैं इस निर्देश को असेंबली के बजाय सी कोड से एक्सेस करना पसंद करूंगा। मैं यह कैसे करु?

मैं कल्पना कोड आदर्श कुछ इस तरह होगा:

int a,b,c; 

a = 1073741824; // 0x40000000 = 0.5 as a D0 fixed point number 
b = 1073741824; // 0x40000000 = 0.5 as a D0 fixed point number 

c = ((long long)a*b) >> 31; // 31 because there are two sign bits after the multiplication 
          // so I can throw away the most significant bit 

जब मैं कोडवॉरिअर में इस कोशिश, मैं ग (536,870,912 = 0.25 एक D0 एफपी संख्या के रूप में) के लिए सही परिणाम मिलता है। मुझे कहीं भी SMMUL निर्देश नहीं दिखाई देता है और गुणा 3 निर्देश हैं (यूएमयूएलएल, विधायक, और विधायक - मुझे समझ में नहीं आता कि यह एक हस्ताक्षरित गुणा का उपयोग क्यों कर रहा है, लेकिन यह एक और सवाल है)। मैंने 32 की सही बदलाव भी की है क्योंकि इससे SMMUL निर्देश के लिए और अधिक समझ हो सकती है, लेकिन यह कुछ भी अलग नहीं करता है।

+0

क्या आप ऑप्टिमाइज़ेशन के साथ संकलित हैं? यदि आपका कंपाइलर इष्टतम कोड उत्पन्न नहीं कर रहा है, तो आप एक छोटे असेंबली फ़ंक्शन को लिख सकते हैं या सी – TJD

उत्तर

6

समस्या आपको लगता है कि कोड के अनुकूलन के साथ मिलता है:

08000328 <mul_test01>: 
8000328: f04f 5000 mov.w r0, #536870912 ; 0x20000000 
800032c: 4770  bx lr 
800032e: bf00  nop 

अपने कोड does not कुछ क्रम ऐसा अनुकूलक सिर्फ अंतिम जवाब की गणना कर सकते हैं।

इस:

.thumb_func 
.globl mul_test02 
mul_test02: 
    smull r2,r3,r0,r1 
    mov r0,r3 
    bx lr 

इस के साथ कहा जाता है:

c = mul_test02(0x40000000,0x40000000); 

देता 0x10000000

UMULL ही परिणाम है क्योंकि आप सकारात्मक संख्या ऑपरेंड उपयोग कर रहे हैं, देता है और परिणाम इतना सब सकारात्मक रहे हैं यह हस्ताक्षरित/हस्ताक्षरित मतभेदों में नहीं मिलता है।

हम्म, ठीक है आप मुझे इस पर मिला है। मैं आपके कोड को 64 बिट तक गुणा करने के लिए संकलक कहने के रूप में पढ़ूंगा। स्मॉल दो 32 बिट ऑपरेशंस है जो 64 बिट परिणाम दे रहा है, जो आपके कोड के लिए नहीं पूछ रहा है .... लेकिन जीसीसी और क्लैंग दोनों ने धुंध का उपयोग किया, भले ही मैंने इसे एक अनिश्चित कार्य के रूप में छोड़ा, तो यह नहीं पता था समय संकलित करें कि ऑपरेटरों के पास 32 से ऊपर कोई महत्वपूर्ण अंक नहीं था, फिर भी उन्होंने धुंध का उपयोग किया।

शायद शिफ्ट कारण था।

यूप, यह था ..

int mul_test04 (int a, int b) 
{ 
    int c; 
    c = ((long long)a*b) >> 31; 
    return(c); 
} 

दोनों जीसीसी और बजना देता

08000340 <mul_test04>: 
8000340: fb81 2300 smull r2, r3, r1, r0 
8000344: 0fd0  lsrs r0, r2, #31 
8000346: ea40 0043 orr.w r0, r0, r3, lsl #1 
800034a: 4770  bx lr 

(अच्छी तरह बजना बजाय R2 और R3 का उपयोग करने का r0 और r1 recycles) लेकिन इस

int mul_test04 (int a, int b) 
{ 
    int c; 
    c = ((long long)a*b); 
    return(c); 
} 

इस

देता है

जीसीसी:

08000340 <mul_test04>: 
8000340: fb00 f001 mul.w r0, r0, r1 
8000344: 4770  bx lr 
8000346: bf00  nop 

बजना: बिट

0800048c <mul_test04>: 
800048c: 4348  muls r0, r1 
800048e: 4770  bx lr 

तो साथ बदलाव compilers महसूस करते हैं कि आप केवल परिणाम के ऊपरी हिस्से में रुचि रखते हैं तो वे ऑपरेंड के ऊपरी भाग को निरस्त कर सकते हैं जिसका अर्थ है smull कर सकते हैं इस्तेमाल किया गया।

अब आप ऐसा करते हैं, तो:

int mul_test04 (int a, int b) 
{ 
    int c; 
    c = ((long long)a*b) >> 32; 
    return(c); 
} 

दोनों compilers विशेष बजना में, यहां तक ​​कि बेहतर हो जाते हैं:

0800048c <mul_test04>: 
800048c: fb81 1000 smull r1, r0, r1, r0 
8000490: 4770  bx lr 

जीसीसी:

08000340 <mul_test04>: 
8000340: fb81 0100 smull r0, r1, r1, r0 
8000344: 4608  mov r0, r1 
8000346: 4770  bx lr 

मुझे लगता है कि के रूप में माना 0x40000000 देख सकते हैं एक फ्लोट जहां आप दशमलव स्थान का ट्रैक रखते हैं, और वह स्थान एक निश्चित स्थान है। 0x20000000 उत्तर के रूप में समझ में आता है। मैं अभी तक तय नहीं कर सकता कि 31 बिट शिफ्ट सार्वभौमिक रूप से काम करती है या सिर्फ इस मामले के लिए।

एक पूरा ऊपर के लिए इस्तेमाल किया उदाहरण यहाँ है

https://github.com/dwelch67/stm32vld/tree/master/stm32f4d/sample01

और मैं यह काम करता है और परिणामों की पुष्टि करने के लिए एक stm32f4 पर चला था।

संपादित करें:

आप के बजाय समारोह के भीतर उन्हें हार्डकोड के समारोह में पैरामीटर पास हैं:

int myfun (int a, int b) 
{ 
    return(a+b); 
} 

संकलक क्रम कोड के बजाय अनुकूलन संकलन समय पर जवाब बनाने के लिए मजबूर कर रहा है।

अब अगर आप हार्डकोडेड संख्या के साथ एक और समारोह से कि फ़ंक्शन को कॉल करें: इस बुला समारोह में

... 
c=myfun(0x1234,0x5678); 
... 

संकलक जवाब गणना करने के लिए और बस संकलन समय पर वहाँ यह जगह चुन सकते हैं। यदि myfun() फ़ंक्शन वैश्विक है (स्थैतिक के रूप में घोषित नहीं किया गया है) तो संकलक को पता नहीं है कि बाद में कुछ अन्य कोड लिंक किए जाएंगे, इसलिए इस फ़ाइल में कॉल पॉइंट के पास भी यह एक उत्तर को अनुकूलित करता है जिसे अभी भी वास्तविक फ़ंक्शन का उत्पादन करना है और कॉल करने के लिए अन्य फ़ाइलों में अन्य कोड के लिए ऑब्जेक्ट में छोड़ दें, ताकि आप अभी भी जांच सकें कि उस सी कोड के साथ कंपाइलर/ऑप्टिमाइज़र क्या करता है। जब तक आप llvm का उपयोग उदाहरण के लिए नहीं करते हैं, जहां आप संपूर्ण प्रोजेक्ट (फाइलों में) को अनुकूलित कर सकते हैं, बाहरी कोड को कॉल करने से यह फ़ंक्शन वास्तविक फ़ंक्शन का उपयोग करेगा और संकलन समय गणना गणना नहीं करेगा।

दोनों जीसीसी और क्लैंग ने जो किया है, वह एक वैश्विक कार्य के रूप में फ़ंक्शन के लिए बाएं रनटाइम कोड है, लेकिन फ़ाइल के भीतर यह संकलन समय पर उत्तर की गणना करता है और फ़ंक्शन को कॉल करने के बजाय कोड में हार्डकोडेड उत्तर डालता है:

int mul_test04 (int a, int b) 
{ 
    int c; 
    c = ((long long)a*b) >> 31; 
    return(c); 
} 
एक ही फाइल में एक और समारोह में

:

hexstring(mul_test04(0x40000000,0x40000000),1); 

समारोह में ही कोड में कार्यान्वित किया जाता है:

0800048c <mul_test04>: 
800048c: fb81 1000 smull r1, r0, r1, r0 
8000490: 0fc9  lsrs r1, r1, #31 
8000492: ea41 0040 orr.w r0, r1, r0, lsl #1 
8000496: 4770  bx lr 

लेकिन जहां यह कहा जाता है कि वे इस सवाल का जवाब hardcoded है, क्योंकि वे सभी जानकारी ऐसा करने के लिए की जरूरत थी:

8000520: f04f 5000 mov.w r0, #536870912 ; 0x20000000 
8000524: 2101  movs r1, #1 
8000526: f7ff fe73 bl 8000210 <hexstring> 

आप हार्डकोडेड जवाब आप एक समारोह है कि में नहीं है उपयोग करने की आवश्यकता नहीं चाहते हैं एक ही अनुकूलन पास।

कंपाइलर और ऑप्टिमाइज़र में हेरफेर करना बहुत अभ्यास में आता है और यह सटीक विज्ञान नहीं है क्योंकि कंपेलर और ऑप्टिमाइज़र लगातार विकसित होते हैं (बेहतर या बदतर के लिए)।
किसी फ़ंक्शन में कोड का एक छोटा सा कोड अलग करके आप किसी अन्य तरीके से समस्याएं पैदा कर रहे हैं, बड़े कार्यों को स्टैक फ्रेम की आवश्यकता होती है और रजिस्टरों से स्टैक तक वैरिएबल को बेदखल कर दिया जाता है, छोटे कार्यों को ऐसा करने की आवश्यकता नहीं होती है और अनुकूलक बदल सकते हैं कि परिणामस्वरूप कोड कैसे लागू किया जाता है। आप कोड खंड को एक तरीका देखने के लिए जांचते हैं कि संकलक क्या कर रहा है, फिर इसे एक बड़े फ़ंक्शन में उपयोग करें और नतीजे न प्राप्त करें। यदि निर्देशों का एक सटीक निर्देश या अनुक्रम है जिसे आप कार्यान्वित करना चाहते हैं .... उन्हें असेंबलर में लागू करें। यदि आप एक विशिष्ट निर्देश सेट/प्रोसेसर में निर्देशों के एक विशिष्ट सेट को लक्षित कर रहे थे तो गेम से बचें, जब आप कंप्यूटर/कंपाइलर्स/आदि बदलते हैं तो अपने कोड को बदलने से बचें, और उस लक्ष्य के लिए केवल असेंबलर का उपयोग करें। यदि आवश्यक हो तो ifdef या अन्यथा असेंबलर के बिना अलग-अलग लक्ष्यों के निर्माण के लिए सशर्त संकलन विकल्पों का उपयोग करें।

+0

से कुछ इनलाइन असेंबली का उपयोग कर सकते हैं। मैंने वर्तमान पूर्व-ज्ञात-कोड-कोडरी जीसीसी कंपाइलर और एलएलवीएम रिलीज 3.0 से क्लैंग का उपयोग किया था। –

+2

ऐसा लगता है कि मैं गलत था। कोडवायरियर जीसीसी का उपयोग नहीं कर रहा है। यह mwccarm नामक एक निष्पादन योग्य संदर्भित करता है, जो एक फ्रीस्केल विशिष्ट संकलक प्रतीत होता है। मैंने एक फ़ंक्शन में गुणा को परिभाषित करने का प्रयास किया है और अभी भी कंपाइलर को स्मॉल कमांड का उपयोग नहीं कर सकता - वास्तव में umull कमांड अभी भी वहां है। मैं जीसीसी या क्लैंग डाउनलोड करने की कोशिश करूंगा और देखें कि क्या होता है। – EpicAdv

+1

मुझे नहीं लगता कि मैं एक स्टैंडअलोन फ़ंक्शन संकलित करने के लिए संकलक को सफलतापूर्वक बता रहा हूं। ऐसा लगता है कि जहां (और अगर) इसे बुलाया जा रहा है और अनुकूलित कर रहा है। जेनेरिक फ़ंक्शन को संकलित करने के लिए मैं इसे कैसे मजबूर कर सकता हूं जैसे आप यहां कर रहे हैं? – EpicAdv

-1

जीसीसी वास्तविक तय सूत्री प्रकार का समर्थन करता: http://gcc.gnu.org/onlinedocs/gcc/Fixed_002dPoint.html

मुझे यकीन है कि क्या शिक्षा के लिए इसका इस्तेमाल नहीं कर रहा हूँ, लेकिन यह आप जीवन को आसान बना सकता है।

+1

लिंक किए गए पृष्ठ से: "सभी लक्ष्य निश्चित-बिंदु प्रकारों का समर्थन नहीं करते हैं।" मेरे अनुभव में, बहुत कम लक्ष्य निश्चित-बिंदु प्रकारों का समर्थन करते हैं। –

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