2010-03-29 18 views
6

मैं TriCore से ARM कॉर्टेक्स (थंब -2 निर्देश सेट) से एक छोटा अकादमिक ओएस पोर्ट कर रहा हूं। शेड्यूलर को काम करने के लिए, मुझे कभी-कभी स्टैक को संशोधित किए बिना और लिंक रजिस्टर के बिना सीधे किसी अन्य फ़ंक्शन पर जंप की आवश्यकता होती है।सीधे किसी अन्य सी ++ फ़ंक्शन पर जाएं

Tricore पर (या, बल्कि, Tricore-जी ++ पर), इस आवरण टेम्पलेट (किसी भी तीन तर्क-समारोह के लिए) काम करता है:

template< class A1, class A2, class A3 > 
inline void __attribute__((always_inline)) 
JUMP3(void (*func)(A1, A2, A3), A1 a1, A2 a2, A3 a3) { 
    typedef void (* __attribute__((interrupt_handler)) Jump3)(A1, A2, A3); 
    ((Jump3)func)(a1, a2, a3); 
} 

//example for using the template: 
JUMP3(superDispatch, this, me, next); 

यह कोडांतरक अनुदेश J (उर्फ जम्प) उत्पन्न होगा बजाय CALL का, स्टैक और सीएसए को अपरिवर्तित छोड़कर (अन्यथा सामान्य) C++ फ़ंक्शन superDispatch(SchedulerImplementation* obj, Task::Id from, Task::Id to) पर अपरिवर्तित छोड़ दिया गया।

अब मैं एआरएम कॉर्टेक्स पर एक समान व्यवहार की जरूरत है (या, बल्कि, हाथ-नन-linux-gnueabi-जी ++ के लिए), यानी एक B (उर्फ शाखा) (लिंक और आदान प्रदान के साथ शाखा उर्फ) BLX के बजाय अनुदेश उत्पन्न । लेकिन arm-g ++ के लिए interrupt_handler विशेषता नहीं है और मुझे कोई समकक्ष विशेषता नहीं मिली।

तो मैं asm volatile का सहारा और एएसएम कोड सीधे लिख करने की कोशिश की:

template< class A1, class A2, class A3 > 
inline void __attribute__((always_inline)) 
JUMP3(void (*func)(A1, A2, A3), A1 a1, A2 a2, A3 a3) { 
    asm volatile (
        "mov.w r0, %1;" 
        "mov.w r1, %2;" 
        "mov.w r2, %3;" 
        "b %0;" 
          : 
          : "r"(func), "r"(a1), "r"(a2), "r"(a3) 
          : "r0", "r1", "r2" 
       ); 
} 

अब तक तो अच्छा है, मेरे सिद्धांत रूप में, कम से कम। थंब -2 को रजिस्टरों में पारित होने के लिए फ़ंक्शन तर्कों की आवश्यकता होती है, यानी इस मामले में r0..r2, इसलिए इसे काम करना चाहिए।

लेकिन तब लिंकर

undefined reference to `r6' 
एएसएम बयान के समापन ब्रैकेट पर

साथ मर जाता है ... और मैं क्या इसके बारे में बनाने के लिए पता नहीं है। ठीक है, मैं सी ++ में विशेषज्ञ नहीं हूं, और एएसएम सिंटैक्स बहुत सीधा नहीं है ... तो क्या किसी को मेरे लिए इशारा मिला है? Arm-g ++ के लिए सही __attribute__ पर एक संकेत एक तरीका होगा, एएसएम कोड को ठीक करने का संकेत एक और होगा। एक और तरीका शायद संकलक को बताना होगा कि a1..a3 रजिस्ट्रार r0..r2 में पहले से ही होना चाहिए जब एएसएम कथन दर्ज किया गया है (मैंने उसमें थोड़ा सा देखा, लेकिन कोई संकेत नहीं मिला)।

+0

क्या ए 1, ए 2, ए 3 पॉइंटर्स हैं? उन्हें '(शून्य *) ' – osgx

+0

में परिवर्तित करने का प्रयास करें एआरएम इंटरप्ट हैंडलर के लिए विशेषता' इंटरप्ट 'है। Http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html –

+0

@ माइक: नहीं, वह विशेषता अभी भी 'BLX' निर्देश उत्पन्न करती है ... – orithena

उत्तर

0

ठीक है, अब मुझे पता चला कि क्या गलत हुआ।

एआरएम कॉर्टेक्स पर सीधे जंपिंग की पूरी अवधारणा एआरएम कॉर्टेक्स पर है, क्योंकि हर बार जब आप किसी अन्य फ़ंक्शन को कॉल करते हैं तो पूरे सीपीयू संदर्भ को सहेजने के लिए ट्रायकोर कॉन्टेक्स्ट सेव एरिया (सीएसए) का उपयोग करता है। इसे एक दूसरे, स्वतंत्र ढेर के रूप में सोचें जो प्रत्येक CALL के साथ बढ़ता है और प्रत्येक RET के साथ घटता है। और प्रत्येक सीएसए ब्लॉक का निरंतर आकार होता है।

दूसरी ओर, एआरएम कॉर्टेक्स, एक साधारण मानक स्टैक का उपयोग करता है (ठीक है, यह सिस्टम स्टैक और थ्रेड स्टैक के बारे में जानता है, लेकिन यह यहां महत्वहीन नहीं है) - और जीसीसी बस प्रत्येक फ़ंक्शन के लिए आवश्यक चीज़ों को बचाता है, इसलिए प्रत्येक फ्रेम का एक अलग आकार होता है। बस किसी अन्य फ़ंक्शन पर कूदना इसलिए सवाल से बाहर है, क्योंकि जैसे ही कूद-टू-फ़ंक्शन गैर-अस्थिर रजिस्टरों को सहेजना शुरू कर देता है, जैसे स्टैक दूषित हो जाएगा।

और आर 6 के अपरिभाषित संदर्भ के साथ लिंकर त्रुटि के बारे में ... अच्छी तरह से, मुझे निर्देश सेट दस्तावेज़ों को अधिक सावधानी से पढ़ना चाहिए था। Bतत्काल पता, BX पर एक बिना शर्त शाखा है जो एक रजिस्टर में शाखा पते की अपेक्षा करता है। मुझे मैनुअल में निर्देश सूची द्वारा बेवकूफ़ बना दिया गया था जहां BX को जल्द ही "एक्सचेंज के साथ शाखा" के रूप में वर्णित किया गया था। मैं कुछ भी विनिमय नहीं करना चाहता था, मैं एक साधारण कूद चाहता था, इसलिए मैंने आगे नहीं पढ़ा।

तो B के साथके साथके साथ विनिमय के बाद कोड संकलित किया गया। लेकिन, जैसा ऊपर बताया गया है, पूरी अवधारणा अपेक्षा के अनुसार काम नहीं कर सकती है। शायद किसी और को उस कोड के लिए उपयोग केस मिल सकता है, मुझे अब क्लासिक फ़ंक्शन कॉलिंग का सहारा लेना है ...

1

लिंक त्रुटि एक सूचक को कूदने के लिए शाखा निर्देश का उपयोग करने का प्रयास कर रही है। यह b r6 जैसे कोड उत्पन्न करता है, जो लिंक करने में विफल रहता है क्योंकि r6 प्रतीक नहीं है। शाखा निर्देश को mov pc,%0 पर बदलें, और आपको सही कूद मिलनी चाहिए।

जैसा कि मैंने टिप्पणियों में उल्लेख किया है, एआरएम हस्तक्षेप हैंडलर को interrupt विशेषता के साथ घोषित किया गया है, लेकिन जैसा कि आपने पाया है कि यह कैसे प्रभावित नहीं होता है। मुझे लगता है कि एक मंच-विशिष्ट चाल थी जो ट्रायकोर पर सही काम करने के लिए हुई थी।

आप जीसीसी के विस्तारित वाक्यविन्यास, register int reg0 asm("r0") = a1; का उपयोग अस्थिर mov निर्देशों के बजाय विशिष्ट रजिस्टरों में चर घोषित करने का प्रयास कर सकते हैं। यह संकलक को बेहतर कोड उत्पन्न करने की अनुमति दे सकता है।

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