di  -  giovedì 26 luglio 2012

L’8086 viene spesso assurto a sinonimo di peccato originale, che rappresenta quindi il massimo “danno” di cui tutte le future generazioni si dovranno fare carico, pagandone le conseguenze in termini di microarchitettura.

In realtà, e proseguendo nell’analisi delle istruzioni legacy della famiglia x86 (e x64) iniziata nel precedente articolo, i successori dell’8086 hanno introdotto parecchie istruzioni, anche molto più complesse di quelle esaminate e oggetto di lamentazioni.

Ciò non deve far pensare subito male. Aggiungere istruzioni è un processo naturale, perché il produttore del microprocessore non può evitare di analizzare la tendenza del mercato, cercando poi di rispondere in maniera adeguata.

Purtroppo certe scelte possono diventare difficili da sostenere molto più avanti, quando il mercato è nuovamente cambiato, perché in quest’ambito la retrocompatibilità è una caratteristica di primaria importanza (ma non intoccabile). Si tratta in ogni caso di una problematica comune ai produttori di processori.

L’80186 venne presentato nello stesso anno dell’80286, il 1982, ed entrambi introducono diverse istruzioni in user-space (il secondo anche e soprattutto in supervisor/kernel space, che non verranno discusse al momento).

Di queste sono poche a poter essere classificate come legacy: INS, OUTS, PUSHA, POPA, BOUND, ENTER, LEAVE. In compenso alcune risultano particolarmente complesse.

INS e OUTS fanno parte del vecchiume che fa capo alle periferiche mappate come “porte” in un apposito spazio d’indirizzamento, quello delle porte di I/O appunto, a cui è stata fornita la capacità di operare anche come “stringhe“. Permettono, quindi, di leggere blocchi di dati sequenzialmente forniti da una precisa porta, oppure scrivere una serie di dati sempre a una determinata porta.

Campionesse di complessità sono, però, le successive due istruzioni, che servono rispettivamente a memorizzare nello stack e a recuperare tutti i registri del processore (8 in tutto, con x86). Compiti che richiedono necessariamente di passare all’uso di microcodice per la loro esecuzione, bloccando la pipeline, a causa dell’elevato numero di operazioni (“basilari”; lasciatemi passare il termine) da compiere.

Si tratta di istruzioni relativamente comode poiché, utilizzando spesso delle routine che ne richiamano altre a loro volta, si presenta l’esigenza di dover salvare il contenuto dei registri prima della chiamata, per poi recuperarli dopo (giocando un po’ con lo stack nel caso fosse necessario conservare qualche valore di ritorno).

Il termine “relativamente” non è messo a caso, in quanto il più grosso problema, nonché barriera all’uso, di queste istruzioni è rappresentato dal dover operare sull’intero insieme dei registri, anziché su un sottoinsieme limitato esclusivamente a quelli che realmente ci serve che siano salvati e ripristinati.

Il concetto, insomma, era valido, ma la scelta implementativa si è rivelata infelice. Alcuni RISC (come ARM e PowerPC, ad esempio), che mettono a disposizione questa funzionalità, consentono, invece, di selezionare singolarmente i registri oggetto di PUSH e POP o, in generale, di load/store da/verso la memoria di più registri.

Ovviamente anche nel loro caso l’implementazione richiede il blocco della pipeline e l’esecuzione di microcodice per ottemperare al compito, il che dimostra come il concetto di legacy, di “pesantezza”, “complessità” di un’ISA sia abbastanza relativo: va bene se applicato ai “soliti noti”, ma si ignora o nasconde con quelli che vengono ritenuti campioni di virtù…

Basti pensare che i membri della famiglia POWER 4 (e molto probabilmente anche i successori) e PowerPC G5 internamente sono dotati di un RISC “ancora più RISC” per l’esecuzione effettiva delle istruzioni, le quali vengono convertite in una o più istruzioni più semplici, facendo ricorso in alcuni casi, come quello citato ad esempio, al microcodice per la loro esecuzione.

Se lo scenario richiama il lavoro fatto da AMD e Intel in questi anni… non è affatto casuale, perché il concetto è proprio lo stesso. Con buona pace dei puristi e di chi si scaglia contro x86 e compagnia che, alla luce di tutto ciò, avviene ormai per mera questione ideologica.

C’è da dire, per completare il discorso, che ARM ha deciso di togliersi questo fardello con la nuova architettura a 64 bit a cui sta lavorando, ARM64, nota anche come ARMv8. Infatti non esistono più istruzioni di load/store multiple (che operano su più registri; anche tutti), ma ne sono state introdotte un paio che consentono di operare soltanto su una coppia di registri.

Si è trattato, a mio modesto avviso, di una scelta obbligata perché, avendo a disposizione opcode a 32 bit, non sarebbe stato possibile definire un’istruzione che in soli 32 bit permettesse di selezionare qualunque sottoinsieme dei 32 registri dell’ISA (se non ricorrendo ad artifizi). La nuova implementazione, inoltre, non dovrebbe creare problemi alla pipeline per la sua esecuzione.

AMD ha pensato bene di anticipare i tempi con la sua architettura AMD64 / x64, rimuovendo del tutto PUSHA e POPA dal set d’istruzioni. D’altra parte è già difficile trovare applicazioni a 32 bit che ne facciano uso, per cui pensare di eseguire il push e il pop di tutti e 16 i registri del processore ogni volta sarebbe stato assolutamente controproducente per le prestazioni.

Tornando alle istruzioni legacy introdotte da 80186 e 80286, BOUND consente di controllare se un valore (in genere l’indice di un vettore) a 16 o 32 bit risulti compreso in un intervallo (i cui estremi sono recuperati da una locazione di memoria specificata). Un’apposita eccezione viene sollevata nel caso in cui la condizione non venga soddisfatta.

Anche qui, si tratta di un’istruzione introdotta nell’ottica di supportare meglio i paradigmi di programmazione che si stavano diffondendo. Il Pascal, adottato come linguaggio principe per introdurre alla programmazione (lo sarà fino ai primi anni ’90), ne avrebbe tratto giovamento.

L’implementazione, però, non è certo delle migliori a causa della scelta di sollevare un’eccezione. Ciò richiede la scrittura di un apposito handler di basso livello, introducendo problematiche relative al “recupero” dell’eccezione partendo dal punto in cui era stata sollevata.

Inoltre, mentre per un s.o. strettamente monotask / batch è plausibile l’installazione di un handler nel vettore delle eccezioni da parte di una singola applicazione, diventa una scelta insostenibile nell’ottica del multitasking o, in generale, del dover permettere l’accesso a uno spazio delicatissimo qual è la tabella degli interrupt, appunto.

A parte la (relativa, in ogni caso) complessità dell’implementazione, sarebbe stato molto meglio utilizzare qualche flag (ad esempio quello di overflow) per segnalare lo sforamento dei limiti, delegando interamente all’applicazione (tutto in user-space) la gestione di questa condizione.

Un errore simile lo commise, ben prima di Intel, Motorola col suo 68000, salvo poi introdurre col 68020 un’altra istruzione che non solleva eccezioni, ma imposta, per l’appunto, un flag. Rimangono, in ogni caso, istruzioni di una certa complessità che sarebbe meglio evitare di implementare. Alcuni RISC mettono a disposizione un controllo su un singolo limite (superiore; C-like), generando un’eccezione, ma si tratta di casi rari.

Forse anche per questo AMD, ancora una volta con x64, ha deciso di eliminare questa istruzione. Mentre Intel ha pensato bene di riutilizzare l’opcode rimasto libero nell’architettura a 64 bit, sfruttandolo come prefisso per implementare le nuove istruzioni di Larrabee / Knights Corner. Ma questa è un’altra storia…

L’ultima coppia di istruzioni, ENTER e LEAVE, sono anch’esse rivolte a supportare un’esigenza comune all’epoca, quella di sistemare lo stack e, in generale, l’ambiente di lavoro all’inizio dell’esecuzione di una routine (procedura e/o funzione). Di queste, LEAVE serve a rimettere a posto il lavoro fatto dalla prima o da equivalenti istruzioni e, data la (relativa) semplicità, risulta ancora utilizzata.

L’autentico mostro di complessità risulta, invece, la prima, ENTER, che si porta dietro anche due valori immediati, a 16 e 8 bit rispettivamente. Sinteticamente, conserva nello stack il valore del registro BP (concettualmente in letteratura viene denominato frame pointer), vi copia il registro dello stack (per il nuovo ambiente / frame d’esecuzione), esegue poi il push nello stack di un certo numero di frame pointer quanti sono i livelli di annidamento della routine (specificati nel valore a 8 bit), e infine sottrae il valore a 16 bit dallo stack pointer per fare spazio alle variabili locali.

Un lavoro immane, come si può ben capire, che si traduce in quella che si può tranquillamente considerare la più complessa istruzione (per lo meno per x86, e in user-space), introdotta per accelerare in hardware l’esecuzione di subroutine per i linguaggi che supportano il concetto di nested procedure (quindi non C & derivati).

Evidentemente alla Intel c’erano degli ingegneri che amavano i linguaggi di Wirth… Il che non dispiace, se non per il fatto che questa istruzione estremamente rara (mai vista finora) dev’essere implementata in tutti i processori x86. Stranamente AMD non ha calato la mannaia con x64 che, quindi, la supporta ancora anche nella modalità a 64 bit.

L’80386 ha introdotto ben poche istruzioni che possano essere classificate come legacy: CWDE, CDQ, che si occupano di estendere un valore da 16 a 32 bit, e da 32 a 64 bit.

In realtà sono state inserite parecchie altre istruzioni anche un po’ complesse, come quelle di caricamento “one-shot” di segmenti/selettori e offset, manipolazione dei singoli bit, ricerca del primo bit a uno, e di shift con inserimento di campi di bit.

In particolare queste ultime (SHLD e SHRD) svolgono un lavoro complesso, ma negli ultimi anni anche nei processori RISC sono state aggiunte parecchie istruzioni di questo tipo, perché poter gestire campi di bit è un’esigenza molto comune e particolarmente importante quando si ha a che fare con operazioni di codifica e decodifica dei dati (ZIP, RAR, GIF, PNG, JPEG, MP3, MPEG, H264, ecc., sono gli esempi più lo eloquenti).

L’80486 introduce poche altre istruzioni, come la BSWAP usata per scambiare i byte di un valore a 32 bit, in modo da favorire la manipolazione di dati in formato big-endian, quindi usata molto raramente (stranamente non nell’eseguibile del MAME; in altri… sì).

Altre istruzioni vengono messe a disposizione per un’implementazione efficiente di meccanismi di lock, semafori, mutex, ecc., da parte dei s.o.. Lo stesso avvenne col Pentium, e in generale con tutti gli altri successori.

Anche qui, si tratta di esigenze comuni che hanno visto pure i RISC arricchirsi di funzionalità simili. Al solito, ciò che poteva essere visto male, come il capestro messo sui soliti noti, in base alle necessità diviene una ghirlanda da usare per decorare il “collo” dei virtuosi…

Perché questa, alla fine, è la realtà che emerge dopo un’attenta analisi delle istruzioni legacy che per anni sono state additate come il male assoluto di cui l’architettura x86 avrebbe dovuto vergognarsi fino alla fine dei tempi.

Non v’è dubbio che alla luce del contesto storico e delle scelte poi effettuate anche dalla concorrenza, processori RISC in primis, il caso delle istruzioni legacy debba necessariamente essere ridimensionato.

Sì, non si può certo nascondere che il “marcio” sia presente, come abbiamo avuto modo di vedere, ma non ha l’enorme portata che le leggende metropolitane hanno consegnato alla storia.

Inoltre la strada intrapresa da x64, che ha fatto fuori parecchie di queste istruzioni, dimostra che la retrocompatibilità a tutti i costi non rappresenta un tabù intoccabile…

30 Commenti »

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.

  • # 1
    massimo
     scrive: 

    Davvero istruttivo, e (finalmente) un articolo sugli instruction set che spiega le cose invece di limitarsi a dire che “Ciò è Male”(TM)…

    Ora, se parlassimo un pò anche degli instruction set dei RISC più importanti tipo MIPS, Alpha, Power… questa diventerebbe proprio una serie di articoli da salvare su disco ^___^

  • # 2
    Cesare Di Mauro (Autore del post)
     scrive: 

    Grazie. Per il momento sono concentrato su x86 e x64, e se gli articoli sono apprezzati continuerò in questa direzione. Ho parecchie informazioni, idee, e riflessioni da esporre sull’argomento.

    MIPS, Alpha e PowerPC sono in lizza da un po’ di anni ormai, ma non ho avuto abbastanza tempo per studiarmi queste architetture. Comunque prima o poi lo farò. :)

  • # 3
    ReNeSiS
     scrive: 

    Condivido in tutto il pensiero di Massimo, compreso i complimenti naturalmente.
    Sogno ancora una settimana con un articolo tuo, uno di Yossarian e magari anche uno di pleg :)

  • # 4
    Michele
     scrive: 

    Complimenti per l’articolo. Molto interessante. Sto leggendo anche tutti gli altri articoli sui vari processori della storia, se tu scrivessi un libro sarei il primo a comprarlo :)

  • # 5
    massimo
     scrive: 

    Alpha ormai è solo di interesse storico, ma MIPS è stata usata per Loongson, il Dragon chip cinese… potrebbe essere il caso di darci una buona occhiata, non si sa mai che i loongson nuovi non ci riservino delle sorprese? :-)

    PowerPC… mi è sempre sembrato strano che non siano riusciti a reggere l’ascesa prestazionale dei Pentium, agli inizi di questo decennio. Cosa è andato storto??

  • # 6
    Cesare Di Mauro (Autore del post)
     scrive: 

    Di Loongson ho già studiato giusto qualche tempo fa quello che è stato messo in piedi per accelerare l’emulazione x86 (più che di emulazione dovremmo parlare di compilazione JIT). Per cui è possibile che lo riprenda alla fine di questi articoli su x86.

    In verità un po’ di anni fa avevo pure studiato PowerPC e Alpha, ma non lavorandoci e/o avendo altro da fare, inevitabilmente sono finiti poi nel dimenticato. Devo necessariamente riprenderli per poterne parlare approfonditamente.

    Per rispondere velocemente alla tua domanda, agli inizi del 2000 Intel e AMD avevano già da tempo imboccato la strada delle prestazioni, che era stata spianata da NexGen con la sua prima CPU x86, che all’interno aveva un RISC per l’esecuzione vera e proprio del codice, concetto che sarà alla base di tutti i processori x86 moderni.
    Ciò ha consentito di avere processori x86 con un backend in grado di garantire prestazioni elevate. A questo uniamo il fatto che il codice x86 è più denso, e quindi occupa meno spazio e richiede meno banda verso la memoria rispetto ai RISC, e infine che le istruzioni fanno mediamente più lavoro “utile” (che richiedono più istruzioni per i RISC, le quali generano anche delle dipendenze; pensa, ad esempio, a come sommare un valore immediato a 32 bit a una locazione di memoria, che su x86 si fa con una sola istruzione, mentre coi RISC ce ne vogliono almeno 4).

    @Michele: prima di scrivere un libro dovrei coprire quanto meno i processori più importanti e noti, e riprendere gli articoli più vecchi perché erano molto più corti e con meno informazioni utili. Però l’idea mi piace, e non è escluso che in futuro non possa succedere (ma prima mi piacerebbe raccogliere tutto il materiale sull’Amiga O:-)

    Grazie a tutti.

  • # 7
    xan
     scrive: 

    la domanda che vorrei farti, ma che credo richieda 20 ore per la risposta è:

    quindi perche l’architettura ARM consuma mediamente 1/100 di quella x86 a parità di prestazioni?

  • # 8
    Cesare Di Mauro (Autore del post)
     scrive: 

    Non si può fornire una risposta generale. In parte ne abbiamo discusso nell’articolo precedente. Ad esempio l’ultima incarnazione di Atom per mobile ha consumi comparabili a soluzioni ARM con prestazioni similari.

    Per contro, non esistono ancora ARM con prestazioni abbastanza aggressive da impensierire Intel. Si aspetta l’A15, che dovrebbe arrivare a breve, e successivamente ARM64 a 64 bit, ma “a naso” non credo che cambierà poi molto.

    Anche volendo isolare la CPU e discutere soltanto di quest’ultima, ci sono tante variabili da considerare. Come già scritto, il decoder di x86/x64 ha sicuramente il suo peso nel bilancio energetico, ma non si può tenere conto esclusivamente di questo.

    Comunque non credo che ci sia un divario così elevato fra le due architetture a livello di consumi. Come scritto in un vecchio articolo, all’aumentare della dimensione dei core (causa integrazione di cache), il peso dei decoder va a incidere sempre meno sul bilancio complessivo.

    Rimane sensibile quando il core (mi riferisco al singolo core x86, nel caso di soluzioni multicore) è abbastanza piccolo e si misura nell’ordine di qualche decina di milioni di transistor, come ad esempio negli Atom e in Knights Corner (ex Larrabee), ma, come già detto, gli ultimi Atom rimangono competitivi con gli ARM proprio tenendo conto dei consumi…

  • # 9
    xan
     scrive: 

    non vorrei dire una cavolata ma da quello che ho letto gli ultimi atom MONOCORE consumano piu del doppio di 4 core ARM cortex a9

    ma su questo vorrei avere conferme che non sono sicurissimo

  • # 10
    Cesare Di Mauro (Autore del post)
     scrive: 

    Non mi sembra sia così: http://www.anandtech.com/show/5365/intels-medfield-atom-z2460-arrive-for-smartphones/

    I consumi, come vedi, sono allineati.

    Inoltre, anche se single core, Atom implementa la tecnologia Hyperthreading, che fa un buon lavoro.

    C’è una disparità per quanto riguarda i core fisici e/o logici, ma le prestazioni non sono certo la metà o 1/4 delle soluzioni quadcore ARM. ;)

    Comunque stiamo andando fuori argomento. Come capita quando si parla di queste cose. :P

  • # 11
    xan
     scrive: 

    era per capire una cosa:

    intel ha avuto una politica conservativa: un binario compilato per pentium 1 o 486 è eseguibile su ivy bridge

    mentre ARM a preferito l’innovazione perdendo la compatilibità con i binari, attualmente siamo ad ARMv7 e presto arriverà ARMv8 e gira tra loro non saranno eseguibili i binari

    volevo capire se è proprio questa scelta di tagliare la retrocompatibilità a ridurre cosi i consumi o no

  • # 12
    Cesare Di Mauro (Autore del post)
     scrive: 

    ARM parte comunque da una base solida da questo punto di vista, avendo potuto contare, per qualunque versione della sua architettura, su una opcode table abbastanza semplice da decodificare (ma MIPS e Alpha sono messi molto meglio).

    Comunque ha rotto la compatibilità binaria soltanto due volte: la prima con ARM v3, dove si è passati dall’ISA a 26 bit (come limite massimo d’indirizzamento della memoria) a quella a 32 bit che abbiamo conosciuto finora (quindi fino alla v7), e a breve con ARMv8, ma qui è stato indispensabile per avere dati e, soprattutto, puntatori a 64 bit.

    Per cui, come vedi, non è che fosse un pallino di ARM quello di introdurre architetture nuove e non retrocompatibili a livello binario, pur di guadagnare in ambito consumi. Le uniche due circostanze sono state dettate da assolute necessità.

    Paradossalmente Intel l’ha superata con 80286 e 80386, e infine con l’x64 introdotto da AMD: ben 3 cambiamenti abbastanza radicali (modalità protetta, 32 bit, 64 bit).

    Purtroppo la base di partenza, cioè l’opcode table, è rimasta fondamentalmente la stessa, con pezze su pezze inserite alla bisogna, che ha portato a complicazioni nelle implementazioni dei decoder.

    Non c’è stato, insomma, il coraggio di cambiare la struttura dell’ISA mantenendo la microarchitettura. Cosa tutt’altro che impossibile o insensata.

    Perché, da programmatore assembly, trovo decisamente comodo lavorare con x86 e, soprattutto, x64, e da questo punto di vista il fatto che l’opcode table e la struttura degli opcode siano pessimi e creino quei problemi per me è assolutamente indifferente: son cose che non vedo, poiché del tutto trasparenti (tranne se sviluppo compilatori o virtual machine).
    Io vedo registri, istruzioni, modalità d’indirizzamento della memoria, e da questo punto di vista mi posso ritenere molto soddisfatto.

    D’altra parte in alcuni ambiti la retrocompatibilità binaria x86 e/o x64 non è affatto necessaria. Faccio un paio di esempi.

    Se pensiamo all’ambito mobile, appunto, ARM domina ed è Intel che deve emulare quell’architettura. Il fatto che sia disponibile Android per x86 non vuol dire che ci si debba legare mani e piedi a x86 a livello binario.

    Altro esempio, il settore HPC/GPGPU computing che Intel sta cercando di attaccare con Knights Corner (ex Larrabee): la compatibilità binaria non è assolutamente necessaria, perché per sfruttare quest’architettura è necessario ricompilare kernel, driver, e applicazioni, altrimenti non sarebbe possibile sfruttare le nuovissime estensioni SIMD. Sì, Larrabee deriva da x86, ma se vuoi sfruttarla come si deve devi scrivere codice apposito (assembly) e/o ricompilare; in entrambi i casi, non serve mantenere lo stesso codice binario.

    In questi casi si potrebbe osare di più, proponendo un’ISA derivata da x86 e/o x64, ma che sia molto più semplice da decodificare. E magari che ne superi (in maniera trasparente) anche i limiti.

    Immagina cosa verrebbe fuori da un oggetto del genere: (all’incirca) la facilità di decodifica di un RISC (tipo Thumb-2, però; quindi con opcode di lunghezza variabile), con le prestazioni di un CISC x86/x64 e… anche di più. ;)

  • # 13
    xan
     scrive: 

    hai appena vinto il premio: “Post piu interessante che io abbia mai letto in tutta la vita !!”

  • # 14
    xan
     scrive: 

    altra domanda:

    un processore x86 a 64 bit puo leggere nativamente un binario a 32 bit se il sistema operativo installato è a 32 bit. in pratica è come se fosse sia a 32 bit che a 64 bit, poi in base al sistema operativo installato viene usato in un modo o nell’altro

    dubito che ARMv8 a 64 bit permetterà la stessa cosa

    questo come viene realizzato? che impatti ha sui consumi? ci sono aspetti negativi?

  • # 15
    Cesare Di Mauro (Autore del post)
     scrive: 

    Questo succede perché con x64 la CPU gira nel cosiddetto “long mode”, che consente di far girare in maniera trasparente applicazioni x86.
    Ma dev’essere il s.o. (x64) a mettere a disposizione questa possibilità, realizzando quanto serve per far comunicare i due mondi (tunnelling 32 < -> 64 bit).

    AMD con x64 ha voluto salvare, quindi, la retrocompatibilità binaria con x86, consentendo di far girare comunque quelle applicazioni (ma NON quelle a 16 bit).
    Più che voluto, diciamo che ha dovuto, a causa dell’enorme parco software disponibile per x86.

    Da quel che ho letto ARM, con la v8, permetterà lo stessa cosa. Non taglia, insomma, la retrocompabilità binaria con v3..7, e lo fa per le stesse motivazioni di AMD.

    Però è chiaro che se vuoi sfruttare la v8 per il nuovo ambiente a 64 bit, devi necessariamente rompere col passato e compilare appositamente per essa.
    Anche qui, come AMD. Solo che quest’ultima, come dicevo, non ha avuto il coraggio di tagliare completamente col passato e progettare una nuova opcode table & relativa struttura degli opcode.
    Cosa che, invece, ARM ha fatto con la v8. Infatti, come dicevo nell’articolo, ha rimosso un po’ di roba “legacy” pure lei. Un esempio su tutti: l’esecuzione condizionale di tutte le istruzioni, che prima era, invece, il suo vanto nonché punto di forza…

  • # 16
    Cesare Di Mauro (Autore del post)
     scrive: 

    Scusami, nella fretta non ho risposto alle ultime domande.

    Sì, ha un impatto sui consumi perché il decoder è ovviamente più complicato, perché deve tenere conto delle varie modalità d’esecuzione del processore (anche in ambiente 32 bit ce ne sono diverse; oltre all’ARM nativa c’è pure quella Thumb/-2, Jazelle, e ThumbEE).

    Ciò anche per sottolineare che pure ARM si sta trascinando dietro un po’ di roba proprio nei decoder. E questo ha ovviamente un impatto negativo, oltre che sui consumi, anche sulla pipeline del processore (credo che si debba utilizzare qualche stadio in più allo scopo).

  • # 17
    Davide Costantini
     scrive: 

    Cesare non ho scritto nulla perché non ho nulla da dire a parte “complimenti”.

    Seguo sempre interessatissimo i tuoi post sulle ISA.

  • # 18
    Giacomo
     scrive: 

    @ xan
    veramente un processore x86 a 64 bit può eseguire un binario a 32 bit anche se il SO installato è a 64 bit (non sempre, con alcuni binari ci sono problemi di compatibilità).. puoi fare la prova con Windows o Linux 64.

  • # 19
    Davide Costantini
     scrive: 

    @Cesare: i nuovi ARM (v8) non metteranno la parola fine all’architettura RISC? So che è un discorso più filosofico che pratico, ma non avevi detto in passato che la dimensione “fissa” delle istruzioni era una prerogativa RISC. Una di quelle più importanti.

  • # 20
    Cesare Di Mauro (Autore del post)
     scrive: 

    Lo è ancora, e ARMv8 sarà ancora un RISC, che presumibilmente utilizzerà opcode di dimensione fissa a 32 bit. Per lo meno da quel che ho letto, non mi pare di aver dedotto che faccia uso di opcode di lunghezza variabile (16/32 bit, come Thumb-2).

    Tuttavia potremmo dire che le carte si sono un po’ mescolate nel corso degli ultimi anni.

    I RISC hanno integrato sempre più istruzioni, arricchendo notevolmente il loro set e rivaleggiando tranquillamente coi CISC da questo punto di vista.

    I CISC hanno integrato un RISC al loro interno, sebbene esclusivamente per l’esecuzione “finale” delle operazioni. Inoltre privilegiano le istruzioni più semplici in quest’operazione di traduzione da opcode CISC a micro-ops RISC.

    E poi c’è una cosa di cui ho parlato tempo fa a proposito dell’architettura Thumb proprio di ARM: http://www.appuntidigitali.it/4947/con-thumb-2-arm-tradisce-i-risc-e-ritorna-ai-cisc/

    In buona sostanza, i RISC hanno integrato… un’ISA con opcode a lunghezza variabile nel momento in cui sono state costrette a fare i conti con la densità di codice, cavallo di battaglia dei CISC.

    Insomma, il confine fra RISC e CISC s’è decisamente assottigliato.

    Personalmente, rispondo all’ultima parte del tuo commento, almeno sulla lunghezza fissa o variabile degli opcode fra le due macrofamiglie ritengo sia possibile ancora suddividerle, e quindi considero Thumb-2 un’ISA CISC… ;)

  • # 21
    Marco
     scrive: 

    @Giacomo
    Non hai letto il commento di Cesare:”Questo succede perché con x64 la CPU gira nel cosiddetto “long mode”, che consente di far girare in maniera trasparente applicazioni x86.”

    @Cesare
    Bella serie di articoli, complimenti.
    Una sola precisazione: quando dici

    “far girare comunque quelle applicazioni (ma NON quelle a 16 bit)”

    sei in errore, in quanto AMD64 mette a disposizione sia il “legacy mode” che ne permette l’esecuzione in real, protected e virtual 8086 che il “compatibility sub-mode” del “long mode” che comunque contempla anche indirizzi a 16 bit.

  • # 22
    Cesare Di Mauro (Autore del post)
     scrive: 

    Sì, vero. Per la fretta ho mischiato le due cose. Scusate.

    Grazie della precisazione.

  • # 23
    banryu
     scrive: 

    @Cesare Di Mauro:
    Complimenti vivissimi per questa serie di articoli, molto interessanti.

    Nonstante io sia un profano, ho comunque una curiosità:

    L’autentico mostro di complessità risulta, invece, la prima, ENTER

    Evidentemente alla Intel c’erano degli ingegneri che amavano i linguaggi di Wirth. Il che non dispiace, se non per il fatto che questa istruzione estremamente rara (mai vista finora) dev’essere implementata in tutti i processori x86. Stranamente AMD non ha calato la mannaia con x64 che, quindi, la supporta ancora anche nella modalità a 64 bit.

    Messa giù così sembra una anomalia inspiegabile.
    Si sa il perchè? O quanto meno puoi fare delle ipotesi al riguardo?

  • # 24
    Cesare Di Mauro (Autore del post)
     scrive: 

    Tuttora non riesco proprio a spiegarmelo.

    Forse per avere una risposta dovrei provare a disassemblare gli eseguibili (a 64 bit) generati da FreePascal e/o Delphi, e controllare la presenza di questa istruzione… :P

  • # 25
    Zio Tom
     scrive: 

    Ciao Cesare, secondo te, c’è la possibilitá di accedere/programmare gli attuali x86 in assembler “risc”, saltando il modulo di traduzione?
    Non sarebbe molto più efficiente?

    Ciao
    Zio Tom

  • # 26
    Cesare Di Mauro (Autore del post)
     scrive: 

    E’ un argomento che ho segnato da parecchi anni e non mi sono mai deciso a parlarne.

    Al momento le risposte sono due no. Il primo perché è impossibile. E il secondo perché sarebbe molto più inefficiente.

    Vedrò se sarà il caso di parlarne alla fine di questo ciclo di articoli, perché mi è sempre interessato.

  • # 27
    Luca
     scrive: 

    Complimenti a Cesare, articolo eccellente! Ora sto lavorando e non posso dilungarmi troppo, ma mi sono segnato questo articolo e altri come letture estive :-)
    Grazie e continua così!

  • # 28
    max
     scrive: 

    @Cesare Scusi se vado ancora OT, ma giusto per completezza di informazione: proprio nell’articolo che linka a supporto della “non superiorità” degli ARM sui nuovi Atom (rispondendo a xan) leggo quanto segue:

    “The A15 is a far more modern design, also out of order but much wider than A9. I fully expect that something A15-class can outperform Medfield, especially if the former is in a dual-core configuration. Krait falls under the A15-class umbrella so I believe Medfield has the potential to lose its CPU performance advantage within a couple of quarters.”

    Saluti

  • # 29
    Cesare Di Mauro (Autore del post)
     scrive: 

    Visto che alla fine discutiamo in un blog, direi di abolire il lei e procedere col tu. ;)

    Riguardo alla parte quotata, concordo, ma prima non mi riferivo strettamente al confronto ARM e Atom, tant’è che nello stessa parte della discussione (più generale) ho parlato sia di A15 che di ARMv8.

    Mi rendo conto che il commento era un po’ ambiguo e poteva dare adito a interpretazioni diverse (specifiche sul confronto ARM vs Atom), ma bisogna considerare anche il contesto. Infatti quella che avevo scritto era una risposta al precedente commento di xen (#7), che era di carattere molto generale.

    Ricordo pure di aver scritto da qualche parte (qualche altro articolo) che al momento Intel con gli Atom è (finalmente) competitiva con gli ARM sia come prestazioni che come consumi, ma che con l’arrivo di A15 dovrà aggiornare la sua (ormai vecchia, perché non è poi cambiata molto da quando è stata introdotta) microarchitettura Atom per rimanere al passo, visto che A15 promette molto bene.

    D’altra parte Atom è un’architettura decisamente poco efficiente perché è stata pensata principalmente per mantenere i consumi. Nonostante ciò rimane competitiva con ARM sul piano prestazionale grazie all’architettura x86 (mia modesta opinione).

    Basti pensare che Atom è un processore in-order, mentre A9 è out-of-order, e se vai a spulciare il manuale delle ottimizzazioni di Intel nella sezione Atom, ti rendi conto delle tante limitazioni che ha quest’architettura e della necessità di avere codice appositamente compilato / ottimizzato per cercare di tirare fuori il più possibile. Eppure, con tutto quest’handicap che si porta dietro, anche eseguendo codice x86 non espressamente pensato per lei, Atom riesce a mostrare prestazioni di tutto rispetto.

    Il passaggio all’out-of-order sarebbe un enorme passo avanti, ma i consumi potrebbero risentirne. Forse Intel s’inventerà qualcos’altro. Vedremo cosa riuscirà a tirare fuori, perché non credo che rimarrà ferma al palo, lasciandosi fregare lo scettro delle prestazioni da ARM con l’A15 (sul mobile).

  • # 30
    Cesare Di Mauro (Autore del post)
     scrive: 

    Ricordavo bene. Ecco qui: http://www.appuntidigitali.it/16697/ultrabook-intel-spinge-apple-verso-arm/

    al commento #29. ;)

Scrivi un commento!

Aggiungi il commento, oppure trackback dal tuo sito.

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.