Le istruzioni condizionali o anche salti condizionati permettono di variare il flusso del programma (variando anche il valore del Program Counter) al verificarsi di una condizione.
beq rs1, rs2, L1
bne rs1, rs2, L1
rs1
e rs2
sono uguali o se non lo sono.Sono presenti anche rami come:
blt rs1, rs2, L1
bgt rs1, rs2, L1
rs1
è minore/maggiore o uguale a rs2
.Esistono anche operazioni di salto condizionato che confrontano i due registri rs1
e rs2
trattandoli come numeri senza segno:
bltu rs1, rs2, L1
bgeu rs1, rs2, L1
Grazie a queste istruzioni è possibile tradurre le istruzioni if-else dei linguaggi di programmazione ad alto livello.
if (i == j)
f = g + h;
else
f = g - h;
if (i == j)
f = g + h;
else
f = g - h;
Posti: f = x19, g = x20, h = x21, i = x22, j = x23
bne x22, x23, ELSE
add x19, x20, x21
bne x0, x0, ENDIF
ELSE: sub x19, x20, x21
ENDIF:
bne x22, x23, ELSE
add x19, x20, x21
bne x0, x0, ENDIF
ELSE: sub x19, x20, x21
ENDIF:
if (i == j)
f = g + h;
else
f = g - h;
Posti: f = x19, g = x20, h = x21, i = x22, j = x23
bne x22, x23, ELSE
add x19, x20, x21
bne x0, x0, ENDIF
ELSE: sub x19, x20, x21
ENDIF:
=== end-multi-column
Premesse:
L'istruzione bne x22, x23, ELSE
: fa in modo che il PC salti all'etichetta ELSE se x22 e x23 non sono uguali. In caso contrario il PC semplicemente avanza di una istruzione, non saltando all'ELSE, eseguendo il codice del caso in cui x22 e x23 sono uguali, dopo il PC avanza, se non ci fosse l'istruzione bne x0, x0, ENDIF
(sempre vera poiché 0 = 0 è si verifica sempre), si eseguirebbe l'etichetta di ELSE, che invece grazie a tale riga viene saltata.
Cosa vuol dire avanzare di una istruzione per il Program Counter? Una istruzione in RISC-V è di 32 bit, come abbiamo visto con i vari formati delle istruzioni (Immediato, Registro, Store), di conseguenza il salto di una istruzione equivale a 4 salti:
Con lo stesso metodo si possono scrivere istruzioni per i cicli for e while.
Cicli for
Una possibile implementazione:
for(i = 0; i < 100; i++){
...
}
for(i = 0; i < 100; i++){
...
}
Posto i = x19
add x19, x0, x0
addi x20, x0, 100
FOR:
bge x19, x20 ENDFOR
...
addi x19, x19, 1
beq x0, x0, FOR
ENDFOR:
add x19, x0, x0
addi x20, x0, 100
FOR:
bge x19, x20 ENDFOR
...
addi x19, x19, 1
beq x0, x0, FOR
ENDFOR:
for(i = 0; i < 100; i++){
...
}
Posto i = x19
add x19, x0, x0
addi x20, x0, 100
FOR:
bge x19, x20 ENDFOR
...
addi x19, x19, 1
beq x0, x0, FOR
ENDFOR:
=== end-multi-column
Cicli while
Una possibile implementazione:
long v[10], k, i;
while(v[i] == k){
...
i = i + 1;
}
long v[10], k, i;
while(v[i] == k){
...
i = i + 1;
}
Posti: i = x22, k = x24, v = x25
LOOP:
slli x10, x22, 3 # Salva in x10 l'indirizzo della double word v[i]
add x10, x10, x25
ld x9, 0(x10)
bne x9, x24, ENDLOOP
...
addi x22, x22, 1
beq x0, x0, LOOP
ENDLOOP:
LOOP:
slli x10, x22, 3 # Salva in x10 l'indirizzo della double word v[i]
add x10, x10, x25
ld x9, 0(x10)
bne x9, x24, ENDLOOP
...
addi x22, x22, 1
beq x0, x0, LOOP
ENDLOOP:
long v[10], k, i;
while(v[i] == k){
...
i = i + 1;
}
Posti: i = x22, k = x24, v = x25
LOOP:
slli x10, x22, 3 # Salva in x10 l'indirizzo della double word v[i]
add x10, x10, x25
ld x9, 0(x10)
bne x9, x24, ENDLOOP
...
addi x22, x22, 1
beq x0, x0, LOOP
ENDLOOP:
=== end-multi-column
Istruzioni di salto condizionato generiche
L'istruzione slt
, o anche slti
(versione immediate) scrive 1 nel registro rd
se il contenuto del registro rs1
< rs2
e scrive 0 altrimenti. Questa istruzione ci consente di effettuare dei salti generici.
if (i < j){
k = 1;
}else{
k = 0;
}
if (i < j){
k = 1;
}else{
k = 0;
}
Posti: i = x19, j = x20, k = x21.
slt x21, x19, x20.
slt x21, x19, x20.
if (i < j){
k = 1;
}else{
k = 0;
}
Posti: i = x19, j = x20, k = x21.
slt x21, x19, x20.
=== end-multi-column
Si può ad esempio inserire dopo slt
l'istruzione beq x21, x19, x20
.
bne
)slt
Le istruzioni esaminate fino ad ora operano su interi con segno:
ld
e sd
e il numero di istruzioni di cui saltare nella bne/beq
sono interi con segno da slt
o slti
si useranno sltu
e sltiu
: in questo caso un confronto del tipo Salti condizionati e linguaggio macchina
Le istruzioni di salto condizionato utilizzano un formato diverso di istruzione, il formato di tipo SB. Questo formato può rappresentare indirizzi di salto da -4096 a 4094, in multipli di due. Ovvero risulta che gli indirizzi del PC saranno sempre pari (in particolare considerando solo istruzioni di 32 bit, saranno sempre multipli di 4), il motivo lo spiegheremo nell'argomentazione che riguarda i salti non condizionati.
Questo tipo di istruzioni utilizzano indirizzamento relativo al PC, ovvero sommano all'indirizzo del PC, l'offset necessario per raggiungere l'etichetta specificata nell'istruzione di branch.
Il campo immediato, contiene tale l'offset, in realtà contiene il numero di istruzioni che devono essere saltate per raggiungere l'etichetta specificata nel branch.
Vediamo un esempio in RISC-V e cerchiamo di capire come avanza il PC:
LOOP:
slli x10, x22, 3
add x10, x10, x25
ld x9, 0(x10)
bne x9, x24, ENDLOOP
addi, x22, x22, 1
beq x0, x0, LOOP
ENDLOOP:
Indirizzo | Istruzione |
---|---|
8000 | 0000000 00011 10110 001 01010 0010011 |
8004 | 0000000 11001 01010 000 01010 0110011 |
8008 | 0000000 00000 01010 011 01001 0000111 |
8012 | 0000000 11000 01001 001 01100 1100011 |
8016 | 0000000 00001 10110 000 10110 0010011 |
80020 | 1111111 00000 00000 000 01101 1100011 |
PC = 8000
L'architettura sa che se l'opcode è 0010011 (Esempio di decodifica di istruzioni in linguaggio macchina) allora si tratta di una istruzione del formato I. Dopo di che guarda il parametro func3 che è 001, che indica una operazione di tipo slli
.
Il PC avanza, PC = 8004.
L'architettura sa che se l'opcode è 0110011 si tratta di una istruzione del formato R. Dopo di che guarda il parametro funcr che è 000, che indica una operazione di tipo add
.
Il PC continua ad avanzare in questo modo, "guardando" opcode e func3.
Nel manuale di RISC-V si trovano le tabelle relative agli opcode e func3, un esempio per il formato R:
Il linguaggio assembler fornisce anche delle pseudoistruzioni.
A questo punto della trattazione aggiungiamo anche delle istruzioni aritmetiche particolari, diverse da quelle trattate fino precedentemente (vedi istruzioni aritmetiche). Questa nuova raccolta di istruzioni aritmetiche le tratteremo nel file: istruzioni aritmetiche 2.
NOTA: oltre ai salti condizionati, il RISC-V consente i salti non condizionati.