Gli opcodes
Una prima area di attenzione riguarda gli mnemonici delle nuove istruzioni
che hanno funzioni simili, ma più ampie di quelle dei mid-range.
Ad esempio, gli shift possono essere effettuati con o senza carry, per cui la
lista :
;shift temporary left 2 times
clrc
rlf TEMP0, f
rlf TEMP0, f
|
potrà essere cambiata in :
;shift temporary left 2 times
rlncf TEMP0, f
rlcf TEMP0, f |
Per chi proviene dall' avere già utilizzato i PIC mid-range, il passaggio ai
PIC 18F è, quindi, assai semplice, oltre che fonte di facilitazioni consistenti. Si possono però creare alcuni punti di ambiguità
per quanto riguarda il nuovo set di istruzioni Un primo punto è la
lunghezza delle istruzioni 18F che è, di base, 16 bits. Quindi le
istruzioni iniziano sempre in locazioni PARI e un salto ad un indirizzo
programma dispari è errato.
Questo è importante per chi ha l' abitudine di utilizzare il simbolo $ per
puntare un salto.
Più avanti un paragrafo tratta esplicitamente di questo argomento, anche
perchè la questione non è così semplice, esistendo nel set istruzioni anche a
32 bit, il che rende il calcolo "manuale" delle destinazioni
abbastanza complesso (basta usare label invece di indirizzi assoluti e il
problema è risolto ).
Un altro punto riguarda le istruzioni di rotazione che, nei mid-range,
coinvolgono sempre il Carry (gli opcodes rlf e rrf).
Nei 18F, invece, sono disponibili due opcodes per ogni direzione della
rotazione, ovvero :
- rrcf / rlcf
che agiscono come gli equivalenti rlf / rrf
- e rrncf / rlncf che, invece, ruotano il registro oggetto
SENZA coinvolgere
il Carry
Dunque una sostituzione diretta dei mid-range rlf /
rrf è, per gli enghanced,
rlcf / rrcf ; in ogni caso MPASM, compilando per un PIC18, indica gli eventuali
opcodes rlf / rrf come errori.
Inoltre varie delle nuove istruzioni hanno un diverso effetto sullo STATUS.
Ad esempio le istruzioni di rotazione dei 18F possono modificare il bit Z
(oltre al nuovo flag N), cosa che, invece, nei mid range non era possibile.
Questo è abbastanza secondario, in quanto il programma mid-range non fa certo
uso di flag che non ha disponibili, mentre il fatto che un test successivo possa
fare leva sul flag Z (che l' istruzione PIC18 ha modificato) può rendere
difficoltoso il debug.
Interessante l' istruzione di sottrazione , subwf dei mid-range,
che nei 18F ha come equivalente subwfb (che, ricordiamo, hanno come
risultato di sottrarre W dal file f !).
Esistono però una subwf, che non tiene conto del borrow , ma anche una
sunbfwb,
che opera in modo opposto, ovvero sottrae f da W,
tenendo conto del borrow.
Per quanto riguarda i branch sui flag dello STATUS, ovvero bc,
bnc, bz,
bnz,
ecc., in effetti si tratta di branch e non di skip , ed è un opcode a
tutti gli effetti e non uno pseudo opcode o una macro :
;verify if zero
addwf res, f
bc
incf res, f
next ... |
da origine ad un immediato errore di assemblaggio perchè bc
si aspetta un indirizzo a cui effettuare il branch.
Il sorgente dovrà
corretto con:
;verify if zero
addwf res, f
bc next
incf res, f
next ... |
Se poi è dichiarata una
macro con lo stesso nome bc, saranno segnalati altri errori.
Analoga situazione nel caso in cui si siano usati gli pseudo opcodes
accettati da MPASM, pratica del tutto comune e lecita per i mid-range, ma non
più adeguata ai 18F. Ad esempio:
skpnc
addlw 0x01
movwf TEMP0 |
non può essere sostituita da :
bnc
addlw 0x01
movwf TEMP0 |
in quanto skpnc
è uno "skip", che, se il carry è 0, salta la riga successiva addlw 0x01
, mentre bnc
è un "branch" e richiede una label a cui saltare:
bnc next
addlw 0x01
next movwf TEMP0 |
Questo punto è sensibile quando si voglia traslare un sorgente mid-range
dove sono stati utilizzati pseudo opcodes accettati da MPASM o macro del
genere:
movf TEMP1, w
skpnz
incfsz TEMP1, w
addwf ACC1, f
|
dove è stato usato lo pseudo opcodes (o la macro) skpnz
, non più utilizzabile con i 18F, e che deve diventare:
movf TEMP1, w
bnz $+4
incfsz TEMP1, w
addwf ACC1, f
|
oppure:
movf TEMP1, w
btfss STATUS,Z
incfsz TEMP1, w
addwf ACC1, f
|
La tabella seguente mette a confronto i vari metodi di branch e che
evidenzia come l' uso delle istruzioni specifiche del set 18F permette
una riduzione sia del codice che del tempo di esecuzione.:
branch
del set PIC18 |
metodi
"tipo PIC16" |
Metodo |
Cicli |
Metodo |
Cicli |
Metodo |
Cicli |
BC carryset |
2 (1) / 1 |
BTFSC STATUS, C
GOTO carryset |
3 (2) / 2
|
BTFSS STATUS, C
GOTO carry0 |
2 (3) / 2 |
BNC carry0 |
BTFSS STATUS, C
GOTO carry0 |
BTFSC STATUS, C
GOTO carryset |
BN negative |
BTFSC STATUS, N
GOTO negative |
BTFSS STATUS, N
GOTO positive |
BNN positive |
BTFSS STATUS, N
GOTO positive |
BTFSC STATUS, N
GOTO negative |
BOV ovflw |
BTFSC STATUS, OV
GOTO ovflw |
BTFSS STATUS, OV
GOTO novflw |
BNOV novflw |
BTFSS STATUS, OV
GOTO novflw |
BTFSC STATUS, OV
GOTO ovflw |
BZ zero |
BTFSC STATUS, Z
GOTO zero |
BTFSS STATUS, Z
GOTO notzero |
BNZ notzero |
BTFSS STATUS, Z
GOTO notzero |
BTFSC STATUS, Z
GOTO zero |
NOTE:
- branch del set 18F hanno la possibilità di spaziare -127
/ +128 istruzioni
- per ampiezze maggiore è necessario ricorrere ai metodi
"tipo PIC16" tenendo presente la possibilità di
sostituire GOTO, che non ha limitazioni di distanza, con BRA
per salti entro 1 k.
|
Azione
La soluzione ideale è impadronirsi del nuovo set di opcodes e
comprenderne bene le funzioni.
|
|