Perché i MIPS includevano shamt e distinguono funct / opcode?


15

Sono confuso sul perché i progettisti di MIPS includano 5 bit dedicati allo spostamento e abbiano opcode e bit funzione separati.

Dato che il MIPS è così RISC, suppongo che il solo spostamento sarebbe stato fatto in poche istruzioni, quindi quei 5 bit sembrano sprecare spazio quando potrebbero essere messi nell'immediato. Presumo che i codici operativi e le funzioni siano separati per distinguere le istruzioni di tipo R e I, ma ciò potrebbe essere fatto estendendo il codice operativo di 1 bit. Con entrambe queste istruzioni di tipo R potrebbe essere lungo 22 bit. Questo non funzionerà se le istruzioni di tipo I e J vogliono mantenere il loro indirizzo e indirizzo immediati, ma entrambi sembrano inutili.

Risposte:


10

Ci sono alcuni diversi compromessi in corso qui.

Innanzitutto, vogliamo che le istruzioni siano a larghezza fissa (32 bit). Ciò garantisce che le istruzioni siano bloccate nella cache e allineate alla pagina, il che semplifica la presenza della cache e della pagina e i controlli delle autorizzazioni.

In secondo luogo vogliamo che i vari campi di istruzione ( opcode/ source regs/ immediates) siano a larghezza fissa e posizione fissa. Ciò li rende più veloci / meno logici da decodificare e sono necessari nelle prime fasi della pipeline. (Il destinationregistro non è necessario fino alla fine della pipeline, quindi può trovarsi in punti Re Iistruzioni diversi). La posizione e l'ampiezza del functioncampo contano un po 'meno perché ciò deve controllare la funzione della ALU, ma questo è nella terza fase della pipeline, quindi hai un po 'di tempo per lavorarci, se necessario.

IJJ228228Ile istruzioni sono utili anche per gli autori di compilatori / linker. (Sullo SPARC, dove il campo immediato era solo 12 bit, dovevano aggiungere un'intera load-highclasse di istruzioni speciali con un immediato 20 bit.)

26=64JRI

Ma questo lascia un po 'di spazio alle Ristruzioni. A parte il codice operativo a 6 bit, questi richiedono solo 15 bit aggiuntivi per la specifica del registro, che lascia 11 bit per il codice operativo esteso e / o la quantità di spostamento.

È necessario considerare il functioncampo come un codice operativo esteso per l' Ristruzione. C'è solo un Rcodice operativo dell'istruzione, ma ci sono 64 differenti functionsche l' Ristruzione può eseguire.

Va bene. Abbiamo 60 Iistruzioni diverse e 64 Ristruzioni diverse , quindi dove dovremmo inserire le istruzioni per il turno immediato?

Bene, non solo ci sono meno Iistruzioni, ma ci sono molte più cose che vogliamo fare con le I istruzioni. Ricorda che tutte le istruzioni di diramazione devono essere Iistruzioni perché hanno un offset relativo (immediato). Inoltre, tutte le istruzioni di caricamento e memorizzazione sono Iformattate su MIPS. E infine abbiamo bisogno che l'istruzione load-upper-immediate sia Iun'istruzione. Non solo, ma le Ristruzioni hanno ancora 5 bit aggiuntivi non utilizzati, (che è ciò di cui abbiamo bisogno per l'immediato di uno spostamento immediato su questa architettura), quindi questo dà ulteriore incentivo a trasformare gli spostamenti-immediati in Ristruzioni speciali (strane) .

Molte di queste decisioni sono più arte che scienza, ma esiste una logica di fondo che può essere individuata. L'obiettivo chiave non è quello di rendere il numero di istruzioni il più piccolo possibile, è quello di ottenere prestazioni elevatepipeline adatta a un singolo chip (in modo che piccole aziende, come MIPS e Sun negli anni '80, potessero competere con IBM e DEC). (Il nome RISC, inventato da David Patterson, è alquanto sfortunato. Ha preso piede perché era carino, non perché "istruzioni ridotte" è una descrizione accurata di ciò che le architetture MIPS e SPARC stavano davvero cercando di fare.) Quindi vuoi il istruzioni a larghezza fissa (e relativamente piccole in modo da ottenere un migliore comportamento della cache I) per rendere più semplice e veloce il recupero, il paging e la decodifica. Volete le parti dell'istruzione che devono essere decodificate in anticipo (ilopcode, i due registri di origine e l'immediato esteso di segno) come una larghezza fissa e in una posizione fissa. Volete che gli immediati siano il più a lungo possibile e volete quanti più tipi di istruzioni possano andare bene, dati tutti gli altri vincoli.


Grazie per la tua risposta informativa, in particolare la parte relativa agli obiettivi dei progettisti dell'architettura. Trovo interessante confrontare MIPS con MOS 6502, perché se lo capisco correttamente il 6502 non ha mai avuto shamt (sto ancora cercando di capire i formati delle istruzioni).
qwr

1
Il 6502 era un design a microprocessore di prima generazione (pre-CISC), sebbene anticipasse il pipelining, in quanto poteva registrare il writeback nello stesso momento in cui stava caricando l'istruzione successiva. Il 6502 aveva codici di byte byte, come la maggior parte dei micro a 8 bit. Un'altra architettura da considerare è l'ARM, che è stato progettato da un gruppo di ingegneri elettronici di livello superiore che hanno letto i documenti RISC di Berkeley e hanno visitato la fabbrica MOS e hanno deciso "ehi, possiamo farlo".
Pseudonimo del

Mi chiedo quali sarebbero le implicazioni se ci fosse un modello di bit shamt che significa "non eseguire le seguenti istruzioni, ma utilizzare i 32 bit che sono stati recuperati come operando di origine per questa istruzione"? In alternativa o in aggiunta, mi chiedo se sarebbe stato pratico avere una buona porzione di spazio di codice operativo dedicato a coppie di semplici istruzioni ininterrotte - un concetto un po 'come il pollice, ma liberamente intercambiabile con le istruzioni a 32 bit e senza la possibilità di saltare direttamente alla seconda istruzione di una parola?
supercat

5

Per comprendere i formati di istruzione MIPS I, è necessario comprendere la pipeline MIPS e ripensare alla tecnologia di implementazione della CPU intorno al 1985. Se si guarda il diagramma (si conosce quello), si vedrà che la lettura del file di registro è nella ID stage, subito dopo IF.

Ai fini di un'istruzione di tipo R, la fase ID deve eseguire le seguenti attività:

  1. Determina che in realtà è un'istruzione di tipo R.
  2. In tal caso, dire al file di registro di caricare i valori dai registri.

Ai fini di questa discussione, è il primo compito a cui devi pensare. Se c'è molto lavoro di decodifica delle istruzioni che devi fare anche per capire se hai bisogno di valori dai registri, questo aumenta il ritardo prima di poter avviare le letture del registro. Aumenta anche la complessità della fase ID. Riservando un unico codice operativo per tutte le istruzioni di tipo R, si riduce al minimo la complessità.

Sembra un po 'strano dedicare cinque bit solo al cambio. Mi vengono in mente alcune possibili spiegazioni. Uno è che semplifica il routing (quei cinque bit sono SEMPRE inseriti direttamente nel file di registro, quei cinque bit sono SEMPRE inseriti nello shifter del barilotto, quei sei bit sono SEMPRE instradati sempre verso l'ALU per determinare quale funzione eseguire).

Potrebbero aver pensato di introdurre in futuro istruzioni combinate di spostamento a sinistra e aggiunta. Questo presumibilmente sarebbe nella forma:

$d = $s + ($t << shamt)

Questa è un'istruzione sorprendentemente utile da avere in giro, come può dirti qualsiasi programmatore di assembly x86. Puoi usarlo per implementare le moltiplicazioni rapide di2S+1 per vari valori di Soppure puoi usarlo per indicizzare array in cui la dimensione di un elemento è una potenza di due (che è un caso molto comune). Ma è ancora abbastanza RISC da poterlo implementare senza penalità significative.

Oggi, probabilmente non ci penseremmo due volte ad avere una fase di decodifica più complessa, soprattutto perché gli accessi ai file di registro tendono ad avvenire più tardi nella pipeline di una tipica CPU superscalare. Molte CPU moderne eseguono anche una decodifica approssimativa delle istruzioni nel momento in cui un'istruzione viene inserita nella cache L1 . Aumentate di qualche bit le linee della cache I per memorizzare le informazioni extra (grazie alla Legge di Moore, avete molti transistor da sprecare) per rendere la decodifica "corretta" delle istruzioni più semplice e veloce.

Uno dei motivi per cui probabilmente volevano mantenere il campo del codice operativo il più piccolo possibile è che non penalizzasse indebitamente le istruzioni di tipo J. Come probabilmente saprai, le istruzioni di tipo J utilizzano l'indirizzamento pseudo-diretto. A beneficio di chiunque suoni insieme a casa, lo spiegherò brevemente.

Il campo dell'indirizzo di un'istruzione di tipo J è di 26 bit. Poiché le istruzioni sono sempre allineate a 4 byte, non è necessario memorizzare i due bit meno significativi, il che significa che si dispone effettivamente di 28 bit di indirizzo. Tuttavia, lo spazio degli indirizzi in MIPS I è a 32 bit. Quindi i primi quattro bit della posizione di salto sono presi dal contatore del programma.

Ciò significa che non è possibile passare direttamente a una posizione in cui i quattro bit più significativi della posizione del PC sono diversi. Dovresti invece fare un salto in tre istruzioni più costoso attraverso un registro scratch:

lui $r,target >> 16
    ori $r,$r,target & 0xFFFF
    jr $r

Oggi non è poi così male, ma nel 1985 ci sono molti cicli di clock.

Rubare un po 'dal campo dell'indirizzo ridurrebbe ulteriormente l'intervallo effettivo di un salto diretto. Puoi vedere come questo potrebbe essere un prezzo troppo alto da pagare.


"istruzioni combinate maiusc-sinistra-e-aggiungi" del tipo visto in seguito in ARM?
Damian Yerrick,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.