Istruzioni MIPS per floating point Architetture dei Calcolatori (lettere A-I) Coprocessore per floating point L architettura MIPS ha un coprocessore (indicato con il numero 1) che opera sui numeri in virgola a mobile a singola e doppia precisione 32 registri $f0 $f31 (ciascuno da 32 bit) che sono dedicati per la rappresentazione in virgola mobile Problema: i registri $f0 $f31 hanno dimensione pari a 32 bit: come fare per rappresentare i numeri a precisione doppia che richiedono 64 bit? Convenzione: si usano i registri a coppie pari/dispari Esempio: la coppia di registri $f0 $f1 è usata per contenere il valore di un numero a precisione doppia Per le operazioni a singola precisione si possono usare soltanto i registri pari $f0, $f2,, $f30 Valeria Cardellini 1
Istruzioni aritmetiche in virgola mobile Doppia versione delle istruzioni in virgola mobile a precisione singola: rappresentazione a 32 bit Nome_istruzione.s a precisione doppia: rappresentazione a 64 bit Nome_istruzione.d Addizione floating point add.s e add.d Esempio: add.s $f2, $f4, $f6 Sottrazione floating point sub.s e sub.d Esempio: sub.d $f2, $f4, $f6 Moltiplicazione floating point mul.s e mul.d Esempio: mul.s $f2, $f4, $f6 Divisione floating point div.s e div.d Valeria Cardellini 2 Istruzioni di confronto e branch in virgola mobile Istruzioni di confronto Precisione singola: c.x.s Precisione doppia: c.x.d x può essere pari a eq (equal), neq (not equal) lt (less than), le (less than or equal) gt (greater than), ge (greater than or equal) L istruzione di confronto pone un flag di condizione (bit) pari a vero o falso; una successiva istruzione di branch permette di saltare in base al valore del flag Istruzioni di branch branch true: bc1t branch false: bc1f Esempio: c.lt.s $f2, $f4 bc1t L1 # salta a L1 se $f2 < $f4 Valeria Cardellini 3
Istruzioni di load/store Per caricare un valore dalla memoria in un registro floating point e memorizzare il valore di un registro floating point in memoria Per load: istruzione lwc1 Per store: istruzione swc1 Esempio Frammento di codice assembler per caricare dalla memoria due numeri a precisione singola (quindi 32 bit), sommarli e memorizzare il risultato lwc1 $f4, 0($t0) lwc1 $f6, 4($t0) add.s $f2, $f4, $f6 swc1 $f2, 8($t0) Valeria Cardellini 4 Esempio 1 Procedura per la conversione da gradi Fahrenheit a gradi Celsius Codice C: float f2c (float fahr) { return ((5.0/9.0) * (fahr - 32.0)); } Per passare parametri floating point si usano i registri $f12-$f15 Per passare il risultato della procedura si usano i registri $f0-$f1 I registri $f0-$f31 devono essere salvati dalla procedura chiamata (stessa convenzione usata per $s0-$s7) Valeria Cardellini 5
Esempio 1 (2) fahr in $f12, celsius in $f0 Costante 5.0 in const5, 9.0 in const9, 32.0 in const32 Codice assembler MIPS: f2c: l.s $f16, const5 l.s $f18, const9 div.s $f16, $f16, $f18 # $f16=5.0/9.0 l.s $f18, const32 sub.s $f18, $f12, $f18 # $f18=fahr-32.0 mul.s $f0, $f16, $f18 jr $ra Valeria Cardellini 6 Esempio 2 Procedura per calcolare il prodotto scalare tra due vettori float a e b di dimensione n Codice C: float DotProd(int n, float *a, float *b) { int i; float result=0.; for (i=0; i<n; i++) result += a[i]*b[i]; return result; } Assunzioni: n in $a0, indirizzo base dei vettori a e b in $a1 e $a2 rispettivamente (attenzione: l indirizzo di memoria è un intero!) Valeria Cardellini 7
Esempio 2 (2) Codice assembler MIPS: DotProd: mtc1 $zero, $f0 # Trasferisce $zero in $f0 slt $t0, $a0, $zero # if (n <= 0) endloop beq $t0, $zero, endloop sll $a0, $a0, 2 # $a0 = $a0 * 4 add $a0, $a1, $a0 loop: lwc1 $f2, 0($a1) # Carica a[i] lwc1 $f4, 0($a2) # Carica b[i] mul.s $f6, $f2, $f4 # Moltiplica a[i] per b[i] add.s $f0, $f0, $f6 # Aggiungi a[i]*b[i] a result ($f0) addi $a1, $a1, 4 # Elemento successivo di a addi $a2, $a2, 4 # Elemento successivo di b bne $a1, $a0, loop endloop: jr $ra # Ritorna al chiamante Valeria Cardellini 8 Istruzioni di conversione Istruzioni per la conversione da valori interi a valori floating point (casting) Tipo di dato in cui convertire Registro destinazione cvt.s.w $f4, $f2 Esempio Tipo di dato da cui convertire (w per interi) Registro sorgente addi $t0, $zero, 32 # $t0 = 32 mtc1 $t0, $f2 # $f2 = 32 intero cvt.s.w $f4, $f2 # $f4 = 32.0 Valeria Cardellini 9