Architettura del set di istruzioni
Nell'ambito dell'ingegneria informatica, un'architettura del set di istruzioni[1][2][3] (in inglese: instruction set architecture), abbreviata come ISA, è un modello astratto che definisce in generale il modo in cui il software controlla la CPU di un computer o di una famiglia di computer.[4] Un dispositivo o un programma che esegue le istruzioni descritte da tale ISA, ad esempio un'unità di elaborazione centrale (CPU), è detto implementazione di tale ISA.
In generale, un'ISA definisce le istruzioni supportate, i tipi di dati, i registri, il supporto hardware per la gestione della memoria principale[non chiaro], le caratteristiche fondamentali (come la consistenza della memoria, le modalità di indirizzamento, la memoria virtuale) e il modello di input/output delle implementazioni dell'ISA.
Un'ISA specifica il comportamento del codice macchina in esecuzione sulle proprie implementazioni in un modo indipendente da esse, garantendone la compatibilità binaria. Ciò consente di avere più implementazioni di un'ISA che differiscono per caratteristiche quali le prestazioni, le dimensioni fisiche e il costo, ma che sono in grado di eseguire lo stesso codice macchina, in modo tale che una macchina con prestazioni inferiori e costi inferiori possa essere sostituita con una macchina con prestazioni superiori e costi più elevati, senza la necessità di sostituire il software. Inoltre, l'ISA consente l'evoluzione delle microarchitetture delle sue implementazioni, in modo da garantire la retrocompatibilità, vale a dire che un'implementazione più recente e più performante di una ISA possa eseguire il software che gira sulle generazioni precedenti di implementazioni.
Se un sistema operativo mantiene un'interfaccia binaria dell'applicazione (ABI) standard e compatibile per una particolare ISA, il codice macchina verrà eseguito sulle future implementazioni di tale ISA e sistema operativo. Tuttavia, se un'ISA supporta l'esecuzione di più sistemi operativi, ciò non garantisce che il codice macchina per un sistema operativo (SO) venga eseguito su un altro SO, a meno che il primo non supporti l'esecuzione di codice macchina creato per il secondo.
Un'ISA può essere estesa aggiungendo istruzioni o altre funzionalità, o aggiungendo il supporto per indirizzi e valori di dati più grandi; un'implementazione dell'ISA estesa sarà comunque in grado di eseguire codice macchina per le versioni dell'ISA che non sono estese. Viceversa, il codice macchina che utilizza tali estensioni verrà eseguito solo su implementazioni che le supportano.
La compatibilità binaria che forniscono rende le ISA una delle astrazioni più fondamentali dell'informatica.
Generalità
[modifica | modifica wikitesto]L'architettura del set di istruzioni si distingue dalla microarchitettura, che è l'insieme delle tecniche di progettazione del processore utilizzate per implementare il set di istruzioni in un particolare processore. Processori con microarchitetture diverse possono condividere un set di istruzioni comune. Ad esempio, l'Intel Pentium e l'AMD Athlon implementano versioni quasi identiche del set di istruzioni x86, pur presentando una progettazione interna radicalmente differente.
Il concetto di architettura, distinto dalla progettazione di una macchina specifica, è stato sviluppato da Fred Brooks all'IBM durante la fase di progettazione del System/360:
«Prima dell'NPL (System/360), i progettisti di computer dell'azienda erano stati liberi di rispettare gli obiettivi di costo non solo selezionando le tecnologie, ma anche creando migliorie funzionali e architetturali. L'obiettivo di compatibilità SPREAD, invece, prevedeva un'unica architettura per una serie di cinque processori che coprivano un'ampia gamma di costi e prestazioni. Nessuno dei cinque team di progettazione poteva contare sulla possibilità di apportare modifiche alle specifiche architetturali per attenuare le difficoltà nel raggiungimento degli obiettivi di costo e prestazioni.»
Alcune macchine virtuali che supportano il bytecode del tipo di ISA, come Smalltalk, la macchina virtuale Java e il Common Language Runtime di Microsoft, lo implementano traducendo il bytecode per i percorsi di codice comunemente utilizzati nel codice macchina nativo. Inoltre, queste macchine virtuali eseguono i percorsi di codice usati meno frequentemente per interpretazione (vedi: compilatore just-in-time). Transmeta ha implementato in questo modo il set di istruzioni x86 sui processori VLIW.
Classificazione delle ISA
[modifica | modifica wikitesto]Un'ISA può essere classificata in diversi modi. Una classificazione comune è quella per complessità architetturale. Un computer con set di istruzioni complesso (CISC) è caratterizzato da molte istruzioni specializzate, alcune delle quali possono essere utilizzate solo raramente nella pratica. Un computer a set di istruzioni ridotto (RISC) semplifica il processore implementando in modo efficiente solo le istruzioni generalmente utilizzate nei programmi, mentre le operazioni meno comuni sono implementate come subroutine, con il conseguente tempo di esecuzione aggiuntivo del processore che però è compensato dalla loro rarità.[6]
Altri tipi includono da un lato le architetture VLIW (Very Long instruction word) e le architetture LIW (Long instruction word), strettamente correlate tra loro, e dall'altro le architetture EPIC (explicitly parallel instruction computing). Queste architetture cercano di sfruttare il calcolo parallelo a livello di istruzioni, richiedendo meno hardware di RISC e CISC e rendendo il compilatore responsabile dell'emissione e dello scheduling delle istruzioni.[7]
Sono state studiate architetture con una complessità ancora minore, come il minimal instruction set computer (MISC) e il one-instruction set computer (OISC). Si tratta di tipologie teoricamente importanti, ma che non sono state commercializzate.[8][9]
Istruzioni
[modifica | modifica wikitesto]Il linguaggio macchina è costituito da istruzioni discrete. Sull'architettura di elaborazione, una data istruzione può specificare:
- opcode (l'istruzione da eseguire): aggiungi, copia, testa;
- qualsiasi operando esplicito:
- registri
- valori letterali/costanti
- modalità di indirizzamento utilizzate per accedere alla memoria.
Operazioni più complesse vengono costruite combinando queste istruzioni semplici, che vengono eseguite in sequenza o come altrimenti indicato dalle istruzioni del flusso di controllo.
Tipologie di istruzioni
[modifica | modifica wikitesto]Esempi di operazioni comuni a molti set di istruzioni sono:
Gestione dei dati e operazioni di memoria
[modifica | modifica wikitesto]- impostare un registro su un valore costante;
- copiare dati da una locazione di memoria o da un registro a una locazione di memoria o a un altro registro (un'istruzione macchina spesso chiamata “move”, ma il termine è fuorviante). Vengono utilizzate per memorizzare il contenuto di un registro, il contenuto di un'altra locazione di memoria o il risultato di un calcolo oppure per recuperare i dati memorizzati per eseguire un calcolo successivo. Spesso vengono chiamate operazioni di load-store;
- leggere e scrivere dati da dispositivi hardware.
Operazioni aritmetiche e logiche
[modifica | modifica wikitesto]- aggiungere, sottrarre, moltiplicare o dividere i valori di due registri, collocando il risultato in un registro, eventualmente impostando uno o più codici di condizione in un registro di stato;[10]
- incrementare, decrementare in alcune ISA, risparmiando il fetch degli operandi nei casi banali;
- eseguire operazioni bitwise, ad esempio, prendere la congiunzione logica e la disgiunzione dei bit corrispondenti in una coppia di registri, prendere la negazione di ciascun bit in un registro;
- confrontare due valori nei registri (ad esempio, per vedere se uno è minore o se sono uguali);
- istruzioni in virgola mobile per l'aritmetica sui numeri in virgola mobile.[11]
Operazioni di controllo del flusso
[modifica | modifica wikitesto]- eseguire un fork verso un'altra posizione del programma in cui esegue le istruzioni;
- diramazione condizionale (conditional brunch) verso un'altra posizione se una certa condizione è soddisfatta.
- diramazione indiretta (indirect branch) verso un'altra posizione.
- richiamare un altro blocco di codice, salvando la posizione dell'istruzione successiva come punto di ritorno.
Istruzioni del coprocessore
[modifica | modifica wikitesto]- caricamento/memorizzazione di dati da e verso un coprocessore o scambio con i registri della CPU.
- eseguire operazioni con il coprocessore.
Istruzioni complesse
[modifica | modifica wikitesto]I processori possono includere istruzioni “complesse” nel loro set di istruzioni. Una singola istruzione “complessa” esegue un'operazione che può richiedere molte istruzioni su altri computer. Tali istruzioni sono caratterizzate da istruzioni che richiedono molteplici passaggi, controllano più unità funzionali o appaiono in altro modo su una scala più ampia rispetto alla maggior parte delle istruzioni semplici implementate da un determinato processore. Alcuni esempi di istruzioni “complesse” sono:
- trasferimento di più registri da o verso la memoria (in particolare lo stack) in una sola volta;
- spostamento di grandi blocchi di memoria (ad esempio, copia di stringhe o trasferimento DMA);
- aritmetica complicata in numeri interi e in virgola mobile (ad esempio, radice quadrata o funzioni trascendenti come logaritmo, seno, coseno, ecc.);
- istruzioni SIMD, una singola istruzione che esegue un'operazione su molti valori omogenei in parallelo, eventualmente in registri SIMD dedicati;
- esecuzione di un'istruzione atomica di test-and-set o di un'altra istruzione atomica di lettura-modifica-scrittura;
- istruzioni che eseguono operazioni ALU con un operando dalla memoria piuttosto che da un registro.
Le istruzioni complesse sono più comuni nei set di istruzioni CISC che in quelli RISC, ma anche i set di istruzioni RISC possono includerle. I set di istruzioni RISC generalmente non includono operazioni ALU con operandi di memoria o istruzioni per spostarne grandi blocchi; la maggior parte dei set di istruzioni RISC include istruzioni SIMD o vettoriali che eseguono la stessa operazione aritmetica su più dati contemporaneamente. Le istruzioni SIMD sono in grado di manipolare vettori e matrici di grandi dimensioni in un tempo minimo. Le istruzioni SIMD consentono una facile parallelizzazione degli algoritmi comunemente utilizzati nell'elaborazione di suoni, immagini e video. Sono state introdotte sul mercato diverse implementazioni SIMD con nomi commerciali come MMX, 3DNow! e AltiVec.
Codifica delle istruzioni
[modifica | modifica wikitesto]Nelle architetture tradizionali, un'istruzione comprende un codice operativo che specifica l'operazione da eseguire, ad esempio aggiungere il contenuto della memoria a un registro, e zero o più specificatori di operando, che possono specificare registri, posizioni di memoria o dati letterali. Gli specificatori di operando possono avere modalità di indirizzamento che ne determinano il significato o possono essere in campi fissi. Nelle architetture VLIW (Very Long Instructions Word), che comprendono molte architetture di microcodice, in una singola istruzione vengono specificati più codici operativi e operandi simultanei.
Alcuni set di istruzioni esotiche non hanno un campo opcode, come le architetture con attivazione del trasporto (transport triggered architectures, TTA), ma solo operandi.
La maggior parte delle macchine a pila ha set di istruzioni di tipo “0-operand” (v. sotto) in cui le operazioni aritmetiche e logiche sono prive di campi di specificazione dell'operando; solo le istruzioni che spingono gli operandi sullo stack di valutazione o che popolano gli operandi dallo stack alle variabili hanno specificatori di operando. Il set di istruzioni esegue la maggior parte delle azioni dell'ALU con operazioni postfix (notazione polacca inversa) che operano solo sulla pila delle espressioni, non sui registri di dati o su celle arbitrarie della memoria principale. Questo può essere molto conveniente per la compilazione di linguaggi di alto livello, perché la maggior parte delle espressioni aritmetiche può essere facilmente tradotta in notazione postfissa.[12]
Le istruzioni condizionali hanno spesso un campo predicato, ovvero alcuni bit che codificano la condizione specifica per cui un'operazione deve essere eseguita piuttosto che non eseguita. Ad esempio, un'istruzione di diramazione condizionale trasferisce il controllo se la condizione è vera, in modo che l'esecuzione proceda a una parte diversa del programma, e non trasferisce il controllo se la condizione è falsa, in modo che l'esecuzione continui in modo sequenziale. Alcuni set di istruzioni prevedono anche spostamenti condizionati, in modo che lo spostamento venga eseguito e i dati memorizzati nella posizione di destinazione (se la condizione è vera), mentre non venga eseguito e la posizione di destinazione non venga modificata (se la condizione è falsa). Analogamente, IBM z/Architecture dispone di un'istruzione di memorizzazione condizionale.
Numero di operandi
[modifica | modifica wikitesto]I set di istruzioni possono essere classificati in base al numero massimo di operandi esplicitamente specificati al loro interno.
(Negli esempi che seguono, a, b e c sono indirizzi (diretti o calcolati) che si riferiscono a celle di memoria, mentre reg1 e così via si riferiscono ai registri della macchina).
- C = A+B
- macchine a 0 operandi (macchine a indirizzo zero), le cosiddette macchine a pila (stack machine): tutte le operazioni aritmetiche avvengono utilizzando le prime due posizioni della pila:[13]
push a
,push b
,add
,pop c
- C = A+B necessita di quattro istruzioni.[14] Per le macchine a pila, i termini "o perandi" e "o0 indirizzi" si applicano alle istruzioni aritmetiche, ma non a tutte le istruzioni, poiché le istruzioni
push
epop
a un operando sono utilizzate per accedere alla memoria.
- C = A+B necessita di quattro istruzioni.[14] Per le macchine a pila, i termini "o perandi" e "o0 indirizzi" si applicano alle istruzioni aritmetiche, ma non a tutte le istruzioni, poiché le istruzioni
- le macchine a un solo indirizzo, le cosiddette macchine ad accumulatore, comprendono i primi computer e molti piccoli microcontrollori: la maggior parte delle istruzioni specifica un singolo operando destro (cioè una costante, un registro o una posizione di memoria), con l'accumulatore implicito come operando sinistro (e la destinazione, se esiste):
load a
,add b
,store c
.C = A+B
necessita tre istruzioni'.[15]
- macchine a 2 operandi, categoria in cui ricadono molte macchine CISC e rISC:
- CISC —
muovi A
a C; quindiaggiungi B
a C.C = A+B
necessita di due istruzioni. Effettivamente, memorizza il risultato senza un'istruzione esplicita in tal senso.
- CISC — spesso le macchine sono limitate a un solo operando idi memoria per operazione:
load a,reg1
;add b,reg1
;store reg1,c
; Questo richiede una coppia di caricamento e memorizzazione per qualsiasi movimento di memoria, indipendentemente dal fatto che il risultato dell'istruzioneadd
sia un argomento localizzato in un indirizzo differente, come nel caso diC = A+B
, ovvero nella stessa cella di memoria:A = A+B
.C = A+B
necessita di tre istruzioni.
- RISC - Richiedendo il caricamento esplicito della memoria, le istruzioni sarebbero:
load a,reg1
;load b,reg2
;add reg1,reg2
;store reg2,c
.C = A+B
necessita di quattro istruzioni.
- CISC —
- macchine a 3 operandi, che permettono un migliore recupero dei dati[16]
- CISC- diventa una singola istruzione:
add a,b,c
C = A+B
necessita di una sola istruzione.
- CISC - oppure, su macchine limitate a due operandi di memoria per istruzione:
move a,reg1
;add reg1,b,c
;C = A+B
necessita di due istruzioni.
- RISC _ le istruzioni aritmetiche utilizzano solo i registri, quindi sono necessarie istruzioni di caricamento e memorizzazione esplicite a due operandi:
load a,reg1
;load b,reg2
;add reg1+reg2->reg3
;store reg3,c
;C = A+B
necessita di quattro istruzioni.- diversamente dal caso a 1 e 2 operandi, questo lascia i tre valori (a, b e c) disponibili nei registri per essere utilizzabili successivamente.[16]
- CISC- diventa una singola istruzione:
- alcune macchine CISC a più operandi permettono una varietà di modalità di indirizzamento che consentono più di 3 operandi (registri o accessi alla memoria), come ad esempio l'istruzione VAX “POLY”, istruzione di valutazione polinomiale.
A causa dell'elevato numero di bit necessari per codificare i tre registri di un'istruzione a 3 operandi, le architetture RISC con istruzioni a 16 bit sono invariabilmente progetti a 2 operandi, come Atmel AVR, TI MSP430 e alcune versioni di ARM Thumb. Le architetture RISC con istruzioni a 32 bit sono solitamente progetti a 3 operandi, come le architetture ARM, AVR32, MIPS, Power ISA e SPARC.
Ogni istruzione specifica un certo numero di operandi (registri, posizioni di memoria o valori immediati) in modo esplicito. Alcune istruzioni forniscono uno o entrambi gli operandi in modo implicito, ad esempio memorizzandoli in cima alla pila o in un registro implicito. Se alcuni operandi sono forniti implicitamente, è necessario specificare nell'istruzione un numero inferiore di operandi. Quando un operando specifica esplicitamente la propria destinazione, è necessario fornire un operando aggiuntivo. Di conseguenza, il numero di operandi codificati in un'istruzione può differire dal numero di argomenti matematicamente necessari per un'operazione logica o aritmetica (l'arietà). Gli operandi sono codificati nella rappresentazione “opcode” dell'istruzione, oppure sono forniti come valori o indirizzi dopo l'opcode.
Pressione di registro
[modifica | modifica wikitesto]La pressione dei registri (register pressure) misura la disponibilità di registri liberi in qualsiasi momento durante l'esecuzione del programma. La pressione dei registri è alta quando un gran numero di registri disponibili è in uso; quindi, più alta è la pressione dei registri, più spesso il contenuto dei registri deve essere riversato in memoria. L'aumento del numero di registri in un'architettura diminuisce la pressione dei registri, ma ne aumenta il costo.[17]
Mentre i set di istruzioni embedded come Thumb soffrono di una pressione sui registri estremamente elevata perché hanno insiemi di registri piccoli, le ISA di tipo RISC a scopo generico come MIPS e DEC Alpha godono di una bassa pressione sui registri. Le ISA di tipo CISC come x86-64 offrono una bassa pressione sui registri, nonostante abbiano insiemi di registri più piccoli. Ciò è dovuto alle numerose modalità di indirizzamento e alle ottimizzazioni (come l'indirizzamento ai sottoregistri, gli operandi di memoria nelle istruzioni dell'ALU, l'indirizzamento assoluto, l'indirizzamento PC-relativo e i versamenti da registro a registro) che le ISA CISC offrono.[18]
Lunghezza dell'istruzione
[modifica | modifica wikitesto]La dimensione o lunghezza di un'istruzione varia notevolmente, da appena quattro bit in alcuni microcontrollori a molte centinaia di bit in alcuni sistemi VLIW. I processori utilizzati nei personal computer, nei mainframe e nei supercomputer hanno dimensioni minime delle istruzioni comprese tra 8 e 64 bit. L'istruzione più lunga possibile su x86 è di 15 byte (120 bit).[19] All'interno di uno stesso set di istruzioni, istruzioni diverse possono avere lunghezze diverse. In alcune architetture, in particolare la maggior parte dei computer a set di istruzioni ridotto (RISC), le istruzioni hanno una lunghezza fissa, in genere corrispondente alla dimensione della parola dell'architettura. In altre architetture, le istruzioni hanno una lunghezza variabile, tipicamente multipli integrali di un byte o di una mezza parola. Alcune, come l'ARM con l'estensione Thumb, hanno una codifica variabile mista, cioè due codifiche fisse, di solito a 32 e 16 bit, in cui le istruzioni non possono essere mescolate liberamente, ma devono essere commutate su una ramificazione (o su un confine di eccezione in ARMv8).
Le istruzioni a lunghezza fissa sono meno complicate da gestire rispetto a quelle a lunghezza variabile per diversi motivi (ad esempio, non devono controllare se un'istruzione si trova a cavallo di una linea di cache o di una pagina di memoria virtuale) e sono quindi più facili da ottimizzare per la velocità.
Densità del codice
[modifica | modifica wikitesto]Nei primi computer degli anni '60, la memoria principale era costosa e molto limitata, anche nei mainframe. Era spesso fondamentale ridurre al minimo le dimensioni di un programma per assicurarsi che si adattasse alla memoria limitata. Pertanto, la dimensione delle istruzioni necessarie per eseguire un particolare compito, la densità del codice, era una caratteristica importante di qualsiasi set di istruzioni. È rimasta importante nelle memorie inizialmente minuscole dei minicomputer e poi dei microprocessori. La densità rimane importante anche oggi, per le applicazioni degli smartphone, per le applicazioni scaricate nei browser su connessioni Internet lente e nelle ROM per le applicazioni incorporate. Un vantaggio più generale dell'aumento della densità è il miglioramento dell'efficacia delle cache e del prefetch delle istruzioni.
I computer ad alta densità di codice hanno spesso istruzioni complesse per l'inserimento di procedure, ritorni parametrici, loop e così via (per questo chiamati retroattivamente Complex Instruction Set Computers, CISC). Tuttavia, le istruzioni CISC più tipiche o frequenti combinano semplicemente un'operazione ALU di base, come "aggiungi", con l'accesso a uno o più operandi in memoria (utilizzando modalità di indirizzamento come diretta, indiretta, indicizzata, ecc.) Alcune architetture possono consentire l'accesso a due o tre operandi (compreso il risultato) direttamente in memoria o possono essere in grado di eseguire funzioni come l'incremento automatico del puntatore, ecc. I set di istruzioni implementati dal software possono avere istruzioni ancora più complesse e potenti.
I computer a set di istruzioni ridotto (RISC) sono stati implementati per la prima volta in un periodo di rapida crescita dei sottosistemi di memoria. Sacrificano la densità del codice per semplificare i circuiti di implementazione e cercano di aumentare le prestazioni attraverso frequenze di clock più elevate e un maggior numero di registri. Una singola istruzione RISC esegue in genere una sola operazione, come un'“addizione” di registri o un “caricamento” da una posizione di memoria a un registro. Un set di istruzioni RISC ha normalmente una lunghezza fissa, mentre un tipico set di istruzioni CISC ha istruzioni di lunghezza molto variabile. Tuttavia, poiché i computer RISC richiedono normalmente un numero maggiore di istruzioni, spesso più lunghe, per implementare un determinato compito, essi fanno intrinsecamente un uso meno ottimale della larghezza di banda del bus e delle memorie cache.
Alcune ISA di tipo RISC embedded, come Thumb e AVR32, presentano in genere una densità molto elevata grazie a una tecnica chiamata compressione del codice. Questa tecnica impacchetta due istruzioni a 16 bit in una parola a 32 bit, che viene poi decompressa nello stadio di decodifica ed eseguita come due istruzioni separate.[20]
I computer con set di istruzioni minime (MISC) sono comunemente una forma di macchina a pila, in cui ci sono poche istruzioni separate (8-32), in modo che più istruzioni possano essere inserite in una singola parola. Questi tipi di core spesso richiedono poco silicio per essere implementati, quindi possono essere facilmente realizzati in un FPGA o in una forma multi-core. La densità di codice del MISC è simile a quella del RISC; la maggiore densità di istruzioni è compensata dalla necessità di un maggior numero di istruzioni primitive per svolgere un compito.
Sono state condotte ricerche sulla compressione degli eseguibili come meccanismo per migliorare la densità del codice. La matematica della complessità di Kolmogorov ne descrive le sfide e i limiti.
In pratica, la densità del codice dipende anche dal compilatore. La maggior parte dei compilatori con ottimizzatore dispone di opzioni che controllano se ottimizzare la generazione del codice per la velocità di esecuzione o per la densità del codice. Ad esempio, GCC ha l'opzione -Os per ottimizzare le dimensioni del codice macchina e -O3 per ottimizzare la velocità di esecuzione al prezzo di un codice macchina più grande.[21][senza fonte]
Rappresentazione
[modifica | modifica wikitesto]Le istruzioni che costituiscono un programma sono raramente specificate utilizzando la loro forma numerica interna (codice macchina); possono essere specificate dai programmatori utilizzando un linguaggio assembly o, più comunemente, possono essere generate da linguaggi di programmazione di alto livello da compilatori.[22]
Progettazione
[modifica | modifica wikitesto]La progettazione dei set di istruzioni è una questione complessa. Nella storia dei microprocessori ci sono state due fasi. La prima è stata quella del CISC (Complex Instruction Set Computer), che aveva molte istruzioni diverse. Negli anni '70, tuttavia, alcuni istituti come l'IBM fecero ricerche e scoprirono che molte istruzioni del set potevano essere eliminate. Il risultato fu il RISC (Reduced Instruction Set Computer), un'architettura che utilizza un set di istruzioni più ridotto. Un set di istruzioni più semplice può offrire il potenziale per velocità più elevate, dimensioni ridotte del processore e consumo energetico ridotto. Tuttavia, un set più complesso può ottimizzare operazioni comuni, migliorare l'efficienza della memoria e della cache o semplificare la programmazione.
Alcuni progettisti di set di istruzioni riservano uno o più codici opzionali a qualche tipo di chiamata di sistema o di interrupt del software. Ad esempio, il MOS Technology 6502 utilizza 00H; lo Zilog Z80 utilizza gli otto codici C7,CF,D7,DF,E7,EF,F7,FFH[23]; il Motorola 68000 utilizza codici nell'intervallo A000..AFFFH.
Le macchine virtuali veloci sono molto più facili da implementare se un set di istruzioni soddisfa i requisiti di virtualizzazione di Popek e Goldberg.
La slitta NOP (NOP slide) utilizzata nella programmazione immunity-aware è molto più facile da implementare se lo stato “non programmato” della memoria viene interpretato come una NOP.
Sui sistemi multiprocessore, gli algoritmi di sincronizzazione non bloccanti sono molto più facili da implementare se il set di istruzioni include il supporto per qualcosa come “fetch-and-add”[24], “load-link/store-conditional”[25] (LL/SC) o “compare-and-swap”.[26]
Istruzione ed implementazione
[modifica | modifica wikitesto]Un determinato set di istruzioni può essere implementato in diversi modi. Tutte le modalità di implementazione di un particolare set di istruzioni forniscono lo stesso modello di programmazione e tutte le implementazioni di quel set di istruzioni sono in grado di eseguire gli stessi eseguibili. I vari modi di implementare un set di istruzioni offrono diversi compromessi tra costi, prestazioni, consumo energetico, dimensioni, ecc.
Quando si progetta la microarchitettura di un processore, gli ingegneri utilizzano blocchi di circuiti elettronici “cablati” (spesso progettati separatamente) come sommatori, multiplexer, contatori, registri, ALU, ecc. Per descrivere la decodifica e la sequenza di ogni istruzione di un'ISA che utilizza questa microarchitettura fisica, viene spesso utilizzato un linguaggio di trasferimento dei registri. Esistono due modi fondamentali di costruire un'unità di controllo per implementare questa descrizione (anche se molti progetti utilizzano vie di mezzo o compromessi):
- alcuni progetti di computer “cablano” la decodifica e la sequenza dell'intero set di istruzioni (proprio come il resto della microarchitettura);
- altri progetti impiegano routine o tabelle di microcodice (o entrambi), utilizzando ROM o RAM scrivibili (archivio di controllo scrivibile), vettori logici programmabili (PLA) o entrambi.
Le CPU progettate per l'elaborazione riconfigurabile[27] possono utilizzare i field-programmable gate array (FPGA).
Un'ISA può anche essere emulata da un interprete a livello di software. Naturalmente, a causa dell'overhead dell'interpretazione, questa operazione è più lenta dell'esecuzione diretta dei programmi sull'hardware emulato, a meno che l'hardware che esegue l'emulatore non sia un ordine di grandezza più veloce. Oggi è prassi comune per i produttori di nuove ISA o microarchitetture mettere a disposizione degli sviluppatori di software emulatori software nell'attesa dell'implementazione dell'hardware.
Spesso i dettagli dell'implementazione hanno una forte influenza sulle particolari istruzioni selezionate per il set di istruzioni. Ad esempio, molte implementazioni della pipeline di istruzioni consentono per ogni istruzione solo un singolo caricamento o salvataggio in memoria, portando a un'architettura di tipo load-store (RISC). Un altro esempio: alcune delle prime implementazioni della pipeline portavano a un branch delay slot.
Le esigenze dell'elaborazione digitale dei segnali ad alta velocità hanno spinto nella direzione opposta, costringendo le istruzioni a essere implementate in un modo particolare. Ad esempio, per eseguire i filtri digitali in modo sufficientemente veloce, l'istruzione MAC in un tipico processore di segnali digitali (DSP) deve utilizzare una sorta di architettura Harvard in grado di recuperare un'istruzione e due parole di dati contemporaneamente, e richiede un moltiplicatore binario[28] a ciclo singolo di moltiplicazione-accumulazione.
Note
[modifica | modifica wikitesto]- ^ M. Palesi, Architettura del set di istruzioni (PDF), su diit.unict.it (archiviato dall'url originale il 5 ottobre 2024).
- ^ Università di Ferrara (PDF), su unife.it (archiviato dall'url originale il 4 agosto 2018).
- ^ Prof. Gascia, Università di Catana (PDF), su diit.unict.it (archiviato dall'url originale il 5 ottobre 2024).
- ^ GLOSSARY: Instruction Set Architecture (ISA), su arm.com (archiviato dall'url originale l'11 novembre 2023).
- ^ Emerson W. Pugh, Lyle R. Johnson e John H. Palmer, IBM's 360 and Early 370 Systems, MIT Press, 1991, ISBN 0-262-16123-0.
- ^ Crystal Chen, Greg Novick e Kirk Shimano, RISC Architecture: RISC vs. CISC, su cs.stanford.edu, 16 dicembre 2006 (archiviato dall'url originale il 21 febbraio 2015).
- ^ Michael S. Schlansker e B. Ramakrishna Rau, EPIC: Explicitly Parallel Instruction Computing, in Computer, vol. 33, n. 2, febbraio 2000, pp. 37–45, DOI:10.1109/2.820037.
- ^ Adnan Shaout e Taisir Eldos, On the Classification of Computer Architecture, in International Journal of Science and Technology, vol. 14, estate 2003, p. 3.
- ^ William F. Gilreath e Phillip A. Laplante, Computer Architecture: A Minimalist Perspective, Springer Science+Business Media, 6 dicembre 2012, ISBN 978-1-4615-0237-1.
- ^ Hennessy, John L.; Patterson, David A. (2003). Computer Architecture: A Quantitative Approach (Third ed.). Morgan Kaufmann Publishers. ISBN 1-55860-724-2
- ^ Hennesey, Patterson (2003), p.108
- ^ Paul Durand, Instruction Set Architecture (ISA), in Introduction to Computer Science CS 0.
- ^ Hennessey, Patterson (2003), p. 92
- ^ Hennnessey, Patterson (2003), p. 93
- ^ Hennessy, Patterson (2003), p. 93
- ^ a b John Cocke e Victoria Markstein, The evolution of RISC technology at IBM (PDF), in IBM Journal of Research and Development, vol. 34, n. 1, gennaio 1990, pp. 4–11, DOI:10.1147/rd.341.0004. URL consultato il 5 ottobre 2022.
- ^ Daniel Page, 11. Compilers, in A Practical Introduction to Computer Architecture, Springer, 2009, p. 464, Bibcode:2009pica.book.....P, ISBN 978-1-84882-255-9.
- ^ Ashish Venkat e Dean M. Tullsen, Harnessing ISA Diversity: Design of a Heterogeneous-ISA Chip Multiprocessor, 41st Annual International Symposium on Computer Architecture, 2014.
- ^ Intel® 64 and IA-32 Architectures Software Developer's Manual, su intel.com, Intel Corporation.
- ^ Vincent M. Weaver e Sally A. McKee, Code density concerns for new architectures, IEEE International Conference on Computer Design, 2009, DOI:10.1109/ICCD.2009.5413117.
- ^ RISC vs. CISC, su cs.stanford.edu. URL consultato il 18 dicembre 2021.
- ^ Hennessey, Patterson (2003), p. 120
- ^ Jack Ganssle, Proactive Debugging, su embedded.com, 26 febbraio 2001.
- ^ L'istruzione di CPU fetch-and-add (FAA) incrementa atomicamente il contenuto di una locazione di memoria di un valore specificato. In altre parole, l'istruzione fetch-and-add esegue la seguente operazione: incrementa il valore all'indirizzo x di a, dove x è una locazione di memoria e a è un valore, e restituisce il valore originale a x.
- ^ Il load-link restituisce il valore corrente di una locazione di memoria, mentre un successivo store-conditional alla stessa locazione di memoria memorizzerà un nuovo valore solo se non si sono verificati aggiornamenti della locazione dopo il load-link.
- ^ compare-and-swap (CAS) è un'istruzione atomica utilizzata nel multithreading per ottenere la sincronizzazione. Confronta il contenuto di una locazione di memoria con un valore dato e, solo se sono uguali, modifica il contenuto di quella locazione di memoria con un nuovo valore dato.
- ^ L'architettura di computer che combina parte della flessibilità del software con le alte prestazioni dell'hardware, elaborando con piattaforme hardware flessibili come gli FPGA
- ^ Un moltiplicatore binario è un circuito elettronico utilizzato nell'elettronica digitale, come i computer, per moltiplicare due numeri binari. Per implementare un moltiplicatore digitale si possono utilizzare diverse tecniche aritmetiche. La maggior parte delle tecniche prevede il calcolo dell'insieme dei prodotti parziali, che vengono poi sommati mediante sommatori binari. Questo processo è simile alla moltiplicazione lunga, ma utilizza un sistema numerico in base 2 (binario).
Voci correlate
[modifica | modifica wikitesto]Altri progetti
[modifica | modifica wikitesto]- Wikimedia Commons contiene immagini o altri file su instruction set
Controllo di autorità | GND (DE) 4129931-0 |
---|