Ensemble d'instructions
Le 68000 possède un ensemble d'instructions orthogonal et régulier. La plupart des instructions acceptent plusieurs modes d'adressage et peuvent opérer sur des tailles différentes (.B, .W, .L), ce qui réduit considérablement le nombre de mnémoniques a mémoriser.
L'ensemble d'instructions se divise en catégories :
- Transfert de données
- Arithmétique entière
- Opérations logiques
- Décalages et rotations
- Manipulation de bits
- Arithmétique BCD (décimal code binaire)
- Branchements et contrôle de flux
- Opérations sur le registre d'état
- Instructions système et privilégiées
Conventions de notation utilisées dans cette page :
| Convention de notation | Description |
|---|---|
| Dn | Registre de données (D0-D7) |
| An | Registre d'adresses (A0-A7) |
| Xn | Registre quelconque (Dn ou An) |
| ea | Adresse effective (effective address) |
| #imm | Valeur immédiate (constante) |
| label | Étiquette (adresse cible) |
| .B | Taille octet (8 bits) |
| .W | Taille mot (16 bits) |
| .L | Taille long mot (32 bits) |
| [CCR] | Drapeaux affectes (X, N, Z, V, C) |
| SR | Registre d'état complet (16 bits) |
| CCR | Partie condition codes du SR (octet bas) |
Tailles par défaut :
- Si aucun suffixe n'est spécifie, la taille par défaut est .W pour la plupart des instructions
- Les instructions sur les registres d'adresses (MOVEA, ADDA, SUBA, CMPA) n'acceptent que .W et .L
- Les instructions rapides (MOVEQ, ADDQ, SUBQ) ont des contraintes de taille spécifiques
Transfert de données
Ces instructions copient des données entre registres, mémoire et valeurs immédiates.
Transfert général
| Instruction | Description |
|---|---|
| MOVE.s ea, ea | Copier la source vers la destination Formes : presque toutes les combinaisons d'adresses effectives sont valides s = B, W ou L [CCR: N, Z mis a jour; V=0, C=0] |
| MOVEA.s ea, An | Copier la source dans un registre d'adresses s = W (signe-étendu a 32 bits) ou L [CCR: non modifie] |
| MOVEQ #imm8, Dn | Charger une constante 8 bits signée dans Dn (signe-étendue a 32 bits) La constante est codée dans l'instruction (pas de mot d'extension, très rapide) [CCR: N, Z mis a jour; V=0, C=0] |
Exemples :
Remarques :
- MOVE est l'instruction la plus utilisée (~40% du code)
- MOVEQ est préféré a MOVE.L #imm,Dn quand la constante tient sur 8 bits signes (-128 a +127)
- MOVE modifie les drapeaux, contrairement a MOV sur x86
- MOVEA ne modifie JAMAIS les drapeaux
Transfert de blocs de registres
| Instruction | Description |
|---|---|
| MOVEM.s liste, ea | Sauvegarder plusieurs registres en mémoire |
| MOVEM.s ea, liste | Restaurer plusieurs registres depuis la mémoire s = W ou L La liste spécifie les registres concernes [CCR: non modifie] |
La liste de registres peut être spécifiée de plusieurs manières :
| Registres | Description |
|---|---|
| D0-D7/A0-A6 | Tous les registres (sauf A7) |
| D0-D3/A0-A2 | Registres D0 a D3 et A0 a A2 |
| D0/D2/D4/A0 | Registres individuels sépares par / |
Exemples :
- MOVEM.L D0-D7/A0-A6, -(A7) ; sauvegarder tous les registres
- MOVEM.L (A7)+, D0-D7/A0-A6 ; restaurer tous les registres
- MOVEM.L D0-D3/A0-A1, -(A7) ; sauvegarder D0-D3 et A0-A1
- MOVEM.W (A0), D0-D3 ; charger 4 mots consecutifs
Remarques :
- Pour la sauvegarde (vers mémoire), le mode -(An) est typiquement utilise (pre-decrement)
- Pour la restauration (depuis mémoire), le mode (An)+ est typiquement utilise (post-incrément)
- MOVEM avec -(An) sauve les registres dans l'ordre inverse (A7 d'abord, D0 en dernier) pour que MOVEM avec (An)+ restaure correctement dans l'ordre normal.
Transfert avec les périphériques
| Instruction | Description |
|---|---|
| MOVEP.s Dn, d16(An) | Transférer un registre vers des octets alternes |
| MOVEP.s d16(An), Dn | Transférer des octets alternes vers un registre s = W (2 octets) ou L (4 octets) [CCR: non modifie] |
MOVEP transfère les octets d'un registre vers des adresses paires (ou impaires) séparées de 2 octets. Ceci permet d'accéder a des périphériques 8 bits connectes sur un bus de données 16 bits.
Exemple :
- MOVEP.W D0, 0(A0) ; [A0] := D0 bits 15-8
- ; [A0+2] := D0 bits 7-0
Chargement d'adresse
| Instruction | Description |
|---|---|
| LEA ea, An | Charger l'adresse effective dans An (pas d'accès mémoire, calcul d'adresse seul) [CCR: non modifie] |
| PEA ea | Empiler l'adresse effective sur la pile A7 -= 4, [A7] := adresse effective [CCR: non modifie] |
Exemples :
- LEA Table(PC), A0 ; A0 := adresse de Table (PIC)
- LEA 8(A6), A0 ; A0 := A6 + 8 (adresse parametre)
- LEA 0(A0,D0.W), A1 ; A1 := A0 + D0.W (adresse calculee)
- PEA Buffer(PC) ; empiler l'adresse de Buffer
Remarques :
- LEA est très utilisée pour calculer des adresses sans accéder a la mémoire
- LEA avec PC-relatif permet du code relogeable
- PEA est utile pour passer des adresses en paramètre sur la pile avant un appel de sous-routine
Échange et permutation
| Instruction | Description |
|---|---|
| EXG Xn, Xn | Échanger le contenu de deux registres 32 bits (données-données, adresses-adresses, ou mixte) [CCR: non modifie] |
| SWAP Dn | Échanger les mots haut et bas d'un registre Dn[31:16] <-> Dn[15:0] [CCR: N, Z mis a jour; V=0, C=0] |
Exemples :
- EXG D0, D1 ; D0 <-> D1
- EXG A0, A1 ; A0 <-> A1
- EXG D0, A0 ; D0 <-> A0
- SWAP D0 ; echange mots haut et bas de D0
Gestion du cadre de pile
| Instruction | Description |
|---|---|
| LINK An, #d16 | Créer un cadre de pile : A7 -= 4, [A7] := An, An := A7, A7 += d16 (d16 est généralement négatif pour réserver de l'espace pour les variables locales) [CCR: non modifie] |
| UNLK An | Détruire un cadre de pile : A7 := An, An := [A7], A7 += 4 [CCR: non modifie] |
Exemple typique d'appel de fonction :
- ; Appelant
- MOVE.L #param1, -(A7) ; empiler le parametre
- JSR MaFonction ; appeler la fonction
- ADDQ.L #4, A7 ; nettoyer la pile
-
- ; MaFonction
- LINK A6, #-8 ; creer cadre, reserver 8 octets
- MOVE.L 8(A6), D0 ; D0 := 1er parametre
- MOVE.W D0, -2(A6) ; variable locale
- ...
- UNLK A6 ; detruire le cadre
- RTS ; retourner a l'appelant
Arithmétique entière
Addition
| Instruction | Description |
|---|---|
| ADD.s ea, Dn | Dn ← Dn + ea [CCR: X, N, Z, V, C] |
| ADD.s Dn, ea | ea ← ea + Dn [CCR: X, N, Z, V, C] |
| ADDA.s ea, An | An ← An + ea (s = W signe-étendu ou L) [CCR: non modifie] |
| ADDI.s #imm, ea | ea ← ea + imm [CCR: X, N, Z, V, C] |
| ADDQ.s #imm3, ea | ea ← ea + imm (imm = 1 a 8) Constante codée dans l'instruction (rapide) [CCR: X, N, Z, V, C] (CCR non modifie si destination est An) |
| ADDX.s Dn, Dn | Dn ← Dn + Dn + X [CCR: X, N, Z, V, C] |
| ADDX.s -(An), -(An) | Addition avec retenue (multi-précision) Le drapeau Z n'est mis a zéro QUE si le résultat est non-nul (pour la multi-précision) |
Exemples :
- ADD.L D0, D1 ; D1 := D1 + D0
- ADD.W #100, D0 ; D0.W := D0.W + 100
- ADDA.L #4, A0 ; A0 := A0 + 4 (pas de modif CCR)
- ADDQ.L #1, D0 ; D0 := D0 + 1 (tres rapide)
- ADDQ.W #2, A7 ; A7 := A7 + 2 (ajuster la pile)
-
- ; Addition 64 bits : D0:D1 := D0:D1 + D2:D3
- ADD.L D3, D1 ; additionner les mots bas
- ADDX.L D2, D0 ; additionner les mots hauts + retenue
Soustraction
| Instruction | Description |
|---|---|
| SUB.s ea, Dn | Dn ← Dn - ea [CCR: X, N, Z, V, C] |
| SUB.s Dn, ea | ea ← ea - Dn [CCR: X, N, Z, V, C] |
| SUBA.s ea, An | An ← An - ea (s = W signe-étendu ou L) [CCR: non modifie] |
| SUBI.s #imm, ea | ea ← ea - imm [CCR: X, N, Z, V, C] |
| SUBQ.s #imm3, ea | ea ← ea - imm (imm = 1 a 8) [CCR: X, N, Z, V, C] (CCR non modifie si destination est An) |
| SUBX.s Dn, Dn | Dn ← Dn - Dn - X [CCR: X, N, Z, V, C] |
| SUBX.s -(An), -(An) | Soustraction avec emprunt (multi-précision) |
| NEG.s ea | ea ← 0 - ea [CCR: X, N, Z, V, C] (complément a deux, négation) |
| NEGX.s ea | ea ← 0 - ea - X [CCR: X, N, Z, V, C] (négation avec emprunt, multi-précision) |
| CLR.s ea | ea ← 0 [CCR: N=0, Z=1, V=0, C=0] |
Exemples :
- SUB.L D0, D1 ; D1 := D1 - D0
- SUBA.L #100, A0 ; A0 := A0 - 100
- SUBQ.L #1, D7 ; D7 := D7 - 1 (compteur)
- NEG.L D0 ; D0 := -D0
- CLR.L D0 ; D0 := 0
Remarques :
- ADDQ/SUBQ sont les instructions les plus rapides pour ajouter/soustraire une petite constante (1 a 8)
- ADDA/SUBA ne modifient pas les drapeaux, ce qui est pratique pour manipuler des pointeurs sans perturber les tests en cours
- CLR effectue d'abord une lecture puis une écriture de la destination (important pour les registres matériels)
Multiplication
| Instruction | Description |
|---|---|
| MULS.W ea, Dn | Dn[31:0] ← Dn[15:0] * ea[15:0] (signe) Multiplication signée 16x16 → 32 bits [CCR: N, Z mis a jour; V=0, C=0] |
| MULU.W ea, Dn | Dn[31:0] ← Dn[15:0] * ea[15:0] (non signe) Multiplication non signée 16x16 → 32 bits [CCR: N, Z mis a jour; V=0, C=0] |
Exemples :
- MULU.W #10, D0 ; D0 := D0.W * 10 (non signe)
- MULS.W D1, D0 ; D0 := D0.W * D1.W (signe)
- MULU.W #640, D0 ; D0 := D0.W * 640 (coord. ecran)
Remarques :
- Le 68000 ne fait que des multiplications 16x16 → 32
- Le 68020 ajoute les multiplications 32x32 → 32/64
- La multiplication prend environ 70 cycles sur le 68000, ce qui est relativement lent
Division
| Instruction | Description |
|---|---|
| DIVS.W ea, Dn | Dn[15:0] ← Dn[31:0] / ea[15:0] (quotient) Dn[31:16] ← Dn[31:0] MOD ea[15:0] (reste) Division signée 32/16 → 16 bits [CCR: N, Z, V mis a jour; C=0] Exception si ea = 0 (division par zéro) |
| DIVU.W ea, Dn | Dn[15:0] ← Dn[31:0] / ea[15:0] (quotient) Dn[31:16] ← Dn[31:0] MOD ea[15:0] (reste) Division non signée 32/16 → 16 bits [CCR: N, Z, V mis a jour; C=0] Exception si ea = 0 (division par zéro) |
Exemples :
- DIVU.W #10, D0 ; D0.W := D0 / 10, D0 haut := reste
- DIVS.W D1, D0 ; D0.W := D0 / D1.W (signe)
-
- ; Extraire quotient et reste
- DIVU.W #100, D0 ; diviser D0 par 100
- MOVE.L D0, D1 ; copier le resultat
- SWAP D1 ; D1.W := reste (etait dans mot haut)
- ; D0.W = quotient, D1.W = reste
Remarques :
- Le 68000 ne fait que des divisions 32/16 → 16+16
- Le 68020 ajoute les divisions 32/32 → 32 et 64/32 → 32
- Si le quotient ne tient pas sur 16 bits, V est mis a 1 et le registre destination n'est pas modifie
- La division prend environ 140 cycles sur le 68000
- La division par zéro généré l'exception vecteur 5
Extension de signe
| Instruction | Description |
|---|---|
| EXT.W Dn | Étendre D0.B (bits 7-0) avec signe dans D0.W (bit 7 copie dans bits 15-8) [CCR: N, Z mis a jour; V=0, C=0] |
| EXT.L Dn | Etendre D0.W (bits 15-0) avec signe dans D0.L (bit 15 copie dans bits 31-16) [CCR: N, Z mis a jour; V=0, C=0] |
Exemples :
- MOVE.B #-5, D0 ; D0.B := $FB
- EXT.W D0 ; D0.W := $FFFB (-5 sur 16 bits)
- EXT.L D0 ; D0.L := $FFFFFFFB (-5 sur 32 bits)
Remarques :
- Sur le 68000, il n'y a pas d'extension directe .B → .L.
Il faut faire EXT.W puis EXT.L - Le 68020 ajoute EXTB.L Dn pour l'extension .B → .L directe
Test et comparaison
| Instruction | Description |
|---|---|
| TST.s ea | Tester l'opérande (comparer avec zéro) [CCR: N, Z mis a jour; V=0, C=0] |
| CMP.s ea, Dn | Calculer Dn - ea, positionner les drapeaux mais ne pas entreposer le résultat [CCR: N, Z, V, C] |
| CMPA.s ea, An | Calculer An - ea, positionner les drapeaux (s = W signe-étendu ou L) [CCR: N, Z, V, C] |
| CMPI.s #imm, ea | Calculer ea - imm, positionner les drapeaux [CCR: N, Z, V, C] |
| CMPM.s (An)+, (Am)+ | Comparer deux blocs mémoire élément par élément Calcule [Am]+ - [An]+, positionne les drapeaux (post-incrément sur les deux registres) [CCR: N, Z, V, C] |
Exemples :
- TST.L D0 ; tester si D0 est zero
- BEQ _est_zero ; sauter si D0 = 0
-
- CMP.W #100, D0 ; comparer D0.W avec 100
- BGT _superieur ; sauter si D0.W > 100 (signe)
-
- CMPA.L A0, A1 ; comparer A1 avec A0
- BEQ _meme_adresse ; sauter si A0 = A1
-
- ; Comparer deux chaines de 10 octets
- LEA Str1, A0
- LEA Str2, A1
- MOVEQ #9, D7 ; compteur = 10 - 1
- cmp_loop:
- CMPM.B (A0)+, (A1)+ ; comparer octet par octet
- DBNE D7, cmp_loop ; continuer si egal et D7 >= 0
Remarques :
- TST ne modifie PAS X (contrairement a CMP)
- CMP ne modifie PAS X (contrairement a SUB)
- CMPM est spécialement conçu pour la comparaison de blocs mémoire, avec auto-incrément des deux pointeurs
- CMPA signe-étend l'opérande .W a 32 bits avant la comparaison
Opérations logiques
Opérations logiques de base
| Instruction | Description |
|---|---|
| AND.s ea, Dn | Dn ← Dn AND ea [CCR: N, Z; V=0, C=0] | AND.s Dn, ea | ea ← ea AND Dn [CCR: N, Z; V=0, C=0] |
| ANDI.s #imm, ea | ea ← ea AND imm [CCR: N, Z; V=0, C=0] |
| OR.s ea, Dn | Dn ← Dn OR ea [CCR: N, Z; V=0, C=0] |
| OR.s Dn, ea | ea ← ea OR Dn [CCR: N, Z; V=0, C=0] |
| ORI.s #imm, ea | ea ← ea OR imm [CCR: N, Z; V=0, C=0] |
| EOR.s Dn, ea | ea ← ea XOR Dn [CCR: N, Z; V=0, C=0] |
| EORI.s #imm, ea | ea ← ea XOR imm [CCR: N, Z; V=0, C=0] |
| NOT.s ea | ea ← NOT ea (complement a un) [CCR: N, Z; V=0, C=0] |
Exemples :
- AND.L #$FF, D0 ; masquer les bits hauts (garder octet)
- OR.W #$8000, D0 ; mettre le bit 15 a 1
- EOR.L D0, D0 ; D0 := 0 (idiome de mise a zero)
- NOT.L D0 ; inverser tous les bits de D0
- ANDI.B #$0F, D0 ; garder les 4 bits bas
Remarques :
- EOR (XOR) sur le 68000 n'accepte comme source QUE Dn (pas d'autre mode d'adressage en source)
- Pour faire ea XOR ea, il faut d'abord charger dans Dn
- ANDI/ORI/EORI acceptent les immédiats en source
Opérations logiques sur le CCR et le SR
| Instruction | Description |
|---|---|
| ANDI.B #imm, CCR | CCR ← CCR AND imm |
| ORI.B #imm, CCR | CCR ← CCR OR imm |
| EORI.B #imm, CCR | CCR ← CCR XOR imm |
| ANDI.W #imm, SR | SR ← SR AND imm (privilégiée) |
| ORI.W #imm, SR | SR ← SR OR imm (privilégiée) |
| EORI.W #imm, SR | SR ← SR XOR imm (privilégiée) |
Exemples :
- ANDI.B #$FE, CCR ; effacer le drapeau C
- ORI.B #$04, CCR ; mettre le drapeau Z a 1
- ANDI.W #$F8FF, SR ; passer au niveau d'interruption 0
- ORI.W #$0700, SR ; masquer toutes les interruptions
Décalages et rotations
Décalages arithmétiques
| Instruction | Description |
|---|---|
| ASL.s #cnt, Dn | Décalage arithmétique a gauche |
| ASL.s Dn, Dn | (cnt = 1 a 8 en immédiat, ou valeur de Dn) |
| ASL.W ea | (décalage de 1 position en mémoire) Bit de poids fort → C et X, 0 → bit 0 [CCR: X, N, Z, V, C] |
| ASR.s #cnt, Dn | Décalage arithmétique a droite |
| ASR.s Dn, Dn | (préserve le bit de signe) |
| ASR.W ea | Bit 0 → C et X, signe préserve [CCR: X, N, Z, V, C] |
Exemples :
- ASL.L #1, D0 ; D0 := D0 * 2
- ASL.L #3, D0 ; D0 := D0 * 8
- ASR.W #1, D0 ; D0.W := D0.W / 2 (signe)
- ASL.W (A0) ; décaler le mot en mémoire
Décalages logiques
| Instruction | Description |
|---|---|
| LSL.s #cnt, Dn | Décalage logique a gauche |
| LSL.s Dn, Dn | Identique a ASL pour le décalage a gauche |
| LSL.W ea | [CCR: X, N, Z, V=0, C] |
| LSR.s #cnt, Dn | Décalage logique a droite |
| LSR.s Dn, Dn | 0 → bit de poids fort, bit 0 → C et X |
| LSR.W ea | (ne préserve PAS le signe) [CCR: X, N, Z, V=0, C] |
Exemples :
- LSL.L #2, D0 ; D0 := D0 * 4 (non signe)
- LSR.L #4, D0 ; D0 := D0 / 16 (non signe)
- LSL.W #1, D0 ; equivalent a ASL.W #1, D0
Remarques :
- ASL et LSL produisent le même résultat
- ASR préserve le signe, LSR insère des zéros
- Le compteur immédiat va de 1 a 8 ; pour des décalages plus grands, utiliser un registre Dn comme compteur
- Les décalages en mémoire ne déplacent que d'1 position et opèrent uniquement en .W
Rotations
| Instruction | Description |
|---|---|
| ROL.s #cnt, Dn | Rotation a gauche |
| ROL.s Dn, Dn | Bit de poids fort → C et bit 0 |
| ROL.W ea | [CCR: N, Z, V=0, C] |
| ROR.s #cnt, Dn | Rotation a droite |
| ROR.s Dn, Dn | Bit 0 → C et bit de poids fort |
| ROR.W ea | [CCR: N, Z, V=0, C] |
| ROXL.s #cnt, Dn | Rotation a gauche a travers X |
| ROXL.s Dn, Dn | MSB → C et X, ancien X → bit 0 |
| ROXL.W ea | [CCR: X, N, Z, V=0, C] |
| ROXR.s #cnt, Dn | Rotation a droite a travers X |
| ROXR.s Dn, Dn | Bit 0 → C et X, ancien X → MSB |
| ROXR.W ea | [CCR: X, N, Z, V=0, C] |
Exemples :
- ROL.L #8, D0 ; rotation de D0 de 8 bits a gauche
- ROR.W #1, D0 ; rotation de D0.W d'1 bit a droite
- ROXL.L #1, D0 ; rotation avec X (multi-precision)
Remarques :
- ROL/ROR n'affectent PAS le drapeau X (seulement C)
- ROXL/ROXR incluent X dans la rotation, formant une chaîne de (taille+1) bits. C'est utile pour les rotations multi-précision
- Les rotations en mémoire ne tournent que d'1 position
Manipulation de bits
Ces instructions testent, modifient ou complémentent un bit individuel dans un registre ou en mémoire. Le bit teste est copie (inverse) dans le drapeau Z du CCR.
| Instruction | Description |
|---|---|
| BTST #bit, ea | Tester le bit : Z ← NOT bit sélectionné |
| BTST Dn, ea | [CCR: Z mis a jour] |
| BSET #bit, ea | Tester puis mettre a 1 : Z ← NOT bit, bit ← 1 |
| BSET Dn, ea | [CCR: Z mis a jour] |
| BCLR #bit, ea | Tester puis mettre a 0 : Z ← NOT bit, bit ← 0 |
| BCLR Dn, ea | [CCR: Z mis a jour] |
| BCHG #bit, ea | Tester puis completer : Z ← NOT bit, |
| BCHG Dn, ea | bit ← NOT bit [CCR: Z mis a jour] |
Le numéro de bit peut être :
- Un immédiat (0 a 31 pour Dn, 0 a 7 pour la mémoire)
- Un registre Dn (modulo 32 pour Dn, modulo 8 pour mémoire)
Quand l'opérande est un registre, l'opération porte sur les 32 bits du registre (bit 0 a 31). Quand l'opérande est en mémoire, l'opération porte sur un octet (bit 0 a 7).
Exemples :
- BTST #0, D0 ; tester le bit 0 de D0
- BNE _impair ; sauter si bit 0 = 1
-
- BSET #7, D0 ; mettre le bit 7 de D0 a 1
- BCLR #31, D0 ; effacer le bit 31 de D0
- BCHG D1, D0 ; completer le bit D1 de D0
-
- BTST #0, (A0) ; tester le bit 0 de l'octet [A0]
- BSET #7, (A0) ; mettre le bit 7 de l'octet [A0]
Remarques :
- Le drapeau Z est l'INVERSE du bit teste : Z = 1 si le bit était 0, Z = 0 si le bit était 1
- Sur le 68000, BTST peut tester n'importe quel mode d'adressage, mais BSET/BCLR/BCHG ne peuvent pas modifier un registre d'adresses directement
Arithmetique BCD (décimal code binaire)
Le 68000 supporte l'arithmétique BCD (Binary Coded Decimal) pour les applications financières et commerciales.
| Instruction | Description |
|---|---|
| ABCD.B Dn, Dn | Dn ← Dn + Dn + X (addition BCD) |
| ABCD.B -(An), -(An) | [CCR: X, C mis a jour; Z non remis a zéro] |
| SBCD.B Dn, Dn | Dn ← Dn - Dn - X (soustraction BCD) |
| SBCD.B -(An), -(An) | [CCR: X, C mis a jour; Z non remis a zéro] |
| NBCD.B ea | ea ← 0 - ea - X (négation BCD) [CCR: X, C mis a jour; Z non remis a zéro] |
Exemples :
- ; Additionner deux nombres BCD de 4 chiffres
- ; D0 = $1234, D1 = $5678, resultat dans D0
- MOVE #$04, CCR ; mettre X = 0 (effacer la retenue)
- ABCD.B D1, D0 ; additionner les octets bas (BCD)
- SWAP D0
- SWAP D1
- ABCD.B D1, D0 ; additionner les octets hauts + retenue
Remarques :
- Les opérations BCD ne travaillent que sur des octets
- Le drapeau Z n'est PAS remis a zéro si le résultat est non-nul (il est seulement mis a 1 si le résultat est 0). Ceci permet de tester le zéro sur des opérations multi-octets en initialisant Z a 1 au départ
- Le mode -(An), -(An) est prévu pour traiter des chaînes BCD en mémoire de droite a gauche
Branchements et contrôle de flux
Sauts inconditionnels
| Instruction | Description |
|---|---|
| JMP ea | Saut inconditionnel a l'adresse effective PC := ea [CCR: non modifie] |
| BRA label | Branchement relatif inconditionnel |
| BRA.S label | PC := PC + déplacement (8 ou 16 bits) |
| BRA.W label | [CCR: non modifie] |
Exemples :
- JMP (A0) ; saut via pointeur dans A0
- JMP Table(PC,D0.W) ; saut via table indexee
- BRA Boucle ; branchement relatif
- BRA.S Suite ; branchement court (8 bits)
Remarques :
- BRA est préféré a JMP pour le code relogeable (PIC)
- BRA.S (short) utilise un déplacement 8 bits (-128 a +126)
- BRA.W utilise un déplacement 16 bits (-32768 a +32766)
- JMP accepte les modes indirects et indexes, pas BRA
Appels de sous-programmes
| Instruction | Description |
|---|---|
| JSR ea | Appel : A7 -= 4, [A7] := PC, PC := ea [CCR: non modifie] |
| BSR label | Appel relatif : A7 -= 4, [A7] := PC, |
| BSR.S label | PC := PC + déplacement |
| BSR.W label | [CCR: non modifie] |
| RTS | Retour de sous-programme : PC := [A7], A7 += 4 [CCR: non modifie] |
| RTR | Retour avec restauration CCR : CCR := [A7], A7 += 2, PC := [A7], A7 += 4 [CCR: restaure depuis la pile] |
| RTE | Retour d'exception (privilégiée) : SR := [A7], A7 += 2, PC := [A7], A7 += 4 [CCR: restaure depuis la pile] |
Exemples :
- JSR MaRoutine ; appel direct
- BSR MaRoutine ; appel relatif (PIC)
- BSR.S Proche ; appel relatif court
- JSR (A0) ; appel indirect via pointeur
Remarques :
- BSR est préféré a JSR pour le code relogeable
- RTS dépile uniquement PC (4 octets)
- RTR dépile CCR (2 octets) puis PC (4 octets)
- RTE dépile SR (2 octets) puis PC (4 octets) et est réservée au mode superviseur
Branchements conditionnels
| Instruction | Description |
|---|---|
| Bcc label | Branchement si condition cc vraie |
| Bcc.S label | PC := PC + deplacement (8 ou 16 bits) |
| Bcc.W label | [CCR: non modifie] |
Les conditions cc sont :
| Condition | Mnémonique | Drapeaux testes |
|---|---|---|
| Égal / zéro | BEQ | Z = 1 |
| Non égal | BNE | Z = 0 |
| Retenue | BCS | C = 1 |
| Pas de retenue | BCC | C = 0 |
| Négatif | BMI | N = 1 |
| Positif ou zéro | BPL | N = 0 |
| Débordement | BVS | V = 1 |
| Pas de débordement | BVC | V = 0 |
Comparaisons non signées (unsigned) :
| Condition | Mnémonique | Drapeaux testes |
|---|---|---|
| Inférieur | BCS / BLO | C = 1 |
| Inf. ou égal | BLS | C = 1 ou Z = 1 |
| Supérieur | BHI | C = 0 et Z = 0 |
| Sup. ou égal | BCC / BHS C = 0 |
Comparaisons signées (signed) :
| Condition | Mnémonique | Drapeaux testes |
|---|---|---|
| Inférieur | BLT | N xor V = 1 |
| Inférieur ou égal | BLE | (N xor V) = 1 ou Z = 1 |
| Supérieur | BGT | (N xor V) = 0 et Z = 0 |
| Supérieur ou égal | BGE | N xor V = 0 |
| Toujours vrai | BRA | (inconditionnel) |
| Toujours faux | (pas de mnémonique ; utiliser NOP ou BRA.S *+2) |
Exemples :
- CMP.W #10, D0
- BEQ _egal ; sauter si D0.W = 10
- BNE _different ; sauter si D0.W <> 10
- BGT _superieur ; sauter si D0.W > 10 (signe)
- BHI _au_dessus ; sauter si D0.W > 10 (non signe)
- BLT _inferieur ; sauter si D0.W < 10 (signe)
- BCS _en_dessous ; sauter si D0.W < 10 (non signe)
-
- TST.L D0
- BMI _negatif ; sauter si D0 < 0
- BPL _positif ; sauter si D0 >= 0
Boucle avec décrementation (DBcc)
| Instruction | Description |
|---|---|
| DBcc Dn, label | Si condition cc est fausse : Dn.W ← Dn.W - 1 Si Dn.W <> -1 : branchement a label Sinon : continuer (fin de boucle) Si condition cc est vraie : Continuer (sortie anticipee) [CCR: non modifie] |
Les conditions cc sont les mêmes que pour Bcc.
DBF est la forme la plus courante (condition toujours fausse, équivalente a DBRA sur certains assembleurs) :
| Instruction | Description | |
|---|---|---|
| DBF Dn, label | Dn.W -= 1, boucler si Dn.W <> -1 | |
| DBRA Dn, label | Synonyme de DBF |
| Instruction | Description |
|---|---|
| Scc ea | Si condition cc vraie : ea.B ← $FF Si condition cc fausse : ea.B ← $00 [CCR: non modifie] |
Les conditions cc sont les mêmes que pour Bcc.
Exemples :
- CMP.W D0, D1
- SEQ D2 ; D2.B := $FF si D0 = D1, $00 sinon
- SLT D3 ; D3.B := $FF si D1 < D0 (signe)
- SNE (A0) ; [A0] := $FF si D0 <> D1
Remarques :
- Scc positionne un octet entier ($FF ou $00), pas un seul bit
- Cela permet d'utiliser le résultat comme masque pour les opérations logiques
- Équivalent de SETcc sur le 80386, mais utilise $FF au lieu de $01
Interruptions logicielles
| Instruction | Description |
|---|---|
| TRAP #vector | Exception logicielle (vecteur 32 + vector) vector = 0 a 15 Sauvegarde PC et SR sur la pile superviseur, puis saut au handler via la table de vecteurs [CCR: non modifie (SR sauvegarde)] |
| TRAPV | Exception si V = 1 (debordement)Équivalent a : si V alors TRAP #7 [CCR: non modifie] |
| CHK.W ea, Dn | Vérifier les bornes d'un indice : Si Dn < 0 ou Dn > ea : exception CHK (vecteur 6) [CCR: N modifie, autres indéfinis] |
Exemples :
- TRAP #0 ; appel systeme (AmigaOS, Atari TOS)
- TRAP #15 ; appel au debugger (tradition 68K)
- TRAPV ; exception si debordement
- CHK.W #99, D0 ; exception si D0 < 0 ou D0 > 99
Remarques :
- TRAP est le mécanisme standard pour les appels système sur les systèmes 68000 (AmigaOS, Atari TOS, Mac OS)
- Les vecteurs TRAP #0 a TRAP #15 occupent les adresses $80 a $BC dans la table des vecteurs d'exception
- CHK est utile pour la vérification automatique des bornes de tableaux
Opérations sur le registre d'état
Accès au CCR et au SR
| Instruction | Description |
|---|---|
| MOVE.W SR, ea | Lire le registre d'état complet (privilégiée sur le 68010+, pas sur le 68000) [CCR: non modifie] |
| MOVE.W ea, SR | Charger le registre d'état (privilégiée) [CCR: modifie selon la valeur chargée] |
| MOVE.W CCR, ea | Lire la partie CCR du registre d'état (disponible a partir du 68010) |
| MOVE.W ea, CCR | Charger la partie CCR (seul l'octet bas est utilise) [CCR: modifie selon la valeur chargée] |
Accès au pointeur de pile utilisateur
| Instruction | Description |
|---|---|
| MOVE.L USP, An | Lire le pointeur de pile utilisateur (privilégiée) |
| MOVE.L An, USP | Charger le pointeur de pile utilisateur (privilégiée) |
Exemples :
Instructions système et privilégiées
Instructions privilégiées
Les instructions suivantes ne peuvent être exécutées qu'en mode superviseur (bit S du SR = 1). Toute tentative d'exécution en mode utilisateur généré une exception de violation de privilège (vecteur 8).
| Instruction | Description |
|---|---|
| STOP #imm16 | Charger SR avec imm16, puis arrêter le processeur jusqu'à la prochaine interruption, exception ou reset [CCR: modifie selon imm16] |
| RESET | Envoyer le signal RESET sur le bus externe (réinitialise les périphériques sans affecter le processeur lui-même) [CCR: non modifie] |
| RTE | Retour d'exception |
| MOVE.W ea, SR | Charger le registre d'état |
| MOVE.L USP, An | Accès au pointeur de pile utilisateur |
| MOVE.L An, USP | Accès au pointeur de pile utilisateur |
| ANDI.W #imm, SR ORI.W #imm, SR EORI.W #imm, SR |
Opérations logiques sur le SR |
Instructions de contrôle
| Instruction | Description |
|---|---|
| NOP | Pas d'opération (force la synchronisation du pipeline) [CCR: non modifie] |
| ILLEGAL | Générer une exception d'instruction illégale (vecteur 4). Le codage est $4AFC. Utile pour le debogage et comme point d'arrêt. |
Remarques :
- STOP est utilisée dans les boucles d'attente d'interruption pour réduire la consommation (idle loop)
- RESET n'affecte pas le processeur lui-même, seulement les périphériques connectes au bus
- NOP sur le 68000 ne fait pas juste "rien" : elle force la complétion de toutes les opérations en cours dans le pipeline de pre-lecture
Résumé et tableau récapitulatif
Nombre approximatif d'instructions par catégorie :
| Catégorie | Nombre |
|---|---|
| Transfert de données | 15 |
| Arithmétique entière | 22 |
| Opérations logiques | 8 |
| Décalages et rotations | 8 |
| Manipulation de bits | 4 |
| Arithmétique BCD | 3 |
| Branchements et contrôle | 20+ |
| Positionnement conditionnel (Scc) | 16 |
| Boucles (DBcc) | 16 |
| Registre d'état | 8 |
| Système et privilégiées | 5 |
| Divers (NOP, ILLEGAL,...) | 2 |
| Total (hors variantes de taille) | ~130 |
Instructions les plus fréquemment utilisées en pratique :
| Instruction | Usage typique |
|---|---|
| MOVE | Transfert de données (~40% des instructions) |
| MOVEQ | Chargement de petites constantes |
| LEA | Calcul d'adresses |
| ADD/SUB | Arithmétique de base |
| ADDQ/SUBQ | Incrément/décrément rapide |
| CMP/TST | Préparation des branchements |
| BRA/Bcc | Contrôle de flux |
| BSR/JSR/RTS | Appels de fonctions |
| CLR | Mise a zéro |
| AND/OR | Masquage et combinaison de bits |
| LSL/LSR | Multiplications/divisions par puissances de 2 |
| DBRA | Boucles avec compteur |
| MOVEM | Sauvegarde/restauration de registres |
| LINK/UNLK | Gestion du cadre de pile |
| SWAP | Accès au mot haut d'un registre |
Comparaison avec l'Intel 80386 :
| Aspect | 68000 | 80386 |
|---|---|---|
| Nombre d'instructions | ~130 | ~180 |
| Tailles d'opérandes | .B / .W / .L | 8 / 16 / 32 bits |
| Suffixe de taille | Obligatoire | Implicite (registre) |
| Opérations mémoire-mémoire | Non (sauf MOVEM, CMPM, ABCD, SBCD) | MOV mem, mem indirect |
| Multiplication | 16x16 → 32 | 8/16/32 → double |
| Division | 32/16 → 16+16 | double → simple |
| Branchement conditionnel | Bcc (8/16 bits) | Jcc (8/32 bits) |
| Boucle avec condition | DBcc (unique!) | LOOP (sans condition) |
| Positionnement cond. | Scc (→ $FF/$00) | SETcc (→ $01/$00) |
| Instructions de chaînes | Non (utiliser DBRA) | MOVS, CMPS,... |
| Auto-incrément/décrément | (An)+, -(An) en EA | Non (sauf PUSH/POP) |
| Modes d'adressage par instruction | Uniformes | Variables selon instruction |
| Drapeaux après MOVE | Modifies | Non modifies |
| Retenue étendue (X) | Oui (drapeau X) | Non (C sert pour tout) |
| Arithmétique BCD | ABCD, SBCD, NBCD | DAA, DAS, AAA, AAS |
| Ports d'entrée/sortie | Memory-mapped | IN/OUT séparés |
Le 68000 se distingue par son jeu d'instructions orthogonal : la plupart des instructions acceptent les mêmes modes d'adressage et les mêmes tailles d'opérandes. Cette régularité simplifie l'apprentissage et la génération de code. Le drapeau X (eXtend) séparé de C (Carry) facilite l'arithmétique multi-précision. En revanche, le 80386 offre des instructions de chaînes (REP MOVS,...) et des opérations mémoire-mémoire plus directes.