# Personal computer/Linguaggio Macchina/DLX/Operazioni

Personal computer
* Storia dei calcolatoriPersonal computer/Storia
* Architettura del calcolatorePersonal computer/Architettura
** CPUPersonal computer/Architettura/CPU
** MemoriaPersonal computer/Architettura/Memoria
** Input/OutputPersonal computer/Architettura/IO
* Linguaggio MacchinaPersonal computer/Linguaggio Macchina
** DLXPersonal computer/Linguaggio Macchina/DLX
*** Operazioni DLXPersonal computer/Linguaggio Macchina/DLX/Operazioni
*** DLX sequenzialePersonal computer/Linguaggio Macchina/DLX/DLX_sequenziale
*** DLX in pipelinePersonal computer/Linguaggio Macchina/DLX/DLX_pipeline
** 8086-8088Personal computer/Linguaggio Macchina/8086
* Mapping di Memorie ed InterfaccePersonal computer/Mapping
** Integrati NotevoliPersonal computer/Mapping#Caratteristiche_e_funzionamento_degli_integrati_notevoli
*** DriverPersonal computer/Mapping/Driver
*** CPUPersonal computer/Mapping/CPU
*** Memoria PrincipalePersonal computer/Mapping/Memorie
*** Interfacce I/OPersonal computer/Mapping/Interfacce
** Gestione delle interfacce tramite programmaPersonal computer/Mapping#Gestione_delle_interfacce_tramite_programma
* Standard alla base di un personal computerPersonal computer/Standard
* Appendici e RiassuntoPersonal computer/Appendici
Modifica il sommario

## Formato operazioni

Ogni OpCode è composto di 6 bit, ogni indirizzo di 5, mentre i restanti bit sono eventualmente per offset o altri tipi di input. Le tre grandi famiglie di comandi sono:
Formato I: Questo formato è quello utilizzato per ogni operazione con operatori immediati. Come si nota l'offset è di soli 16 bit, il che significa che non si può passare come argomento direttamente un dato a 32 bit, bensì bisogna suddividerlo in due passaggi con in mezzo uno shift di 16 posizioni (un esempio è l'istruzioni LHI)
Formato R: Questo è il formato delle operazioni fra registri. Gli 11 bit finali vengono utilizzati per rendere più specifiche alcune operazioni (ricordiamo che essendoci solo 6 bit per le operazioni, il numero massimo di queste è $2^{6}=64$).
Formato J: Quest'ultimo è il formato dei salti condizionati o meno.

## Operazioni

* Trasferimenti di dati
** LB, LBU, SB Carica un byte, carica un byte senza segno, memorizza un byte
** LH, LHU, SH Carica halfword, carica halfword senza segno, memorizza halfword
** LW, SW Load word, store word (a/da registri integer)
** LF, LD, SF, SD Load SP float, load DP float, store SP float, store DP float (SP - single precision, DP - double precision)
** MOVI2S, MOVS2I Move from/to GPR to/from a special register
** MOVF, MOVD Copy one floating-point register or a DP pair to another register or pair
** MOVFP2I, MOVI2FP Move 32 bits from/to FP tegister to/from integer registers
* Aritmetica/Logica
** ADD, ADDI, ADDU, ADDUI Add, add immediate (tutti gli immediati sono a 16 bit); signed and unsigned
** SUB, SUBI, SUBU, SUBUI Subtract, subtract immediate; signed and unsigned
** MULT, MULTU, DIV, DIVU Multiply and divide, signed and unsigned; Gli operandi devono essere registri Floating-point; Tutte le operazioni richiedono valori a 32 bit e danno come risultato valori a 32 bit.
** AND, ANDI And, And immediate
** OR, ORI, XOP, XOPI Or, or immediate, exclusive or, exclusive or immediate
** LHI Load high immediate - carica nella parte alta del registro il dato immediato
** SLL, SRL, SRA, SLLI, SRLI, SRAI Shifts: sia immediato(S__I) che variabile (S__); gli shift sono Shift Left Logical, Right Logical, Right Arithmetic
** S__, S__I, S__U Set condizionati: "__" può essere LT less than, GT greather than, LE less-equal, GE greater-equal, EQ equal, NE not equal
* Controllo
** BEQZ, BNEZ Branch GPR equal/not equal to zero; 16-bit offset from PC
** BFPT, BFPF Test comparison bit in the FP status register and branch; 16-bit offset from PC
** J, JR Jumps: 26-bit offset from PC(J) or target in register(JR)
** JAL, JALR Jump and link: save PC+4 to R31, target is PC-relative(JAL) ot a register(JALR)
** TRAP Transfer to operating system at a vectored address
** RFE Return to user code From an Exception; restore user code
* Virgola Mobile
** ADDD, ADDF Add DP, numeri SP
** SUBD, SUBF Subtract DP, numeri SP
** MULTD, MULTF Multiply DP, SP floating point
** DIVD, DIVF Divide DP, SP floating point
** CVTF2D, CVTF2I, CVTD2F,
** CVTD2I, CVTI2F, CVTI2D Istruzioni di Conversione: CVTx2y converte dal tipo x al tipo y, dove x e y sono I(Integer), D(Double precision), o F(Single precision). Entrambi gli operandi sono nel registro FP
** __D, __F confronti DP e SP: "__" può essere LT, GT, LE, GE, EQ, NE; impostare il bit di paragone nel registro FP.

### Istruzioni aritmetiche e logiche

Sono istruzioni a tre operandi, il primo è il registro destinazione, gli altri due registri sorgente
Ad esempio ADD R1, R2, R3 eseguel l'operazione R1 = R2 + R3 ADDI R1, R0, 100 esegue R1 = 100 (R0 vale sempre 0 e non è modificabile) ADD R1, R2, R0 esegue R1 <- R2 (assegna ad R1 il valore di R2)
Le istruzioni di set condizionato ( S__ ) eseguono un confronto tra i due operando sorgente ed assegnano il valore 0 oppure 1 a seconda del risultato del contronto, per cui
SNE R1, R2, R3 assegnerà il valore 1 ad R1 se R2 ed R3 non sono uguali, in caso contrario assegnerà il valore 0
Le operazioni di confronto possono essere eseguite anche tra un registro e un operando immediato
SLTI R1, R2, 10 assegna 1 ad R1 se R2 è più piccolo di 10
o tra operandi senza segno (e non in complemento a due)
SGTU R1, R2, R3 assegna 1 ad R1 se R2 è più grande di R3

### Istruzioni di trasferimento dati

Dato che il DLX è un Instruction Set R-R prima di utilizzare dei valori presenti in memoria deve copiarli in un registro interno alla CPU per questo motivo esistono operazioni di prelievo e scrittura di dati da e verso la memoria.
Sono istruzioni codificate nel formato I per cui richiedono tre operandi espliciti, nella forma destinazione, offset(registro). L'indirizzo di memoria a cui accedere sarà calcolato come la somma del valore in registro e dell' offset, ad esempio
LW R1, 100(R2) preleva una parola ( Load Word ) di trentadue bit dall'indirizzo di memoria 100 + R2 e la memorizza in R1, operazione che si può anche scrivere come R1 <-32 M[100+R2]
Analogamente SW R1, 20(R3) salverà nell'indirizzo di memoria 20 + R3 la parola (Store Word) contenuta nel registro R1

### Istruzioni di trasferimento del controllo

Nel DLX queste istruzioni sono di tre tipi:
* Jump Effettua un salto, un trasferimento del controllo, incondizionato
* Jump And Link Trasferisce il controllo salvando l'indirizzo di ritorno nel registro R31 (si parla anche di chiamata a procedura)
* Branch Trasferisce il controllo soltanto dopo aver verificato una condizione ( salto condizionato )
Le istruzioni di Jump e Jump And Link possono essere sia di tipo I che J
Jump con istruzione di tipo I
J R3 Modifica il program counter con il valore del registro R3, PC <- R3
Jump And Link con instruzioni di tipo I
JALR R3 Salva l'indirizzo della prossima istruzione nel registro R31 e assegna al program counter il valore di R3, ovvero R31 <- (PC + 4) ; PC <- R3
Jump con istruzione di tipo J Le istruzioni di tipo J usano un solo operatore di offset da 26 bit
J alfa Salta all'operazione nell'indirizzo di memoria distante alfa dalla prossima istruzione da eseguire, PC <- (PC + 4) + alfa
Jump And Link con istruzione di tipo J
JAL alfa Si comporta come l'operazione di Jump, ma salvando l'indirizzo della prossima istruzione del registro R31, R31 <- (PC + 4); PC <- (PC + 4) + alfa
L'operazione di ritorno da una procedura è JR R31 Assegna al program counter il valore che un'istruzione di Jump And Link ha memorizzato in R31, PC <- R31
Le operazioni di Branch invece possono essere soltanto di tipo I, l'OP code definisce il tipo di controllo da eseguire prima di effettuare il salto, il primo operatore è il registro su cui fare questo controllo, il secondo è l'offset di 16 bit relativo, come nei casi precedenti, ad program counter, per cui
BNEZ R3, alfa Salta all'istruzione nell'indirizzo di memoria (PC + 4) + l'offset alfa soltanto se R3 non è uguale a zero (Branch Not Equal to Zero), in altri termini if (R3 != 0) : PC <- (PC + 4) + alfa

### Esempi di codice in assembler per una macchina R-R
#### Somma degli elementi di un vettore A di 8 elementi

Se si utilizzano i seguenti registri per
* R1 per la somma corrente
* R2 per l’indice
* R3 per il contatore delle iterazioni
Il codice si può scrivere
Ovviamente si può sostituire ADDI R3,R3,-1 con SUBI R3,R3,1

#### Creazione di uno Stack pointer che supporti l'annidamento

Abbiamo visto che il DLX non supporta l'annidamento ( nesting ) delle chiamate a procedura poiché non ha un stack ed utilizza come unico registro di ritorno R31, con questo codice si può implementare via software uno stack pointer con il registro R30. R30 rappresenta l'indirizzo dell'ultima word di 32 bit (4 byte) inserita nello stack, per cui decresce man mano che lo stack si riempie e cresce man mano che si svuota.
Le prime due istruzioni vanno aggiunte prima delle istruzioni della procedura e servono per memorizzare il valore di R31 (indirizzo di ritorno dalla procedura) nello stack implementato grazie al registro R30
... istruzioni della procedura ...
Al termine della procedura sono necessarie alcune righe aggiuntive per permettere il ritorno all'istruzione mappata nell'ultimo indirizzo di memoria dello stack pointer

#### Gestione di word (32 bit)

Supponiamo di voler copiare un vettore di 1K word (32 bit) memorizzato all’indirizzo 1000H in un vettore di identico formato memorizzato all’indirizzo 40001000H. Le istruzioni del DLX permettono operandi (immediati) al massimo di 16 bit per cui si usino le istruzioni
LHI Rx, IMMEDIATE (Load High Immediate), che carica nella parte alta (16 bit più significativi) del registro destinazione Rx una costante a 16 bit ed azzera la parte bassa (16 bit meno significativi) di tale registro
ORI Rx, IMMEDIATE (OR Immediate) scrive in Rx il valore IMMEDIATE senza estenderlo (corrispondere a scrivere soltanto i 16 bit meno significativi)

#### Massimo di un vettore di unsigned-word (32 bit)

Si scriva una procedura che ricevendo in ingresso i parametri R1 : registro con l'indirizzo del vettore R2 : dimensione del registro (numero di elementi) R3 : registro usato dalla procedura per memorizzare il valore massime del vettore di unsigned-word