You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
swap d4<br />
moveq #0,d5<br />
m0ve.w OnScreenDim,d5<br />
divu.1 d5,d4 ; d4=Step<br />
moveq #O,dl ; dl=v<br />
m0ve.w #320,d3 ;d3=Dimensioni riga schermo<br />
m0ve.w yO,d5<br />
mu1u.w d3,d5<br />
move.1 ScreenBase,a2<br />
adda.w xO,a2<br />
adda.1 d5,a2 ;a2=ptr allo schermo<br />
m0ve.w OnScreenDim,d7 ;d7=y<br />
subq.w #l,d7<br />
loopy :<br />
moveq #O,dO ; dO=u<br />
move.1 dl,d5<br />
swap d5<br />
mu1u.w TextureDim,d5<br />
move.1 TextureBase,aO<br />
adda.1 d5,aO<br />
move.1 a2,al<br />
m0ve.w OnScreenDim,d6 ;d6=x<br />
subq.w #l,d6<br />
loopx :<br />
swap do<br />
m0ve.b (aO,dO.w),(al)+ ;Scrive il pixel<br />
swap do<br />
add.1 d4,dO ; u+=Step<br />
dbra d6,loopx<br />
;Passa alla prossima riga di schermo<br />
adda.w d3,a2<br />
add.1 d4,dl ;v+=Step<br />
dbra d7,loopy<br />
Lasciamo le altre ottimizzazioni, per esempio quelle rela-<br />
tive alle moltiplicazioni e agli accessi assoluti alla memo-<br />
ria, come esercizio.<br />
Si osservi ora il ciclo identificato dalla label loopx, la cui<br />
ottimizzazione è di vitale importanza. Infatti è in questo<br />
piccolo ciclo che il processore impiega la maggior parte<br />
del proprio tempo, e le tecniche per ottimizzarlo sono al-<br />
meno due, entrambe molto efficaci.<br />
Iniziamo con la tecnica più importante e meno conosciuta,<br />
quella che ritroveremo in tutti i cicli di texture<br />
mapping ben ottimizzati. Come avrete notato, la prima<br />
istruzione di swap serve per mettere nella word bassa di<br />
do la parte intera di u, in modo da poterla utilizzare nell'indirizzamento<br />
indiretto indicizzato, necessario per leggere<br />
il pixel dalla texture. Subito dopo, una seconda<br />
istruzione di swap riporta do nel formato originario, necessario<br />
alla istruzione di somma. È possibile eliminare<br />
dal ciclo le due istruzioni di swap? Ebbene, la risposta è<br />
sì.<br />
Normalmente, la parte intera di un numero in virgola<br />
fissa è contenuta nella parte alta di un registro, mentre<br />
la parte frazionaria è contenuta nella parte bassa, ma<br />
nulla ci vieta di invertire tale ordine, in modo che la<br />
parte intera sia già dove ci interessa e che le due istru-<br />
zioni di swap non siano più necessarie. Owiamente en-<br />
trambi gli addendi devono essere rappresentati nello<br />
stesso formato. Nascono però due problemi. Nella som-<br />
ma di due long, il riporto si propaga, come è logico che<br />
sia, dalla word bassa a quella alta, cosa che nel nostro<br />
caso non deve assolutamente accadere. Sarebbe infatti<br />
totalmente sbagliato che un eventuale overflow della<br />
parte intera andasse a intaccare la parte frazionaria (pri-<br />
mo problema). Al contrario, il riporto deve propagarsi<br />
dalla word alta a quella bassa (secondo problema).<br />
Il primo problema, nel nostro caso, è inconsistente, in<br />
quanto la parte intera dei due valori da sommare può as-<br />
sumere il valore massimo di TextureDim (128), per cui in<br />
nessun caso pratico è possibile che si verifichi un over-<br />
flow della word bassa.<br />
La soluzione del secondo problema è un po' più com-<br />
plessa. A prima vista, per fare in modo che il riporto di<br />
una somma si propaghi dalla word alta a quella bassa,<br />
bisognerebbe utilizzare due istruzioni di somma:<br />
L'istruzione addx di somma estesa (con d2=0) serve<br />
esclusivamente a sommare alla parte bassa di do il ri-<br />
porto della somma precedente. In questo modo, però,<br />
sono necessarie due istruzioni di somma e un registro<br />
(d2) in più che, tra l'altro, potrebbe non essere libero.<br />
Possiamo allora pensare di utilizzare la sola istruzione di<br />
somma estesa, avendo l'accortezza di evitare altre istru-<br />
zioni che modificano il flag di X:<br />
loopx:<br />
m0ve.b (aO,dO.w),(al)+ ;Scrive il pixel<br />
addx.1 d4,dO ; u+=Step<br />
dbra d6,loopx<br />
Il ciclo appena descritto funziona abbastanza bene, ma<br />
non è perfetto, in quanto il riporto (costituito come<br />
sappiamo dal flag X) viene sommato alla word bassa di<br />
do con un ciclo di ritardo, generando delle lievi impre-<br />
cisioni. Tali imprecisioni sono del tutto impercettibili,<br />
ma se è possibile eliminarle facilmente, perché non far-<br />
lo? A tale scopo è infatti sufficiente, subito prima del ci-<br />
clo loopx, sommare a u la sola parte frazionaria di Step<br />
move.1 d4,d2 ;Copia Step in un registro<br />
c1r.w d2 ;Elimina la parte intera<br />
add.1 d2,dO ;Somma a u la parte frazionaria