L'accès à la mémoire, en plus des protections d'accès habituelles, doit se faire avec le bon alignement ; à savoir, l'accès en lecture ou en ecriture à une donnée doit se faire à une adresse multiple de la taille de la donnée.
ld | Charge un mot-mémoire (32 bits) dans le registre spécifié.
(Load) |
ldsb | Charge un octet dans le registre, avec extension de signe dans les
24 bits hauts du registre.
(Load Signed byte) |
ldub | Charge un octet dans les 8 bits-low du registre; le reste du registre
est mis à zéro.
(load Unsigned byte) |
ldsh | Charge un demi-mot de 16 bits, avec extension de signe dans les 16
bits haut du registre.
(Load Signed Half-word) |
lduh | charge un demi-mot, avec mise à zéro des 16 bits hauts
du registre.
(Load Unsigned Half-word) |
ldd | charge un double-mot; le premier mot est copié dans le registre
spécifié rn, le mot suivant est copié dans Rn+1.
n doit être pair.
(Load double word) |
st | Ecrit le contenu du registre à l'adresse spécifiée.
(Store) |
stb | Ecrit les 8-bits bas du registre en mémoire.
(Store Byte) |
sth | Ecrit les 16 bits bas du registre en mémoire
(Store Halfword) |
std | Ecrit les registres Rn et Rn+1 dans les 8 octets suivant l'adresse
spécifiée. n doit être pair.
(Store doubleword) |
ldstub | Cette instruction sert d'instruction "Test & Set": dans un cycle
indivisible, elle charge l'octet mémoire dans le registre en
même temps qu'elle ecrit ce registre en mémoire.
La syntaxe est celle d'une instruction load : ldstub [adresse],reg.
(Load/Store unsigned byte)(instruction atomique) |
swap | Comme son nom l'indique, cette instruction echange le contenu d'un
octet mémoire avec un registre. Attention cependant, selon les
architectures, ce n'est pas une instruction atomique comme ldstub, et
n'est donc pas utilisable en toute sécurité dans un
rôle de Test and Set.
(la syntaxe est celle d'une instruction load : swap [adresse],reg) |
add | Le registre de destination reçoit op1+op2 |
addx | Le registre de destination reçoit op1+op2+retenue |
sub | Le registre de destination reçoit op1-op2 |
subx | Le registre de destination reçoit op1-op2-retenue |
addcc , addxcc
subcc , subxcc
tagged add et sub.. d'etranges instructions
fournies pour faciliter l'implémentation du Lisp:
Les mots additionnés par ces instructions peuvent être
soit des entiers normaux codés sur 30 bits, indiqué par
le fait que les 2 bits les moins significatifs sont à 0
Soit "autre chose" ( pointeur, code spécial) si au moins
un de ces 2 bits est à 1.
les "tagged" instructions effectuent une addition/soustraction
normale s'il s'agit d'entiers (et preservent les 2 bits à 0
dans le résultat); si ce n'est pas le cas, c'est un 'cas
spécial' et dans ce cas, un Trap est exécuté qui
se chargera de le gérer correctement.
L'hypothèse ici est que les cas "deux operandes de type entier"
est le plus fréquent, menant à une execution rapide de
ce qui nécessiterait un test logiciel incessant. (Voici
mes références pour découvrir le rôle
de ces instructions étranges....)
taddcc | tagged add & modify cc - |
tsubcc | tagged sub & modify cc - |
TADDccTV | tagged add & modify cc, and trap on overflow - |
tsubccTV | tagged sub & modify cc, and trap on overflow - |
or | orcc | OR logique entre le opérandes source. |
orn | orncc | OR logique entre la premiere opérande et NOT la deuxieme
opérande.
( non symétrique) |
and | andcc | AND logique.. |
andn | andncc | AND logique... avec NOT la deuxième opérande
( non symétrique) |
xor | xorcc | OR eXclusif |
xnor | xnorcc | op1 XOR (NOT op2)
( commutatif !) |
sll | décalage logique vers la gauche de la première
opérande du nombre de bits spécifié dans la 2eme.
Les nouveaux bits à droite sont mis à zéro. (Shift Left Logical) |
srl | Décalage logique vers la droite. Les bits laissés à
gauche sont mis à zéro.
(Shift Right Logical) |
sra | Décalage arithmétique vers la droite. Les bits
de gauche sont assignés à la valeur du msb ( most significant
bit) pour conserver le signe .
(Shift Right Arithmetic) |
sethi const22,reg
remplit alors les 22 bits hauts du registre avec la constante spécifiée,
les 10 bits bas étant mis à zéro. Pour terminer l'assignement
du registre, on positionne ces 10 bits à l'aide d'une instruction
or ou add. L'assembleur fournit les opérateurs %hi
et %lo qui extraient les 22 bits haut et les 10 bits bas d'une constante
pour faciliter ceci:
sethi %hi(constante_1),reg
or reg,%lo(constante_1),reg
b ; ba | Branchement inconditionnel | 1 |
bcc ; bgeu | Branch if Cary Clear / Greater or Equal Unsigned
( si cmp op1,op2 donne op1>=op2 avec interpretation non signée |
not C |
bgu | Branch if Greater Unsigned
si op1>op2 dans l'interprétation non signée |
not (C or Z) |
bge | b. if Greater or Equal
si op1>=op2, dans l'interpretation signée |
not ( N xor V ) |
bg ; bgt | b if Greater (than)
si Op1>op2, signé |
not(Z or (N xor V)) |
bleu | b. if Lower or Equal Unsigned
op1<=op2, non signé |
C or Z |
bcs ; blu | b if Carry Set / Lower Unsigned
op1<op2 non signé |
C |
ble | b. if Lower or Equal
op1<=op2 , interprétation signée |
Z or (N xor V) |
bl ; blt | b. if Lower (than)
op1<op2, signé |
N xor V |
bpos | Branch if test Positive
si un test renvoie le flag "positif" (ou egal=0) |
not N |
bneg | b. if Negative ( strict ) | N |
bvc | b if Overflow clear ( =not overflow) | not V |
bvs | b if Overflow Set | V |
be ; beq ; bz | b. if Equal / Zero
( si les termes comparés sont egaux / si une instruction donne un résultat nul) |
Z |
bne ; bnz | b. if Not equal/zero
Si différent / résultat non nul |
not Z |
bn | Branch Never : n'effectue jamais le branchement.
( hemmm...) |
0 |
mov op1,%r2 | Copie op1 (registre ou constante 13 bits) dans %r2 | or %g0,op1,%r2 |
set Constante,%r | Assigne une constante 32 bits au registre | sethi %hi(Constante),%r
or %lo(constante),%r |
clr %reg | Efface le registre
Clear |
or %g0,%g0,%reg |
clrb/clrh/clr [adress] | Efface l'octet/le demi-mot/le mot en mémoire | stb/sth/st %g0,[adress] |
inc | incremente le registre | add reg,1,reg |
inccc | idem avec positionnement indicateurs | addcc reg,1,reg |
dec | decremente le registre | sub reg,1,reg |
deccc | subcc reg,1,reg | |
neg reg | reg est remplacé par son opposé | sub %g0,reg,reg |
cmp reg,op2 | Compare reg avec op2 (influence les indicateurs) | subcc reg,op2,%g0 |
bset op1,reg | Met a 1 les bits de reg spécifiés dans op1
(bit set) |
or reg,op1,reg |
bclr | Met à 0 les bits de reg masqués par op1
(Bit clear) |
andn reg,op1,reg |
btst | Teste les bits de reg avec op1
(Bit Test) |
andcc reg,op1,%g0 |
btog op1,reg | Fait commuter les bits de reg spécifiés dans op1
(bit toggle) |
xor reg,op1,reg |
tst reg | Positionne les indicateurs selon le contenu de reg | orcc %g0,reg,%g0 |
not reg | NON logique du registre | orn %g0,reg,reg
ou xnor reg,%g0,reg |
nop | Rien. ( utile pour les delay-slots à la suite des sauts conditionnels et autres branchements) | Tout ce qui ne fait rien:
or %g0,%g0,%g0, etc.. |
jmpl [adresse],regd | (jump & Link);
L'adresse de la routine doit d'abord être déterminée par le programme et placé dans un registre regs; on fera alors en général jmpl [regs],regd - les combinaisons jmpl [regs+r2],regd ou jmpl [rgs+const],regd sont moins fréquentes . Le registre regd est utilisé pour mémoriser le PC courant, pour pouvoir effectuer le retour de procedure. Conventionnellement, on utilise %o7. cette instruction est aussi utilisée pour effectuer un retour; si %i7 contient le PC de l'instruction appelante, on pourra rendre la main par jmpl[%i7+8],%g0. car %i7+8 est l'adresse de l'instruction qui suit l'appel ET le delay-slot (qu'on ne veut en general pas executer en double), et le PC actuel etant sans intérêt, il est oublié dans %g0. Attention au nom de registre utilisé: %o7 ou %i7 ? cela dépend de la position de la fenêtre de registre; pour être sûr: utilisez les instructions synthétiques et respectez les conventions ! |
call <constante> | Effectue un appel de procédure .
Le saut est PC-relatif (c'est l'offset de la procédure par rapport à l'intruction courante qui est codé) cette instruction peut adresser toute la mémoire (30 bits sont reservés pour l''offset, multiplié par 4 en interne en raison de l'alignement des instructions sur frontière de mot ). mecanisme : place PC de cette instruction dans %o7, puis saute à l'adresse de la routine. Instruction retardée (suivie d'un delay-slot) On peut aussi utiliser la syntaxe call reg ou call imm13, dans ce cas c'est un alias pour jmpl adresse,%o7. |
jmp adresse | Alias pour jmpl adresse,%g0 |
ret | Retour de sous-routine
(alias pour jmpl [%i7+8],%g0) |
retl | Return from Leaf sub-routine
Retour d'une routine feuille ( qui n'a pas installé de nouvelle fenêtre de registres) =jmpl [%o7+8],%g0 ( noter la subtilité...) |
save %r1,cst,%r2 | Installe une nouvelle fenêtre de registre et alloue la pile
Cette instruction demande le décalage de la fenêtre de registre; Elle en profite aussi pour effectuer une addition. En pratique cette addition est utilisée pour allouer de la place sur la pile, avec une constante négative: save %sp,-64,%sp alloue 64 octets sur la pile ( la taille minimale pour que le système puisse swapper les registres sans problème). Attention!La dénomination des registres change en cours de l'execution de l'instruction; Notons save %sp1,-64,%sp2 : sp2 est le %sp de la nouvelle fenetre(=%o6_2) alors que sp1 est celui de l'ancienne fenetre (=%o6_1 = %i6_2 = %bp_2) |
restore | Revient à l'ancienne fenêtre de registre. Sa position
standard est dans le delay slot de l'isntruction de retour:
ret restore (note : la syntaxe complete est celle d'une instruction d'addition (comme save) : restore r1,r_or_imm,rd qui effectue rd:=r1+r_or_imm; cette caracteristique n'est en pratique jamais utilisée; à optimiser ?... :) |