Studi e sperimentazioni su processori ad architettura ARM: il set di
Transcript
Studi e sperimentazioni su processori ad architettura ARM: il set di
Università Politecnica delle Marche Facoltà di Ingegneria Corso di Laurea in Ingegneria Informatica e dell’Automazione Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Relatore: Tesi di Laurea di: Prof. Aldo Franco Dragoni Loredano Rapari Anno Accademico 2010-2011 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Sommario 1. 2. 3. INTRODUZIONE ................................................................................................................................................. 6 1.1. OBIETTIVI ............................................................................................................................................................ 6 1.2. HARDWARE E SOFTWARE ....................................................................................................................................... 6 1.3. STRUTTURA DELL’ELABORATO.................................................................................................................................. 6 SISTEMI EMBEDDED E ARM ............................................................................................................................... 7 2.1. SISTEMI EMBEDDED............................................................................................................................................... 7 2.2. EVOLUZIONE DI ARM ............................................................................................................................................ 9 2.3. LA DIFFUSIONE DI ARM ....................................................................................................................................... 11 2.3.1. I partners di ARM Ltd. ............................................................................................................................... 11 2.3.2. I principali prodotti sul mercato ................................................................................................................ 13 ARCHITETTURA ARM ........................................................................................................................................15 3.1. LA LOGICA RISC ................................................................................................................................................. 15 3.2. LA PIPELINE ....................................................................................................................................................... 16 3.3. ORGANIZZAZIONE DELLA CACHE ............................................................................................................................. 16 3.4. GESTIONE DELLA MEMORIA................................................................................................................................... 18 3.4.1. Organizzazione della memoria.................................................................................................................. 18 3.4.2. Traduzione degli indirizzi di memoria virtuale .......................................................................................... 19 3.4.3. Controllo dell’accesso ............................................................................................................................... 20 3.5. TIPI DI DATI DI ARM ........................................................................................................................................... 20 3.6. TIPI DI OPERAZIONI.............................................................................................................................................. 21 3.6.1. 3.7. MODI DI INDIRIZZAMENTO DI ARM........................................................................................................................ 23 3.7.1. Indirizzamento load/store ......................................................................................................................... 23 3.7.2. Indirizzamento di istruzioni di processamento dati .................................................................................. 24 3.7.3. Istruzioni di salto ....................................................................................................................................... 24 3.7.4. Indirizzamento load/store multiplo........................................................................................................... 24 3.8. IL PROCESSORE ARM .......................................................................................................................................... 25 3.8.1. Organizzazione del processore .................................................................................................................. 25 3.8.2. Modi del processore .................................................................................................................................. 27 3.8.3. Organizzazione dei registri ........................................................................................................................ 27 3.8.3.1. Registri a uso generale......................................................................................................................................28 3.8.3.2. Registri di stato del programma .......................................................................................................................29 3.8.4. 4. Codici di condizione ................................................................................................................................... 22 Gestione degli Interrupt ............................................................................................................................ 29 MARVELL KIRKWOOD 88F6281 .........................................................................................................................31 4.1. CARATTERISTICHE DELLA SCHEDA ........................................................................................................................... 31 4.1.1. Componenti di sistema.............................................................................................................................. 31 4.1.2. Schema a blocchi dell’ hardware .............................................................................................................. 32 1 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 5. SET DI ISTRUZIONI THUMB (MANUALE PARTE 1) ..............................................................................................33 5.1. INTRODUZIONE AL SET DI ISTRUZIONI THUMB ........................................................................................................... 34 5.1.1. Attivare lo stato Thumb ............................................................................................................................ 34 5.1.2. ECCEZIONI ......................................................................................................................................................... 35 5.2. CODIFICA DEL SET ISTRUZIONI ................................................................................................................................ 36 5.2.1. 5.3. Istruzioni varie ........................................................................................................................................... 37 ISTRUZIONI DI SALTO............................................................................................................................................ 38 5.3.1. Salto condizionato..................................................................................................................................... 38 5.3.2. Salto incondizionato .................................................................................................................................. 38 5.3.3. Salto con scambio ..................................................................................................................................... 38 5.4. ISTRUZIONI DATA-PROCESSING.............................................................................................................................. 39 5.4.1. Istruzioni che operano sui registri bassi .................................................................................................... 39 5.4.2. Istruzioni che operano sui registri alti ....................................................................................................... 41 5.4.3. Formati...................................................................................................................................................... 42 5.5. ISTRUZIONI LOAD AND STORE REGISTER .................................................................................................................. 44 5.5.1. 5.6. Formati...................................................................................................................................................... 44 ISTRUZIONI LOAD AND STORE MULTIPLE ................................................................................................................. 46 5.6.1. Formati...................................................................................................................................................... 46 5.6.2. Esempi ....................................................................................................................................................... 46 5.7. ISTRUZIONI PER LA GENERAZIONE DI ECCEZIONI ......................................................................................................... 47 5.7.1. 5.8. 6. Codifica delle istruzioni ............................................................................................................................. 47 SPAZIO INDEFINITO DELLE ISTRUZIONI...................................................................................................................... 48 ISTRUZIONI THUMB (MANUALE PARTE 2) ........................................................................................................49 6.1. 2 Tesi di Laurea di: Loredano Rapari matr. 1029262 LISTA IN ORDINE ALFABETICO DELLE ISTRUZIONI THUMB.............................................................................................. 50 6.1.1. Note generali ............................................................................................................................................ 50 6.1.2. ADC ........................................................................................................................................................... 52 6.1.3. ADD(1) ....................................................................................................................................................... 53 6.1.4. ADD(2) ....................................................................................................................................................... 54 6.1.5. ADD(3) ....................................................................................................................................................... 55 6.1.6. ADD(4) ....................................................................................................................................................... 56 6.1.7. ADD(5) ....................................................................................................................................................... 57 6.1.8. ADD(6) ....................................................................................................................................................... 58 6.1.9. ADD(7) ....................................................................................................................................................... 59 6.1.10. AND ...................................................................................................................................................... 60 6.1.11. ASR(1) ................................................................................................................................................... 61 6.1.12. ASR(2) ................................................................................................................................................... 63 6.1.13. B(1) ....................................................................................................................................................... 65 6.1.14. B(2) ....................................................................................................................................................... 67 6.1.15. BIC ........................................................................................................................................................ 69 6.1.16. BKPT ..................................................................................................................................................... 70 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.17. BL, BLX(1) ............................................................................................................................................. 72 6.1.18. BLX(2) ................................................................................................................................................... 75 6.1.19. BX ......................................................................................................................................................... 76 6.1.20. CMN ..................................................................................................................................................... 78 6.1.21. CMP(1).................................................................................................................................................. 79 6.1.22. CMP(2).................................................................................................................................................. 80 6.1.23. CMP(3).................................................................................................................................................. 81 6.1.24. CPS........................................................................................................................................................ 83 6.1.25. CPY ....................................................................................................................................................... 85 6.1.26. EOR ....................................................................................................................................................... 87 6.1.27. LDMIA ................................................................................................................................................... 88 6.1.28. LDR(1) ................................................................................................................................................... 91 6.1.29. LDR(2) ................................................................................................................................................... 93 6.1.30. LDR(3) ................................................................................................................................................... 95 6.1.31. LDR(4) ................................................................................................................................................... 97 6.1.32. LDRB(1) ................................................................................................................................................. 99 6.1.33. LDRB(2) ............................................................................................................................................... 100 6.1.34. LDRH(1) .............................................................................................................................................. 101 6.1.35. LDRH(2) .............................................................................................................................................. 103 6.1.36. LDRSB ................................................................................................................................................. 105 6.1.37. LDRSH ................................................................................................................................................. 106 6.1.38. LSL(1) .................................................................................................................................................. 108 6.1.39. LSL(2) .................................................................................................................................................. 109 6.1.40. LSR(1) ................................................................................................................................................. 111 6.1.41. LSR(2) ................................................................................................................................................. 112 6.1.42. MOV(1) ............................................................................................................................................... 114 6.1.43. MOV(2) ............................................................................................................................................... 115 6.1.44. MOV(3) ............................................................................................................................................... 116 6.1.45. MUL .................................................................................................................................................... 118 6.1.46. MVN ................................................................................................................................................... 119 6.1.47. NEG .................................................................................................................................................... 120 6.1.48. ORR..................................................................................................................................................... 121 6.1.49. POP ..................................................................................................................................................... 122 6.1.50. PUSH................................................................................................................................................... 125 6.1.51. REV ..................................................................................................................................................... 128 6.1.52. REV16 ................................................................................................................................................. 129 6.1.53. REVSH ................................................................................................................................................. 130 6.1.54. ROR..................................................................................................................................................... 131 6.1.55. SBC ..................................................................................................................................................... 133 6.1.56. SETEND ............................................................................................................................................... 134 3 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.57. STMIA ................................................................................................................................................. 135 6.1.58. STR(1) ................................................................................................................................................. 138 6.1.59. STR(2) ................................................................................................................................................. 140 6.1.60. STR(3) ................................................................................................................................................. 142 6.1.61. STRB(1) ............................................................................................................................................... 144 6.1.62. STRB(2) ............................................................................................................................................... 146 6.1.63. STRH(1) ............................................................................................................................................... 147 6.1.64. STRH(2) ............................................................................................................................................... 149 6.1.65. SUB(1)................................................................................................................................................. 151 6.1.66. SUB(2)................................................................................................................................................. 152 6.1.67. SUB(3)................................................................................................................................................. 153 6.1.68. SUB(4)................................................................................................................................................. 154 6.1.69. SWI ..................................................................................................................................................... 155 6.1.70. SXTB.................................................................................................................................................... 156 6.1.71. SXTH ................................................................................................................................................... 157 6.1.72. TST ...................................................................................................................................................... 158 6.1.73. UXTB ................................................................................................................................................... 159 6.1.74. UXTH .................................................................................................................................................. 160 6.2. 7. ISTRUZIONI THUMB E VERSIONE ARCHITETTURA ...................................................................................................... 161 TEST................................................................................................................................................................162 7.1. IMPOSTAZIONI TEST........................................................................................................................................... 162 7.2. PROGRAMMA TEST: FATTORIALE.......................................................................................................................... 163 7.2.1. Codice C ................................................................................................................................................... 163 7.2.2. Codice Assembler .................................................................................................................................... 164 7.2.2.1. Arm .................................................................................................................................................................164 7.2.2.2. Thumb.............................................................................................................................................................165 7.2.2.3. Thumb con ottimizzazione –O1 ......................................................................................................................167 7.2.2.4. Thumb con ottimizzazione –O2 ......................................................................................................................168 7.2.2.5. Thumb con ottimizzazione –O3 ......................................................................................................................170 7.2.3. 7.3. Tempi di esecuzione ................................................................................................................................ 176 PROGRAMMA TEST: FATTORI PRIMI ...................................................................................................................... 178 7.3.1. Codice C ................................................................................................................................................... 178 7.3.2. Codice Assembler .................................................................................................................................... 179 7.3.2.1. Arm .................................................................................................................................................................179 7.3.2.2. Thumb.............................................................................................................................................................180 7.3.2.3. Thumb con ottimizzazione –O1 ......................................................................................................................182 7.3.2.4. Thumb con ottimizzazione –O2 ......................................................................................................................183 7.3.2.5. Thumb con ottimizzazione –O3 ......................................................................................................................184 7.3.3. 7.4. 4 Tesi di Laurea di: Loredano Rapari matr. 1029262 Tempi di esecuzione ................................................................................................................................ 186 PROGRAMMA TEST: SERIE DI FIBONACCI................................................................................................................ 188 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 7.4.1. Codice C ................................................................................................................................................... 188 7.4.2. Codice Assembler .................................................................................................................................... 188 7.4.2.1. Arm .................................................................................................................................................................188 7.4.2.2. Thumb.............................................................................................................................................................189 7.4.2.3. Thumb con ottimizzazione –O1 ......................................................................................................................190 7.4.2.4. Thumb con ottimizzazione –O2 ......................................................................................................................191 7.4.2.5. Thumb con ottimizzazione –O3 ......................................................................................................................192 7.4.3. Tempi di esecuzione ................................................................................................................................ 194 8. CONCLUSIONI .................................................................................................................................................196 9. BIBLIOGRAFIA E SITOGRAFIA ..........................................................................................................................197 5 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 1. Introduzione In questa tesi andrò a descrivere il funzionamento dell’architettura dei processori ARM, soffermandomi soprattutto sulla parte che riguarda il set di istruzioni Thumb. La scelta di questo argomento è dettata dalla grade espansione, negli ultimi tempi, di questa particolare architettura, adatta per sistemi embedded e per dispositivi portatili, entrambi in grande crescita. Nella stragrande maggioranza dei cellulari (smartphone), in molti televisori, nei dispositivi di rete, nelle centraline delle automobili e in molti altri dispositivi sono presenti processori con questa architettura. 1.1. Obiettivi L’obiettivo principale è quello di creare un manuale completo, in italiano, sull’architettura ARMv5TE, per poi poterlo sfruttare in futuro per sperimentazioni e studi sul processore disponibile in laboratorio con questa architettura. Come è possibile dedurre dal titolo, mi sono occupato della parte del manuale che parla del set di istruzioni Thumb. Un altro obiettivo è sicuramente quello di studiare questo particolare tipo di architettura che sfrutta set di istruzioni RISC (Reduced Instruction Set Computer). Dopo aver completato la parte di manuale e studiato l’architettura, il terzo obiettivo è quello di fare dei test con dei programmi compilati appositamente con istruzioni del set Thumb sul processore disponibile in laboratorio e valutarne i risultati. 1.2. Hardware e Software L’hardware utilizzato è un dispositivo embedded, uno Sheevaplug computer, nel quale sono presenti alcune porte di I/O ed è dotato del processore Marvell Kirkwood 88F6281 basato sull’architettura ARMv5TE. Nel dispositivo gira un sistema operativo Linux Debian. Per fare i test ho scritto dei semplici programmi in C e li ho compilati con il compilatore da linea di comando nella shell di Linux. Il compilatore che ho scelto è Sourcery G++ Lite 2011.03-41 for ARM GNU/Linux. 1.3. Struttura dell’elaborato Dopo questa introduzione, l’elaborato è costituito da una prima parte in cui si parla in generale dei sistemi SoC (System on a Chip) e in particolare di quelli che utilizzano l’architettura ARM. Poi c’è una descrizione dell’architettura ARM in generale, nella quale si parla della logica RISC, della pipeline e dell’organizzazione e gestione delle risorse del processore. Nel quarto capitolo si parla della scheda disponibile in laboratorio che monta il processore con architettura ARM (Marvell Kirkwood 88F6281). Nel quinto capitolo vengono riportati i programmi di test e i risultati ottenuti. Infine nel sesto capitolo ho allegato la parte di manuale sulle istruzioni Thumb. 6 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 2. Sistemi embedded e ARM L’architettura ARM ha origine da principi di progetto di tipo RISC e viene utilizzata in sistemi embedded. Vedremo più avanti in dettaglio l’architettura RISC dell’ARM. In questo paragrafo si spiegherà il concetto di sistema embedded, per poi rivolgersi ai sistemi ARM. 2.1. Sistemi embedded Quando parliamo di un sistema ebedded ci riferiamo all’utilizzo di elettronica e software all’interno di un prodotto, in contrapposizione a sistemi a utilizzo generale (general-purpose), come i desktop o i portatili. Una definizione di sistema embedded è la seguente: Una combinazione di hardware e software, ed eventualmente di altre componenti meccaniche, progettata per assolvere ad un compito specifico. In molti casi i sistemi embedded sono parte di un sistema o di un prodotto più grande, come nel caso del sistema ABS di un’automobile. Tabella 2.1 Esempi di sistemi embedded e loro mercato Mercato Dispositivo Automobilistico Sistema di accensione Controllo del motore Sistema frenante Elettronica di consumo Televisione digitale e analogica DVD, videoregistratori, decoder Dispositivi palmari (PDA) Elettrodomestici (frigoriferi, tostapane, microonde) Giochi Telefoni, cellulari, cercapersone Macchine fotografiche GPS Controllo industriale Robotica e sistemi di controllo per la produzione industriale Sensori Medicina Pompe a infusione Macchine per dialisi Dispositivi protesici Monitor cardiaci Office automation Fax Fotocopiatrici Stampanti Monitor Scanner 7 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 I sistemi embedded sono di gran lunga più diffusi dei computer general-purpose, perché vengono utilizzati in una vastissima gamma di applicazioni (Tabella 2.1). Tali sistemi possono avere una grande varietà di requisiti e vincoli, come nei casi seguenti: sistemi piccoli e grandi implicano vincoli differenti in termini di costi di produzione, e quindi necessità diverse per quanto riguarda ottimizzazione e riutilizzo; sono soggetti a vincoli molto restrittivi e a combinazioni diverse di requisiti di qualità, ad esempio in termini di sicurezza, affidabilità, risposta in tempo reale, flessibilità e rispetto delle normative vigenti; tempo di vita da breve a lungo; diverse combinazioni ambientali in termini di radiazioni, vibrazioni e umidità, solo per citare alcuni esempi; Figura 2.1 Possibile organizzazione di un sistema embedded. 8 differenti caratteristiche delle applicazioni, che possono essere statiche o dinamiche, lente o veloci, rivolte al calcolo o ad un utilizzo intensivo dell’interfaccia, e/o combinazioni di queste; diversi modelli di computazione (solitamente chiamati sistemi ibridi) che variano da sistemi a eventi discreti a sistemi con dinamiche a tempo continuo. Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Spesso i sistemi embedded sono strettamente relazionati al contesto di utilizzo. Questo può dare origine a vincoli di real-time imposti dalla necessità di interagire con il contesto. I vincoli, come la velocità di movimento, la precisione delle misurazioni e il periodo di tempo richiesti impongono una precisa temporizzazione delle operazioni da eseguire. Se più attività devono essere svolte simultaneamente, i vincoli real-time saranno più restrittivi. La figura 2.1 mostra in termini generali l’organizzazione di un sistema embedded. Oltre a processore e memoria vi è un certo numero di elementi che normalmente non sono utilizzati nei computer desktop o portatili: una varietà di interfacce che permette al sistema di misurare, manipolare e interagire con l’ambiente esterno; l’interfaccia con l’utente può essere molto semplice, come una spia lampeggiante, ma anche molto complicata, come una vista robotica in tempo reale; la porta per la diagnostica è utilizzabile per esaminare il sistema che viene controllato, non solo per la diagnosi del computer; dispositivi logici programmabili (FPGA, Field Programmable Gate Array), specifici per applicazioni (ASIC, Application Specific Integrated Circuit) o hardware non digitale sono utilizzabili per migliorare prestazioni e sicurezza; il software ha spesso funzionalità prefissate ed è specifico per una data applicazione. 2.2. Evoluzione di ARM ARM è una famiglia di microprocessori e microcontrollori di tipo RISC, progettati da ARM Inc. di Cambridge (Inghilterra). ARM progetta processori e architetture multicore e da in licenza i progetti ad aziende esterne che li producono. I chip ARM sono processori ad alta velocità famosi per le piccole dimensioni e la bassa potenza richiesta. Gli ARM vengono usati in maniera massiccia in computer palmari (PDA) e altri dispositivi portatili, inclusi videogiochi, telefoni e un’ampia varietà di prodotti di consumo. Ad esempio i ben noti dispositivi Apple iPhone e iPod contengono dei chip ARM. L’architettura ARM è probabilmente la più diffusa nei sistemi embedded e dunque i chip ARM sono anche i processori più diffusi al mondo. Le origini della tecnologia ARM vanno ricondotte alla inglese Acorn Computers. All’inizio degli anni ’80 Acorn stipulò un accordo con British Broadcasting Corporation (BBC) per lo sviluppo di un nuovo microprocessore per il progetto BBC Computer Literacy. Il successo di questo accordo permise alla Acorn di continuare nello sviluppo e progettare il primo processore RISC commerciale, l’Acorn RISC Machine (ARM). La prima versione, ARM1, divenne operativa nel 1985 e fu utilizzata per ricerche interne e sviluppo, oltre ad essere utilizzata come coprocessore nel progetto per la BBC. Sempre nel 1985, Acorn rilasciò l’ARM2, un processore delle stesse dimensioni del precedente, ma più veloce e con più funzioni. Ulteriori migliorie furono realizzate con il processore ARM3 (1989). Durante questo periodo Acorn affidò alla società VLSI Technology la fabbricazione dei suoi chip. VLSI poteva commercializzare i chip, ed ebbe un grande successo nel convincere altre aziende a montare processori ARM nei loro prodotti, in particolare come processori embedded. Il progetto ARM andava incontro alla domanda commerciale di processori per applicazioni embedded ad alte prestazioni, bassi consumi, piccole dimensioni e costi contenuti, ma ulteriori sviluppi andavano oltre le capacità di Acorn. Fu così creata una nuova società, la ARM Ltd., che vedeva la partecipazione di Acorn, VLSI e Apple Computer. Acorn RISC Machine fu rinominata Advanced RISC Machine (La società abbandonò la denominazione Advanced RISC Machine alla fine degli anni ’90. Al giorno d’oggi tale architettura è conosciuta semplicemente come ARM). Il primo 9 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 prodotto offerto dalla nuova società fu ARM6, una versione migliorata di ARM3. In seguito, la società introdusse diverse nuova famiglie di processori, con sempre più numerose funzionalità e migliori prestazioni. La Tabella 2.2 mostra alcune caratteristiche delle diverse famiglie di architetture ARM. I numeri della tabella sono solamente indicativi; i valori reali variano a seconda delle differenti implementazioni. Tabella 2.2 Evoluzione di ARM Famiglia ARM1 ARM2 ARM3 ARM6 ARM7 ARM8 ARM9 ARM9E ARM10E ARM11 Cortex XScale Funzionalità rilevanti 32-bit RISC Istruzioni di moltiplicazione e scambio; unità di gestione della memoria, grafica e processore I/O integrati Primo utilizzo della cache del processore Primo a supportare indirizzi a 32 bit; unità floating point (virgola mobile) SoC (System on a Chip) integrato Pipeline a 5 stadi; predizione statica dei salti Istruzioni DSP migliorate Pipeline a 6 stadi Pipeline a 9 stadi Pipeline superscalare a 13 stadi Processore per le applicazioni: pipeline a 7 stadi Figura 2.2 Evoluzione delle famiglie di processori 10 Cache No No MIPS tipico @ MHz 4 KB unificata 4 KB unificata 12 MIPS @ 25 MHz 28 MIPS @ 33 MHz 8 KB unificata 8 KB unificata 16 KB / 16 KB 16 KB / 16 KB 32 KB / 32 KB Variabile Variabile 32 KB / 32 KB L1 512 KB L2 60 MIPS @ 60 MHz 84 MIPS @ 72 MHz 300 MIPS @ 300 MHz 220 MIPS @ 200 MHz 7 MIPS @ 12 MHz 740 MIPS @ 665 MHz 2000 MIPS @ 1 GHz 1000 MIPS @ 1,25 GHz Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Conformemente a quanto descritto sul sito web di ARM (arm.com), i processori ARM sono progettati per soddisfare tre diverse categorie di sistemi: sistemi embedded real-time: sistemi di memorizzazione, comparto automobilistico e industriale, applicazioni di rete; piattaforme applicative: dispositivi che utilizzano sistemi operativi come Linux, Palm OS, Symbian OS, e Windows CE per applicazioni wireless e di intrattenimento digitale; applicazioni per la sicurezza: smart card, SIM card e terminali Bancomat. 2.3. La diffusione di ARM Come abbiamo già detto i processori con architettura ARM sono i più diffusi al mondo grazie al rapporto qualità-costo davvero eccellente. Abbiamo anche detto che ARM realizza i progetti delle varie architetture e poi le cede in licenza ai produttori, andiamo quindi a vedere i prteners di ARM Ltd. e i principali prodotti sul mercato che utilizzano questi processori. 2.3.1. I partners di ARM Ltd. Di seguito la lista dei principali membri della ARM Connected Community. Tabella 2.3 Licenze della famiglia di processori Cortex Processor Cortex-A15 Cortex-A9 Cortex-A8 Cortex-A5 Cortex-R4(F) Cortex-M4 Cortex-M3 Cortex-M0 Selection of Public Licensees Texas Instruments, ST-Ericsson, nVIDIA, Samsung Electronics Broadcom Corporation, NEC Electronics, nVIDIA, STMicroelectronics, Texas Instruments, Toshiba, Mindspeed Technologies Broadcom Corporation, Freescale Semiconductor, Matsushita, Samsung Electronics, STMicroelectronics, Texas Instruments, PMC-Sierra, 3Dlabs Cambridge Silicon Radio Broadcom Corporation, Texas Instruments, Toshiba, Infineon NXP, STMicroelectronics, Texas Instruments, Freescale Accent Srl, Actel Corporation, Broadcom Corporation, Cypress Semiconductor, Ember, Energy Micro, Fujitsu, NXP, Fuzhou Rockchip Electronics CO. Ltd., STMicroelectronics, Texas Instruments, Toshiba, Zilog, Austriamicrosystems, Chungbuk Technopark, NXP, Triad Semiconductor, Melfas 11 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Tabella 2.4 Licenze della famiglia di processori ARM11 Processor ARM11 MPCore ARM1176JZ(F)-S ARM1156T2(F)S ARM1136J(F)-S Public Licensees Intel Corporation, NEC Electronics, Netronome, NVIDIA, PMC Sierra, Renesas, Sarnoff Broadcom Corporation, Infineon Technologies AG, Matsushita, NEC Electronics,NXP,Renesas, Sunplus, Texas Instruments , Toshiba Comsys, LSI Logic, NEC Electronics Accent, Broadcom Corporation, Ceroma, eSilicon Corporation, Freescale Semiconductor,LSI Logic, Matsushita, Mindspeed, NEC Electronics, Qualcomm, Renesas,STMicroelectronics, Texas Instruments , Toshiba Tabella 2.5 Licenze della famiglia di processori ARM9 Accent Alcatel Alchip All Winner Technology (Holding) Ltd Altera Analog Devices Inc. ARCA Atheros Communications Atmel Corporation Austriamicrosystems Avago Technologies Avalink Incorporated Beken Corporation Broadcom Corporation Cambridge Silicon Radio Capital Semiconductor Ltd Chongqing Chongyou IT Cirrus Logic Conexant Systems Inc. Datang Microelectronics Technology eSilicon Corporation Faraday TechFocus Enhancements Freescale Semiconductor Fujitsu GCT Semiconductor 12 Global Unichip Corporation Huawei Technologies ICP Infineon Technologies AG Ironkey Incorporated Kawasaki Microelectronics Key ASIC Leadcore Technology Co Ltd LSI Logic Marvell Semiconductor Mediatek Inc Micrel Mindspeed Technologies Inc. Moschip Semiconductor Mtekvision NationZ Technologies Inc NEC Electronics Neo Magic Corporation NXP Nuvoton Technology Corporation NVidia Corporation OKI Panasonic Parrot PulseLink Qualcomm Quanta Computer Inc Renesas Technology RF Micro Devices Rohm Samsung Electronics Sandisk Sanyo Electric Co Ltd Shanghai Jade Technologies Sharp Corporation Sierra Wireless SA Skyworks Solutions Inc. Socle Technology Corp Sony STMicroelectronics Standard Microsystems Telechips Texas Instruments Toshiba TSMC Verisilicon Wisair Zoran Corporation Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 2.3.2. Tesi di Laurea di: Loredano Rapari matr. 1029262 I principali prodotti sul mercato Motorola Atrix 4G Nvidia Tegra2 (dual-core Cortex-A9) LG Optimus Quantum Qualcomm QSD8650 (ARMv7 instruction set) GREE Water-Cooled Centrifugal Chiller (condizionatore indusatriale) NXP LPC21xx MCU(ARM7TDMI) Sony Ericsson Xperia Play Qualcomm QSD8550 ARMv7 Motorola Xoom Nvidia Tegra 2 (Cortex-A9) Itron OpenWay CENTRON Smart Meter (misuratore consumo energetico) Accent ASMgrid Platform - Integrated ARM® Cortex-M3 Web Tube (Samsung Smart TV) Samsung (Cortex-A8) Olivetti Olipad 100 Nvidia Tegra 2 (Cortex-A9) 13 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Apple iPod Nano Dual ARM7TDMI HP Deskjet 5940 ARM946E-S 14 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 3. Architettura ARM L’architettura ARM si è evoluta a un punto tale che supporta implementazioni su un ampio spettro di punti di prestazioni. Sono stati prodotti più di due miliardi di pezzi, il che stabilisce l’architettura come quella dominante in vari segmenti di mercato. La semplicità dell’architettura dei processori ARM ha portato nel corso del tempo a implementazioni sempre più piccole, queste implementazioni permettono ai dispositivi un consumo energetico molto basso. Dimensioni, prestazioni e consumi molto bassi rimangono punti chiave nello sviluppo dell’architettura ARM. La maggior parte delle versioni dell’architettura supporta due tipi di set di istruzioni: un set codificato a 32 bit che viene chiamato ARM instructions set e un set codificato a 16 bit chiamato Thumb instructions set. Entrambi sono Reduced Instruction Set Computer (RISC) e comprendo le caratteristiche tipiche delle architetture RISC. 3.1. La logica RISC A differenza di come è specificato nella definizione (Reduced Instruction Set Computer), RISC non significa tanto avere a che fare con meno istruzioni, ma bensì con una architettura circuitale che sia molto semplice nel consentire di ottenere maggiore compattezza, velocità di operazione ed esecuzione delle istruzioni in un singolo colpo di clock. La lunghezza delle istruzioni viene mantenuta costante in modo da garantire una prevedibilità nei tempi di esecuzione delle istruzioni. La semplice filosofia che sta dietro l’architettura RISC è riassunta dalla figura 3.1. Abbiamo una unità centrale, il processore, che è la parte intelligente del sistema. Un insieme di registri consente di movimentare i dati all’interno della CPU. I dati e le istruzioni vengono caricati dalla memoria. Non si possono eseguire dunque operazioni dirette sui dati in memoria, ma solo tra registri interni. Figura 3.1 Filosofia architettura RISC Le principali caratteristiche delle architetture RISC sono: un file di registro grande e uniforme; un’architettura load/store, poiché le operazioni sui dati avvengono nei registri interni al processore e non direttamente in memoria; modalità di indirizzamento semplice, con tutti gli indirizzi determinati solamente dal contenuto dei registri e dei campi delle istruzioni; campi delle istruzioni uniformi e di lunghezza fissa, per semplificare la decodifica dell’istruzione. In più l’architettura ARM, fornisce: modalità di indirizzamento con auto-incremento e auto-decremento per ottimizzare i cicli; istruzioni di load e store multiplo per massimizzare il throughput dei dati; 15 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 esecuzione condizionata per quasi tutte le istruzioni per massimizzare il throughput di esecuzione. I miglioramenti all’architettura RISC di base, permettono ai processori ARM di raggiungere un buon bilanciamento tra alte prestazioni, dimensioni del codice, basso consumo e grandezza del chip. 3.2. La pipeline Nei RISC ogni istruzione è organizzata in modo che le azioni vengano svolte seguendo sempre una medesima successione, eventualmente lasciano un buco, o NOP, se quel particolare passo non serve. Questo fa si che si possa evitare di aspettare che un’istruzione sia completamente eseguita, prima di iniziare la successiva. Mentre un’istruzione è in corso di esecuzione, se ne potrebbe iniziare un’altra. Questo approccio si dice organizzazione a pipeline. Nell’ARM7 classicamente si adotta una pipeline a 3 livelli: Figura 3.2 Organizzazione pipeline L’organizzazione a pipeline deve essere realizzata all’atto della realizzazione hardware del dispositivo. Può dare buoni benefici, occorre però fare attenzione perché l’organizzazione a pipeline può portare a colli di bottiglia, se non accuratamente progettata. 3.3. Organizzazione della cache L’organizzazione della cache nei processori ARM ha seguito l’evoluzione dell’architettura della famiglia ARM, rispecchiando la continua ricerca di prestazioni che è la forza motrice dei progettisti di processori. La Tabella 3.1 mostra questa evoluzione. Il modello ARM7 utilizzava una cache unificata, mentre tutti i modelli seguenti utilizzano una cache per le istruzioni e una per i dati. Tutti i progetti ARM utilizzano cache set-associative, con diversi gradi di associatività e dimensioni di linea. Gli ARM con cache dotati di MMU (Memory Management Unit) utilizzano una cache logica nelle famiglie da ARM7 a ARM10, inclusi i processori Intel StrongARM e Intel Xscale. La famiglia ARM11 utilizza una cache fisica. La differenza tra cache logica e cache fisica è illustrata in figura 3.3. 16 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Tabella 3.1 Caratteristiche della cache di ARM Core Tipo di cache Dimensione della cache (KB) Dimensione della linea di cache (parole) Associatività Locazione ARM720T ARM920T ARM926EJ-S ARM1022E ARM1026EJ-S Intel StrongARM Intel Xscale ARM1136JF-S Unificata Separata Separata Separata Separata Separata 8 16/16 D/I 4-128/4-128 D/I 16/16 D/I 4-128/4-128 D/I 16/16 D/I 4 8 8 8 8 4 4 vie 64 vie 4 vie 64 vie 4 vie 32 vie Logica Logica Logica Logica Logica Logica Dimensione del buffer di scrittura (parole) 8 16 16 16 8 32 Separata Separata 32/32 D/I 4-64/4-64 D/I 8 8 32 vie 4 vie Logica Fisica 32 32 Un’interessante funzionalità dell’architettura ARM è l’utilizzo di un piccolo buffer di scrittura FIFO (First In First Out) per migliorare le prestazioni di scrittura in memoria. Il buffer di scrittura è interposto tra la cache e la memoria principale e consiste in un insieme di indirizzi e un insieme di dati. Il buffer è piccolo rispetto alla cache e può immagazzinare fino a quattro indirizzi. Tipicamente il buffer di scrittura è abilitato per tutta la memoria principale, anche se può essere selettivamente disabilitato a livello di pagina. La figura 3.4 mostra le relazioni tra buffer di scrittura, cache e memoria principale. Figura 3.4 Organizzazione della cache di ARM e del buffer di scrittura Figura 3.3 Cache fisica e logica Vediamo come funziona il buffer di scrittura. Quando il processore scrive in una zona abilitata all’utilizzo del buffer, il dato è posto nel buffer ad una velocità pari a quella del processore e il processore continua la sua esecuzione. La scrittura ha luogo quando il dato presente nella cache è ricopiato nella memoria principale. Il dato da scrivere viene trasferito dalla cache al buffer di scrittura. Il buffer di scrittura realizza quindi la scrittura esterna in parallelo. Se il buffer di scrittura è pieno (sia perché è stato raggiunto il massimo numero di parole nel buffer, sia perché non ci sono più posizioni per nuovi indirizzi) il processore viene bloccato finché non c’è spazio sufficiente nel buffer. Mentre vengono eseguite operazioni che non 17 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 coinvolgono scritture, il buffer di scrittura continua a scrivere sulla memoria principale fino a quando si svuota completamente. I dati scritti nel buffer di scrittura non sono disponibili per la lettura nella cache fino a quando non sono stati trasferiti dal buffer alla memoria centrale. Questa è la ragione principale per cui il buffer è così piccolo. Anche in questo modo, a meno che una grande porzione di programma esegua operazioni di scrittura, il buffer di scrittura riesce a migliorare le prestazioni. 3.4. Gestione della memoria ARM offre un’architettura di memoria virtuale versatile adattabile alle esigenze dei progettisti di sistemi embedded. 3.4.1. Organizzazione della memoria La figura 3.5 fornisce una visione d’insieme dell’hardware di gestione della memoria in ARM. Il dispositivo di traduzione della memoria virtuale utilizza uno o due livelli di tabelle per la traduzione da indirizzi virtuali a indirizzi fisici. Il buffer TLB (Translation Lookaside Buffer) è una cache di voci della tabella delle pagine recenti. Se una voce è disponibile nel buffer TLB l’indirizzo fisico per un’operazione di lettura o scrittura è mandato alla memoria principale direttamente dal TLB. I dati vengono scambiati tra la memoria principale e il processore attraverso la cache. Se si utilizza una organizzazione logica della cache (Figura 3.3a) il processore ARM, in caso di miss, passa l’indirizzo alla cache ma anche al TLB. Se si utilizza un’organizzazione fisica della cache (Figura 3.3b) tocca al TLB passare l’indirizzo fisico alla cache. Figura 3.5 Il sistema di memoria ARM. Le voci della tabella di traduzione includono anche i bit di controllo di accesso, che determinano se un dato processo può accadere a una data porzione di memoria. Se l’accesso viene negato, il dispositivo di controllo di accesso invia un segnale di insuccesso al processore ARM. 18 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 3.4.2. Tesi di Laurea di: Loredano Rapari matr. 1029262 Traduzione degli indirizzi di memoria virtuale Il processore ARM supporta l’accesso alla memoria basto su sezioni o su pagine: Supersezioni (opzionale): consistono in blocchi di memoria principale da 16 MB Sezioni: consistono in blocchi di memoria principale da 1 MB Pagine grandi: consistono in blocchi di memoria principale da 64 KB Pagine piccole: consistono in blocchi di memoria principale da 4 KB Il supporto di sezioni e supersezioni permette di indirizzare una grande porzione di memoria utilizzando un’unica voce nel TLB. Meccanismi aggiuntivi di controllo di accesso vengono estesi alle pagine piccole e sottopagine di 1 KB e dalle pagine grandi a sottopagine di 16 KB. La tabella di traduzione presente nella memoria principale ha due livelli: Tabella di primo livello: mantiene le traduzioni di sezioni e sottosezioni e i puntatori alla tabella di secondo livello Tabella di secondo livello: mantiene la traduzione di pagine piccole e grandi L’unità di gestione della memoria (MMU) traduce indirizzi virtuali generati dal processore in indirizzi fisici per l’accesso alla memoria principale; inoltre, ricava e controlla i permessi di accesso. La traduzione viene effettuata in seguito ad un miss di TLB e inizia da un fetch di primo livello. Un indirizzamento a sezione richiede soltanto fetch di primo livello, mentre un indirizzamento a pagine richiede anche fetch di secondo livello. Figura 3.6 Traduzione di indirizzi di memoria virtuale per pagine piccole in ARM. La figura 3.6 mostra il processo di traduzione di indirizzi di secondo livello per pagine piccole. È presente una tabella delle pagine di livello 1 (L1) con 4K entry di 32 bit. Ogni entry di L1 punta a 19 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 una tabella delle pagine di livello 2 (L2) con 255 entry di 32 bit. Ogni entry di L2 punta ad una pagina di 4 KB nella memoria principale. L’indirizzo virtuale di 32 bit è interpretato come segue. I 12 bit più significativi sono un indice nella tabella L1. I successivi 8 bit sono un indice nella tabella L2 appropriata. I primi 12 bit meno significativi indicano un byte della pagina appropriata in memoria centrale. Per le pagine grandi viene utilizzata una procedura di lookup a due pagine simile a questa. Per le sezioni e le supersezioni è richiesta la ricerca nella sola tabella di pagina L1. 3.4.3. Controllo dell’accesso In ogni entry sono presenti due bit chiamati AP che controllano l’accesso di un dato processo ad una regione di memoria. Un’area di memoria può essere marcata come non accessibile, accessibile in sola lettura o in lettura e scrittura. Inoltre l’area di memoria può essere designata per soli accessi privilegiati, riservata al sistema operativo e non disponibile per le applicazioni. ARM utilizza anche il concetto di dominio, una collezione di sezioni e/o pagine con permessi particolari di accesso. L’architettura ARM prevede 16 domini. L’impiego di domini permette a più processori di utilizzare la stessa tabella di traduzione e contemporaneamente mantenere alcune protezioni gli uni dagli altri. Ogni entry di tabella delle pagine e ogni entry TLB contengono un campo che specifica a quale dominio appartiene un entry. Un campo di 2 bit nel registro Domain Access Control controlla l’accesso a ogni dominio. Ogni campo permette di abilitare o disabilitare molto rapidamente l’accesso a un intero dominio in modo che intere aree di memoria possano essere trasferite dentro e fuori la memoria virtuale in maniera molto efficiente. Ci sono due tipi di accesso al dominio: Client: utenti dei domini (che eseguono programmi e accedono ai dati) che devono osservare i permessi di accesso alle singole sezioni e/o pagine che compongono il dominio Manager: controllano il comportamento del dominio (le pagine e le sezioni correnti nel dominio e l’accesso al dominio) ed evitano i permessi di accesso per le entry in tale dominio Un programma può essere un client di certi domini, un manager di altri e non avere accesso ai rimanenti. Ciò permette una protezione molto difficile della memoria per programmi che accedono a diverse risorse di memoria. 3.5. Tipi di dati di ARM L’ARM può trattare tipi di dato da 8 bit (byte), da 16 bit (mezza parola) e da 32 bit (parola). In genere, l’accesso alla mezza parola deve essere allineato alla mezza parola, mentre gli accessi di parola devono essere allineati alla parola. In caso di accesso non allineato, l’architettura prevede tre alternative: 20 Caso di deault: - L’indirizzo viene considerato troncato, i bit di indirizzo *1:0+ corrispondono a zero per gli accessi di parola e il bit di indirizzo [0] corrisponde a zero per gli accessi di mezza parola. - Le istruzioni ARM di caricamento della singola parola prevedono, dal punto di vista dell’architettura, di traslare a destra dei dati allineati alla parola uno, due o tre byte a seconda del valore dei due bit di indirizzo meno significativi, trasferiti da un indirizzo non allineato. Controllo di allineamento: se è definito un bit di controllo appropriato, un segnale indica un errore di allineamento dovuto a un tentativo di accesso non allineato. Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Accesso non allineato: in questo caso il processore utilizza uno o più accessi di memoria per generare il trasferimento richiesto di byte adiacenti, in modo trasparente al programmatore. Per tutti e tre i tipi di dati (byte, mezza parola e parola) è possibile un’interpretazione senza segno, in cui il valore rappresenta un intero senza segno, non negativo. I tre tipi di dato possono essere utilizzati per interi con segno in complemento a due. La maggior parte delle implementazioni per ARM non fornisce hardware in virgola mobile, a vantaggio di spazio e potenza. Se in tali processori dovesse rendersi necessaria un’aritmetica in virgola mobile, questa dovrà essere realizzata dal software. L’ARM può prevedere un coprocessore opzionale in virgola mobile per i tipi di dato in virgola mobile a precisione singola e doppia definiti nello standard IEEE 754. 3.6. Tipi di operazioni L’architettura ARM mette a disposizione un ampio repertorio di tipi di operazioni: Istruzioni di load e store: nell’architettura ARM unicamente le istruzioni di load e store accedono alle locazioni di memoria. Le istruzioni aritmetiche e logiche vengono eseguite sui registri e i valori immediati sono codificati nell’istruzione. Questa è una caratteristica della progettazione RISC. L’architettura ARM ha due tipi generici di istruzione che spostano il valore di un registro, o di due, da e verso la memoria: (1) carica o registra una parola di 32 bit oppure un byte a 8 bit senza segno e (2) carica o registra una mezza parola di 16 bit senza segno e carica ed estende il segno di una mezza parola a 16 bit oppure di un byte ad 8 bit. Istruzioni di salto: ARM supporta un’istruzione di salto condizionato in avanti o indietro fino a 32 MB. Dal momento che il program counter è uno dei registri generici (R15), si può ottenere un salto anche scrivendo un valore in R15. È possibile eseguire una chiamata di procedura tramite una variante dell’istruzione di salto standard. Oltre a eseguire un salto, l’istruzione BL, di salto con link (Branch with Link), scrive l’indirizzo dell’istruzione successiva al salto (indirizzo di ritorno) nel registro LR (R14). I salti vengono determinati da un campo di condizione a 4 bit nell’istruzione. Istruzioni di processamento dati: tale categoria include istruzioni logiche (AND, OR, XOR), la somma e la sottrazione, e istruzioni di verifica e di confronto. Istruzioni di moltiplicazione: le istruzioni di moltiplicazione di interi operano su parole e mezze parole e possono produrre risultati normali o lunghi: ad esempio, un’istruzione di moltiplicazione che utilizza due operandi a 32 bit e produce un risultato a 64 bit. Istruzioni parallele di somma e sottrazione: oltre alle normali istruzioni dei due tipi precedenti, c’è un insieme di istruzioni parallele di somma e sottrazione nelle quali parti degli operandi vengono elaborate in parallelo. Ad esempio, ADD16 somma le parti alte delle mezze parole di due registri per formare la parte alta della mezza parola del risultato e somma le parti basse delle mezze parole degli stessi due registri per formare la parte bassa della mezza parola del risultato. Queste istruzioni sono utili nelle applicazioni grafiche, come le istruzioni MMX della famiglia x86. Istruzioni di estensione: ci sono varie istruzioni per spacchettare i dati, che grazie al segno oppure allo zero possono estendere i byte in mezze parole o parole e le mezze parole in parole. Istruzioni di accesso al registro di stato: ARM offre la capacità di leggere, oltre che di scrivere, porzioni del registro di stato. 21 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 3.6.1. Tesi di Laurea di: Loredano Rapari matr. 1029262 Codici di condizione L’architettura ARM definisce quattro flag di condizione memorizzati nel registro di stato del programma: N, Z, C e V (Negative, Zero, Carry e oVerflow). I quattro flag citati costituiscono un codice di condizione in ARM. La tabella 3.2 mostra le combinazioni delle condizioni, previste per l’esecuzione condizionale. Due inconsueti aspetti dell’utilizzo dei codici di condizione in ARM sono: 1. Tutte le istruzioni, non solo quelle di salto condizionato, includono un campo codice di condizione. Quindi, virtualmente, tutte le istruzioni potrebbero essere eseguite in modalità condizionale. Ogni combinazione delle impostazioni di flag, fatta eccezione per 1110 e 1111, in un campo del codice di condizione dell’istruzione significa che quell’istruzione sarà eseguita solo se si verifica la condizione richiesta. 2. Tutte le istruzioni di elaborazione dati (aritmetiche e logiche) includono un bit S, quindi in caso di aggiornamento dell’istruzione la condizione genera un segnale. Tabella 3.2 Condizioni di ARM per l’esecuzione condizionale delle istruzioni Codice 0000 0001 0010 Simbolo EQ NE CS/HS Condizione da verificare Z=1 Z=0 C=1 0011 CC/LO C=0 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 MI PL VS VC HI LS GE LT GT LE AL - N=1 N=0 V=1 V=0 C = 1 AND Z = 0 C = 0 OR Z = 1 N = V [(N = 1 AND V = 1) OR (N = 0 AND V = 0)] N ≠ V [(N = 1 AND V = 0) OR (N = 0 AND V = 1)] (Z = 0) AND (N = V) (Z = 1) OR (N ≠ V) - Commenti Uguale Diverso Imposta riporto/senza segno più alto o uguale Cancella riporto/senza segno più basso Meno/negativo Più/positivo oppure zero Overflow No overflow Senza segno più alto Senza segno più basso oppure uguale Con segno maggiore o uguale Con segno minore Con segno maggiore Con segno minore o uguale Sempre (non condizionato) Questa istruzione può essere eseguita solo in modalità non condizionata L’utilizzo dell’esecuzione condizionale e dell’impostazione condizionale per i flag di condizione è di aiuto alla progettazione di programmi più corti, che utilizzano meno memoria. D’altro canto, tutte le istruzioni includono 4 bit per il codice condizionale. Si ha quindi un compromesso con il fatto che non tutti i bit delle istruzioni a 32 bit sono utilizzabili per codice operativo e operandi. Tale compromesso può essere considerato ragionevole, proprio perché ARM è un’architettura RISC che si affida pesantemente all’indirizzamento dei registri. 22 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 3.7. Modi di indirizzamento di ARM A differenza delle CISC, le macchine RISC utilizzano in genere modi di indirizzamento semplici e relativamente diretti. L’architettura ARM si discosta un po’ da questa tradizione, offrendo un insieme piuttosto ricco di modi di indirizzamento. Tali modi vengono classificati in maniera più conveniente in relazione al tipo di istruzione. 3.7.1. Indirizzamento load/store Le istruzioni di load e store sono le uniche che fanno riferimento alla memoria, in modo indiretto, tramite un registro base sommato a uno spiazzamento. Figura 3.7 Metodi di indicizzazione di ARM 23 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Le alternative di indicizzazione sono le seguenti tre (Figura 3.7): Spiazzamento (offset). Questo indirizzamento non prevede indicizzazione. Lo spiazzamento viene sommato o sottratto al valore del registro base per formare l’indirizzo di memoria. La figura 3.7° mostra un esempio di questo metodo con l’istruzione STRB r0, *r1, #12+, che è l’istruzione di memorizzazione di un byte. In questo caso l’indirizzo di base è nel registro r1 e lo spiazzamento è il valore immediato 12. L’indirizzo risultante (base più spiazzamento) è la locazione di memoria in cui registrare il byte meno significativo di r0. Preindicizzazione (preindex). L’indirizzo di memoria è formato come nel caso precedente, ma viene riscritto anche nel registro base. In altre parole, il valore del registro base viene incrementato o decrementato del valore dello spiazzamento. La figura 3.7b illustra questo metodo con l’istruzione STRB r0, *r1, #12+!. Il punto esclamativo sta proprio a indicare la preindicizzazione. Postindicizzazione (postindex). L’indirizzo di memoria è il valore del registro base. Uno spiazzamento viene aggiunto o sottratto al valore del registro base. La figura 3.7c illustra questo metodo con l’istruzione STRB r0, *r1+, #12. Si noti come ciò a cui ARM fa riferimento come registro base si comporta poi da registro indice per la preindicizzazione e la postindicizzazione. Il valore di spiazzamento può essere sia un valore immediato contenuto nell’istruzione sia il valore di un altro registro. Se il valore di spiazzamento è un registro, è disponibile un’altra caratteristica utile: l’indirizzamento di registro scalare. Il valore nel registro di spiazzamento viene scalato da uno degli operatori di shift: shift logico a sinistra, shift logico a destra, shift aritmetico a destra, rotazione verso destra oppure rotazione estesa verso destra (che include il bit di riporto nella rotazione). L’entità di uno shift è specificata come valore immediato nell’istruzione. 3.7.2. Indirizzamento di istruzioni di processamento dati Queste istruzioni possono utilizzare l’indirizzamento con registro o quello immediato. Nel primo caso, il valore di uno degli operandi può essere scalato utilizzando uno degli operatori di shift definiti nel paragrafo precedente. 3.7.3. Istruzioni di salto Per queste istruzioni esiste solo l’indirizzamento immediato. L’istruzione di salto contiene un valore a 24 bit. Per il calcolo degli indirizzi il valore viene spostato a sinistra di 2 bit, in modo che l’indirizzo sia allineato come una parola. In questo modo, la gamma degli indirizzi effettivi raggiungibili si estende a ±32 MB dal program counter. 3.7.4. Indirizzamento load/store multiplo Le istruzioni di caricamento multiplo portano dati dalla memoria a un sottoinsieme dei registri a uso generale (o a tutti). Le istruzioni di store multiplo memorizzano i dati di un sottoinsieme dei registri a uso generale (o di tutti). La lista dei registri da caricare e salvare viene specificata in un campo a 16 bit dell’istruzione dove ogni bit corrisponde a uno dei 16 registri. Queste modalità di indirizzamento producono una sequenza di indirizzi di memoria. Il registro numericamente più basso viene salvato all’indirizzo di memoria più basso, mentre il registro numericamente più alto verrà salvato all’indirizzo più alto. I quattro tipi di indirizzamento utilizzati, rappresentati nella figura 3.8, sono: incremento successivo, incremento antecedente, decremento successivo e decremento antecedente. Un registro base specifica un indirizzo di memoria principale da dove i valori vengono prelevati oppure nei quali vengono salvati, in locazioni di parola ascendenti 24 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 (incremento) oppure discendenti (decremento). Tale incremento, o decremento, ha inizio prima oppure dopo il primo accesso alla memoria. Figura 3.8 Indirizzamento load/store multiplo in ARM Queste istruzioni sono utili per caricamenti o salvataggi in blocco, per le operazioni sulla pila e per le sequenze di uscita dalle procedure. 3.8. Il processore ARM ARM è essenzialmente un sistema RISC con le seguenti caratteristiche degne di nota. Una piccola schiera di registri uniformi, più di quelli che ci sono in alcuni sistemi RISC, ma meno di quelli che si trovano in molti sistemi CISC. Un modello load/store di elaborazione dati nel quale le istruzioni lavorano sugli operandi nei registri e non direttamente in memoria. Tutti i dati devono essere caricati nei registri prima di poter essere elaborati. Il risultato può essere utilizzato per ulteriori operazioni oppure essere salvato in memoria. Un set standard di istruzioni a 32 bit e un set di istruzioni Thumb a 16 bit. Per rendere ogni istruzione di elaborazione dati più flessibile è possibile preprocessare uno dei registri sorgente con uno shift o una rotazione. Per utilizzare in maniera più efficiente questa funzionalità esiste un’unità aritmetico logica (ALU) separata e un’unità shifter. Pochi modi di indirizzamento, determinati dai registri e dai campi dell’istruzione. Non sono utilizzati indirizzamenti indiretti o indicizzati che coinvolgono valori in memoria. Per migliorare l’esecuzione dei cicli nei programmi sono utilizzate modalità di auto incremento e auto decremento dell’indirizzo. L’esecuzione condizionale delle istruzioni riduce il numero delle istruzioni di salto condizionato, migliorando quindi l’efficienza della pipeline, perché gli svuotamenti della pipeline vengono ridotti. 3.8.1. Organizzazione del processore L’organizzazione del processore ARM varia notevolmente da un’implementazione all’altra, in particolare quando è basata su diverse versioni dell’architettura ARM. È tuttavia utile presentare una versione generica e semplificata dell’organizzazione, illustrata nella figura 3.9. Le frecce indicano il flusso dei dati. Ogni riquadro rappresenta un’unità funzionale hardware o un’unità di memorizzazione. 25 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 I dati vengono scambiati tra il processore e la memoria esterna attraverso il bus dati. Il valore trasferito può essere sia un dato (istruzione di load/store) sia il fetch di un’istruzione. Le istruzioni prelevate passano attraverso un decodificatore prima di essere eseguite, sotto il controllo di un’unità apposita. Quest’ultima include la pipeline logica e fornisce i segnali di controllo (non mostrati nella figura) a tutte le unità hardware del processore. I dati vengono messi nel banco dei registri (a 32 bit). I byte e le mezze parole trattate come numeri in complemento a due sono estesi a 32 bit. Le istruzioni di elaborazione dei dati di ARM hanno tipicamente due registri sorgente, Rn e Rm, e un registro destinazione (o risultato), Rd. I valori dei registri sorgente vengono dati in pasto alla ALU o a un’unità separata per le moltiplicazioni che usa registri aggiuntivi per l’accumulo di risultati parziali. Il processore ARM incorpora anche un’unità hardware che può shiftare o ruotare il valore di Rm prima che venga immesso nella ALU. Quest’ultima operazione viene eseguita nei limiti del tempo di esecuzione dell’istruzione e aumenta la potenza e la flessibilità di molte operazioni di processamento dati. Figura 3.9 Organizzazione semplificata di ARM 26 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 3.8.2. Tesi di Laurea di: Loredano Rapari matr. 1029262 Modi del processore È abbastanza comune che un processore supporti un numero ridotto di modi di utilizzo. Ad esempio, molti sistemi operativi utilizzano soltanto due modi: un modo utente e un modo kernel, dove quest’ultimo è usato per l’esecuzione di software di sistema dotato di privilegi. Contrariamente a quanto detto, la flessibilità dell’architettura ARM permette ai sistemi operativi di utilizzare varie politiche di protezione. L’architettura ARM supporta sette modi di esecuzione. La maggior parte dei programmi applicativi viene eseguita in modo utente (user mode). In questa modalità il programma in esecuzione non può accedere alle risorse protette del sistema e non può cambiare il modo, se non sollevando un’eccezione. I restanti sei modi di utilizzo sono detti privilegiati. Questi modi sono utilizzati per eseguire software di sistema. I principali vantaggi nel definire così tanti modi privilegiati differenti sono due: 1. il sistema operativo può adattare l’utilizzo del software di sistema a svariate circostanze; 2. alcuni registri vengono dedicati all’utilizzo in ogni modo privilegiato, permettendo così rapidi cambi di contesto. I modi eccezione hanno accesso completo alle risorse di sistema e possono cambiare modo liberamente. Cinque dei sei modi privilegiati sono conosciuti come modi eccezione. È possibile entrare in queste modalità d’uso quando si verifica una specifica eccezione. Ognuna di queste modalità ha dei registri dedicati che sostituiscono alcuni dei registri del modo utente e che sono utilizzati per evitare di compromettere informazioni di stato del modo utente quando si verifica un’eccezione. I modi eccezione sono i seguenti. Modo supervisore (supervisor mode): il modo in cui opera di solito il sistema operativo. Si entra in questo modo quando il processore incontra un’istruzione di interruzione software. Le interruzioni software sono un modo standard per invocare un servizio del sistema operativo sui processori ARM. Modo abort (abort mode): vi si entra in risposta a errori di memoria. Modo indefinito (undefined mode): vi si entra quando il processore tenta di eseguire un’istruzione che non è supportata né dall’unità principale intera né da uno dei coprocessori. Modo interrupt veloce (fast interrupt mode): vi si entra ogni volta che il processore riceve un segnale di interrupt dalla sorgente designata di interrupt veloce. Un interrupt veloce non può essere interrotto, ma può interrompere un normale interrupt. Modo interrupt: vi si entra quando il processore riceve un segnale di interrupt da una sorgente di interrupt (diversa dalla sorgente di interrupt veloce). Un interrupt può essere interrotto soltanto da un interrupt veloce. Il modo privilegiato che resta è il modo sistema (system mode). Questo modo utilizza gli stessi registri del modo utente e non è accessibile tramite alcuna eccezione. Il modo sistema è utilizzato per eseguire alcuni task privilegiati del sistema operativo. I task nel modo sistema possono essere interrotti da ognuno dei cinque modi eccezione. 3.8.3. Organizzazione dei registri La figura 3.10 illustra i registri ARM visibili all’utente. Il processore ARM ha 37 registri da 32 bit in torale, classificati come segue: 31 registri definiti nel manuale come registri a uso generale, anche se alcuni, come il program counter, hanno compiti specifici; 27 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 sei registri di stato del programma. I registri sono sistemati in banchi parzialmente sovrapposti. Il modo del processore determina quale banco è disponibile. Sono sempre disponibili 16 registri numerati e uno o due registri di stato del programma, per un totale di 17 o 18 registri visibili al software. La figura 3.10 va letta come segue: i registri da R0 a R7, il registro R15 (il program counter) e il registro di stato corrente del programma (CPSR) sono visibili e condivisi da tutti i modi; i registri da R8 a R12 sono condivisi da tutti i modi eccetto quello di interrupt veloce, che ha i suoi registri dedicati da R8_fiq a R12_fiq; tutti i modi eccezione hanno la propria versione dei registri R13 e R14; tutti i modi eccezione hanno un registro di stato del programma salvato (CPSR). Figura 3.10 Organizzazione dei registri in ARM 3.8.3.1. Registri a uso generale Il registro R13 è normalmente usato come Stack Pointer ed è anche chiamato SP. Poiché ogni modo eccezione ha il suo registro R13, ogni modo eccezione può avere il suo stack dedicato. Il registro R14 è noto come registro link (LR) e viene utilizzato per mantenere gli indirizzi di ritorno da procedure e dal modo eccezione. Il registro R15 è il Program Counter (PC). 28 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 3.8.3.2. Tesi di Laurea di: Loredano Rapari matr. 1029262 Registri di stato del programma Il registro CPSR è accessibile in tutti i modi del processore. Ogni modo del processore ha il suo registro SPSR dedicato, utilizzato per preservare il valore di CPSR quando si verifica l’eccezione associata. I 16 bit più significativi di CPSR contengono dei flag visibili in modo utente, utilizzabili per condizionare il funzionamento del programma (Figura 3.11). I flag sono i seguenti. Flag di codice di condizione: i flag N, Z, C e V visti precedentemente. Flag Q: usato per indicare il verificarsi di un overflow e/o la saturazione in alcune istruzioni SIMD-oriented. Bit J: indica l’utilizzo di speciali istruzioni a 8 bit, dette istruzioni Jazelle. Bit GE [3:0]: le istruzioni SIMD utilizzano i bit [19:16] come flag di maggiore o uguale (GE) per byte singoli o mezze parole del risultato. I 16 bit meno significativi di CPSR contengono flag di controllo di sistema che possono essere modificati soltanto quando il processore è in modo privilegiato. I campi sono i seguenti. Bit E: controlla il tipo di endian per i dati di load e store; viene ignorato per il fetch delle istruzioni. Bit di disabilitazione degli interrupt: il bit A, quando vale 1, disabilita gli abort per dati imprecisi; il bit I, quando vale 1, disabilita gli interrupt IRQ; il bit F, quando vale 1, disabilita gli interrupt FIQ. Bit T: indica se le istruzione devono essere interpretate come normali istruzioni o come istruzioni Thumb. Bit di modo: indicano il modo del processore. 3.8.4. Gestione degli Interrupt Come ogni processore il processore ARM possiede una funzione che gli permette di interrompere il programma in esecuzione per gestire condizioni di eccezione. Le eccezioni vengono generate da sorgenti interne o esterne per consentire al precessore la gestione di un evento. Lo stato del processore un attimo prima che si occupi dell’eccezione viene di norma preservato in modo che l’esecuzione del programma originale possa riprendere una volta che la routine di gestione dell’eccezione è completata. È possibile che si presentino più eccezioni contemporaneamente. L’architettura ARM ne supporta sette tipi. La tabella 3.3 elenca i tipi di eccezione e i modi di processore che vengono utilizzati per affrontare questi tipi. Quando si verifica un’eccezione, viene forzata l’esecuzione a partire da un indirizzo di memoria fissato dipendente dal tipo di eccezione. Questi indirizzi fissi sono chiamati vettore di eccezione. Se ci sono più interruzioni in attesa, queste vengono gestite in ordine di priorità. La tabella 3.3 elenca le eccezioni in ordine di priorità, dalla più alta alla più bassa. Quando si verifica un’eccezione il processore blocca l’esecuzione dell’istruzione che segue quella corrente. Lo stato del processore viene salvato nel registro SPSR corrispondente al tipo di eccezione, in modo che l’esecuzione del programma originale possa riprendere una volta che la routine di gestione dell’eccezione è completata. L’indirizzo dell’istruzione che il processore stava per eseguire viene messo nel registro link del modo di processore appropriato. Per il ritorno dopo la gestione dell’eccezione il registro SPSR viene spostato nel registro CPSR e il contenuto di R14 viene trasferito nel PC. 29 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Tabella 3.3 Vettori di interrupt ARM Tipo di eccezione Reset Abort di dati Modo Indirizzo normale di entrata Supervisore 0x00000000 Abort 0x00000010 FIQ (Interrupt veloce) FIQ 0x0000001C IRQ (Interrupt) IRQ 0x00000018 Abort di prefetch Abort 0x0000000C Istruzioni indefinite Indefinito 0x00000004 Interrupt software Supervisore 0x00000008 30 Descrizione Si verifica quando il sistema viene inizializzato. Si verifica quando si accede ad un indirizzo di memoria non valido, come nei casi in cui l’indirizzo fisico di memoria non esiste o non si hanno i necessari permessi per accedere all’indirizzo. Si verifica quando un dispositivo esterno attiva il pin FIQ del processore. Un interrupt non può essere interrotto se non da un interrupt veloce. FIQ è progettato per supportare trasferimento dati e applicazioni su canali e ha un numero di registri privati sufficiente a eliminare il bisogno di salvare i registri, permettendo in questo modo di minimizzare l’overhead del cambio di contesto. L’interrupt veloce non può essere interrotto. Si verifica quando un dispositivo esterno attiva il pin IRQ del processore. Un interrupt può essere interrotto soltanto da un interrupt veloce. Si verifica quando un tentativo di fetch di un istruzione genera un errore di memoria. L’eccezione viene sollevata quando l’istruzione entra nello stadio di esecuzione della pipeline. Si verifica quando un’istruzione che non fa parte del set di istruzioni raggiunge lo stadio di esecuzione della pipeline. È generalmente utilizzata per permettere a programmi in modalità utente di invocare il sistema operativo. Il programma utente esegue un’interruzione SWI con un argomento che identifica la funzione che l’utente vuole realizzare. Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 4. Marvell Kirkwood 88F6281 Come processore di test per provare i programmi compilati con le istruzioni Thumb, è stato usato un dispositivo presente in laboratorio che monta un processore con architettura ARM. Il dispositivo è uno Sheevaplug, cioè un plug computer progettato per consentire funzionalità di calcolo standard nel minor spazio possibile. Un plug computer è un piccolo server per l’utilizzo in casa o in ufficio. Comparati al PC, i plug computer hanno costi minori, minori consumi, spesso non hanno la scheda video e sono pensati per stare accesi continuamente. Infatti i plug computer sono spesso racchiusi nei trasformatori stessi che convertono la corrente, il termine “plug” si riferisce al fatto che appaiono della stessa forma dei dispositivi “plug and play”. Il plug computer disponibile in laboratorio monta il processore Marvell Kirkwood aka Feroceon 88F6281 basato su architettura ARMv5TE 4.1. Caratteristiche della scheda Nella tabella 4.1 sono elencate le caratteristiche della scheda. Tabella 4.1 Caratteristiche del plug computer Caratteristiche Forma compatta del prodotto finale Piattaforma Open Source Alte prestazioni a bassi consumi Processore di classe GHz 4.1.1. Benefici Adatto per test e prove iniziali Riduzione dei tempi di produzione Disponibile a basso costo per ogni sviluppatore interessato Disponibili diverse distribuzioni Linux Supporto della Community Ideale per applicazioni sempre attive Facilità di porting del software senza modifiche Esegue più applicazioni contemporaneamente Risposte veloci alle applicazioni interattive Accesso rapido ai dispositivi di memoria connessi via USB 2.0 Componenti di sistema Sheeva CPU Core - Velocità di clock 1.2 GHz Cache L1: 16 KB istruzioni + 16 KB dati Cache L2: 256 KB Memoria - Ram: DDR2 400 MHz, bus 16 bit, 512 MB Rom: NAND Flash Controller, bus 8 bit, 512 MB, boot diretto Alimentazione - Input: 100-240 V AC/50-60 Hz 20 W Max. Output: 5 V DC/3.0 A Max. Interfaccia di sviluppo 31 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb - Tavola di sviluppo del sistema Interfacce JTAG e Console via USB Espansione SDIO Supporto JTAG OpenOCD via USB Certificati UL/CE/FCC I/O - 1 x Gigabit Ethernet 1 x USB 2.0 collegamento dispositivi di memorizzazione 1 x USB 2.0 collegamento a PC per sviluppo AC/DC 5 V In 4.1.2. Schema a blocchi dell’ hardware Figura 4.1 Schema a blocchi dell’hardware 32 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5. Set di Istruzioni Thumb (Manuale Parte 1) In questo capitolo si introduce il set di istruzioni Thumb e si descrive come il Thumb usa il Modello Programmatori ARM. Il capitolo contiene le seguenti sezioni: Introduzione al Thumb Instruction Set Codifica del Set istruzioni Istruzioni di salto Istruzioni Data-processing Istruzioni Load and Store Register Istruzioni Load and Store Multiple Istruzioni per la generazione di eccezioni Spazio indefinito delle istruzioni 33 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5.1. Introduzione al set di istruzioni Thumb Il set delle istruzioni Thumb è un subset ricodificato del set di istruzioni ARM. Il Thumb è pensato per aumentare le performance delle implementazioni ARM che usano un bus dati a 16-bit o anche più piccolo e per permettere una densità di codice migliore di quella fornita dal set di istruzioni ARM. La variante T dell’architettura ARMv5 incorpora entrambi i set di istruzioni, sia quello ARM a 32-bit che quello Thumb a 16-bit. Ogni istruzione Thumb è codificata in 16 bits. Il supporto al Thumb è obbligatorio in ARMv6. Il Thumb non altera il modello basilare della programmazione dell’architettura ARM. Presenta solamente un accesso limitato a questo modello. Tutte le istruzioni data-processing del Thumb operano su valori a 32-bit, e indirizzi a 32-bit sono prodotti sia dalle istruzioni data-processing sia dal fetch dell’istruzione. Quando il processore sta eseguendo le istruzioni Thumb, sono disponibili 8 registri generici, da R0 a R7, i quali sono gli stessi registri fisici da R0 a R7 di quando esegue le istruzioni ARM. Alcune istruzioni Thumb accedono anche al Program Counter (in ARM è il registro 15), al Link Register (in ARM è il registro 14) e allo Stack Pointer (in ARM è il registro 13). Le altre istruzioni permettono un accesso limitato ai registri ARM da 8 a 15, i quali sono detti high registers. Quando R15 viene letto, il bit[0] è zero e i bits[31:1] contengono il PC. Quando R15 viene scritto, il bit[0] viene ignorato e i bits[31:1] vengono scritti nel PC. A seconda di come è usato, il valore del PC o è l’indirizzo dell’istruzione più 4 oppure è sconosciuto. L’esecuzione in Thumb è “flaggata” dal bit T (bit*5+) nel registro CSPR (Current State Program Register): T=0 Nella fase di fetch vengono prelevate istruzioni a 32-bit (il PC viene incrementato di 4) e sono eseguite come istruzioni ARM. T=1 Nella fase di fetch vengono prelevate istruzioni a 16-bit (il PC viene incrementato di 2) e sono eseguite come istruzioni Thumb. In ARMv6 le istruzioni Thumb forniscono un accesso limitato al CPSR con l’istruzione CPS. Non c’è un accesso diretto ai registri SPRS. Versioni precedenti non forniscono un accesso diretto al CPSR mentre nel set ARM le istruzioni MSR ed MRS lo permettono. 5.1.1. Attivare lo stato Thumb L’esecuzione Thumb è normalmente attivata dall’esecuzione dell’istruzione ARM BX (Branch and Exchange). Questa istruzione salta ad un indirizzo memorizzato in un registro generico, e se il bit*0+ di questo registro è 1, l’esecuzione Thumb parte dall’istruzione puntata dall’indirizzo contenuto nel registro. Se il bit*0+ è 0, continua l’esecuzione ARM dall’istruzione puntata dall’indirizzo contenuto nel registro. Dalla versione ARMv5T le istruzioni BLX e LDR/LDM che caricano il PC possono essere usate in modo simile. L’esecuzione Thumb può anche essere iniziata settando il bit T del registro SPSR ed eseguendo un istruzione ARM che ripristina il CPSR dal SPSR. Questo permette al sistema operativo di rieseguire un processo indipendentemente dal fatto che questo stia eseguendo un codice Thumb oppure ARM. Il risultato è imprevedibile se il bit T viene alterato direttamente scrivendo sul CPSR. 34 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5.1.2. Eccezioni Le eccezioni generate durante l’esecuzione Thumb passano all’esecuzione ARM prima di eseguire il gestore delle eccezioni (la prima istruzione del quale si trova nel vettore hardware). Lo stato del bit T è mantenuto nel SPSR, e il registro LR (Link Register, R14) della modalità eccezione è settato in modo che l’istruzione di ritorno all’esecuzione normale funzioni correttamente, questo accade sempre quando si verifica un’eccezione, non importa che l’esecuzione sia ARM o Thumb. La tabella A6-1 elenca i valori del registro LR del modo Eccezione per le eccezioni generate durante l’esecuzione Thumb. Tabella 5.1 Istruzioni di ritorno dalle Eccezioni Eccezione Valore di LR del modo Eccezione Istruzione di ritorno Reset Valore IMPREVEDIBILE - Undefined Indirizzo dell’istruzione Undefined + 2 MOVS PC, R14 SWI Indirizzo dell’istruzione SWI + 2 MOVS PC, R14 Prefetch Abort Indirizzo dell’istruzione Prefetch Abort + 4 SUBS PC, R14, #4 Data Abort Indirizzo dell’istruzione che ha generato l’errore +8 SUBS PC, R14, #8 IRQ Indirizzo dell’istruzione successiva da eseguire SUBS PC, R14, #4 FIQ Indirizzo dell’istruzione successiva da eseguire SUBS PC, R14, #4 --------------- Note ------------------------Per ogni eccezione, l’istruzione di ritorno indicate dalla tabella A6-1 è la stessa istruzione richiesta se l’esecuzione avvenisse durante l’esecuzione ARM. Comunque i seguenti due tipi di eccezioni hanno un metodo di ritorno secondario, per il quale sono necessarie diverse istruzioni di ritorno a seconda che l’eccezione avvenga durante l’esecuzione ARM oppure Thumb: Per l’eccezione Data Abort, il metodo di ritorno principale causa la ripresa dell’esecuzione proprio dall’istruzione che ha generato l’eccezione, la quale viene rieseguita. È anche possibile ritornare all’istruzione successiva a quella che ha generato l’eccezione, usando l’istruzione SUBS PC, R14, #4. Se questo tipo di ritorno è richiesto per un Data Abort causato da un’istruzione Thumb, si usa SUBS PC, R14, #6 come istruzione di ritorno. Per l’eccezione Undefined, il metodo principale di ritorno causa la ripresa dell’esecuzione dall’istruzione successiva a quella che ha generato l’eccezione. È anche possibile ritornare all’istruzione stesa che ha generato l’eccezione usando SUBS PC, R14, #4. Se questo tipo di ritorno è richiesto per un Undefined causato da un’istruzione Thumb si usa SUBS PC, R14, #2. Comunque, l’uso principale di questo tipo di ritorno è per alcuni tipi di istruzioni coprocessore, e siccome il set di istruzioni Thumb non contiene alcuna istruzione coprocessore, è improbabile necessitare di questo metodo secondario di ritorno per istruzioni Thumb. Quando sono usati questi metodi secondari di ritorno, il codice che gestisce le eccezioni deve testare il bit T del registro SPSR per determinare quale delle due istruzioni di ritorno deve usare. ----------------------------------------------35 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5.2. Codifica del set istruzioni Nella figura 5.1 è riportata la codifica del set di istruzioni Thumb. Figura 5.1 Panorama della codifica del set di istruzioni Thumb 1. Il campo opc non può essere 11 in questa riga. Altre righe trattano il caso in cui il campo opc è 11. 2. Il campo cond non può essere 1110 o 1111 in questa riga. Altre righe trattano il caso in cui il campo cond è 1110 o 1111. 3. La forma con L = 1 è IMPREVEDIBILE prima della versione ARMv5T. 4. Questa è un’istruzione indefinita prima di ARMv5T. 36 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 5.2.1. Tesi di Laurea di: Loredano Rapari matr. 1029262 Istruzioni varie La figura A6-2 elenca le istruzioni miste Figura 5.2 Istruzioni varie Thumb 1. Era un’istruzione indefinita prima di ARMv5. 2. Erano istruzioni indefinite prima di ARMv6. --------------- Note ------------------------Ogni istruzione con i bits[15:12] = 1011, e che non è illustrata in figura A6-2 è un’istruzione indefinita. ----------------------------------------------- 37 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5.3. Istruzioni di salto Il Thumb supporta sei tipi di istruzioni di salto: un salto condizionato che permette salti in avanti e all’indietro fino a 256 bytes un salto incondizionato che permette salti in avanti o all’indietro fino a 2 KB un salto con link (chiamata a una funzione) è supportato con una coppia di istruzioni che permettono salti in avanti e all’indietro fino a 4 MB (-222 <= offset <= +222 - 2) un salto con link e scambio usa una coppia di istruzioni, simili alle precedenti, ma in più passa all’esecuzione di codice ARM un’istruzione si salto e scambio salta ad un indirizzo in un registro e opzionalmente salta all’esecuzione di codice ARM una seconda forma di istruzione di salto con link e scambio esegue una chiamata ad una subroutine il cui indirizzo è in un registro e opzionalmente passa all’esecuzione di codice ARM La codifica di queste istruzioni è illustrata di seguito. 5.3.1. B Salto condizionato <condizione> <indirizzo di destinazione> 5.3.2. Salto incondizionato B <indirizzo di destinazione> BL <indirizzo di destinazione> ; Produce due istruzioni da 16-bit BLX <indirizzo di destinazione> ; Produce due istruzioni da 16-bit 5.3.3. BX <Rm> BLX <Rm> 38 Salto con scambio Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5.4. Istruzioni Data-Processing Le istruzioni di processamento dei dati del set Thumb, sono un sottoinsieme di quelle del set ARM. Sono divise in due gruppi: il primo gruppo può operare solo sui registri bassi, r0-r7, il secondo può operare sui registri alti, r8-r15, oppure su entrambi. 5.4.1. Istruzioni che operano sui registri bassi Le istruzioni che operano sui registri bassi sono mostrate in Tabella A6-2. Alcune di queste istruzioni appaiono anche nella lista di istruzioni che operano sui registri alti. Quando operano sui registri bassi, tutte le istruzioni in questa tabella, eccetto CPY, modificano i flags di stato. Tabella 5.2 Istruzioni Data-Processing che operano sui registri bassi 39 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Tabella 5.2 Istruzioni Data-Processing che operano sui registri bassi (continua) Per esempio: ADD SUB ADD ADD NEG AND EOR CMP CMP MOV 40 R0, R6, R0, R1, R3, R2, R1, R2, R7, R0, R4, R7 R1, R2 #255 R4, #4 R1 R5 R6 R3 #100 #200 ; ; ; ; ; ; ; ; ; ; R0 = R4 + R7 R6 = R1 – R2 R0 = R0 + 255 R1 = R4 + 4 R3 = 0 – R1 R2 = R2 AND R5 R1 = R1 EOR R6 aggiorna il flag dopo R2 – R3 aggiorna il flag dopo R7 – 100 R0 = 200 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 5.4.2. Tesi di Laurea di: Loredano Rapari matr. 1029262 Istruzioni che operano sui registri alti Ci sono otto tipi di istruzioni data-processing che operano sui registri ARM dall’8 al 14 e sul PC come mostrato nella tabella A6-3. A parte cmp, le istruzioni nella tabella non cambiano i flag di stato. Tabella 5.3 Istruzioni Data-Processing che operano sui registri alti Per esempio: MOV ADD MOV CMP SUB ADD ADD ADD R0, R10, PC, R10, SP, SP, R2, R0, R12 R1 LR R11 #12 #16 SP, PC, ; ; ; ; ; ; #20 ; #500 ; R0 = R12 R10 = R10 + R1 PC = R14 aggiorna i flag dopo R10 – R11 incrementa lo stack pointer di 12 bytes decrementa lo stack pointer di 16 bytes R2 = SP + 20 R0 = PC + 500 41 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 5.4.3. Formati Le istruzioni data-processing usano i seguenti otto formati: Formato 1 Formato 2 Formato 3 Formato 4 Formato 5 Formato 6 42 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Formato 7 Formato 8 43 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5.5. Istruzioni Load and Store Register Il Thumb supporta otto tipi di istruzioni di lettura e scrittura sui registri. Sono disponibili due modi di indirizzamento di base. Questi permettono la lettura e la scrittura di parole (4 Bytes), mezze parole (2 Bytes) e bytes (1 Byte), e anche di mezze parole e bytes con segno: registro più registro registro più 5-bit immediato (non disponibile per le mezze parole e i bytes con segno) Se viene usato un offset immediato, viene scalato di 4 per l’accesso ad una parola e di 2 per l’accesso ad una mezza parola. In più, tre istruzioni speciali permettono: alle parole di essere caricate usando il PC come base con un offset immediato di 1 KB alle parole di essere caricate e salvate con lo stack pointer (R13) come base e un offset immediato di 1 KB 5.5.1. Formati Le istruzioni di lettura e scrittura sui registri hanno i seguenti formati: Formato 1 Formato 2 Formato 3 Formato 4 44 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Per esempio: LDR LDR STR STRB STRH LDRH LDRB LDR LDR STR R4, R4, R0, R1, R4, R3, R2, R6, R5, R4, [R2, [R2, [R7, [R5, [R2, [R6, [R1, [PC, [SP, [SP, #4] R1] #0x7C] #31] R3] R5] #5] #0x3FC] #64] #0x260] ; ; ; ; ; ; ; ; ; ; Carica la parola in R4 dall’indirizzo R2 + 4 Carica la parola in R4 dall’indirizzo R2 + R1 Scrive la parola da R0 all’indirizzo R7 + 124 Scrive il byte da R1 all’indirizzo R5 + 31 Scrive una mezza parola da R4 a R2 + R3 Carica una mezza parola in R3 da R6 + R5 Carica un byte in R2 da R1 + 5 Carica R6 da PC + 0x3FC Carica R5 da SP + 64 Carica R5 da SP + 0x260 45 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5.6. Istruzioni Load and Store Multiple Il Thumb supporta quattro tipi di istruzioni di lettura e scrittura multipla: Due istruzioni, LDMIA e STMIA, sono progettate per supportare la copia di blocchi. Hanno un indirizzamento con post-incremento fisso da un registro di base. Le altre due istruzioni, PUSH e POP, hanno anche loro un modo di indirizzamento fisso. Implementano uno stack a cascata e lo stack pointer (R13) è usato come base. Tutte e quattro le istruzioni aggiornano il registro base dopo il trasferimento e tutte possono trasferire alcuni o tutti gli 8 registri. PUSH può anche impilare l’indirizzo di ritorno, e POP può caricare il PC. 5.6.1. Formati Le istruzioni di lettura e scrittura multipla hanno I seguenti formati: Formato 1 Formato 2 5.6.2. LDMIA STMIA Esempi R7!, R0!, {R0-R3,R5} {R3, R4, R5} ; ; Carica R0 in R3-R5 da R7, aggiunge 20 a R7 Scrive R3-R5 in R0, aggiunge 12 in R0 ; ; ; ; ; push nello stack (R13) R0-R7 e l’indirizzo di ritorno al codice del corpo della funzione ricarica R0-R7 dallo stack e il PC, e ritorna function PUSH {R0-R7, LR} POP {R0-R7, PC} … … 46 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5.7. Istruzioni per la generazione di eccezioni Il set di istruzioni Thumb fornisce due tipi di istruzione il quale scopo principale è di far verificare eccezione di processore: L’istruzione Software Interrupt (SWI) è usata per causare un’eccezione SWI (vedere Software Interrupt Exception). Questo è il meccanismo principale con il quale il codice Utente può fare chiamate al codice privilegiato del Sistema Operativo. L’istruzione Breakpoint (BKPT) è usata per punti di rottura (breakpoints) software in ARMv5T e superiori. Il suo comportamento di default è quello di causare un’eccezione di Prefetch Abort (vedere Prefetch Abort (fallimento di fetch dell’istruzione da memoria)). Un programma monitor di debug che è stato preventivamente installato nel vettore Prefetch Abort può gestire questa eccezione. Se è presente nel sistema il debug hardware, è autorizzato a non tener conto del comportamento di default. 5.7.1. Codifica delle istruzioni In entrambe swi e bkpt, il campo immed_8 dell’istruzione è ignorato dal processore ARM. I gestori delle interruzioni possono essere opzionalmente scritti per caricare l’istruzione che ha causato l’eccezione ed estrarre questi campi. Questo permette loro di essere usati per comunicare informazioni extra riguardo le chiamate al Sistema Operativo. 47 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 5.8. Spazio indefinito delle istruzioni Le seguenti istruzioni sono INDEFINITE nel set Thumb: In generale, queste istruzioni possono essere usate per estendere il set Thumb in futuro. Tuttavia, è sottointeso che un futuro gruppo di istruzioni non sarà usato in questa maniera: Usare una di queste istruzioni se si vuole usare un’istruzione indefinita per scopi software, con il minimo rischio che un futuro hardware le tratterà come istruzioni definite. 48 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6. Istruzioni Thumb (Manuale parte 2) Questo capitolo descrive la sintassi e l’uso di ogni istruzione Thumb, nelle sezioni: Lista in ordine alfabetico delle istruzioni Thumb Istruzioni Thumb e versioni dell’architettura 49 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1. Lista in ordine alfabetico delle istruzioni Thumb Tutte le istruzioni Thumb sono presenti nelle seguenti pagine. Ogni descrizione mostra: la codifica dell’istruzione la sintassi dell’istruzione le versioni di ARM in cui l’istruzione è valida le eccezioni che potrebbero verificarsi uno pseudocodice su come opera l’istruzione note sull’uso e casi speciali l’equivalente codifica ARM 6.1.1. Note generali Queste note spiegano il tipo di informazioni e abbreviazioni usate nelle pagine successive. Sintassi abbreviazioni Sono usate le seguenti abbreviazioni: immed_<n> È un valore immediato a <n>-bit. Per esempio, un valore a 8-bit immediato è rappresentato da: immed_8 signed_immed_<n> È un valore immediato con segno a <n>-bit. Per esempio, un valore con segno a 8-bit immediato è rappresentato da: immed_signed_8 Versione architettura Questa sezione descrive la versione dell’architettura ARM con cui è associata l’istruzione, non la versione del set di istruzioni Thumb. Ci sono tre versioni del set Thumb: THUMBv1 è usato nella variante T di ARMv4. THUMBv2 è usato nella variante T di ARMv5. THUMBv3 è usato in ARMv6 e superiori. Le istruzioni che sono descritte come presenti in tutte le varianti T sono presenti in THUMBv1, THUMBv2 e THUMBv3. Quelle che sono descritte come appartenenti alla variante T delle versioni 6 e superiori sono presenti solo nel THUMBv3. Sintassi e codifica ARM equivalenti Questa sezione mostra la sintassi e la codifica dell’istruzione ARM equivalente. Quando non è disponibile un equivalente preciso, viene mostrata un’istruzione simile e vengono spiegate le ragioni per cui non esiste l’equivalente preciso. Una ragione comune per cui non ci sono istruzioni equivalenti è che queste leggono il valore del PC. Questo produce l’indirizzo dell’istruzione più N, dove N è 8 per le istruzioni ARM e 4 per le istruzioni Thumb. Questa differenza può essere spesso compensata con l’aggiustamento di una costante immediata nell’equivalente istruzione ARM. Nella codifica equivalente, i campi con nome e i vari bits devono essere riempiti con i corrispondenti campi e bits dell’istruzione Thumb, o in alcuni casi con i valori derivati dall’istruzione Thumb come descritto nel testo. I campi dell’istruzione ARM sono normalmente della stessa lunghezza dei campi dell’istruzione Thumb corrispondente, con una importante eccezione. I campi registro del Thumb sono lunghi normalmente 3 bits, dove invece i campi registro dell’ARM sono di 4 bits. In questi casi, il campo registro del Thumb deve essere esteso con uno 0 nel bit più significativo quando va a sostituire il campo registro dell’ARM, così che l’istruzione ARM fa riferimento al registro corretto tra R0 e R7. 50 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Informazioni sull’uso L’informazione sull’uso è data per l’istruzione Thumb solo se questa differisce significativamente dall’uso della corrispondente istruzione ARM. Se questa sezione non compare bisogna andare a vedere la sezione informazioni sull’uso della corrispondente istruzione ARM. 51 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.2. Tesi di Laurea di: Loredano Rapari matr. 1029262 ADC ADC (Add with Carry) somma due valori e il flag Carry. Usare ADC per sintetizzare le addizioni multi-parola. ADC aggiorna i flag di stato, a seconda del risultato. Sintassi ADC <Rd>, <Rm> dove: <Rd> Memorizza il primo valore dell’addizione, ed è il registro di destinazione. <Rm> Specifica il registro che contiene il secondo operando dell’addizione. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rd + Rm + C Flag N Flag = Rd[31] // Flag Negative, se 1 è negativo, se 0 è positivo Z Flag = if(Rd == 0) {1} else {0} // Flag Zero C Flag = CarryFrom(Rd + Rm + C Flag) // Flag Carry V Flag = OverflowFrom(Rd + Rm + C Flag) // Flag Overflow Sintassi e codifica equivalente ARM ADCS <Rd>, <Rd>, <Rm> 52 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.3. Tesi di Laurea di: Loredano Rapari matr. 1029262 ADD(1) ADD(1) somma il valore di una piccola costante ad un registro e salva il risultato in un secondo registro. Aggiorna i flag di stato, a seconda del risultato. Sintassi ADD <Rd>, <Rn>, #<immed_3> dove: <Rd> Registro di destinazione. <Rn> Specifica il registro che contiene l’operando dell’addizione. <immed_3> Specifica un valore a 3-bit che viene aggiunto ad Rn. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rn + immed_3 N Flag = Rd[31] Z Flag = if(Rd == 0) {1} else {0} C Flag = CarryFrom(Rn + immed_3) V Flag = OverflowFrom(Rn + immed_3) Sintassi e codifica equivalente ARM ADDS <Rd>, <Rn>, #<immed_3> 53 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.4. Tesi di Laurea di: Loredano Rapari matr. 1029262 ADD(2) ADD(2) somma il valore di una grande costante ad un registro e salva il risultato nel registro stesso. Aggiorna i flag di stato, a seconda del risultato. Sintassi ADD <Rd>, #<immed_8> dove: <Rd> Contiene il primo operando dell’addizione ed è il registro di destinazione. <immed_8> Specifica un valore a 8-bit che viene aggiunto ad Rd. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rd + immed_8 N Flag = Rd[31] Z Flag = if(Rd == 0) {1} else {0} C Flag = CarryFrom(Rd + immed_8) V Flag = OverflowFrom(Rd + immed_8) Sintassi e codifica equivalente ARM ADDS <Rd>, <Rd>, #<immed_8> 54 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.5. Tesi di Laurea di: Loredano Rapari matr. 1029262 ADD(3) ADD(3) somma il valore di un registro al valore di un secondo registro e salva il risultato in un terzo registro. Aggiorna i flag di stato, a seconda del risultato. Sintassi ADD <Rd>, <Rn>, <Rm> dove: <Rd> È il registro di destinazione del risultato della somma. <Rn> È il registro che contiene il primo operando dell’ addizione. <Rm> È il registro che contiene il secondo operando dell’ addizione. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rn + Rm N Flag = Rd[31] Z Flag = if(Rd == 0) {1} else {0} C Flag = CarryFrom(Rn + Rm) V Flag = OverflowFrom(Rn + Rm) Sintassi e codifica equivalente ARM ADDS <Rd>, <Rn>, <Rm> 55 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.6. Tesi di Laurea di: Loredano Rapari matr. 1029262 ADD(4) ADD(4) somma i valori di due registri, di cui uno o entrambi sono registri alti. Diversamente dalle istruzioni add che agiscono solo sui registri bassi, questa istruzione non cambia i flags. Sintassi ADD <Rd>, <Rm> dove: <Rd> Specifica il registro contenente il primo valore, ed è anche il registro di destinazione. Può essere uno qualunque tra R0 e R15. Il numero del registro è codificato nell’istruzione in H1 (bit più significativo) e in Rd (i restanti 3 bit). <Rm> Specifica il registro contenente il secondo valore. Può essere uno qualunque tra R0 e R15. Il numero del registro è codificato nell’istruzione da H2 (bit più significativo) e da Rm (restanti 3 bit). Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rd + Rm Note Se vengono specificati due registry bassi in Rd e Rm, il risultato è IMPREVEDIBILE. Sintassi e codifica equivalente ARM Un equivalente simile è: ADD <Rd>, <Rd>, <Rm> Ci sono lievi differenze quando l’istruzione accede al PC, a causa delle differenti definizioni di PC durante l’esecuzione del codice ARM e Thumb. 56 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.7. Tesi di Laurea di: Loredano Rapari matr. 1029262 ADD(5) ADD(5) somma un valore immediato al PC e scrive l’indirizzo relativo risultante in un registro di destinazione. Il valore immediato può essere un multiplo di 4 nel range tra 0 e 1020. I flags di stato non vengono modificati. Sintassi ADD <Rd>, PC, #<immed_8> * 4 dove: <Rd> È il registro di destinazione. PC Indica il Program Counter. <immed_8> Specifica un valore immediato ad 8 bit che viene moltiplicato per 4 e aggiunto al PC. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = (PC AND 0xFFFFFFFC) + (immed_8 * 4) Sintassi e codifica equivalente ARM Un equivalente simile è: ADD <Rd>, PC, #<immed_8> * 4 Le definizioni di PC differiscono tra i codici ARM e Thumb. Questo implica una differenza tra i risultati precisi delle istruzioni. 57 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.8. Tesi di Laurea di: Loredano Rapari matr. 1029262 ADD(6) ADD(6) somma un valore immediato allo SP e scrive l’indirizzo relativo risultante in un registro di destinazione. Il valore immediato può essere un multiplo di 4 nel range tra 0 e 1020. I flags di stato non vengono modificati. Sintassi ADD <Rd>, SP, #<immed_8> * 4 dove: <Rd> È il registro di destinazione. SP Indica lo Stack Pointer. <immed_8> Specifica un valore immediato ad 8 bit che viene moltiplicato per 4 e aggiunto al SP. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = SP + (immed_8 << 2) // l’operatore ‘<<’ indica lo shift aritmetico a sinistra di n bit, che equivale a moltiplicare per 2n. Sintassi e codifica equivalente ARM ADD <Rd>, SP, #<immed_8> * 4 58 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.9. Tesi di Laurea di: Loredano Rapari matr. 1029262 ADD(7) ADD(7) incrementa lo SP di un valore a 7 bit moltiplicato per 4 (range tra 0 e 508). I flags di stato non vengono modificati. Sintassi ADD SP, #<immed_7> * 4 dove: SP Contiene il primo operando della somma ed è anche il registro di destinazione. <immed_7> Specifica un valore immediato a 7 bit che viene moltiplicato per 4 e aggiunto allo SP. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione SP = SP + (immed_7 << 2) // l’operatore ‘<<’ indica lo shift aritmetico a sinistra di n bit, che n equivale a moltiplicare per 2 . Uso Per lo stack decrescente che usa il set Thumb, incrementare lo SP significa eliminare i dati all’inizio dello stack. Note Questa istruzione può anche essere scritta in questo modo: add SP, SP, #<immed_7> * 4. Sintassi e codifica equivalente ARM ADD SP, SP, #<immed_7> * 4 59 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.10. AND AND (AND logico) esegue un AND bit a bit tra i valori dei due registri. Aggiorna i flag di stato, a seconda del risultato. Sintassi AND <Rd>, <Rm> dove: <Rd> Specifica il registro contenente il primo operando ed è anche il registro di destinazione. <Rm> Specifica il registro contenente il secondo operando. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rd AND Rm N Flag = Rd[31] Z Flag = if(Rd == 0) {1} else {0} C Flag = non interessato V Flag = non interessato Sintassi e codifica equivalente ARM ANDS <Rd>, <Rd>, <Rm> 60 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.11. ASR(1) (Arithmetic Shift Right) fornisce il valore con segno del contenuto di un registro diviso per una costante potenza del 2. ASR Aggiorna i flag di stato, a seconda del risultato. Sintassi ASR <Rd>, <Rm>, #<immed_5> dove: <Rd> Specifica il registro di destinazione. <Rm> Specifica il registro contenente il valore che deve essere shiftato. <immed_5> Specifica il valore dello shift da 1 a 31. Lo shift da 1 a 31 è codificato direttamente in immed_5. Uno shift di 32 è codificato come immed_5 = 0. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione if (immed_5 == 0) C Flag = Rm[31] if (Rm[31] == 0 then) Rd = 0 else /* Rm[31] == 1 */ Rd = 0xFFFFFFFF else /* immed_5 > 0 */ C Flag = Rm[immed_5 - 1] Rd = Rm Arithmetic_Shift_Right immed_5 N Flag = Rd[31] Z Flag = if (Rd == 0) {1} else {0} V Flag = unaffected 61 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Sintassi e codifica equivalente ARM MOVS <Rd>, <Rm>, asr #<immed_5> Shift Aritmetico destro Ogni bit dell’operando è semplicemente spostato verso destra di un dato numero di bit, e le posizioni che rimangono vuote vengono riempite. Invece di riempirle con tutti zeri, come nello shift logico, il bit più significativo (MSB – di solito rappresenta il segno nella rappresentazione binaria dei numeri) viene replicato per riempire tutte le posizioni rimaste vuote. Fare lo shift destro di n bits in un numero binario con segno in complemento a due, equivale a dividerlo per 2 n, con il risultato arrotondato per difetto. 62 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.12. ASR(2) (Arithmetic Shift Right) fornisce il valore con segno del contenuto di un registro diviso per una variabile potenza del 2. ASR Aggiorna i flag di stato, a seconda del risultato. Sintassi ASR <Rd>, <Rs> dove: <Rd> Contiene il valore da shiftare ed è il registro di destinazione. <Rs> Specifica il registro contenente il valore dello shift. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione if (Rs[7:0] == 0) C Flag = unaffected Rd = unaffected else if (Rs[7:0] < 32) C Flag = Rd[Rs[7:0] - 1] Rd = Rd Arithmetic_Shift_Right Rs[7:0] else /* Rs[7:0] >= 32 */ C Flag = Rd[31] if (Rd[31] == 0) Rd = 0 else /* Rd[31] == 1 */ Rd = 0xFFFFFFFF N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 V Flag = unaffected 63 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Sintassi e codifica equivalente ARM MOVS <Rd>, <Rd>, asr <Rs> 64 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.13. B(1) B (Branch) salto condizionato verso un indirizzo. Sintassi B <cond>, <target_address> dove: <cond> È la condizione sotto la quale l’istruzione viene eseguita. <target_address> Specifica l’indirizzo a cui saltare. L’indirizzo è calcolato in questo modo: 1. Shiftando verso sinistra di un bit il campo signed_immed_8 dell’istruzione. 2. Estendendo il segno a 32 bits. 3. Aggiungendo il risultato al contenuto del PC (che contiene l’indirizzo dell’istruzione di salto più 4). Questa istruzione può quindi specificare un salto di -256 o + 254 bytes, relativamente al valore corrente del PC (R15). Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione if (ConditionPassed(cond)) PC = PC + (SignExtend(signed_immed_8) << 1) // ‘<<’ indica lo shift aritmetico a sinistra Uso Per calcolare l’esatto valore di signed_immed_8, l’assembler deve: 1. Formare l’indirizzo base per il salto. Ossia l’indirizzo dell’istruzione di salto, più 4. In altre parole, l’indirizzo base è uguale al valore del PC letto da questa istruzione. 2. Sottrarre l’indirizzo base dall’indirizzo di destinazione per formare l’offset. Questo offset è sempre pari, perché tutte le istruzioni Thumb sono allineate a mezze parole (2 bytes). 3. Se l’offset è fuori dall’intervallo da -256 a +254, una strategia di generazione dell’indirizzo alternativa oppure generare un errore appropriato. 4. Altrimenti, settare il campo signed_immed_8 dell’istruzione nel byte offset diviso 2. 65 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Limiti di memoria Tesi di Laurea di: Loredano Rapari matr. 1029262 Saltare all’indietro prima dello zero o in avanti oltre la fine dello spazio indirizzi a 32-bit porta risultati imprevedibili. Condizione AL Se nel campo condizione è presente la condizione AL (0b1110), l’istruzione è indefinita. Quando è richiesto un salto incondizionato si usa l’istruzione apposita descritta in seguito. Condizione NV Se nel campo condizione è indicato (Software Interrupt). NV (0b1111), l’istruzione indica un SWI Sintassi e codifica equivalente ARM B <cond>, <target_address> Questa istruzione è diversa dall’istruzione Thumb, perché l’offset dell’istruzione ARM viene shiftato a sinistra di sue bit prima di essere aggiunto al PC, invece l’offset dell’istruzione Thumb viene shiftato verso sinistra di un bit. Così il valore del PC letto dalle istruzioni ARM e Thumb sono diversi. 66 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.14. B(2) B (2) salto incondizionato verso un indirizzo. Sintassi B <target_address> dove: <target_address> Specifica l’indirizzo a cui saltare. L’indirizzo è calcolato in questo modo: 1. Shiftando verso sinistra di un bit il campo signed_immed_11 dell’istruzione. 2. Estendendo il segno a 32 bits. 3. Aggiungendo il risultato al contenuto del PC (che contiene l’indirizzo dell’istruzione di salto più 4). Questa istruzione può quindi specificare un salto di -2048 o + 2046 bytes, relativamente al valore corrente del PC (R15). Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione PC = PC + (SignExtend(signed_immed_11) << 1) // ‘<<’ indica lo shift aritmetico a sinistra Uso Per calcolare l’esatto valore di signed_immed_11, l’assembler deve: 1. Formare l’indirizzo base per il salto. Ossia l’indirizzo dell’istruzione di salto, più 4. In altre parole, l’indirizzo base è uguale al valore del PC letto da questa istruzione. 2. Sottrarre l’indirizzo base dall’indirizzo di destinazione per formare l’offset. Questo offset è sempre pari, perché tutte le istruzioni Thumb sono allineate a mezze parole (2 bytes). 3. Se l’offset è fuori dall’intervallo da -2048 a +2046, una strategia di generazione dell’indirizzo alternativa oppure generare un errore appropriato. 4. Altrimenti, settare il campo signed_immed_11 dell’istruzione nel byte offset diviso 2. 67 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Limiti di memoria Tesi di Laurea di: Loredano Rapari matr. 1029262 Saltare all’indietro prima dello zero o in avanti oltre la fine dello spazio indirizzi a 32-bit porta risultati imprevedibili. Sintassi e codifica equivalente ARM B <target_address> Questa istruzione è diversa dall’istruzione Thumb, perché l’offset dell’istruzione ARM viene shiftato a sinistra di sue bit prima di essere aggiunto al PC, invece l’offset dell’istruzione Thumb viene shiftato verso sinistra di un bit. Così il valore del PC letto dalle istruzioni ARM e Thumb sono diversi. 68 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.15. BIC (Bit Clear) esegue un AND bit a bit tra il valore di un registro e il valore dell’altro registro negato. BIC Aggiorna i flag di stato, a seconda del risultato. Sintassi BIC <Rd>, <Rm> dove: <Rd> Specifica il registro contenente il primo operando ed è anche il registro di destinazione. <Rm> Specifica il registro contenente il secondo operando il quale verrà negato. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rd AND NOT Rm N Flag = Rd[31] Z Flag = if(Rd == 0) {1} else {0} C Flag = non interessato V Flag = non interessato Sintassi e codifica equivalente ARM BICS <Rd>, <Rd>, <Rm> 69 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.16. BKPT (Breakpoint) causa il verificarsi di un’interruzione software. Questo breakpoint può essere gestito da un gestore delle eccezioni installato nel vettore Prefetch Abort. Nelle implementazioni che includono anche hardware di debug, l’hardware può anche scavalcare questo comportamento di default e gestire il breakpoint. BKPT Sintassi BKPT <immed_8> dove: <immed_8> È un valore immediato di 8-bit, inserito nei bit*7:0+ dell’istruzione. Questo valore è ignorato dall’hardware ARM, ma può essere usato da un debugger per memorizzare delle informazioni riguardo il breakpoint. Versione architettura Varianti T di ARMv5 e superiori. Eccezioni Prefetch Abort. Operazione if (not overridden by debug hardware) R14_abt = address of BKPT instruction + 4 SPSR_abt = CPSR CPSR[4:0] = 0b10111 /* Enter Abort mode */ CPSR[5] = 0 /* Execute in ARM state */ /* CPSR[6] is unchanged */ CPSR[7] = 1 /* Disable normal interrupts */ CPSR[8] = 1 /* Disable imprecise aborts - v6 only*/ CPSR[9] = CP15_reg1_EEbit if (high vectors configured) PC = 0xFFFF000C else PC = 0x0000000C 70 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Uso L’uso esatto di BKPT dipende dal sistema di debug usato. Un sistema di debug può usare BKPT in due modi: L’hardware di debug (se presente) non scavalca la normale procedura di BKPT, e così si entra nel vettore di Prefetch Abort. Se il sistema permette anche l’avvenimento di un Prefetch Abort reale, il gestore delle interruzioni determina (in un modo dipendente dal sistema) se l’elemento del vettore è il risultato di un’istruzione BKPT o il risultato di un Prefetch Abort reale, e salta di conseguenza al codice di debug o al codice di Prefetch Abort. Diversamente, il gestore di Prefetch Abort salta direttamente al codice di debug. Quando è usato in questo modo, BKPT deve essere evitato nei gestori delle eccezioni, poiché cambia i valori di R14_abt e SPSR_abt. Per la stessa ragione deve essere evitato nei gestori FIQ, poiché un’interruzione FIQ può avveneire nel gestore degli abort. Il debug hardware scavalca la normale procedura di BKPT e gestisce il breakpoint software da solo. Quando finisce, tipicamente riprende l’esecuzione dall’istruzione seguente a BKPT, oppure lo rimpiazza con un’altra istruzione e riprende l’esecuzione da quest’ultima. Quando BKPT è usato in questo modo, R14_abt e SPSR_abt non vengono cambiati, e così le restrizioni di prima riguardo l’uso di BKPT nei gestori di abort e FIQ non vengono applicate. Note Scavalcamento Hardware Il debug hardware viene appositamente permesso per scavalcare la normale procedura di BKPT. A causa di ciò, il software non deve usare questa istruzione se non per gli scopi permessi dal sistema di debug che si sta usando. In particolare, il software non può dipendere dal verificarsi dell’eccezione di Prefetch Abort, a meno che sia garantito che non ci sia un debug hardware nel sistema e che il sistema di debug specifica che l’eccezione avviene. Sintassi e codifica equivalente ARM BKPT <immed_8> 71 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.17. BL, BLX(1) (Branch with link) fa una chiamata incondizionata ad una subroutine Thumb. Il ritorno dalla subroutine viene effettuato dai seguenti comandi: BL mov PC, LR bx LR un’istruzione di pop che carichi il PC. (1) (Branch with Link and Exchange) fa una chiamata incondizionata ad una subroutine ARM. Il ritorno dalla subroutine viene effettuato tramite l’istruzione bx LR, oppure da un’istruzione ldr o ldm che carichi il PC. BLX Per permettere una grandezza dell’offset ragionevole, le istruzioni bl e blx sono automaticamente tradotte dall’assembler in una sequenza di due istruzioni Thumb 16-bit: La prima istruzione ha H = 10 e fornisce la parte alta dell’offset del salto. Questa istruzione prepara per la chiamata alla subroutine ed è condivisa tra bl e blx. La seconda istruzione ha H = 11 (per bl) o H = 01 (per blx). Fornisce la parte bassa dell’offset del salto e fa prendere posto alla chiamata alla subroutine. Sintassi BL <target_addr> BLX <target_addr> dove: <target_addr> Specifica l’indirizzo a cui saltare. Questo indirizzo è calcolato in questo modo: 1. Shiftando il campo offset_11 della prima istruzione a sinistra di 12 bits. 2. Estendendo il segno del risultato a 32-bit. 3. Aggiungendolo al contenuto del PC (che contiene l’indirizzo della prima istruzione più 4). 4. Aggiungendo due volte il campo offset_11 della seconda istruzione. L’istruzione può quindi compiere un salto di ±4MB. Versione architettura BL (H == 10 e H == 11) in tutte le variant T. BLX (H == 01 form) nelle variant T di ARMv5 e superiori. Eccezioni Nessuna 72 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Operazione if (H == 10) LR = PC + (SignExtend(offset_11) << 12) else if (H == 11) PC = LR + (offset_11 << 1) LR = (address of next instruction) | 1 else if (H == 01) PC = (LR + (offset_11 << 1)) AND 0xFFFFFFFC LR = (address of next instruction) | 1 CPSR T bit = 0 Uso Per generare la giusta coppia di istruzioni, l’assembler deve prima generare l’offset del salto, come segue: 1. Forma l’indirizzo base del salto. È l’indirizzo della prima delle due istruzioni Thumb (quella con H = 10), più 4. In altre parole, l’indirizzo base è uguale al valore del PC letto da quest’istruzione. 2. Se l’istruzione è BLX, si imposta il bit*1+ dell’indirizzo di destinazione uguale al bit*1+ dell’indirizzo base. È un’eccezione alla regola che i bits*1:0+ dell’indirizzo di un’istruzione ARM sono 0b00. Questo aggiustamento è necessario per assicurare che le restrizioni associate con la forma dell’istruzione H = 01 siano ottemperate. 3. Sottrarre l’indirizzo base dall’indirizzo di destinazione (target) per formare l’offset. L’offset risultante è sempre pari. Se l’offset è fuori dall’intervallo: -222 ≤ offset ≤ +222 – 2 L’indirizzo di destinazione giace al di fuori dall’intervallo di queste istruzioni. Risulta quindi un codice alternativo o un errore. Se l’offset si trova nell’intervallo, deve essere generata una sequenza di due istruzioni Thumb, entrambe usanti la forma vista in precedenza: La prima con H = 10 e offset_11 = offset[22:12] La seconda con H = 11 (per BL) o H = 01 (per BLX) e offset_11 = offset[11:1] Note Codifica Se H = 00, l’istruzione rappresenta un salto incondizionato (vedere b(2)) Bit[0] per BLX Se H = 01, il bit*0+ dell’istruzione deve essere zero, altrimenti l’istruzione risulta indefinita. Il metodo di calcolo dell’offset descritto sopra assicura che l’offset calcolato per un’istruzione BLX è un multiplo di quattro, e questa restrizione è rispettata. Limiti memoria Il risultato di salti al di fuori dello spazio di memoria a 32-bit è imprevedibile. 73 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Coppie di istruzioni Queste istruzioni Thumb devono sempre verificarsi in coppia come descritto sopra. In particolare: Se l’istruzione Thumb all’indirizzo A è nella forma H = 10, l’istruzione all’indirizzo A + 2 deve essere nella forma H = 01 oppure H = 11. Se l’istruzione Thumb all’indirizzo A è nella forma H = 01 oppure H = 11, l’istruzione all’indirizzo A – 2 deve essere nella forma H = 10. Ancora, eccetto ciò che è notificato in Eccezioni sotto, la seconda istruzione della coppia non deve essere l’obiettivo di alcun salto, così come il risultato di un’istruzione di salto o di altre istruzioni che cambiano il PC. Il non attenersi a ognuna di queste restrizioni può risultare in sviluppi imprevedibili. Eccezioni È definito dall’implementazione se le eccezioni del processore possono avvenire anche tra la coppia di istruzioni di BL e BLX. Se possono, le istruzioni ARM usate per il ritorno dall’eccezione devono essere capaci di ritornare correttamente alla seconda istruzione della coppia. Quindi, i gestori delle eccezioni non devono prendere particolari precauzioni riguardo il ritorno alla seconda istruzione di una coppia BL o BLX. Sintassi e codifica equivalente ARM Le istruzioni più simili a queste istruzioni Thumb sono le seguenti. Per chiamare una subroutine Thumb: BLX <target_addr> dove L = offset[1] Per chiamare una routine ARM: BL <target_addr> Differiscono leggermente dalle coppie di istruzioni Thumb a causa dei differenti valori del Pc nei codici ARM e Thumb. Può essere compensato aggiustando l’offset di 4. 74 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.18. BLX(2) (2) chiama una subroutine ARM o Thumb dal set istruzino Thumb, a un indirizzo specificato in un registro. L’istruzione fa il salto e seleziona il decoder da usare per decodificare le istruzioni alla destinazione del salto. BLX Il bit T del CPSR viene aggiornato con il bit[0] del valore del registro Rm. Per ritornare dalla subroutine al chiamante si usa BX R14. Sintassi BLX <Rm> dove: <Rm> Specifica il registro contenente l’indirizzo a cui saltare. Può essere uno qualsiasi tra R0 e R14. Il numero del registro è codificato nell’istruzione in H2 (bit più significativo) e in Rm (i rimanenti tre bit). Se viene specificato R15 come Rm il risultato è imprevedibile. Versione architettura Varianti T di ARMv5 e superiori. Eccezioni Nessuna Operazione target = Rm LR = (address of the instruction after this BLX) | 1 CPSR T bit = target[0] PC = target AND 0xFFFFFFFE Sintassi e codifica equivalente ARM BLX <Rm> 75 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.19. BX BX (Branch and Exchange) salta tra il codice ARM e il codice Thumb. Sintassi BX <Rm> dove: <Rm> Specifica il registro contenente l’indirizzo a cui saltare. Può essere uno qualsiasi tra R0 e R14. Il numero del registro è codificato nell’istruzione in H2 (bit più significativo) e in Rm (i rimanenti tre bit). Versione architettura Tutte le varianti T. Eccezioni Nessuna Operazione CPSR T bit = Rm[0] PC = Rm[31:1] << 1 Uso L’istruzione normale di ritorno dalla subroutine in Thumb è bx R14. Le seguenti istruzioni di chiamata lasciano un valore di ritorno appropriato in R14: Le istruzioni blx di ARM. Le istruzioni bl e blx di Thumb. Nelle varianti T di ARMv4, una chiamata ad una routine ARM può essere fatta dal seguente codice: <Put address of routine to call in Ra> MOV LR, PC ; Return to second following instruction BX Ra Nelle varianti T di ARMv5 e superiori, la chiamata può essere fatta in modo più efficiente con l’istruzione BLX. 76 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Sintassi e codifica equivalente ARM BX <Rm> 77 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.20. CMN (Compare Negative) compara il valore di un registro con la negazione del valore di un altro registro. Aggiorna i flag di stato, a seconda del risultato della somma dei valori dei due registri, così che le istruzioni seguenti possano essere eseguite a seconda della condizione (usando un salto condizionato). CMN Sintassi CMN <Rn>, <Rm> dove: <Rn> Specifica il registro contenente il primo valore da comparare. <Rm> Specifica il registro contenente il secondo valore da comparare. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione alu_out = Rn + Rm N Flag = alu_out[31] Z Flag = if (alu_out == 0) {1} else {0} C Flag = CarryFrom(Rn + Rm) V Flag = OverflowFrom(Rn + Rm) Sintassi e codifica equivalente ARM CMN <Rn>, <Rm> 78 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.21. CMP(1) CMP(1) (Compare) compara il valore di un registro con un valore immediato di 8-bit. I flag di stato vengono aggiornati, in base al risultato della sottrazione del valore immed_8 dal valore del registro, così che le istruzioni seguenti possano essere eseguite a seconda della condizione (usando un salto condizionato). Sintassi CMP <Rn>, #<immmed_8> dove: <Rn> Specifica il registro contenente il primo valore da comparare. <immed_8> Specifica il secondo valore da comparare. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione alu_out = Rn - immed_8 N Flag = alu_out[31] Z Flag = if (alu_out == 0) {1} else {0} C Flag = NOT BorrowFrom(Rn - immed_8) V Flag = OverflowFrom(Rn - immed_8) Sintassi e codifica equivalente ARM CMP <Rn>, #<immed_8> 79 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.22. CMP(2) CMP(2) compara i valori di due registri. I flag di stato vengono aggiornati, in base al risultato della sottrazione del valore del secondo registro dal valore del primo, così che le istruzioni seguenti possano essere eseguite a seconda della condizione (usando un salto condizionato). Sintassi CMP <Rn>, <Rm> dove: <Rn> Specifica il registro contenente il primo valore da comparare. <Rm> Specifica il registro contenente il secondo valore da comparare. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione alu_out = Rn - Rm N Flag = alu_out[31] Z Flag = if (alu_out == 0) {1} else {0} C Flag = NOT BorrowFrom(Rn - Rm) V Flag = OverflowFrom(Rn - Rm) Sintassi e codifica equivalente ARM CMP <Rn>, <Rm> 80 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.23. CMP(3) CMP(3) compara i valori di due registri, uno dei quali o entrambi sono registri alti. I flags di stato vengono aggiornati, in base al risultato della sottrazione del valore del secondo registro dal valore del primo, così che le istruzioni seguenti possano essere eseguite a seconda della condizione (usando un salto condizionato). Sintassi CMP <Rn>, <Rm> dove: <Rn> Specifica il registro contenente il primo valore da comparare. Può essere uno qualsiasi tra R0 e R14. Il numero del registro è dato da H1 (bit più significativo) e Rn (i restanti tre bit). <Rm> Specifica il registro contenente il secondo valore da comparare. Può essere uno qualsiasi tra R0 e R14. Il numero del registro è dato da H2 (bit più significativo) e Rm (i restanti tre bit). Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione alu_out = Rn - Rm N Flag = alu_out[31] Z Flag = if (alu_out == 0) {1} else {0} C Flag = NOT BorrowFrom(Rn - Rm) V Flag = OverflowFrom(Rn - Rm) Note Restrizione operandi Se viene specificato un registro basso per entrambi gli operandi il risultato è imprevedibile. 81 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Sintassi e codifica equivalente ARM Un equivalente simile è: CMP <Rn>, <Rm> Ci sono leggere differenze quando le istruzioni accedono al PC, a causa delle differenti definizioni di PC nell’esecuzione di codice ARM e Thumb. 82 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.24. CPS (Change Processor State) cambia uno o più dei bit A, I, e F del CPSR, senza cambiare altri bit del CPSR. CPS Sintassi CPS <effect>, <iflags> dove: <effect> <iflags> Specifica quale effetto si vuole sui bit di disabilitazione dell’interrupt A, I, e F del CPSR. Possono essere: IE Interrupt Enable, codificato da imod = 0b0. Setta il bit specificato a zero. ID Interrupt Disable, codificato da imod = 0b1. Setta il bit specificato a 1. È una sequenza di uno o più dei seguenti flags, che specificano quali bit di disabilitazione dell’interrupt sono modificati: A Imposta il bit A (bit[2]) I Imposta il bit I (bit[1]) F Imposta il bit F (bit[0]) Versione architettura ARMv6 e superiori Eccezioni Nessuna Operazione if (InAPrivilegedMode()) if A == 1 then CPSR[8] = imod if I == 1 then CPSR[7] = imod if F == 1 then CPSR[6] = imod /* else no change to interrupt disable bits */ Note User mode Questa istruzione non ha effetti in modalità utente. 83 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Sintassi e codifica equivalente ARM cps <effect>, <iflags> 84 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.25. CPY (Copy) copia un valore da un registro alto o basso ad un altro registro alto o basso senza cambiare i flags di stato. CPY Sintassi CPY <Rd>, <Rm> dove: <Rd> Specifica il registro di destinazione. Può essere uno qualsiasi tra R0 e R15. Il numero del registro è dato da H1 (bit più significativo) e Rn (i restanti tre bit). <Rm> Specifica il registro contenente il valore da copiare. Può essere uno qualsiasi tra R0 e R15. Il numero del registro è dato da H2 (bit più significativo) e Rm (i restanti tre bit). Versione architettura Varianti T di ARMv6 e superiori. Eccezioni Nessuna Operazione Rd = Rm Uso CPY PC, R14 può essere usata come istruzione di ritorno da una subroutine se il chiamante è anch’essa una routine Thumb. Comunque, è più comune usare bx R14, che funzione sia che il chiamante fosse una routine ARM sia che fosse una routine Thumb. Note Codifica ha la stessa funzionalità di mov(3), e usa la stessa codifica di istruzione, ma ha una sintassi assembler che permette a entrambi gli operandi di essere registri bassi. CPY Sintassi e codifica equivalente ARM Un equivalente simile è: 85 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb CPY Tesi di Laurea di: Loredano Rapari matr. 1029262 <Rd>, <Rm> Ci sono leggere differenze quando le istruzioni accedono al PC, a causa delle differenti definizioni di PC nell’esecuzione di codice ARM e Thumb. 86 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.26. EOR EOR (Exclusive Or) esegue un or esclusivo bit a bit tra i valori dei due registri. Aggiorna i flag di stato, a seconda del risultato. Sintassi EOR <Rd>, <Rm> dove: <Rd> Specifica il registro contenente il primo operando ed è anche il registro di destinazione. <Rm> Specifica il registro contenente il secondo operando. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rd EOR Rm N Flag = Rd[31] Z Flag = if (Rd == 0) {1} else {0} C Flag = unaffected V Flag = unaffected Sintassi e codifica equivalente ARM EOR <Rd>, <Rd>, <Rm> 87 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.27. LDMIA (Load Multiple Increment After) carica un sottoinsieme non vuoto, oppure tutti, i registry generic (R0-R7) da locazioni di memoria sequenziali. LDMIA Sintassi LDMIA <Rn>!, <registers> dove: <Rn> Specifica il registro contenente l’indirizzo di inizio per l’istruzione. ! Causa la riscrittura del registro base, e non è opzionale. <registers> È la lista dei registri da caricare, separati da una virgola e racchiusi tra parentesi graffe. La lista è codificata nel campo register_list dell’istruzione, settando il bit*i+ a 1 se il registro Ri è incluso nella lista, a zero altrimenti per ogni i da 0 a 7. Almeno un registro deve essere caricato. Se tutti i bit[7:0] sono a zero il risultato è imprevedibile. I registri vengono caricati in sequenza, dal registro col numero più basso a cui corrisponde l’indirizzo più piccolo in memoria (l’indirizzo iniziale), fino al registro col numero più alto a cui corrisponde l’indirizzo più grande in memoria (l’indirizzo finale). L’indirizzo iniziale è il valore del registro base Rn. Gli indirizzi succesivi sono formati incrementando l’indirizzo precedente di 4. Viene prodotto un indirizzo per ogni registro specificato in register_list. L’indirizzo finale è formato da: registro_base + 4 * (numero_registri_specificati – 1). Infine, quando Rn non fa parte dei registri specificati in register_list, il suo valore è incrementato di quattro volte i registri specificati in register_list. Vedere le restrizioni sull’operando. Versione architettura Tutte le varianti T Eccezioni Data Abort 88 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Operazione MemoryAccess(B-bit, E-bit) start_address = Rn end_address = Rn + (Number_Of_Set_Bits_In(register_list) * 4) - 4 address = start_address for i = 0 to 7 if (register_list[i] == 1) Ri = Memory[address,4] address = address + 4 assert end_address == address - 4 Rn = Rn + (Number_Of_Set_Bits_In(register_list) * 4) Uso Usare LDMIA come istruzione per caricare blocchi dalla memoria. In combinazione con stmia permette un’efficiente gestione della copia di blocchi di memoria. Note Restrizione operandi Se Rn è specificato nella register_list, il valore finale di Rn è quello caricato da memoria e non quello riscritto come mostrato prima. Data Abort Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Se un implementazione include un sistema di controllo coprocessore e il controllo dell’allineamento è abilitato, un indirizzo con i bit*1:0+ != 0b00 causa un’eccezione di allineamento. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Time order Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. L’ordine cronologico di accesso alle parole individuali della memoria generato da questa istruzione è definito solo in alcune circostanze. Vedere Restrizioni di accesso alla memoria per maggiori dettagli. 89 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Sintassi e codifica equivalente ARM Se Rn non è nel register_list (W = 1): LDMIA <Rn>!, <registers> Se Rn è nel register_list (W = 0): LDMIA <Rn>, <registers> 90 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.28. LDR(1) LDR(1) (Load Register) permette di caricare un dato di 32-bit dalla memoria in un registro. Il modo di indirizzamento è utile per accedere a strutture (record). Con un offset di zero l’indirizzo prodotto è l’inalterato valore del registro base Rn. Sintassi LDR <Rd>, [<Rn>, #<immed_5> * 4] dove: <Rd> È il registro di destinazione della parola caricata dalla memoria. <Rn> È il registro contenente l’indirizzo base dell’istruzione. <immed_5> È un valore di 5-bit che viene moltiplicato per 4 e aggiunto ad Rn per formare l’indirizzo di memoria. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) address = Rn + (immed_5 * 4) if (CP15_reg1_Ubit == 0) if (address[1:0] == 0b00) data = Memory[address,4] else data = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ data = Memory[address,4] Rd = data 91 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non era allineato alla parola, i dati letti dalla memoria erano casuali. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM LDR <Rd>, [<Rn>, #<immed_5> * 4] 92 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.29. LDR(2) LDR(2) permette di caricare un dato di 32-bit dalla memoria in un registro. Il modo di indirizzamento è utile per puntatori + offset e per accedere ad un elemento di un vettore. Sintassi LDR <Rd>, [<Rn>, <Rm>] dove: <Rd> È il registro di destinazione della parola caricata dalla memoria. <Rn> È il registro contenente il primo valore usato per formare l’indirizzo. <Rm> È il registro contenente il secondo valore usato per formare l’indirizzo. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) address = Rn + Rm if (CP15_reg1_Ubit == 0) if (address[1:0] == 0b00) data = Memory[address,4] else data = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ data = Memory[address,4] Rd = data 93 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non era allineato alla parola, i dati letti dalla memoria erano casuali. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM LDR <Rd>, [<Rn>, <Rm>] 94 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.30. LDR(3) LDR(3) permette di caricare un dato di 32-bit dalla memoria in un registro. Il modo di indirizzamento è utile per accedere alla memoria partendo dall’indirizzo contenuto nel PC. Sintassi LDR <Rd>, [PC, #<immed_8> * 4] dove: <Rd> È il registro di destinazione della parola caricata dalla memoria. PC È il Program Counter. Il suo valore è usato per calcolare l’indirizzo di memoria. Il bit 1 viene forzato a 0 in modo che l’indirizzo sia allineato. <immed_8> È un valore di 8-bit che moltiplicato per 4 e aggiunto al valore del PC forma l’indirizzo di memoria. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) address = (PC & 0xFFFFFFFC) + (immed_8 * 4) Rd = Memory[address, 4] Note Data Abort Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non era allineato alla parola, i dati letti dalla memoria erano casuali. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; 95 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb - Tesi di Laurea di: Loredano Rapari matr. 1029262 e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM Un equivalente simile è: LDR <Rd>, [PC, #<immed_8> * 4] Ci sono leggere differenze quando le istruzioni accedono al PC, a causa delle differenti definizioni di PC nell’esecuzione di codice ARM e Thumb. 96 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.31. LDR(4) LDR(4) permette di caricare un dato di 32-bit dalla memoria in un registro. Il modo di indirizzamento è utile per accedere allo stack. Sintassi LDR <Rd>, [SP, #<immed_8> * 4] dove: <Rd> È il registro di destinazione della parola caricata dalla memoria. SP È lo Stack Pointer. Il suo valore è usato per calcolare l’indirizzo di memoria. <immed_8> È un valore di 8-bit che moltiplicato per 4 e aggiunto al valore dello SP forma l’indirizzo di memoria. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) address = SP + (immed_8 * 4) if (CP15_reg1_Ubit == 0) if (address[1:0] == 0b00) data = Memory[address,4] else data = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ data = Memory[address,4] Rd = data 97 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non era allineato alla parola, i dati letti dalla memoria erano casuali. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM LDR <Rd>, [SP, #<immed_8> * 4] 98 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.32. LDRB(1) LDRB(1) (Load Register Byte) carica un byte da memoria, estende il dato con degli zeri per portarlo alla dimensione di 32-bit, e scrive il risultato in un registro generico. Il modo di indirizzamento è utile per accedere a strutture o record. Con un offset pari a zero, l’indirizzo prodotto è il valore inalterato dell’indirizzo base Rn. Sintassi LDRB <Rd>, [<Rn>, #<immed_5>] dove: <Rd> È il registro di destinazione del byte caricato dalla memoria. <Rn> È il registro contenente l’indirizzo base per l’istruzione. <immed_5> È un valore di 5-bit che viene aggiunto al valore di Rn per formare l’indirizzo di memoria. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione address = Rn + immed_5 Rd = Memory[address,1] Note Data Abort Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Sintassi e codifica equivalente ARM LDRB <Rd>, [<Rn>, #<immed_5>] 99 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.33. LDRB(2) LDRB(2) carica un byte da memoria, estende il dato con degli zeri per portarlo alla dimensione di 32-bit, e scrive il risultato in un registro generico. Il modo di indirizzamento è utile per puntatori + offset e per accedere ad un elemento di un vettore. Sintassi LDRB <Rd>, [<Rn>, <Rm>] dove: <Rd> È il registro di destinazione del byte caricato dalla memoria. <Rn> È il registro contenente il primo valore usato per formare l’indirizzo. <Rm> È il registro contenente il secondo valore usato per formare l’indirizzo. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione address = Rn + Rm Rd = Memory[address,1] Note Data Abort Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Sintassi e codifica equivalente ARM LDRB <Rd>, [<Rn>, <Rm>] 100 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.34. LDRH(1) LDRH(1) (Load Register Halfword) carica mezza parola (16-bit) da memoria, estende il dato con degli zeri per portarlo alla dimensione di 32-bit, e scrive il risultato in un registro generico. Il modo di indirizzamento è utile per accedere a strutture o record. Con un offset pari a zero, l’indirizzo prodotto è il valore inalterato dell’indirizzo base Rn. Sintassi LDRH <Rd>, [<Rn>, #<immed_5> * 2] dove: <Rd> È il registro di destinazione della mezza parola caricata dalla memoria. <Rn> È il registro contenente l’indirizzo base per l’istruzione. <immed_5> È un valore di 5-bit che moltiplicato per 2 viene aggiunto al valore di Rn per formare l’indirizzo di memoria. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) address = Rn + (immed_5 * 2) if (CP15_reg1_Ubit == 0) if (address[0] == 0b0) data = Memory[address,2] else data = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ data = Memory[address,2] Rd = ZeroExtend(data[15:0]) 101 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non era allineato alla parola, i dati letti dalla memoria erano casuali. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM LDRH <Rd>, [<Rn>, #<immed_5> * 2] 102 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.35. LDRH(2) LDRH(2) carica mezza parola (16-bit) da memoria, estende il dato con degli zeri per portarlo alla dimensione di 32-bit, e scrive il risultato in un registro generico. Il modo di indirizzamento è utile per puntatori + offset e per accedere ad un elemento di un vettore. Sintassi LDRH <Rd>, [<Rn>, <Rm>] dove: <Rd> È il registro di destinazione della mezza parola caricata dalla memoria. <Rn> È il registro contenente il primo valore usato per formare l’indirizzo. <Rm> È il registro contenente il secondo valore usato per formare l’indirizzo. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) address = Rn + Rm if (CP15_reg1_Ubit == 0) if (address[0] == 0b0) data = Memory[address,2] else data = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ data = Memory[address,2] Rd = ZeroExtend(data[15:0]) 103 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non era allineato alla parola, i dati letti dalla memoria erano casuali. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM LDRH <Rd>, [<Rn>, <Rm>] 104 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.36. LDRSB (Load Register Signed Byte) carica un byte da memoria, fa un’estensione di segno fino a 32bit, e scrive il risultato in un registro generico. LDRSB Sintassi LDRSB <Rd>, [<Rn>, <Rm>] dove: <Rd> È il registro di destinazione del byte caricato dalla memoria. <Rn> È il registro contenente il primo valore usato per formare l’indirizzo. <Rm> È il registro contenente il secondo valore usato per formare l’indirizzo. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione address = Rn + Rm Rd = SignExtend(Memory[address,1]) Note Data Abort Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Sintassi e codifica equivalente ARM LDRSB <Rd>, [<Rn>, <Rm>] 105 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.37. LDRSH LDRSH (Load Register Signed Halfword) carica mezza parola (16-bit) da memoria, fa un’estensione di segno fino a 32-bit, e scrive il risultato in un registro generico. Sintassi LDRSB <Rd>, [<Rn>, <Rm>] dove: <Rd> È il registro di destinazione della mezza parola caricata dalla memoria. <Rn> È il registro contenente il primo valore usato per formare l’indirizzo. <Rm> È il registro contenente il secondo valore usato per formare l’indirizzo. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) address = Rn + Rm if (CP15_reg1_Ubit == 0) if (address[0] == 0b0) data = Memory[address,2] else data = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ data = Memory[address,2] Rd = SignExtend(data[15:0]) 106 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non era allineato alla parola, i dati letti dalla memoria erano casuali. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM LDRSH <Rd>, [<Rn>, <Rm>] 107 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.38. LSL(1) LSL(1) (Logical Shift Left) fornisce il valore di un registro moltiplicato per una costante potenza di due. Inserisce degli zeri nelle posizioni liberate dai bit shiftati, e aggiorna i flags di stato, a seconda del risultato. Sintassi LSL <Rd>, <Rn>, #<immed_5> dove: <Rd> È il registro di destinazione dell’operazione. <Rn> È il registro contenente il valore da shiftare. <immed_5> Specifica il numero dello shift da 0 a 31. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione if immed_5 == 0 C Flag = unaffected Rd = Rm else /* immed_5 > 0 */ C Flag = Rm[32 - immed_5] Rd = Rm Logical_Shift_Left immed_5 N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 V Flag = unaffected Sintassi e codifica equivalente ARM MOVS <Rd>, <Rn>, lsl #<immed_5> 108 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.39. LSL(2) LSL(2) fornisce il valore di un registro moltiplicato per una variabile potenza di due. Inserisce degli zeri nelle posizioni liberate dai bit shiftati, e aggiorna i flags di stato, a seconda del risultato. Sintassi LSL <Rd>, <Rs> dove: <Rd> Contiene il valore da shiftare ed è il registro di destinazione dell’operazione. <Rs> È il registro contenente il valore di shift. Il valore è memorizzato nel byte meno significativo. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione if Rs[7:0] == 0 C Flag = unaffected Rd = unaffected else if Rs[7:0] < 32 then C Flag = Rd[32 - Rs[7:0]] Rd = Rd Logical_Shift_Left Rs[7:0] else if Rs[7:0] == 32 then C Flag = Rd[0] Rd = 0 else /* Rs[7:0] > 32 */ C Flag = 0 Rd = 0 N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 V Flag = unaffected 109 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Sintassi e codifica equivalente ARM MOVS <Rd>, <Rd>, lsl #<Rs> 110 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.40. LSR(1) LSR(1) (Logical Shift Right) fornisce il valore senza segno di un registro diviso per una costante potenza di due. Inserisce degli zeri nelle posizioni liberate dai bit shiftati, e aggiorna i flags di stato, a seconda del risultato. Sintassi LSR <Rd>, <Rn>, #<immed_5> dove: <Rd> È il registro di destinazione dell’operazione. <Rn> È il registro contenente il valore da shiftare. <immed_5> Specifica il numero dello shift da 1 a 32. Lo shift di 32 è indicato con immed_5 = 0. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione if immed_5 == 0 C Flag = Rm[31] Rd = 0 else /* immed_5 > 0 */ C Flag = Rm[immed_5 - 1] Rd = Rm Logical_Shift_Right immed_5 N Flag = Rd[31] /* 0b0 */ Z Flag = if Rd == 0 then 1 else 0 V Flag = unaffected Sintassi e codifica equivalente ARM MOVS <Rd>, <Rn>, lsr #<immed_5> 111 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.41. LSR(2) LSR(2) fornisce il valore senza segno di un registro diviso per una variabile potenza di due. Inserisce degli zeri nelle posizioni liberate dai bit shiftati, e aggiorna i flags di stato, a seconda del risultato. Sintassi LSR <Rd>, <Rs> dove: <Rd> Contiene il valore da shiftare ed è il registro di destinazione dell’operazione. <Rs> È il registro contenente il valore di shift. Il valore è memorizzato nel byte meno significativo. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione if Rs[7:0] == 0 then C Flag = unaffected Rd = unaffected else if Rs[7:0] < 32 then C Flag = Rd[Rs[7:0] - 1] Rd = Rd Logical_Shift_Right Rs[7:0] else if Rs[7:0] == 32 then C Flag = Rd[31] Rd = 0 else /* Rs[7:0] > 32 */ C Flag = 0 Rd = 0 N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 V Flag = unaffected 112 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Sintassi e codifica equivalente ARM MOVS <Rd>, <Rn>, lsr <Rs> 113 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.42. MOV(1) MOV(1) (Move) sposta un grande valore immediato in un registro. Aggiorna i flags di stato in base al risultato. Sintassi MOV <Rd>, #<immed_8> dove: <Rd> È il registro di destinazione dell’operazione. <immed_8> Valore immediato di 8-bit nell’intervallo 0-255 che viene scritto in Rd. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = immed_8 N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = unaffected V Flag = unaffected Sintassi e codifica equivalente ARM MOVS <Rd>, #<immed_8> 114 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.43. MOV(2) MOV(2) sposta un valore da un registro basso ad un altro. Aggiorna i flags di stato in base al risultato. Sintassi MOV <Rd>, <Rn> dove: <Rd> È il registro di destinazione dell’operazione. <Rn> Registro che contiene il valore da copiare. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rn N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = 0 V Flag = 0 Note Codifica Questa istruzione è codificata come ADD Rd, Rn, #0. Sintassi e codifica equivalente ARM ADDS <Rd>, <Rn>, #0 115 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.44. MOV(3) MOV(3) sposta un valore da un registro alto ad un altro. Diversamente da MOV(2) questa istruzione non aggiorna i flags di stato. Sintassi MOV <Rd>, <Rm> dove: <Rd> Specifica il registro di destinazione. Può essere uno qualsiasi tra R0 e R15. Il numero del registro è dato da H1 (bit più significativo) e Rd (i restanti tre bit). <Rm> Specifica il registro contenente il valore da copiare. Può essere uno qualsiasi tra R0 e R15. Il numero del registro è dato da H2 (bit più significativo) e Rm (i restanti tre bit). Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rm Uso L’istruzione MOV PC, R14 può essere usata come istruzione di ritorno da una subroutine se si sa che la subroutine è di tipo Thumb. Comunque, è fortemente raccomandato usare BX R14. L’istruzione BX R14 funziona sempre sia che il chiamante fosse una ruotine ARM sia che fosse una routine Thumb, ed ha vantaggi prestazionali su alcuni processori. 116 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Sintassi Assembler Se vengono specificati due registri bassi, la sintassi assembler <Rn> viene riportata all’istruzione MOV(2). Tesi di Laurea di: Loredano Rapari matr. 1029262 MOV <Rd>, Entrambi reg. bassi Se H1 == 0 e H2 == 0 nella codifica, l’istruzione specifica una copia di contenuti senza modificare i flags di stato. Questa istruzione non può essere scritta usando la sintassi MOV <Rd>, <Rm> poiché andrebbe a modificare i flags di stato. Comunque si può scrivere usando CPY. ------- Nota ---------------Nelle vers. precedenti ARMv6, specificando due reg. bassi il ris. è impreved. ------------------------------Sintassi e codifica equivalente ARM Un equivalente simile è: MOV <Rd>, <Rm> Ci sono leggere differenze quando le istruzioni accedono al PC, a causa delle differenti definizioni di PC nell’esecuzione di codice ARM e Thumb. 117 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.45. MUL MUL (Multiply) moltiplica variabili con o senza segno per ottenere un risultato di 32-bit. MUL aggiorna i flags di stato, in base al risultato. Sintassi MUL <Rd>, <Rm> dove: <Rd> Contiene il valore da moltiplicare con il valore di <Rm> ed è il registro di destinazione dell’operazione. <Rm> È il registro contenente il valore da moltiplicare con il valore di <Rd>. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = (Rm * Rd)[31:0] N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = unaffected /* See "C flag" note */ V Flag = unaffected Note Con e senza segno C Flag Siccome MUL produce solamente i 32 bits meno significativi di un prodotto a 64-bit, MUL da lo stesso risultato per moltiplicazioni di numeri con o senza sengo. L’istruzione MUL è definita in modo da lasciare il flag C inalterato in ARMv5 e superiori. Nelle versioni precedenti il valore del flag C è imprevedibile dopo l’esecuzione dell’istruzione MUL. Restrizione operandi Prima di ARMv6 specificare lo stesso registro per Rd e Rm ha risultati imprevedibili. Sintassi e codifica equivalente ARM MULS <Rd>, <Rm>, <Rd> 118 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.46. MVN MVN (Move NOT) fa il complemento di un valore in un registro. MVN aggiorna i flags di stato, in base al risultato. Sintassi MVN <Rd>, <Rm> dove: <Rd> È il registro di destinazione dell’operazione. <Rm> È il registro contenente il valore il cui complemento viene scritto in <Rd>. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = NOT Rm N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = unaffected V Flag = unaffected Sintassi e codifica equivalente ARM MVNS <Rd>, <Rm> 119 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 6.1.47. NEG NEG (Negate) nega il valore di un registro e lo salva in una altro registro. NEG aggiorna i flags di stato, in base al risultato. Sintassi NEG <Rd>, <Rm> dove: <Rd> È il registro di destinazione dell’operazione. <Rm> È il registro contenente il valore che verrà sottratto da zero. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = 0 - Rm N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = NOT BorrowFrom(0 - Rm) V Flag = OverflowFrom(0 - Rm) Sintassi e codifica equivalente ARM RSBS <Rd>, <Rm>, #0 120 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.48. ORR ORR (Logical OR) fa un OR bit a bit tra i valori di due registri. ORR aggiorna i flags di stato, in base al risultato. Sintassi ORR <Rd>, <Rm> dove: <Rd> È il registro di destinazione dell’operazione. <Rm> È il registro contenente il valore che verrà confrontato con quello in <Rd>. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rd OR Rm N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = unaffected V Flag = unaffected Sintassi e codifica equivalente ARM ORRS <Rd>, <Rd>, <Rm> 121 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.49. POP (Pop Multiple Registers) carica un sottoinsieme (o tutti) di registri generici R0-R7 e il PC dallo stack. POP I registri generici caricati possono includere il PC. Se è così, la parola caricata per il PC è trattata come un indirizzo e avviene un salto a questo indirizzo. In ARMv5 e superiori, il bit[0] del valore caricato determina se l’esecuzione continua, dopo questo salto, nello stato ARM o nello stato Thumb, come se fosse stata eseguita l’istruzione seguente: BX (loaded_value) Nelle varianti T di ARMv4, il bit*0+ del valore caricato viene ignorato e l’esecuzione continua nello stato Thumb, come se fosse stata eseguita la seguente istruzione: MOV PC, (loaded_value) Sintassi POP <registers> dove: <registers> È la lista dei registri da caricare, separati da una virgola e racchiusi tra parentesi graffe. La lista è codificata nel campo register_list dell’istruzione, settando il bit*i+ a 1 se il registro Ri è incluso nella lista, a zero altrimenti per ogni i da 0 a 7. Il bit R è settato a 1 se il PC è incluso nella lista, è settato a 0 altrimenti. Almeno un registro deve essere caricato. Se tutti i bit[8:0] sono a zero il risultato è imprevedibile. I registri vengono caricati in sequenza, dal registro col numero più basso a cui corrisponde l’indirizzo più piccolo in memoria (l’indirizzo iniziale), fino al registro col numero più alto a cui corrisponde l’indirizzo più grande in memoria (l’indirizzo finale). Se il PC è specificato nella lista (bit*8+ settato a 1), l’istrtuzione causa un salto all’indirizzo caricato nel PC. L’indirizzo iniziale è il valore del registro SP. Gli indirizzi succesivi sono formati incrementando l’indirizzo precedente di 4. Viene prodotto un indirizzo per ogni registro specificato in register_list. L’indirizzo finale è formato da: registro_base + 4 * (numero_registri_specificati – 1). Infine il valore di SP è incrementato di quattro volte i registri specificati in register_list. Versione architettura Tutte le varianti T Eccezioni Data Abort. 122 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Operazione MemoryAccess(B-bit, E-bit) start_address = SP end_address = SP + 4*(R + Number_Of_Set_Bits_In(register_list)) address = start_address for i = 0 to 7 if register_list[i] == 1 then Ri = Memory[address,4] address = address + 4 if R == 1 then value = Memory[address,4] PC = value AND 0xFFFFFFFE if (architecture version 5 or above) then T Bit = value[0] address = address + 4 assert end_address = address SP = end_address Uso Usare POP per operazioni di stack. Un’istruzione POP con il PC nella lista dei registri può essere usata per un’efficiente procedura di uscita, infatti, ripristina i registri salvati, carica il PC con l’indirizzo di ritorno, e aggiorna lo stack pointer con una sola istruzione. Note Data Abort Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. CPSR Solo il bit T del CPSR può essere aggiornano da pop gli altri bit non vengono modificati. Allineamento Se un implementazione include un sistema di controllo coprocessore e il controllo dell’allineamento è abilitato, un indirizzo con i bit*1:0+ != 0b00 causa un’eccezione di allineamento. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un DataAbort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; 123 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb - Tesi di Laurea di: Loredano Rapari matr. 1029262 e CP15_reg1_Ubit == 1, un accesso non allineato causa un DataAbort. Trasferimento ARM/Thumb In ARMv5 e superiori se i bits[1:0] del valore caricato per R15 sono 0b10, il risultato è imprevedibile, poiché i salti a parole non allineate non sono possibili nello stato ARM. Time order L’ordine cronologico di accesso alle parole individuali della memoria generato da questa istruzione è definito solo in alcune circostanze. Vedere Restrizioni di accesso alla memoria per maggiori dettagli. Sintassi e codifica equivalente ARM LDMIA SP!, <registers> 124 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.50. PUSH (Push Multiple Registers) salva un sottoinsieme (o tutti) di registri generici R0-R7 e LR nello stack. PUSH Sintassi PUSH <registers> dove: <registers> È la lista dei registri da salvare, separati da una virgola e racchiusi tra parentesi graffe. La lista è codificata nel campo register_list dell’istruzione, settando il bit*i+ a 1 se il registro Ri è incluso nella lista, a zero altrimenti per ogni i da 0 a 7. Il bit R è settato a 1 se il PC è incluso nella lista, è settato a 0 altrimenti. Almeno un registro deve essere salvato. Se tutti i bit[8:0] sono a zero il risultato è imprevedibile. I registri vengono salvati in sequenza, dal registro col numero più basso a cui corrisponde l’indirizzo più piccolo in memoria (l’indirizzo iniziale), fino al registro col numero più alto a cui corrisponde l’indirizzo più grande in memoria (l’indirizzo finale). Se il PC è specificato nella lista (bit*8+ settato a 1), l’istrtuzione causa un salto all’indirizzo caricato nel PC. L’indirizzo iniziale è il valore del registro SP. Gli indirizzi succesivi sono formati incrementando l’indirizzo precedente di 4. Viene prodotto un indirizzo per ogni registro specificato in register_list. L’indirizzo finale è formato da: registro_base + 4 * (numero_registri_specificati – 1). Infine il valore di SP è incrementato di quattro volte i registri specificati in register_list. Versione architettura Tutte le varianti T Eccezioni Data Abort. 125 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Operazione MemoryAccess(B-bit, E-bit) start_address = SP - 4*(R + Number_Of_Set_Bits_In(register_list)) end_address = SP - 4 address = start_address for i = 0 to 7 if register_list[i] == 1 Memory[address,4] = Ri address = address + 4 if R == 1 Memory[address,4] = LR address = address + 4 assert end_address == address - 4 SP = SP - 4*(R + Number_Of_Set_Bits_In(register_list)) if (CP15_reg1_Ubit == 1) /* ARMv6 */ if Shared(address then /* from ARMv6 */ physical_address = TLB(address ClearExclusiveByAddress(physical_address, size) Uso Usare PUSH per operazioni di stack. Un’istruzione PUSH con LR nella lista dei registri può essere usata per un’efficiente procedura di entrata, infatti, salva i registri (incluso l’indirizzo di ritorno), e aggiorna lo stack pointer con una sola istruzione. Una corrispondente istruzione pop può essere usata dopo per ritornare dalla procedura. 126 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Allineamento Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Se un implementazione include un sistema di controllo coprocessore e il controllo dell’allineamento è abilitato, un indirizzo con i bit*1:0+ != 0b00 causa un’eccezione di allineamento. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Time order Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un DataAbort. L’ordine cronologico di accesso alle parole individuali della memoria generato da questa istruzione è definito solo in alcune circostanze. Vedere Restrizioni di accesso alla memoria per maggiori dettagli. Sintassi e codifica equivalente ARM STMD SP!, <registers> 127 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.51. REV (Byte-Reverse Word) inverte l’ordine del byte in un registro a 32-bit. Non ha effetti sui flags di stato. REV Sintassi REV <Rd>, <Rn> dove: <Rd> È il registro di destinazione dell’operazione. <Rn> È il registro che contiene l’operando. Versione architettura ARMv6 e superiori. Eccezioni Nessuna Operazione Rd[31:24] = Rn[ 7: 0] Rd[23:16] = Rn[15: 8] Rd[15: 8] = Rn[23:16] Rd[ 7: 0] = Rn[31:24] Uso Usare REV per convertire un dato a 32-bit codificato con l’ordine “big-endian” in “little-endian” o viceversa. Sintassi e codifica equivalente ARM REV <Rd>, <Rm> 128 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.52. REV16 REV16 (Byte-Reverse Packed Halfword) inverte l’ordine di ogni parola a 16-bit di un registro a 32bit. Non ha effetti sui flags di stato. Sintassi REV16 <Rd>, <Rn> dove: <Rd> È il registro di destinazione dell’operazione. <Rn> È il registro che contiene l’operando. Versione architettura ARMv6 e superiori. Eccezioni Nessuna Operazione Rd[15: 8] = Rn[ 7: 0] Rd[ 7: 0] = Rn[15: 8] Rd[31:24] = Rn[23:16] Rd[23:16] = Rn[31:24] Uso Usare REV16 per convertire un dato a 16-bit codificato con l’ordine “big-endian” in “little-endian” o viceversa. Sintassi e codifica equivalente ARM REV16 <Rd>, <Rm> 129 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.53. REVSH (Byte-Reverse Signed Halfword) inverte l’ordine della parola a 16-bit nella parte bassa di un registro a 32-bit ed estende il segno fino a 32-bit. Non ha effetti sui flags di stato. REVSH Sintassi REVSH <Rd>, <Rn> dove: <Rd> È il registro di destinazione dell’operazione. <Rn> È il registro che contiene l’operando. Versione architettura ARMv6 e superiori. Eccezioni Nessuna Operazione Rd[15: 8] = Rn[ 7: 0] Rd[ 7: 0] = Rn[15: 8] if Rn[7] == 1 then Rd[31:16] = 0xFFFF else Rd[31:16] = 0x0000 Uso Usare REVSH per convertire: un dato a 16-bit codificato in “big-endian” in un dato “little-endian” con segno a 32-bit. un dato a 16-bit codificato in “little-endian” in un dato “big-endian” con segno a 32-bit. Sintassi e codifica equivalente ARM REVSH <Rd>, <Rm> 130 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.54. ROR (Rotate Right Register) fornisce il contenuto di un registro ruotato di un valore variabile. I bit che escono a destra nella rotazione vengono inseriti nei posti vuoti sulla sinistra. ROR ROR aggiorna i flags di condizione, a seconda del risultato. Sintassi ROR <Rd>, <Rs> dove: <Rd> Contiene il valore da ruotare, ed è anche il registro di destinazione dell’operazione. <Rs> È il registro contenente la rotazione applicata al valore di <Rd>. Il valore di rotazione è contenuto nel byte meno significativo. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione if Rs[7:0] == 0 then C Flag = unaffected Rd = unaffected //se gli ultimi 5 bit sono zeri significa che ruota di un multiplo di 32, quindi <Rd> rimane invariato else if Rs[4:0] == 0 then C Flag = Rd[31] Rd = unaffected else /* Rs[4:0] > 0 */ C Flag = Rd[Rs[4:0] - 1] Rd = Rd Rotate_Right Rs[4:0] N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 V Flag = unaffected 131 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Sintassi e codifica equivalente ARM MOV <Rd>, <Rd>, ror <Rs> 132 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.55. SBC (Subtract with Carry) sottrae il valore del secondo operando e del flag C negato dal primo operando. SBC SBC aggiorna i flags di condizione, a seconda del risultato. Usare SBC per sintetizzare sottrazioni multiparola. Sintassi SBC <Rd>, <Rm> dove: <Rd> Contiene il primo operando della sottrazione, ed è anche il registro di destinazione dell’operazione. <Rm> Contiene il valore da sottrarre ad <Rd>. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rd - Rm - NOT(C Flag) N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = NOT BorrowFrom(Rd - Rm - NOT(C Flag)) V Flag = OverflowFrom(Rd - Rm - NOT(C Flag)) Sintassi e codifica equivalente ARM SBCS <Rd>, <Rd>, <Rm> 133 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.56. SETEND SETEND modifica il bit E del CPSR, senza toccare gli altri bits del CPSR. Sintassi SETEND <endian_specifier> dove: <endian_specifier> Può essere: LE E=0 BE E=1 Versione architettura ARMv6 e superiori Eccezioni Nessuna Operazione CPSR = CPSR con modifica opportune del bit E Uso Usare SETEND per cambiare l’ordine di accesso ai byte dei dati. Si può usare SETEND per incrementare l’efficienza di accesso ad una serie di dati big-endian in una diversa applicazione little-endian, o viceversa. Vedere la sezione Supporto Endian per maggiori informazioni. Sintassi e codifica equivalente ARM SETEND 134 <endian_specifier> Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.57. STMIA (Store Multiple Increment After) salva un sottoinsieme non vuoto, oppure tutti, i registri generici (R0-R7) in locazioni di memoria sequenziali. STMIA Sintassi STMIA <Rn>!, <registers> dove: <Rn> Specifica il registro contenente l’indirizzo di inizio per l’istruzione. ! Causa la riscrittura del registro base, e non è opzionale. <registers> È la lista dei registri da salvare, separati da una virgola e racchiusi tra parentesi graffe. La lista è codificata nel campo register_list dell’istruzione, settando il bit[i] a 1 se il registro Ri è incluso nella lista, a zero altrimenti per ogni i da 0 a 7. Almeno un registro deve essere salvato. Se tutti i bit[7:0] sono a zero il risultato è imprevedibile. I registri vengono salvati in sequenza, dal registro col numero più basso a cui corrisponde l’indirizzo più piccolo in memoria (l’indirizzo iniziale), fino al registro col numero più alto a cui corrisponde l’indirizzo più grande in memoria (l’indirizzo finale). L’indirizzo iniziale è il valore del registro base Rn. Gli indirizzi succesivi sono formati incrementando l’indirizzo precedente di 4. Viene prodotto un indirizzo per ogni registro specificato in <registers>. L’indirizzo finale è formato da: registro_base + 4 * (numero_registri_specificati – 1). Infine, il valore di <Rn> è incrementato di quattro volte i registri specificati in <registers>. Versione architettura Tutte le varianti T Eccezioni Data Abort 135 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Operazione MemoryAccess(B-bit, E-bit) processor_id = ExecutingProcessor() start_address = Rn end_address = Rn + (Number_Of_Set_Bits_In(register_list) * 4) - 4 address = start_address for i = 0 to 7 if register_list[i] == 1 Memory[address,4] = Ri if Shared(address) then /* from ARMv6 */ physical_address = TLB(address) ClearExclusiveByAddress(physical_address,4) address = address + 4 assert end_address == address - 4 Rn = Rn + (Number_Of_Set_Bits_In(register_list) * 4) Uso Usare STMIA come istruzione per salvare blocchi dalla memoria. In combinazione con ldmia permette un’efficiente gestione della copia di blocchi di memoria. Note Restrizione operandi Se <Rn> è specificato in <registers>: Data Abort se <Rn> è l’ultimo registro specificato in <registers>, il suo valore originale viene salvato altrimenti, il valore salvato per <Rn> è imprevedibile Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Se un implementazione include un sistema di controllo coprocessore e il controllo dell’allineamento è abilitato, un indirizzo con i bit*1:0+ != 0b00 causa un’eccezione di allineamento. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: 136 Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Time order Tesi di Laurea di: Loredano Rapari matr. 1029262 L’ordine cronologico di accesso alle parole individuali della memoria generato da questa istruzione è definito solo in alcune circostanze. Vedere Restrizioni di accesso alla memoria per maggiori dettagli. Sintassi e codifica equivalente ARM STMIA <Rn>!, <registers> 137 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.58. STR(1) STR(1) (Store Register) permette di salvare un dato di 32-bit da un registro in memoria. Il modo di indirizzamento è utile per accedere a strutture (record). Con un offset di zero l’indirizzo prodotto è l’inalterato valore del registro base Rn. Sintassi STR <Rd>, [<Rn>, #<immed_5> * 4] dove: <Rd> È il registro che contiene il valore della parola da salvare in memoria. <Rn> È il registro contenente l’indirizzo base dell’istruzione. <immed_5> È un valore di 5-bit che viene moltiplicato per 4 e aggiunto ad Rn per formare l’indirizzo di memoria. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) processor_id = ExecutingProcessor() address = Rn + (immed_5 * 4) if (CP15_reg1_Ubit == 0) if address[1:0] == 0b00 then Memory[address,4] = Rd else Memory[address,4] = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ Memory[address,4] = Rd if Shared(address) then /* from ARMv6 */ physical_address = TLB(address) ClearExclusiveByAddress(physical_address, 4) 138 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non è allineato alla parola, l’istruzione è imprevedibile. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM STR <Rd>, [<Rn>, #<immed_5> * 4] 139 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.59. STR(2) STR(2) permette di salvare un dato di 32-bit da un registro in memoria. Il modo di indirizzamento è utile per puntatori + offset e per accedere ad un elemento di un vettore. Sintassi STR <Rd>, [<Rn>, <Rm>] dove: <Rd> È il registro contenente la parola da salvare in memoria. <Rn> È il registro contenente il primo valore usato per formare l’indirizzo. <Rm> È il registro contenente il secondo valore usato per formare l’indirizzo. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) processor_id = ExecutingProcessor() address = Rn + Rm if (CP15_reg1_Ubit == 0) if address[1:0] == 0b00 then Memory[address,4] = Rd else Memory[address,4] = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ Memory[address,4] = Rd if Shared(address) then /* from ARMv6 */ physical_address = TLB(address) ClearExclusiveByAddress(physical_address, 4) 140 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non è allineato alla parola, l’istruzione è imprevedibile. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM STR <Rd>, [<Rn>, <Rm>] 141 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.60. STR(3) STR(3) permette di salvare un dato di 32-bit da un registro in memoria. Il modo di indirizzamento è utile per accedere allo stack. In questo caso, str salva una parola da <Rd> in memoria. Sintassi STR <Rd>, [SP, #<immed_8> * 4] dove: <Rd> È il registro che contiene la parola da salvare in memoria. SP È lo Stack Pointer. Il suo valore è usato per calcolare l’indirizzo di memoria. <immed_8> È un valore di 8-bit che moltiplicato per 4 e aggiunto al valore del SP forma l’indirizzo di memoria. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) processor_id = ExecutingProcessor() address = SP + (immed_8 * 4) if (CP15_reg1_Ubit == 0) if address[1:0] == 0b00 then Memory[address,4] = Rd else Memory[address,4] = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ Memory[address,4] = Rd if Shared(address) then /* from ARMv6 */ physical_address = TLB(address) ClearExclusiveByAddress(physical_address, 4) 142 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non è allineato alla parola, l’istruzione è imprevedibile. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM STR <Rd>, [SP, #<immed_8> * 4] 143 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.61. STRB(1) STRB(1) (Store Register Byte) salva un dato di 8-bit da un registro generico in memoria. Il modo di indirizzamento è utile per accedere a strutture o record. Con un offset pari a zero, l’indirizzo prodotto è il valore inalterato dell’indirizzo base Rn. Sintassi STRB <Rd>, [<Rn>, #<immed_5>] dove: <Rd> È il registro contenente il byte da salvare in memoria. <Rn> È il registro contenente l’indirizzo base per l’istruzione. <immed_5> È un valore di 5-bit che viene aggiunto al valore di Rn per formare l’indirizzo di memoria. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) processor_id = ExecutingProcessor() address = Rn + immed_5 Memory[address,1] = Rd[7:0] if Shared(address) then /* from ARMv6 */ physical_address = TLB(address) ClearExclusiveByAddress(physical_address, 1) 144 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Sintassi e codifica equivalente ARM STRB <Rd>, [<Rn>, #<immed_5>] 145 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.62. STRB(2) STRB(2) salva un dato di 8-bit contenuto in un registro in memoria. Il modo di indirizzamento è utile per puntatori + offset e per accedere ad un elemento di un vettore. Sintassi STRB <Rd>, [<Rn>, <Rm>] dove: <Rd> È il registro contenente il byte da salvare in memoria. <Rn> È il registro contenente il primo valore usato per formare l’indirizzo. <Rm> È il registro contenente il secondo valore usato per formare l’indirizzo. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) processor_id = ExecutingProcessor() address = Rn + Rm Memory[address,1] = Rd[7:0] if Shared(address) then /* from ARMv6 */ physical_address = TLB(address) ClearExclusiveByAddress(physical_address, 1) Note Data Abort Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Sintassi e codifica equivalente ARM STRB <Rd>, [<Rn>, <Rm>] 146 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.63. STRH(1) STRH(1) (Store Register Halfword) salva mezza parola (16-bit) contenuta in un registro generico in memoria. Il modo di indirizzamento è utile per accedere a strutture o record. Con un offset pari a zero, l’indirizzo prodotto è il valore inalterato dell’indirizzo base Rn. Sintassi STRH <Rd>, [<Rn>, #<immed_5> * 2] dove: <Rd> È il registro contenente la mezza parola da salvare in memoria. <Rn> È il registro contenente l’indirizzo base per l’istruzione. <immed_5> È un valore di 5-bit che moltiplicato per 2 viene aggiunto al valore di Rn per formare l’indirizzo di memoria. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) processor_id = ExecutingProcessor() address = Rn + (immed_5 * 2) if (CP15_reg1_Ubit == 0) if address[0] == 0b0 then Memory[address,2] = Rd[15:0] else Memory[address,2] = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ Memory[address,2] = Rd[15:0] if Shared(address) then /* from ARMv6 */ physical_address = TLB(address) ClearExclusiveByAddress(physical_address, 2) 147 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non era allineato alla parola, i dati letti dalla memoria erano casuali. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM STRH <Rd>, [<Rn>, #<immed_5> * 2] 148 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.64. STRH(2) STRH(2) salva mezza parola (16-bit) da un registro generico in memoria. Il modo di indirizzamento è utile per puntatori + offset e per accedere ad un elemento di un vettore. Sintassi STRH <Rd>, [<Rn>, <Rm>] dove: <Rd> È il registro contenente la mezza parola da salvare in memoria. <Rn> È il registro contenente il primo valore usato per formare l’indirizzo. <Rm> È il registro contenente il secondo valore usato per formare l’indirizzo. Versione architettura Tutte le varianti T Eccezioni Data Abort Operazione MemoryAccess(B-bit, E-bit) processor_id = ExecutingProcessor() address = Rn + Rm if (CP15_reg1_Ubit == 0) if address[0] == 0b0 then Memory[address,2] = Rd[15:0] else Memory[address,2] = UNPREDICTABLE else /* CP15_reg1_Ubit == 1 */ Memory[address,2] = Rd[15:0] if Shared(address) then /* from ARMv6 */ physical_address = TLB(address) ClearExclusiveByAddress(physical_address, 2) 149 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Note Data Abort Tesi di Laurea di: Loredano Rapari matr. 1029262 Per i dettagli sugli effetti dell’istruzione se avviene un Data Abort controllare la sezione Effetti delle istruzioni che hanno provocato un Data-Abort. Allineamento Prima di ARMv6, se l’indirizzo di memoria non era allineato alla parola, i dati letti dalla memoria erano casuali. Il controllo di allineamento (si verifica un Data-Abort quando i bit*1:0+ dell’indirizzo sono diversi da 0b00), e il supporto per dati più grandi di 32-bit erano opzioni delle implementazioni. L’opzione di controllo dell’allineamento viene supportata dall’ARMv6 in poi: Se CP15_reg1_Abit == 1, un accesso non allineato causa un Data-Abort. Se CP15_reg1_Abit == 0: - e CP15_reg1_Ubit == 0, l’istruzione ignora i due bit meno significativi dell’indirizzo; - e CP15_reg1_Ubit == 1, un accesso non allineato causa un Data-Abort. Sintassi e codifica equivalente ARM STRH <Rd>, [<Rn>, <Rm>] 150 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.65. SUB(1) SUB(1) (Subtract) sottrare il valore di una piccola costante dal valore di un registro e mette il risultato in un secondo registro. Aggiorna i flag di stato, a seconda del risultato. Sintassi SUB <Rd>, <Rn>, #<immed_3> dove: <Rd> Registro di destinazione. <Rn> Specifica il registro che contiene il primo operando della sottrazione. <immed_3> Specifica un valore a 3-bit che viene sottratto a <Rn>. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rn - immed_3 N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = NOT BorrowFrom(Rn - immed_3) V Flag = OverflowFrom(Rn - immed_3) Sintassi e codifica equivalente ARM SUBS <Rd>, <Rn>, #<immed_3> 151 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.66. SUB(2) SUB(2) sottrare il valore di una grande costante dal valore di un registro e mette il risultato nel registro stesso. Aggiorna i flag di stato, a seconda del risultato. Sintassi SUB <Rd>, #<immed_8> dove: <Rd> Specifica il registro che contiene il primo operando della sottrazione, ed è anche il registro di destinazione. <immed_8> Specifica un valore a 8-bit che viene sottratto a <Rd>. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rd - immed_8 N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = NOT BorrowFrom(Rd - immed_8) V Flag = OverflowFrom(Rd - immed_8) Sintassi e codifica equivalente ARM SUBS <Rd>, <Rd>, #<immed_8> 152 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.67. SUB(3) SUB(3) sottrare il valore di un registro dal valore di un secondo registro e salva il risultato in un terzo registro. Aggiorna i flag di stato, a seconda del risultato. Sintassi SUB <Rd>, <Rn>, <Rm> dove: <Rd> È il registro di destinazione. <Rn> Contiene il primo operando della sottrazione. <Rm> Contiene il valore che viene sottratto a <Rn>. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione Rd = Rn - Rm N Flag = Rd[31] Z Flag = if Rd == 0 then 1 else 0 C Flag = NOT BorrowFrom(Rn - Rm) V Flag = OverflowFrom(Rn - Rm) Sintassi e codifica equivalente ARM SUBS <Rd>, <Rn>, <Rm> 153 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.68. SUB(4) SUB(4) decrementa lo SP di 4 volte un valore immediato a 7-bit (cioè un multiplo di 4 nell’intervallo 0-508). I flags di stato non vengono modificati. Sintassi SUB SP, #<immed_7> * 4 dove: <SP> Indica lo Stack Pointer. Il risultato dell’operazione viene salvato nello SP. <immed_7> Valore immediato di 7-bit che viene sottratto allo SP. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione SP = SP - (immed_7 << 2) // l’operatore ‘<<’ indica lo shift aritmetico a sinistra di n bit, che n equivale a moltiplicare per 2 . Uso Per lo stack decrescente che usa il set Thumb, decrementeare lo SP significa allocare ulteriore memoria all’inizio dello stack. Note Questa istruzione può anche essere scritta in questo modo: SUB SP, SP, #<immed_7> * 4. Sintassi e codifica equivalente ARM SUB SP, SP, #<immed_7> * 4 154 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.69. SWI (Software Interrupt) genera un’interruzione software o SWI, che è gestita dal sistema operativo. SWI Usare quest’istruzione come chiamata ad un servizio del sistema operativo per fornire un servizio. Sintassi SWI #<immed_8> dove: <immed_8> È un valore di 8-bit inserito nei bits*7:0+ dell’istruzione. Questo valore è ignorato dal processore, ma può essere usato da un gestore di SWI del sistema operativo per capire quale servizio si sta richiedendo. Versione architettura Tutte le varianti T Eccezioni Software Interrupts Operazione R14_svc = address of next instruction after the SWI instruction SPSR_svc = CPSR CPSR[4:0] = 0b10011 /* Enter Supervisor mode */ CPSR[5] = 0 /* Execute in ARM state */ /* CPSR[6] is unchanged */ CPSR[7] = 1 /* Disable normal interrupts */ /* CPSR[8] is unchanged */ CPSR[9] = CP15_reg1_EEbit if high vectors configured then PC = 0xFFFF0008 else PC = 0x00000008 Sintassi e codifica equivalente ARM SWI #<immed_8> 155 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.70. SXTB (Signed Extend Byte) estrae gli 8-bit meno significativi dell’operando e fa un’estensione di segno a 32-bit. SXTB Non modifica i flags di stato. Sintassi SXTB <Rd>, <Rm> dove: <Rd> Specifica il registro di destinazione. <Rm> Specifica il registro dell’operando. Versione architettura ARMv6 e superiori Eccezioni Nessuna Operazione Rd = SignExtend(Rm[7:0]) Uso Usare SXTB per fare un’estensione di segno di un byte ad una parola, per esempio su sequenze di istruzioni che lavorano su dati di tipo signed char in C/C++. Sintassi e codifica equivalente ARM SXTB <Rd>, <Rm> 156 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.71. SXTH (Signed Extend Halfword) estrae i 16-bit meno significativi dell’operando e fa un’estensione di segno a 32-bit. SXTH Non modifica i flags di stato. Sintassi SXTH <Rd>, <Rm> dove: <Rd> Specifica il registro di destinazione. <Rm> Specifica il registro dell’operando. Versione architettura ARMv6 e superiori Eccezioni Nessuna Operazione Rd = SignExtend(Rm[15:0]) Uso Usare SXTH per fare un’estensione di segno di una mezza parola ad una parola, per esempio su sequenze di istruzioni che lavorano su dati di tipo signed short in C/C++. Sintassi e codifica equivalente ARM SXTH <Rd>, <Rm> 157 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.72. TST (Test) determina se in un particolare sottoinsieme di bits in un registro è presente almeno un bit ad settato ad 1. Un uso comune di TST è per testare se un singolo bit è settato ad 1 o a 0. TST Aggiorna i flags di stato, a seconda del risultato. Sintassi TST <Rn>, <Rm> dove: <Rn> Specifica il registro contenente il primo operando dell’operazione. <Rm> È il valore con il quale si fa un AND Logico con il valore in <Rn>. Versione architettura Tutte le varianti T Eccezioni Nessuna Operazione alu_out = Rn AND Rm N Flag = alu_out[31] Z Flag = if alu_out == 0 then 1 else 0 C Flag = unaffected V Flag = unaffected Sintassi e codifica equivalente ARM TST <Rn>, <Rm> 158 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.73. UXTB (Unsigned Extend Byte) estrae gli 8-bit meno significativi dell’operando e fa un’estensione di zeri a 32-bit. UXTB Non modifica i flags di stato. Sintassi UXTB <Rd>, <Rm> dove: <Rd> Specifica il registro di destinazione. <Rm> Specifica il registro dell’operando. Versione architettura ARMv6 e superiori Eccezioni Nessuna Operazione Rd = Rm AND 0x000000ff Uso Usare UXTB per fare un’estensione di zeri di un byte ad una parola, per esempio su sequenze di istruzioni che lavorano su dati di tipo unsigned char in C/C++. Sintassi e codifica equivalente ARM UXTB <Rd>, <Rm> 159 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.1.74. UXTH (Unsigned Extend Halfword) estrae i 16-bit meno significativi dell’operando e fa un’estensione di zeri a 32-bit. UXTH Non modifica i flags di stato. Sintassi UXTH <Rd>, <Rm> dove: <Rd> Specifica il registro di destinazione. <Rm> Specifica il registro dell’operando. Versione architettura ARMv6 e superiori Eccezioni Nessuna Operazione Rd = Rm AND 0x0000ffff Uso Usare UXTH per fare un’estensione di zeri di una mezza parola ad una parola, per esempio su sequenze di istruzioni che lavorano su dati di tipo unsigned short in C/C++. Sintassi e codifica equivalente ARM UXTH <Rd>, <Rm> 160 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 6.2. Istruzioni Thumb e versione architettura La tabella mostra quali istruzioni sono presenti in ogni architettura ARM che supporta il Thumb. Tabella 6.1 Istruzioni presenti nelle varie versioni dell’architettura Istruzioni v4T v5T v6 ADC Si Si Si ADD (tutte le forme) Si Si Si AND Si Si Si ASR (entrambe le forme) Si Si Si B (entrambe le forme) Si Si Si BIC Si Si Si BKPT No Si Si BL Si Si Si BLX (entrambe le forme) No Si Si BX Si Si Si CMN Si Si Si CMP (tutte le forme) Si Si Si CPS No No Si CPY No No Si EOR Si Si Si LDMIA Si Si Si LDR (tutte le forme) Si Si Si LDRB (entrambe le forme) Si Si Si LDRH (entrambe le forme) Si Si Si LDRSB Si Si Si LDRSH Si Si Si LSL (entrambe le forme) Si Si Si LSR (entrambe le forme) Si Si Si MOV (tutte le forme) Si Si Si MUL Si Si Si MVN Si Si Si NEG Si Si Si ORR Si Si Si POP Si Si Si PUSH Si Si Si REV (tutte le forme) No No Si ROR Si Si Si SBC Si Si Si SETEND No No Si STMIA Si Si Si STR (tutte le forme) Si Si Si STRB (entrambe le forme) Si Si Si STRH (entrambe le forme) Si Si Si SUB (tutte le forme) Si Si Si SWI Si Si Si SXTB/H No No Si TST Si Si Si UXTB/H No No Si 161 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 7. Test Finora sono state descritte le varie funzionalità dell’architettura ARM, la configurazione dell’hardware disponibile e le istruzioni del set Thumb. Ora vediamo in che modo funziona questo particolare set di istruzioni a 16 bit facendo dei test sul processore con dei semplici programmini. 7.1. Impostazioni test Innanzitutto si ha un programma scritto in C. La scelta di questo linguaggio di programmazione è quasi ovvia quando sappiamo che sulla scheda gira un sistema Linux debian e i programmi da realizzare per i test sono davvero semplici. Quindi si ha il codice C del programma, il quale viene compilato tramite il compilatore Sourcery G++ Lite 2011.03-41 for ARM GNU/Linux , in ambiente Linux. Il comando usato per compilare il codice è: arm-none-linux-gnueabi-gdb [options] nome_file specificando le opzioni: -mthumb specifica al compilatore che il set di istruzioni con cui compilare il programma è il set Thumb (istruzioni a 16 bit) -S genera il file contenente il codice assembler invece che il binario eseguibile -o output specifica il nome del file di output -O1, -O2, -O3 con queste opzioni si specificano le varie ottimizzazioni che il compilatore è in grado di apportare al codice generato Con queste opzioni il codice generato è di default per l’architettura ARMv5TE, proprio quella del processore considerato. Per quanto riguarda le ottimizzazioni, invece, queste sono le principali modifiche apportate dalla prima ottimizzazione (-O1): - Aumento e decremento degli indirizzi combinati con gli accessi in memoria; Fa un propagamento di copia per ridurre le dipendenze di scheduling prima e dopo l’allocazione dei registri; Esegue l’eliminazione di codice morto; Usa l’esecuzione condizionata, dove possibile, per trasformare i salti condizionati in codice equivalente senza salti; Scopre quali funzioni sono pure e quali costanti; Esegue l’eliminazione condizionata di codice morto per chiamate a funzioni di sistema. La seconda ottimizzazione (-O2) apporta le modifiche della prima, in più fa anche le seguenti operazioni: - Allinea l’inizio delle funzioni in memoria su indirizzi multipli di potenze di due; Abilita l’allocazione dei valori sui registri che verranno usati dalle chiamate di funzione; Esegue altre piccole ottimizzazioni su codice che può risultare pesante. La terza ottimizzazione (-O3) fa tutto ciò che fanno la prima e la seconda, in più: - 162 Integra tutte le funzioni semplici nei loro chiamanti; Aumenta molto il codice cercando di eliminare il più possibile cicli e salti per rendere il programma lineare. Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Come si può notare le prime due ottimizzazioni tendono a ridurre il codice, mentre la terza lo aumenta ma lo rende più lineare. Dopo aver creato i file binari si eseguono dei test di velocità di esecuzione del programma sulla cpu, tramite l’apposito comando Linux: time ./nome_eseguibile Questo comando può essere anteposto a qualsiasi altro comando per ottenere statistiche sul tempo di esecuzione: - real: tempo trascorso dall’invocazione alla terminazione del comando; user: tempo di CPU in user space; sys: tempo di CPU in kernel space. Vengono effettuate 10 prove per ogni codice e si calcolano i tempi medi. Dopodiché viene realizzato un grafico della distribuzione gaussiana dei tempi per confrontare i vari test. 7.2. Programma test: Fattoriale Questo semplice programma esegue il fattoriale di 100 numeri da 0 a 99 e scrive i risultati a schermo. 7.2.1. Codice C Fattoriale.c /----------------------------------------------------------------------------------------/ #include <stdio.h> double factorial(double n) { if (n == 0) return 1; return n * factorial (n - 1); } int main () { int i; double n; for (i = 0; i < 100; ++i) { n = factorial (i); printf ("factorial(%d) = %.0e\n", i, n); } return 0; } /----------------------------------------------------------------------------------------/ 163 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 7.2.2. Tesi di Laurea di: Loredano Rapari matr. 1029262 Codice Assembler Di seguito i vari codici assembler ottenuti dal compilatore compilando il codice C precedente, con le varie ottimizzazioni. 7.2.2.1. Arm .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 6 .eabi_attribute 18, 4 .file "main.c" .global __aeabi_dcmpeq .global __aeabi_dsub .global __aeabi_dmul .text .align 2 .global factorial .type factorial, %function factorial: .fnstart .LFB0: @ args = 0, pretend = 0, frame = 8 @ frame_needed = 1, uses_anonymous_args = 0 stmfd sp!, {fp, lr} .save {fp, lr} .setfp fp, sp, #4 add fp, sp, #4 .pad #8 sub sp, sp, #8 strd r0, [fp, #-12] ldrd r0, [fp, #-12] mov r2, #0 mov r3, #0 bl __aeabi_dcmpeq mov r3, r0 cmp r3, #0 beq .L6 .L5: mov r2, #0 mov r3, #1069547520 add r3, r3, #3145728 b .L4 .L6: ldrd r0, [fp, #-12] mov r2, #0 mov r3, #1069547520 add r3, r3, #3145728 bl __aeabi_dsub mov r2, r0 mov r3, r1 mov r0, r2 mov r1, r3 bl factorial mov r2, r0 mov r3, r1 mov r0, r2 mov r1, r3 ldrd r2, [fp, #-12] bl __aeabi_dmul mov r2, r0 mov r3, r1 .L4: mov r0, r2 mov r1, r3 sub sp, fp, #4 ldmfd sp!, {fp, pc} .fnend .size factorial, .-factorial .global __aeabi_i2d .section .rodata 164 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 .align 2 .LC0: .ascii "factorial(%d) = %.0e\012\000" .text .align 2 .global main .type main, %function main: .fnstart .LFB1: @ args = 0, pretend = 0, frame = 16 @ frame_needed = 1, uses_anonymous_args = 0 stmfd sp!, {fp, lr} .save {fp, lr} .setfp fp, sp, #4 add fp, sp, #4 .pad #16 sub sp, sp, #16 mov r3, #0 str r3, [fp, #-8] b .L8 .L9: ldr bl mov mov mov mov bl strd ldr mov ldr ldrd bl ldr add str r0, [fp, #-8] __aeabi_i2d r2, r0 r3, r1 r0, r2 r1, r3 factorial r0, [fp, #-20] r3, .L10 r0, r3 r1, [fp, #-8] r2, [fp, #-20] printf r3, [fp, #-8] r3, r3, #1 r3, [fp, #-8] ldr cmp ble mov mov sub ldmfd r3, [fp, #-8] r3, #99 .L9 r3, #0 r0, r3 sp, fp, #4 sp!, {fp, pc} .L8: .L11: .align 2 .L10: .word .LC0 .fnend .size main, .-main .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.2.2.2. Thumb .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 6 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "main.c" .global __aeabi_dcmpeq .global __aeabi_dsub .global __aeabi_dmul .text .align 2 .global factorial .code 16 .thumb_func .type factorial, %function factorial: 165 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 .fnstart .LFB0: .save {r4, r7, lr} push {r4, r7, lr} .pad #12 sub sp, sp, #12 .setfp r7, sp, #0 add r7, sp, #0 str r0, [r7] str r1, [r7, #4] ldr r0, [r7] ldr r1, [r7, #4] ldr r3, .L7+4 ldr r2, .L7 bl __aeabi_dcmpeq mov r3, r0 cmp r3, #0 beq .L6 .L5: ldr ldr b r3, .L7+8 r4, .L7+12 .L4 ldr ldr ldr ldr bl mov mov mov mov bl mov mov mov mov ldr ldr bl mov mov r0, [r7] r1, [r7, #4] r2, .L7+8 r3, .L7+12 __aeabi_dsub r3, r0 r4, r1 r0, r3 r1, r4 factorial r3, r0 r4, r1 r0, r3 r1, r4 r2, [r7] r3, [r7, #4] __aeabi_dmul r3, r0 r4, r1 .L6: Alcune righe sono del codice morto, registri caricati, spostati e salvati inutilmente, queste righe vengono ridotte o eliminate nella prima ottimizzazione. .L4: mov r0, r3 mov r1, r4 mov sp, r7 add sp, sp, #12 @ sp needed for prologue pop {r4, r7, pc} .L8: .align 3 .L7: .word 0 .word 0 .word 0 .word 1072693248 .fnend .size factorial, .-factorial .global __aeabi_i2d .section .rodata .align 2 .LC0: .ascii "factorial(%d) = %.0e\012\000" .text .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB1: .save {r4, r7, lr} push {r4, r7, lr} .pad #20 sub sp, sp, #20 .setfp r7, sp, #0 add r7, sp, #0 mov r3, #0 str r3, [r7, #12] 166 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb b .L10 ldr bl mov mov mov mov bl mov mov str str ldr ldr ldr ldr mov mov mov mov bl ldr add str r0, [r7, #12] __aeabi_i2d r3, r0 r4, r1 r0, r3 r1, r4 factorial r3, r0 r4, r1 r3, [r7] r4, [r7, #4] r1, .L12 r2, [r7, #12] r3, [r7] r4, [r7, #4] r0, r1 r1, r2 r2, r3 r3, r4 printf r3, [r7, #12] r3, r3, #1 r3, [r7, #12] Tesi di Laurea di: Loredano Rapari matr. 1029262 .L11: Alcune righe sono del codice morto, registri caricati, spostati e salvati inutilmente, queste righe vengono ridotte o eliminate nella prima ottimizzazione. Le righe sottolineate vengono accorpate in un numero minore di istruzioni dall’ottimizzazione –O1 .L10: ldr r3, [r7, #12] cmp r3, #99 ble .L11 mov r3, #0 mov r0, r3 mov sp, r7 add sp, sp, #20 @ sp needed for prologue pop {r4, r7, pc} .L13: .align 2 .L12: .word .LC0 .fnend .size main, .-main .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.2.2.3. Thumb con ottimizzazione –O1 .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 1 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "main.c" .global __aeabi_dcmpeq .global __aeabi_dsub .global __aeabi_dmul .text In questo caso la seconda ottimizzazione non cambia di molto il codice ottenuto .align 2 con la prima, a parte il fatto che divide la parte .LFB11(del codice –O1) in due .global factorial .code 16 parti e aggiunge qualche riga di spostamenti dei registri .thumb_func .type factorial, %function factorial: .fnstart .LFB11: .save {r3, r4, r5, lr} push {r3, r4, r5, lr} mov r4, r0 mov r5, r1 ldr r3, .L4+4 ldr r2, .L4 bl __aeabi_dcmpeq cmp r0, #0 bne .L3 167 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb mov mov ldr ldr bl bl mov mov bl b r0, r4 r1, r5 r2, .L4+8 r3, .L4+12 __aeabi_dsub factorial r2, r4 r3, r5 __aeabi_dmul .L2 ldr ldr r0, .L4+8 r1, .L4+12 Tesi di Laurea di: Loredano Rapari matr. 1029262 .L3: .L2: @ sp needed for prologue pop {r3, r4, r5, pc} .L5: .align 3 .L4: .word 0 .word 0 .word 0 .word 1072693248 .fnend .size factorial, .-factorial .global __aeabi_i2d .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB12: .save push mov ldr {r3, r4, r5, lr} {r3, r4, r5, lr} r4, #0 r5, .L9 .L7: mov r0, r4 bl __aeabi_i2d bl factorial mov r2, r0 mov r3, r1 mov r0, r5 mov r1, r4 bl printf add r4, r4, #1 cmp r4, #100 bne .L7 mov r0, #0 @ sp needed for prologue pop {r3, r4, r5, pc} .L10: .align 2 .L9: .word .LC0 .fnend .size main, .-main .section .rodata.str1.4,"aMS",%progbits,1 .align 2 .LC0: .ascii "factorial(%d) = %.0e\012\000" .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.2.2.4. Thumb con ottimizzazione –O2 .arch armv5te .fpu softvfp .eabi_attribute .eabi_attribute .eabi_attribute .eabi_attribute .eabi_attribute .eabi_attribute .eabi_attribute .eabi_attribute .code 16 168 20, 21, 23, 24, 25, 26, 30, 18, 1 1 3 1 1 2 2 4 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb .file "main.c" .global __aeabi_dcmpeq .global __aeabi_dsub .global __aeabi_dmul .text .align 2 .global factorial .code 16 .thumb_func .type factorial, %function factorial: .fnstart .LFB11: .save {r3, r4, r5, lr} push {r3, r4, r5, lr} ldr r3, .L6+4 ldr r2, .L6 mov r4, r0 mov r5, r1 bl __aeabi_dcmpeq cmp r0, #0 beq .L5 ldr r0, .L6+8 ldr r1, .L6+12 .L2: @ sp needed for prologue pop {r3, r4, r5, pc} .L5: ldr r2, .L6+8 ldr r3, .L6+12 mov r0, r4 mov r1, r5 bl __aeabi_dsub bl factorial mov r2, r4 mov r3, r5 bl __aeabi_dmul b .L2 .L7: .align 3 .L6: .word 0 .word 0 .word 0 .word 1072693248 .fnend .size factorial, .-factorial .global __aeabi_i2d .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB12: .save {r3, r4, r5, lr} push {r3, r4, r5, lr} ldr r5, .L12 mov r4, #0 .L9: mov r0, r4 bl __aeabi_i2d bl factorial mov r2, r0 mov r3, r1 mov r0, r5 mov r1, r4 add r4, r4, #1 bl printf mov r0, r4 bl __aeabi_i2d bl factorial mov r2, r0 mov r3, r1 mov r0, r5 mov r1, r4 add r4, r4, #1 bl printf cmp r4, #100 Tesi di Laurea di: Loredano Rapari matr. 1029262 Data la complessità del programma fattoriale, il quale è realizzato con la chiamata ricorsiva della funzione fattoriale, la terza ottimizzazione non opera tagli di codice sulla seconda, bensì aumenta di molto il codice per renderlo più lineare; questa operazione può sembrare controproducente, ma andando ad analizzare, più avanti, i tempi medi di esecuzione del programma si può notare un miglioramento nel passaggio dalla seconda alla terza ottimizzazione. 169 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 bne .L9 mov r0, #0 @ sp needed for prologue pop {r3, r4, r5, pc} .L13: .align 2 .L12: .word .LC0 .fnend .size main, .-main .section .rodata.str1.4,"aMS",%progbits,1 .align 2 .LC0: .ascii "factorial(%d) = %.0e\012\000" .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.2.2.5. Thumb con ottimizzazione –O3 .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 2 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "main.c" .global __aeabi_dcmpeq .global __aeabi_dsub .global __aeabi_dmul .text .align 2 .global factorial .code 16 .thumb_func .type factorial, %function factorial: .fnstart .LFB11: .save {r4, r5, r6, r7, lr} push {r4, r5, r6, r7, lr} .pad #60 sub sp, sp, #60 ldr r3, .L30+4 ldr r2, .L30 mov r4, r0 mov r5, r1 bl __aeabi_dcmpeq cmp r0, #0 beq .L21 ldr r0, .L30+8 ldr r1, .L30+12 .L2: add sp, sp, #60 @ sp needed for prologue pop {r4, r5, r6, r7, pc} .L21: ldr r2, .L30+8 ldr r3, .L30+12 mov r0, r4 mov r1, r5 bl __aeabi_dsub ldr r3, .L30+4 ldr r2, .L30 mov r6, r0 mov r7, r1 bl __aeabi_dcmpeq cmp r0, #0 beq .L22 ldr r2, .L30+8 ldr r3, .L30+12 .L3: mov r0, r4 mov r1, r5 bl __aeabi_dmul 170 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb b .L2 ldr ldr mov mov bl ldr ldr str str bl cmp beq ldr ldr r2, .L30+8 r3, .L30+12 r0, r6 r1, r7 __aeabi_dsub r3, .L30+4 r2, .L30 r0, [sp] r1, [sp, #4] __aeabi_dcmpeq r0, #0 .L23 r2, .L30+8 r3, .L30+12 mov mov bl mov mov b r0, r6 r1, r7 __aeabi_dmul r2, r0 r3, r1 .L3 ldr ldr ldr ldr bl ldr ldr str str bl cmp beq ldr ldr r2, .L30+8 r3, .L30+12 r0, [sp] r1, [sp, #4] __aeabi_dsub r3, .L30+4 r2, .L30 r0, [sp, #8] r1, [sp, #12] __aeabi_dcmpeq r0, #0 .L24 r2, .L30+8 r3, .L30+12 ldr ldr bl mov mov b r0, [sp] r1, [sp, #4] __aeabi_dmul r2, r0 r3, r1 .L4 ldr ldr ldr ldr bl ldr ldr str str bl cmp beq ldr ldr r2, .L30+8 r3, .L30+12 r0, [sp, #8] r1, [sp, #12] __aeabi_dsub r3, .L30+4 r2, .L30 r0, [sp, #16] r1, [sp, #20] __aeabi_dcmpeq r0, #0 .L25 r2, .L30+8 r3, .L30+12 ldr ldr bl mov mov b r0, [sp, #8] r1, [sp, #12] __aeabi_dmul r2, r0 r3, r1 .L5 ldr ldr ldr ldr bl ldr ldr str str bl cmp beq r2, .L30+8 r3, .L30+12 r0, [sp, #16] r1, [sp, #20] __aeabi_dsub r3, .L30+4 r2, .L30 r0, [sp, #24] r1, [sp, #28] __aeabi_dcmpeq r0, #0 .L26 Tesi di Laurea di: Loredano Rapari matr. 1029262 .L22: .L4: .L23: .L5: .L24: .L6: .L25: 171 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb ldr ldr r2, .L30+8 r3, .L30+12 ldr ldr bl mov mov b r0, [sp, #16] r1, [sp, #20] __aeabi_dmul r2, r0 r3, r1 .L6 ldr ldr ldr ldr bl ldr ldr str str bl cmp beq ldr ldr r2, .L30+8 r3, .L30+12 r0, [sp, #24] r1, [sp, #28] __aeabi_dsub r3, .L30+4 r2, .L30 r0, [sp, #32] r1, [sp, #36] __aeabi_dcmpeq r0, #0 .L27 r2, .L30+8 r3, .L30+12 ldr ldr bl mov mov b r0, [sp, #24] r1, [sp, #28] __aeabi_dmul r2, r0 r3, r1 .L7 ldr ldr ldr ldr bl ldr ldr str str bl cmp beq ldr ldr r2, .L30+8 r3, .L30+12 r0, [sp, #32] r1, [sp, #36] __aeabi_dsub r3, .L30+4 r2, .L30 r0, [sp, #40] r1, [sp, #44] __aeabi_dcmpeq r0, #0 .L28 r2, .L30+8 r3, .L30+12 ldr ldr bl mov mov b r0, [sp, #32] r1, [sp, #36] __aeabi_dmul r2, r0 r3, r1 .L8 ldr ldr ldr ldr bl ldr ldr str str bl cmp beq ldr ldr r2, .L30+8 r3, .L30+12 r0, [sp, #40] r1, [sp, #44] __aeabi_dsub r3, .L30+4 r2, .L30 r0, [sp, #48] r1, [sp, #52] __aeabi_dcmpeq r0, #0 .L29 r2, .L30+8 r3, .L30+12 ldr ldr bl mov mov b r0, [sp, #40] r1, [sp, #44] __aeabi_dmul r2, r0 r3, r1 .L9 ldr ldr ldr ldr r2, r3, r0, r1, .L7: .L26: .L8: .L27: .L9: .L28: .L10: .L29: 172 .L30+8 .L30+12 [sp, #48] [sp, #52] Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb bl bl mov mov ldr ldr bl mov mov b Tesi di Laurea di: Loredano Rapari matr. 1029262 __aeabi_dsub factorial r2, r0 r3, r1 r0, [sp, #48] r1, [sp, #52] __aeabi_dmul r2, r0 r3, r1 .L10 .L31: .align 3 .L30: .word 0 .word 0 .word 0 .word 1072693248 .fnend .size factorial, .-factorial .global __aeabi_i2d .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB12: .save push mov .save push ldr ldr ldr mov mov mov ldr ldr bl mov mov mov mov bl bl mov mov mov mov mov bl ldr ldr mov mov mov mov bl ldr ldr mov mov bl bl mov mov mov mov bl ldr ldr mov mov mov mov bl {r4, r5, r6, r7, lr} {r4, r5, r6, r7, lr} r7, r8 {r8} {r7} r3, .L58+32 r5, .L58+4 r4, .L58 r8, r3 r0, r3 r1, #0 r3, .L58+4 r2, .L58 printf r2, r4 r3, r5 r0, r4 r1, r5 __aeabi_dsub factorial r6, #3 r2, r0 r3, r1 r0, r4 r1, r5 __aeabi_dmul r4, .L58+8 r5, .L58+12 r2, r0 r3, r1 r0, r8 r1, #1 printf r3, .L58+4 r2, .L58 r0, r4 r1, r5 __aeabi_dsub factorial r2, r0 r3, r1 r0, r4 r1, r5 __aeabi_dmul r4, .L58+16 r5, .L58+20 r2, r0 r3, r1 r0, r8 r1, #2 printf .L55: 173 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb ldr ldr mov mov bl bl mov mov mov mov bl mov mov mov mov add bl cmp beq r3, .L58+4 r2, .L58 r0, r4 r1, r5 __aeabi_dsub factorial r2, r0 r3, r1 r0, r4 r1, r5 __aeabi_dmul r2, r0 r3, r1 r0, r8 r1, r6 r6, r6, #1 printf r6, #100 .L56 mov bl ldr ldr mov mov bl cmp beq ldr ldr r0, r6 __aeabi_i2d r2, .L58+24 r3, .L58+28 r4, r0 r5, r1 __aeabi_dcmpeq r0, #0 .L57 r3, .L58+4 r2, .L58 mov mov add bl mov bl ldr ldr mov mov bl cmp beq ldr ldr r1, r6 r0, r8 r7, r6, #1 printf r0, r7 __aeabi_i2d r2, .L58+24 r3, .L58+28 r4, r0 r5, r1 __aeabi_dcmpeq r0, #0 .L51 r3, .L58+4 r2, .L58 mov mov add bl mov bl ldr ldr mov mov bl cmp beq ldr ldr r1, r7 r0, r8 r7, r6, #2 printf r0, r7 __aeabi_i2d r2, .L58+24 r3, .L58+28 r4, r0 r5, r1 __aeabi_dcmpeq r0, #0 .L53 r3, .L58+4 r2, .L58 mov mov add bl mov bl ldr ldr mov mov bl cmp beq mov ldr ldr r1, r7 r0, r8 r6, r6, #3 printf r0, r6 __aeabi_i2d r2, .L58+24 r3, .L58+28 r4, r0 r5, r1 __aeabi_dcmpeq r0, #0 .L55 r1, r6 r3, .L58+4 r2, .L58 .L35: .L50: .L52: .L54: 174 Tesi di Laurea di: Loredano Rapari matr. 1029262 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb mov add bl cmp bne Tesi di Laurea di: Loredano Rapari matr. 1029262 r0, r8 r6, r6, #1 printf r6, #100 .L35 .L56: mov r0, #0 @ sp needed for prologue pop {r2} mov r8, r2 pop {r4, r5, r6, r7, pc} .L57: ldr ldr mov mov bl bl mov mov mov mov bl mov mov b r3, .L58+4 r2, .L58 r0, r4 r1, r5 __aeabi_dsub factorial r2, r0 r3, r1 r0, r4 r1, r5 __aeabi_dmul r2, r0 r3, r1 .L50 ldr ldr mov mov bl bl mov mov mov mov bl mov mov b r3, .L58+4 r2, .L58 r0, r4 r1, r5 __aeabi_dsub factorial r2, r0 r3, r1 r0, r4 r1, r5 __aeabi_dmul r2, r0 r3, r1 .L54 ldr ldr mov mov bl bl mov mov mov mov bl mov mov b r3, .L58+4 r2, .L58 r0, r4 r1, r5 __aeabi_dsub factorial r2, r0 r3, r1 r0, r4 r1, r5 __aeabi_dmul r2, r0 r3, r1 .L52 .L53: .L51: .L59: .align 3 .L58: .word 0 .word 1072693248 .word 0 .word 1073741824 .word 0 .word 1074266112 .word 0 .word 0 .word .LC0 .fnend .size main, .-main .section .rodata.str1.4,"aMS",%progbits,1 .align 2 .LC0: .ascii "factorial(%d) = %.0e\012\000" .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 175 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 7.2.3. Tesi di Laurea di: Loredano Rapari matr. 1029262 Tempi di esecuzione I file binari ottenuti dai codici precedenti, sono stati eseguiti sul processore, ed hanno dato i seguenti risultati per quanto riguarda i tempi di esecuzione: Tabella 7.1 Tempi di esecuzione del programma Fattoriale (tempi in ms) Prova 1 2 3 4 5 6 7 8 9 10 176 arm real user sys real user sys real user sys real user sys real user sys real user sys real user sys real user sys real user sys real user sys 254 60 90 250 80 80 259 90 70 251 50 110 241 80 80 255 70 80 261 80 70 272 110 60 256 80 70 261 70 90 real user sys 256 77 80 Codifica e ottimizzazioni thumb thumb_O1 thumb_O2 thumb_O3 268 258 246 259 70 90 80 90 100 60 80 70 280 258 253 252 70 90 90 90 90 70 60 60 287 259 253 252 90 80 70 60 80 80 90 100 262 272 245 256 40 60 90 70 120 110 60 80 271 253 262 246 90 60 70 70 70 90 90 90 280 262 256 261 120 100 90 80 50 50 60 70 257 256 262 255 90 70 70 90 70 90 100 70 271 261 254 238 100 100 70 90 70 50 80 60 262 260 260 247 90 80 90 80 70 80 80 70 259 260 256 251 100 100 100 60 60 50 50 100 Tempi medi 269,7 259,9 254,7 251,7 86 83 82 78 78 73 75 77 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Figura 7.1 Grafico della distribuzione gaussiana dei tempi di esecuzione(real) rilevati. 1200 1000 Frequenza 800 ARM Thumb 600 Thumb_O1 Thumb_O2 400 Thumb_O3 200 0 200 220 240 260 280 300 320 340 Tempi [ms] Come si può vedere dal grafico le distribuzioni hanno una varianza abbastanza bassa, quindi i risultati si possono considerare piuttosto attendibili. Dai tempi medi: - Arm: Thumb: Thumb_O1: Thumb_O2: Thumb_O3: 256 269,7 259,9 254,7 251,7 ms ms ms ms ms si può notare che il programma in Arm viene eseguito in tempi minori di quello in Thumb. Adottando le varie ottimizzazioni il tempo di esecuzione scende. Il tempo più basso si ha con la terza ottimizzazione nonostante sia quella che crea un codice di volume maggiore. 177 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 7.3. Programma test: Fattori primi Questo programma ricava i fattori primi di un numero dato in input. Per questo test ho scelto il numero “222881507” come input in tutti i casi. 7.3.1. Codice C /----------------------------------------------------------------------------------------/ #include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { int n, d = 2; n = atoi(argv[1]); if (n < 1) return 0; printf ("\nScomposizione in fattori primi di %d:\n", n); if(n == 1) printf ("1\n"); while (n != 1) { if ((n % d) == 0) { printf ("%d\n", d); n /= d; } else { d++; } } return 0; } /----------------------------------------------------------------------------------------/ 178 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 7.3.2. Tesi di Laurea di: Loredano Rapari matr. 1029262 Codice Assembler Di seguito i vari codici assembler ottenuti dal compilatore compilando il codice C precedente, con le varie ottimizzazioni. 7.3.2.1. Arm .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 6 .eabi_attribute 18, 4 .file "fatt_primi.c" .section .rodata .align 2 .LC0: .ascii "\012Scomposizione in fattori primi di %d:\012\000" .align 2 .LC1: .ascii "1\000" .global __aeabi_idivmod .align 2 .LC2: .ascii "%d\012\000" .global __aeabi_idiv .text .align 2 .global main .type main, %function main: .fnstart .LFB0: @ args = 0, pretend = 0, frame = 16 @ frame_needed = 1, uses_anonymous_args = 0 stmfd sp!, {fp, lr} .save {fp, lr} .setfp fp, sp, #4 add fp, sp, #4 .pad #16 sub sp, sp, #16 str r0, [fp, #-16] str r1, [fp, #-20] mov r3, #2 str r3, [fp, #-12] ldr r3, [fp, #-20] add r3, r3, #4 ldr r3, [r3, #0] mov r0, r3 bl atoi str r0, [fp, #-8] ldr r3, [fp, #-8] cmp r3, #0 bgt .L2 mov r3, #0 b .L3 .L2: ldr mov ldr bl ldr cmp bne ldr bl b r3, .L8 r0, r3 r1, [fp, #-8] printf r3, [fp, #-8] r3, #1 .L5 r0, .L8+4 puts .L5 ldr mov ldr bl mov r3, [fp, #-8] r0, r3 r1, [fp, #-12] __aeabi_idivmod r3, r1 .L7: 179 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb cmp bne ldr mov ldr bl ldr ldr bl mov str b r3, #0 .L6 r3, .L8+8 r0, r3 r1, [fp, #-12] printf r0, [fp, #-8] r1, [fp, #-12] __aeabi_idiv r3, r0 r3, [fp, #-8] .L5 ldr add str r3, [fp, #-12] r3, r3, #1 r3, [fp, #-12] ldr cmp bne mov r3, [fp, #-8] r3, #1 .L7 r3, #0 mov sub ldmfd r0, r3 sp, fp, #4 sp!, {fp, pc} Tesi di Laurea di: Loredano Rapari matr. 1029262 .L6: .L5: .L3: .L9: .align 2 .L8: .word .LC0 .word .LC1 .word .LC2 .fnend .size main, .-main .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.3.2.2. Thumb .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 6 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "fatt_primi.c" .section .rodata .align 2 .LC0: .ascii "\012Scomposizione in fattori primi di %d:\012\000" .align 2 .LC2: .ascii "1\000" .global __aeabi_idivmod .align 2 .LC4: .ascii "%d\012\000" .global __aeabi_idiv .text .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB0: .save {r7, lr} push {r7, lr} .pad #16 sub sp, sp, #16 .setfp r7, sp, #0 add r7, sp, #0 str r0, [r7, #4] 180 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb str mov str ldr add ldr mov bl mov str ldr cmp bgt mov b r1, [r7] r3, #2 r3, [r7, #8] r3, [r7] r3, r3, #4 r3, [r3] r0, r3 atoi r3, r0 r3, [r7, #12] r3, [r7, #12] r3, #0 .L2 r3, #0 .L3 ldr ldr mov mov bl ldr cmp bne ldr mov bl b r2, .L8 r3, [r7, #12] r0, r2 r1, r3 printf r3, [r7, #12] r3, #1 .L5 r3, .L8+4 r0, r3 puts .L5 ldr mov ldr bl mov cmp bne ldr ldr mov mov bl ldr ldr bl mov str b r3, [r7, #12] r0, r3 r1, [r7, #8] __aeabi_idivmod r3, r1 r3, #0 .L6 r2, .L8+8 r3, [r7, #8] r0, r2 r1, r3 printf r0, [r7, #12] r1, [r7, #8] __aeabi_idiv r3, r0 r3, [r7, #12] .L5 ldr add str r3, [r7, #8] r3, r3, #1 r3, [r7, #8] ldr cmp bne mov r3, [r7, #12] r3, #1 .L7 r3, #0 Tesi di Laurea di: Loredano Rapari matr. 1029262 Alcune righe sono del codice morto, registri caricati, spostati e salvati inutilmente, queste righe vengono ridotte nella prima ottimizzazione. .L2: Questo codice morto, è un doppio caricamento inutile. .L7: .L6: .L5: Ci sono 2 righe di codice morto, si può notare che si sposta un dato e lo si salva, invece di salvarlo direttamente. Altre istruzioni vengono accorpate, infatti nella ottimizzazione –O1 i registri sono già caricati e si effettuano meno accessi in memoria. Queste righe sono del codice morto in quanto prima caricano un dato e poi lo salvano nella stessa posizione, vengono quindi eliminate con la prima ottimizzazione .L3: mov r0, r3 mov sp, r7 add sp, sp, #16 @ sp needed for prologue pop {r7, pc} .L9: .align 2 .L8: .word .LC0 .word .LC2 .word .LC4 .fnend .size main, .-main .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 181 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 7.3.2.3. Tesi di Laurea di: Loredano Rapari matr. 1029262 Thumb con ottimizzazione –O1 .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 1 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "fatt_primi.c" .global __aeabi_idivmod .global __aeabi_idiv .text .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB18: .save push ldr mov mov bl mov cmp ble ldr mov bl mov cmp bne ldr bl b {r4, r5, r6, lr} {r4, r5, r6, lr} r0, [r1, #4] r1, #0 r2, #10 strtol r5, r0 r0, #0 .L2 r0, .L9 r1, r5 printf r4, #2 r5, #1 .L3 r0, .L9+4 puts .L2 ldr r6, .L9+8 mov mov bl cmp bne mov mov bl mov mov bl mov b r0, r5 r1, r4 __aeabi_idivmod r1, #0 .L4 r0, r6 r1, r4 printf r0, r5 r1, r4 __aeabi_idiv r5, r0 .L5 add r4, r4, #1 cmp bne r5, #1 .L7 Queste due righe che fanno un confronto vengono sostituite da un’unica istruzione nella seconda ottimizzazione. .L3: .L7: .L4: .L5: Queste due righe vengono accorpate in .L7 nella seconda ottimizzazione. .L2: mov r0, #0 @ sp needed for prologue pop {r4, r5, r6, pc} .L10: .align 2 .L9: .word .LC0 .word .LC2 .word .LC4 .fnend .size main, .-main .section .rodata.str1.4,"aMS",%progbits,1 .align 2 .LC0: 182 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 .ascii "\012Scomposizione in fattori primi di %d:\012\000" .LC2: .ascii "1\000" .space 2 .LC4: .ascii "%d\012\000" .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.3.2.4. Thumb con ottimizzazione –O2 .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 2 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "fatt_primi.c" .global __aeabi_idivmod .global __aeabi_idiv .text .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB18: .save push ldr mov mov bl sub ble ldr mov bl mov cmp beq ldr b {r4, r5, r6, lr} {r4, r5, r6, lr} r0, [r1, #4] r2, #10 r1, #0 strtol r5, r0, #0 .L2 r0, .L11 r1, r5 printf r4, #2 r5, #1 .L10 r6, .L11+4 .L7 add cmp beq r4, r4, #1 r5, #1 .L2 mov mov bl cmp bne mov mov bl mov mov bl mov cmp bne r0, r5 r1, r4 __aeabi_idivmod r1, #0 .L4 r1, r4 r0, r6 printf r0, r5 r1, r4 __aeabi_idiv r5, r0 r5, #1 .L7 Il codice prodotto dalla terza ottimizzazione è uguale a quello prodotto dalla seconda ottimizzazione, non ci sono quindi cambiamenti importanti da evidenziare. Si vedrà infatti più avanti che i tempi di esecuzione tra questi due codici sono praticamente identici. .L4: .L7: .L2: mov r0, #0 @ sp needed for prologue pop {r4, r5, r6, pc} .L10: ldr bl b r0, .L11+8 puts .L2 .L12: .align 2 183 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 .L11: .word .LC0 .word .LC4 .word .LC2 .fnend .size main, .-main .section .rodata.str1.4,"aMS",%progbits,1 .align 2 .LC0: .ascii "\012Scomposizione in fattori primi di %d:\012\000" .LC2: .ascii "1\000" .space 2 .LC4: .ascii "%d\012\000" .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.3.2.5. Thumb con ottimizzazione –O3 .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 2 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "fatt_primi.c" .global __aeabi_idivmod .global __aeabi_idiv .text .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB18: .save push ldr mov mov bl sub ble ldr mov bl mov cmp beq ldr b {r4, r5, r6, lr} {r4, r5, r6, lr} r0, [r1, #4] r2, #10 r1, #0 strtol r5, r0, #0 .L2 r0, .L11 r1, r5 printf r4, #2 r5, #1 .L10 r6, .L11+4 .L7 add cmp beq r4, r4, #1 r5, #1 .L2 mov mov bl cmp bne mov mov bl mov mov bl mov cmp bne r0, r5 r1, r4 __aeabi_idivmod r1, #0 .L4 r1, r4 r0, r6 printf r0, r5 r1, r4 __aeabi_idiv r5, r0 r5, #1 .L7 .L4: .L7: .L2: 184 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 mov r0, #0 @ sp needed for prologue pop {r4, r5, r6, pc} .L10: ldr bl b r0, .L11+8 puts .L2 .L12: .align 2 .L11: .word .LC0 .word .LC4 .word .LC2 .fnend .size main, .-main .section .rodata.str1.4,"aMS",%progbits,1 .align 2 .LC0: .ascii "\012Scomposizione in fattori primi di %d:\012\000" .LC2: .ascii "1\000" .space 2 .LC4: .ascii "%d\012\000" .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 185 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 7.3.3. Tesi di Laurea di: Loredano Rapari matr. 1029262 Tempi di esecuzione I file binari ottenuti dai codici precedenti, sono stati eseguiti sul processore, ed hanno dato i seguenti risultati per quanto riguarda i tempi di esecuzione: Tabella 7.2 Tempi di esecuzione del programma Fattori Primi (tempi in ms) Prova 1 2 3 4 5 6 7 8 9 10 186 real user sys real user sys real user sys real user sys real user sys real user sys real user sys real user sys real user sys real user sys arm 450 370 50 443 360 50 448 340 70 457 360 60 440 370 50 441 370 50 439 340 70 441 340 70 442 360 60 435 350 60 real user sys 443,6 356 59 Codifica e ottimizzazioni thumb thumb_1 thumb_2 thumb_3 457 435 428 422 400 340 340 330 30 50 50 60 460 430 417 417 360 330 320 340 60 70 70 50 452 425 422 429 380 320 320 360 40 70 80 40 455 427 421 416 380 320 350 360 40 70 50 40 455 421 425 419 390 330 370 350 40 70 30 50 462 428 420 422 370 340 320 360 60 60 70 40 461 420 427 424 380 330 330 340 40 70 60 60 452 428 426 427 360 340 320 320 60 60 70 70 452 425 421 425 370 340 350 350 60 50 50 40 467 423 416 425 370 350 330 360 60 40 70 30 Tempi medi 457,3 426,2 422,3 422,6 376 334 335 347 49 61 60 48 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Figura 7.2 Grafico della distribuzione gaussiana dei tempi di esecuzione(real) rilevati. 1200 1000 Frequenza 800 Arm Thumb 600 Thumb_O1 Thumb_O2 400 Thumb_O3 200 0 350 400 450 500 550 Tempi [ms] Come si può vedere dal grafico le distribuzioni hanno una varianza abbastanza bassa, quindi i risultati si possono considerare piuttosto attendibili. Dai tempi medi: - Arm: Thumb: Thumb_O1: Thumb_O2: Thumb_O3: 443,6 457,3 426,2 422,3 422,6 ms ms ms ms ms si può notare che il programma in Arm viene eseguito in tempi minori di quello in Thumb. Adottando le varie ottimizzazioni il tempo di esecuzione scende. Il tempo più basso si ha con la seconda ottimizzazione che è molto vicino a quello della terza. 187 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 7.4. Programma test: Serie di Fibonacci Questo programma stampa a video la serie di Fibonacci dei numeri da 0 a 40. 7.4.1. Codice C /----------------------------------------------------------------------------------------/ #include <stdio.h> int main() { int x, y = 1, z = 0, i; printf("\nSerie di Fibonacci dei primi 40 numeri:\n"); printf("F(0) = 0\nF(1) = 1\n"); for (i = 2; i < 41; i++) { x = y + z; printf("F(%d) = %d\n", i, x); z = y; y = x; } return 0; } /----------------------------------------------------------------------------------------/ 7.4.2. Codice Assembler Di seguito i vari codici assembler ottenuti dal compilatore compilando il codice C precedente, con le varie ottimizzazioni. 7.4.2.1. Arm .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 6 .eabi_attribute 18, 4 .file "fibonacci.c" .section .rodata .align 2 .LC0: .ascii "\012Serie di Fibonacci dei primi 40 numeri:\000" .align 2 .LC1: .ascii "F(0) = 0\012F(1) = 1\000" .align 2 .LC2: .ascii "F(%d) = %d\012\000" .text .align 2 .global main .type main, %function main: .fnstart 188 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 .LFB0: @ args = 0, pretend = 0, frame = 16 @ frame_needed = 1, uses_anonymous_args = 0 stmfd sp!, {fp, lr} .save {fp, lr} .setfp fp, sp, #4 add fp, sp, #4 .pad #16 sub sp, sp, #16 mov r3, #1 str r3, [fp, #-8] mov r3, #0 str r3, [fp, #-12] ldr r0, .L4 bl puts ldr r0, .L4+4 bl puts mov r3, #2 str r3, [fp, #-16] b .L2 .L3: ldr ldr add str ldr mov ldr ldr bl ldr str ldr str ldr add str r2, [fp, #-8] r3, [fp, #-12] r3, r2, r3 r3, [fp, #-20] r3, .L4+8 r0, r3 r1, [fp, #-16] r2, [fp, #-20] printf r3, [fp, #-8] r3, [fp, #-12] r3, [fp, #-20] r3, [fp, #-8] r3, [fp, #-16] r3, r3, #1 r3, [fp, #-16] ldr cmp ble mov mov sub ldmfd r3, [fp, #-16] r3, #40 .L3 r3, #0 r0, r3 sp, fp, #4 sp!, {fp, pc} .L2: .L5: .align 2 .L4: .word .LC0 .word .LC1 .word .LC2 .fnend .size main, .-main .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.4.2.2. Thumb .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 6 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "fibonacci.c" .section .rodata .align 2 .LC0: .ascii "\012Serie di Fibonacci dei primi 40 numeri:\000" .align 2 .LC2: .ascii "F(0) = 0\012F(1) = 1\000" .align 2 .LC4: 189 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 .ascii "F(%d) = %d\012\000" .text .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB0: .save {r7, lr} push {r7, lr} .pad #16 sub sp, sp, #16 .setfp r7, sp, #0 add r7, sp, #0 mov r3, #1 str r3, [r7, #12] mov r3, #0 str r3, [r7, #8] ldr r3, .L4 mov r0, r3 bl puts ldr r3, .L4+4 mov r0, r3 bl puts mov r3, #2 str r3, [r7, #4] b .L2 Queste due righe vengono ridotte a meno istruzioni nella prima ottimizzazione. .L3: ldr ldr add str ldr ldr ldr mov mov mov bl ldr str ldr str ldr add str r2, [r7, #12] r3, [r7, #8] r3, r2, r3 r3, [r7] r1, .L4+8 r2, [r7, #4] r3, [r7] r0, r1 r1, r2 r2, r3 printf r3, [r7, #12] r3, [r7, #8] r3, [r7] r3, [r7, #12] r3, [r7, #4] r3, r3, #1 r3, [r7, #4] Questo codice morto non fa altro che spostare dei registri da e verso la memoria centrale e viene eliminato nella prima ottimizzazione. .L2: ldr r3, [r7, #4] cmp r3, #40 ble .L3 mov r3, #0 mov r0, r3 mov sp, r7 add sp, sp, #16 @ sp needed for prologue pop {r7, pc} .L5: .align 2 .L4: .word .LC0 .word .LC2 .word .LC4 .fnend .size main, .-main .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.4.2.3. Thumb con ottimizzazione –O1 .arch armv5te .fpu softvfp .eabi_attribute .eabi_attribute .eabi_attribute .eabi_attribute .eabi_attribute .eabi_attribute 190 20, 21, 23, 24, 25, 26, 1 1 3 1 1 2 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 .eabi_attribute 30, 1 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "fibonacci.c" .text .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB11: .save push ldr bl ldr bl mov mov mov ldr b {r3, r4, r5, r6, r7, lr} {r3, r4, r5, r6, r7, lr} r0, .L4 puts r0, .L4+4 puts r4, #2 r3, #0 r5, #1 r7, .L4+8 .L2 mov mov r3, r5 r5, r6 .L3: .L2: add r6, r3, r5 mov r0, r7 mov r1, r4 mov r2, r6 bl printf add r4, r4, #1 cmp r4, #41 bne .L3 mov r0, #0 @ sp needed for prologue pop {r3, r4, r5, r6, r7, pc} .L5: .align 2 .L4: .word .LC0 .word .LC2 .word .LC4 .fnend .size main, .-main .section .rodata.str1.4,"aMS",%progbits,1 .align 2 .LC0: .ascii "\012Serie di Fibonacci dei primi 40 numeri:\000" .space 3 .LC2: .ascii "F(0) = 0\012F(1) = 1\000" .space 2 .LC4: .ascii "F(%d) = %d\012\000" .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.4.2.4. Thumb con ottimizzazione –O2 .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 2 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "fibonacci.c" .text .align 2 .global main .code 16 .thumb_func 191 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb .type Tesi di Laurea di: Loredano Rapari matr. 1029262 main, %function main: .fnstart .LFB11: .save push ldr bl ldr bl mov mov mov ldr b {r3, r4, r5, r6, r7, lr} {r3, r4, r5, r6, r7, lr} r0, .L6 puts r0, .L6+4 puts r4, #2 r5, #0 r6, #1 r7, .L6+8 .L2 add mov mov mov bl add r6, r6, r5 r1, r4 r0, r7 r2, r6 printf r4, r4, #1 .L3: Queste righe di codice vengono aggiunte nella seconda ottimizzazione rispetto alla prima. .L2: add r5, r5, r6 mov r1, r4 mov r0, r7 mov r2, r5 add r4, r4, #1 bl printf cmp r4, #41 bne .L3 mov r0, #0 @ sp needed for prologue pop {r3, r4, r5, r6, r7, pc} .L7: .align 2 .L6: .word .LC0 .word .LC2 .word .LC4 .fnend .size main, .-main .section .rodata.str1.4,"aMS",%progbits,1 .align 2 .LC0: .ascii "\012Serie di Fibonacci dei primi 40 numeri:\000" .space 3 .LC2: .ascii "F(0) = 0\012F(1) = 1\000" .space 2 .LC4: .ascii "F(%d) = %d\012\000" .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 7.4.2.5. Thumb con ottimizzazione –O3 .arch armv5te .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 2 .eabi_attribute 18, 4 .code 16 //Specifica che si tratta di istr. a 16 bit, quindi di istr. Thumb .file "fibonacci.c" .text .align 2 .global main .code 16 .thumb_func .type main, %function main: .fnstart .LFB11: .save 192 {r4, r5, r6, r7, lr} Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb push mov .save push ldr bl ldr bl ldr mov mov mov bl mov mov mov bl mov mov mov mov b {r4, r5, r6, r7, lr} r7, r8 {r8} {r7} r0, .L10 puts r0, .L10+4 puts r5, .L10+8 r1, #2 r2, #1 r0, r5 printf r0, r5 r1, #3 r2, #2 printf r3, #2 r4, #4 r6, #1 r8, r3 .L2 add mov mov add mov bl add mov mov add mov bl add mov mov bl add mov r8, r8, r1, r7 r2, r8 r6, r6, r0, r5 printf r1, r7, r7, r6 r2, r6 r7, r7, r0, r5 printf r1, r4, r0, r5 r2, r7 printf r4, r4, r8, r7 Tesi di Laurea di: Loredano Rapari matr. 1029262 Nella terza ottimizzazione, anche in questo caso, come nel primo programma, vengono aggiunte diverse righe di codice, le quali però, in questo caso, non portano vantaggi in termini di prestazioni, come si vedrà più avanti, bensì il tempo medio di esecuzione aumenta leggermente. .L3: r6 r8 #1 r8 #3 #4 .L2: add r6, r6, r8 mov r0, r5 mov r1, r4 mov r2, r6 add r7, r4, #1 bl printf cmp r7, #41 bne .L3 mov r0, #0 @ sp needed for prologue pop {r2} mov r8, r2 pop {r4, r5, r6, r7, pc} .L11: .align 2 .L10: .word .LC0 .word .LC2 .word .LC4 .fnend .size main, .-main .section .rodata.str1.4,"aMS",%progbits,1 .align 2 .LC0: .ascii "\012Serie di Fibonacci dei primi 40 numeri:\000" .space 3 .LC2: .ascii "F(0) = 0\012F(1) = 1\000" .space 2 .LC4: .ascii "F(%d) = %d\012\000" .ident "GCC: (Sourcery G++ Lite 2011.03-41) 4.5.2" .section .note.GNU-stack,"",%progbits 193 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb 7.4.3. Tesi di Laurea di: Loredano Rapari matr. 1029262 Tempi di esecuzione I file binari ottenuti dai codici precedenti, sono stati eseguiti sul processore, ed hanno dato i seguenti risultati per quanto riguarda i tempi di esecuzione: Tabella 7.3 Tempi di esecuzione del programma Serie di (tempi in ms) Prova 1 2 3 4 5 6 7 8 9 10 194 real user sys real user sys real user sys real user sys real user sys real user sys real user sys real user sys real user sys real user sys arm 97 10 60 96 10 70 99 10 60 100 20 50 100 10 70 99 0 70 94 10 60 102 10 60 102 0 80 97 20 50 real user sys 98,6 10 63 Codifica e ottimizzazioni thumb thumb_1 thumb_2 thumb_3 91 97 92 101 20 0 10 10 60 70 60 60 99 100 96 99 0 20 10 0 70 60 60 70 97 96 105 109 10 10 10 0 70 60 70 80 105 95 95 94 0 10 0 0 70 70 70 60 91 97 95 104 0 0 10 20 60 60 70 60 96 102 95 98 0 10 0 0 70 60 70 70 98 99 90 96 0 10 10 20 70 60 60 60 95 99 98 93 10 0 10 0 60 70 60 70 104 97 97 100 0 0 20 10 70 70 50 70 99 101 98 93 0 0 10 20 70 70 70 50 Tempi medi 97,5 98,3 96,1 98,7 4 6 9 8 67 65 64 65 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 Figura 7.3 Grafico della distribuzione gaussiana dei tempi di esecuzione(real) rilevati. 1000 900 800 Frequenza 700 600 Arm Thumb 500 Thumb_O1 400 Thumb_O2 300 Thumb_O3 200 100 0 70 80 90 100 110 120 Tempi [ms] Come si può vedere dal grafico le distribuzioni hanno una varianza abbastanza bassa, quindi i risultati si possono considerare piuttosto attendibili. Dai tempi medi: - Arm: Thumb: Thumb_O1: Thumb_O2: Thumb_O3: 98,6 97,5 98,3 96,1 98,7 ms ms ms ms ms In questo caso, si può notare che il programma in Arm viene eseguito in tempi maggiori di quello in Thumb. Adottando le varie ottimizzazioni il tempo di esecuzione non sempre scende. Il tempo più basso si ha con la seconda ottimizzazione. 195 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 8. Conclusioni Dopo aver visto la forma dell’architettura ARM, la gestione delle risorse e tutto il set di istruzioni Thumb, ho effettuato i test descritti precedentemente sulla scheda disponibile in laboratorio. Dando un’occhiata ai risultati ottenuti sui tempi di esecuzione si può notare come nei primi due casi, cioè nel programma del fattoriale e nel programma dei fattori primi, l’esecuzione sia mediamente più veloce usando il set di istruzioni ARM piuttosto che il Thumb. Le cose cambiano nell’ultimo programma di test, cioè quello della serie di Fibonacci, nel quale, dall’analisi dei tempi medi di esecuzione, si può notare che il codice Thumb viene eseguito leggermente più veloce rispetto al codice ARM. Per quanto riguarda le ottimizzazioni, invece, si può notare il trend a scendere dei tempi medi di esecuzione in entrambi i primi due casi. Nel terzo caso invece risulta più veloce la seconda ottimizzazione piuttosto che la terza, la quale risulta addirittura la più lenta in esecuzione (anche se di poco) rispetto a tutti gli altri codici. Le variazioni dei tempi di esecuzione ottenute con le varie ottimizzazioni possono essere spiegate con il fatto che viene eliminato del codice morto, cioè del codice che il compilatore inserisce in un primo momento, ma che poi può essere cancellato dato che non è utile all’esecuzione finale del programma. Queste variazioni dipendono molto anche dalla struttura dei programmi stessi e dei registri che vanno a sfruttare. Questo fatto è dimostrato proprio dal terzo programma (la serie di Fibonacci) che viene eseguito più velocemente con codifica Thumb a 16 bit piuttosto che con la codifica ARM a 32 bit. Come spiegato all’inizio del capitolo 5 il set di istruzioni Thumb ha accesso completo ai primi otto registri (R0-R7), mentre l’accesso ai restanti otto registri (R8-R15), detti registri alti, è piuttosto limitato. Inoltre viene anche detto che “Il Thumb è pensato per aumentare le performance delle implementazioni ARM che usano un bus dati a 16-bit o anche più piccolo e per permettere una densità di codice migliore di quella fornita dal set di istruzioni ARM”. In questo modo si può capire perchè il nostro processore (il quale ha un bus dati di 32 bit), in generale, senza ottimizzazioni, esegue più velocemente il codice ARM. In conclusione, il set di istruzioni Thumb sarebbe più adatto per processori che hanno un bus istruzioni di 16 bit, piuttosto che 32 bit come nel nostro caso, e comunque alcune piccole differenze si sono potute notare anche con questo processore data la diversità di accesso ai registri. 196 Studi e sperimentazioni su processori ad architettura ARM: il set di istruzioni Thumb Tesi di Laurea di: Loredano Rapari matr. 1029262 9. Bibliografia e sitografia “Architettura e organizzazione dei calcolatori – Progetto e prestazioni”, ed. Pearson, di William Stallings, ottava edizione “ARMv5 Architecture Reference Manual” dal sito www.arm.com “System on chip architecture”, ed. Addison-Wesley, di Steve Furber, seconda edizione “ARM System developers guide”, ed. Elsevier, di A.N. Sloss, D. Symes, C. Wright http://arm.com/products/processors/licensees.php http://arm.com/products/processors/index.php http://www.marvell.com/processors/embedded/kirkwood/assets/FS_88F6180_9x_6281_OpenSo urce.pdf http://www.globalscaletechnologies.com/t-sheevaplugdetails.aspx#features 197