शुभ दिन।
काफी समय पहले कुछ प्रोसेसर के एक एमुलेटर लिखने की इच्छा थी।
और साइकिल का आविष्कार करने से बेहतर क्या हो सकता है?
बाइक का नाम V16 है, शब्द आभासी शब्द से और वास्तव में, थोड़ी गहराई से।
कहाँ से शुरू करें?
और आपको प्रोसेसर के विवरण के साथ, निश्चित रूप से शुरू करने की आवश्यकता है।
बहुत शुरुआत में, मैंने DCPU-16 एमुलेटर लिखने की योजना बनाई, लेकिन इंटरनेट पर इस तरह के चमत्कारों की संख्या बहुत अधिक है, इसलिए मैंने केवल DCPU-16 1.1 के साथ सबसे बुनियादी "चाट" पर ध्यान केंद्रित करने का फैसला किया।
आर्किटेक्चर
मेमोरी और पोर्ट
- V16 रैम के 128Kb (65536 शब्द) को संबोधित करता है, जिसे डिवाइस बफ़र्स और स्टैक के रूप में भी इस्तेमाल किया जा सकता है।
- स्टैक एफएफएफएफ पते से शुरू होता है, इसलिए, आरएसपी का मानक मान 0xFFFF है
- V16 I / O पोर्ट में 256 हैं, इन सभी की लंबाई 16 बिट्स है। उनमें से पढ़ना और लिखना
IN b, a
और OUT b, a
के निर्देशों के माध्यम से किया जाता OUT b, a
।
रजिस्टरों
V16 में सामान्य प्रयोजन रजिस्टर के दो सेट हैं: प्राथमिक और वैकल्पिक।
एक प्रोसेसर केवल एक सेट के साथ काम कर सकता है, इसलिए आप XCR
निर्देश का उपयोग करके सेट के बीच स्विच कर सकते हैं।
अनुदेश
सभी निर्देशों में अधिकतम तीन शब्द होते हैं और पहले पूरी तरह से परिभाषित होते हैं
पहले शब्द को तीन मूल्यों में विभाजित किया गया है: कम बाइट ओपकोड है, दो 4-बिट मान के रूप में उच्च बाइट ऑपरेंड का वर्णन है।
बीच में आता है
यहां व्यवधान उन पतों से अधिक कुछ नहीं है जिनके पते प्रोसेसर प्रोसेसर CALL
निर्देश को CALL
। यदि पता मान शून्य है, तो व्यवधान कुछ भी नहीं करता है, यह केवल एचएफ ध्वज को रीसेट करता है।
छद्मकोश और शब्दों का एक उदाहरण जिसमें यह सब अनुवाद किया जाना चाहिए:
MOV RAX, 0xABCD ; 350D ABCD MOV [RAX], 0x1234 ; 354D 1234
साइकिल (चक्र)
V16 1, 2 या 3 उपायों में एक निर्देश निष्पादित कर सकता है। प्रत्येक मेमोरी एक्सेस एक अलग घड़ी चक्र है। निर्देश नहीं है !
लिखना शुरू करते हैं!
बुनियादी प्रोसेसर संरचनाओं का कार्यान्वयन
रजिस्टर का एक सेट। केवल चार रजिस्टर हैं, लेकिन स्थिति में सुधार है कि प्रोसेसर में दो ऐसे सेट हैं। XCR
अनुदेश का उपयोग करके स्विचिंग होती है।
typedef struct Regs { uint16_t rax, rbx;
झंडे। DCPU-16 के विपरीत, V16 में सशर्त जंप, सबरूटीन कॉल और उसी से रिटर्न होता है। फिलहाल, प्रोसेसर में 8 झंडे हैं, जिनमें से 5 हालत झंडे हैं।
दरअसल, प्रोसेसर ही। यह रुकावट के पतों की तालिका का भी वर्णन करता है, जिसे डिस्क्रिप्टर कहा जा सकता है और x86 का एक और संदर्भ मिल सकता है।
typedef struct CPU {
संकार्य। मूल्यों को प्राप्त करते समय, हमें पहले पढ़ने की ज़रूरत है, फिर बदलें, और उसके बाद मान वापस लिखें जहां हमें यह मिला है।
typedef struct Opd { uint8_t code : 4; uint16_t value; uint16_t nextw; } opd_t;
संरचनाओं के साथ काम करने के लिए कार्य
जब सभी संरचनाओं का वर्णन किया जाता है, तो आवश्यकता उन कार्यों के लिए पैदा होती है जो इन संरचनाओं को बुझती हुई कोड की जादुई शक्ति से समाप्त कर देंगे।
cpu_t * cpu_create(void);
इसके अलावा, मैंने ऑपरेशन कोड के साथ एक बड़ी गणना का उल्लेख नहीं किया है, लेकिन यह आवश्यक नहीं है और केवल यह समझने के लिए आवश्यक है कि सभी गड़बड़ी में क्या हो रहा है।
टिक () फ़ंक्शन
इसके अलावा, केवल tick()
से कॉल करने के लिए इच्छित स्थिर कार्यों के लिए कॉल हैं।
void cpu_tick(cpu_t *cpu) {
आगे क्या करना है?
इस प्रश्न का उत्तर खोजने की कोशिश में, मैंने एम से सी से सी ++ तक पांच बार रिवाइटर किया, और इसके विपरीत।
हालाँकि, मुख्य लक्ष्यों को अब पहचाना जा सकता है:
- सामान्य इंटरप्ट को फास्ट करें (केवल एक फ़ंक्शन को कॉल करने और अन्य इंटरप्ट को प्राप्त करने पर प्रतिबंध लगाने के बाद, फ़ंक्शन कॉल करें और कतार में नए इंटरप्ट को जोड़ें)।
- स्क्रू डिवाइस, साथ ही उनके साथ संवाद करने के तरीके, opcodes का लाभ 256 हो सकता है।
- पढ़ाने के लिए
अपने आप को हैबर पर कोई विधर्म नहीं लिखें प्रोसेसर 200 MHz की विशिष्ट घड़ी की गति से संचालित होता है।
निष्कर्ष
मुझे उम्मीद है कि यह "लेख" किसी के लिए उपयोगी होगा, कोई उन्हें कुछ समान लिखने के लिए संकेत देगा।
मेरे प्यादों को गितुब पर देखा जा सकता है।
इसके अलावा, डरावनी के बारे में, मेरे पास इस इम्यूलेटर के पुराने संस्करण के लिए कोडांतरक है (नहीं, यहां तक कि प्रयास न करें, एमुलेटर कम से कम गलत ROM प्रारूप के बारे में शिकायत करेगा)