Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

MIPS/SPIM Reference Card

CORE INSTRUCTION SET (INCLUDING PSEUDO INSTRUCTIONS)


MNE- FOR- OPCODE/
MON- MAT FUNCT
NAME IC OPERATION (in Verilog) (Hex)
Add add R R[rd]=R[rs]+R[rt] (1) 0/20
Add Immediate addi I R[rt]=R[rs]+SignExtImm (1)(2) 8
Add Imm. Unsigned addiu I R[rt]=R[rs]+SignExtImm (2) 9
Add Unsigned addu R R[rd]=R[rs]+R[rt] (2) 0/21
Subtract sub R R[rd]=R[rs]-R[rt] (1) 0/22
Subtract Unsigned subu R R[rd]=R[rs]-R[rt] 0/23
And and R R[rd]=R[rs]&R[rt] 0/24
And Immediate andi I R[rt]=R[rs]&ZeroExtImm (3) c
Nor nor R R[rd]=∼(R[rs]|R[rt]) 0/27
Or or R R[rd]=R[rs]|R[rt] 0/25
Or Immediate ori I R[rt]=R[rs]|ZeroExtImm (3) d
Xor xor R R[rd]=R[rs]ˆR[rt] 0/26
Xor Immediate xori I R[rt]=R[rs]ˆZeroExtImm e
Shift Left Logical sll R R[rd]=R[rs]shamt 0/00
Shift Right Logical srl R R[rd]=R[rs]shamt 0/02
Shift Right Arithmetic sra R R[rd]=R[rs]>shamt 0/03
Shift Left Logical Var. sllv R R[rd]=R[rs]R[rt] 0/04
Shift Right Logical Var. srlv R R[rd]=R[rs]R[rt] 0/06
Shift Right Arithmetic Var. srav R R[rd]=R[rs]>R[rt] 0/07
Set Less Than slt R R[rd]=(R[rs]<R[rt])?1:0 0/2a
Set Less Than Imm. slti I R[rt]=(R[rs]<SignExtImm)?1:0 (2) a
Set Less Than Imm. Unsign. sltiu I R[rt]=(R[rs]<SignExtImm)?1:0 (2)(6) b
Set Less Than Unsigned sltu R R[rd]=(R[rs]<R[rt])?1:0 (6) 0/2b
Branch On Equal beq I if(R[rs]==R[rt]) PC=PC+4+BranchAddr (4) 4
Branch On Not Equal bne I if(R[rs]!=R[rt]) PC=PC+4+BranchAddr (4) 5
Branch Less Than blt P if(R[rs]<R[rt]) PC=PC+4+BranchAddr
Branch Greater Than bgt P if(R[rs]>R[rt]) PC=PC+4+BranchAddr
Branch Less Than Or Equal ble P if(R[rs]<=R[rt]) PC=PC+4+BranchAddr
Branch Greater Than Or Equal bge P if(R[rs]>=R[rt]) PC=PC+4+BranchAddr
Jump j J PC=JumpAddr (5) 2
Jump And Link jal J R[31]=PC+4; (5) 2
PC=JumpAddr
Jump Register jr R PC=R[rs] 0/08
Jump And Link Register jalr R R[31]=PC+4; 0/09
PC=R[rs]
Move move P R[rd]=R[rs]
Load Byte lb I R[rt]={24’b0, M[R[rs]+ZeroExtImm](7:0)} (3) 20
Load Byte Unsigned lbu I R[rt]={24’b0, M[R[rs]+SignExtImm](7:0)} (2) 24
Load Halfword lh I R[rt]={16’b0, M[R[rs]+ZeroExtImm](15:0)} (3) 25
Load Halfword Unsigned lhu I R[rt]={16’b0, M[R[rs]+SignExtImm](15:0)} (2) 25
Load Upper Imm. lui I R[rt]={imm,16’b0} f
Load Word lw I R[rt]=M[R[rs]+SignExtImm] (2) 23
Load Immediate li P R[rd]=immediate
Load Address la P R[rd]=immediate
Store Byte sb I M[R[rs]+SignExtImm] (7:0)=R[rt](7:0) (2) 28
Store Halfword sh I M[R[rs]+SignExtImm] (15:0)=R[rt](15:0) (2) 29
Store Word sw I M[R[rs]+SignExtImm]=R[rt] (2) 2b
REGISTERS
NAME NMBR USE STORE? (1) May cause overflow exception
$zero 0 The Constant Value 0 N.A. (2) SignExtImm ={16{immediate[15]},immediate }
(3) ZeroExtImm ={16{1b’0},immediate }
$at 1 Assembler Temporary No
(4) BranchAddr = {14{immediate[15]},immediate,2’b0 }
$v0-$v1 2-3 Values for Function Results and No
(4) JumpAddr = {PC[31:28], address, 2’b0 }
Expression Evaluation
(6) Operands considered unsigned numbers (vs. 2 s comp.)
$a0-$a3 4-7 Arguments No
$t0-$t7 8-15 Temporaries No BASIC INSTRUCTION FORMATS,
$s0-$s7 16-23 Saved Temporaries Yes FLOATING POINT INSTRUCTION FORMATS
$t8-$t9 24-25 Temporaries No 31
R opcode 26 25 rs 21 20 rt 16 15
rd 11 10 shamt 6 5 funct 0
$k0-$k1 26-27 Reserved for OS Kernel No 31 26 25 21 20 16 15 0
$gp 28 Global Pointer Yes I opcode rs rt immediate
31
$sp 29 Stack Pointer Yes J opcode 26 25 immediate 0

$fp 30 Frame Pointer Yes FR 31 opcode 26 25 fmt 21 20 ft 16 15


fs 11 10 fd 65
funct 0

$ra 31 Return Address Yes FI 31


opcode 26 25
fmt 21 20
rt 16 15
immediate 0

$f0-$f31 0-31 Floating Point Registers Yes

Copyright c 2007 Jan Wätzig, Staatliche Studienakademie Dresden (www.ba-dresden.de/∼jan)


This reference card may be used for educational purposes only.
ARITHMETIC CORE INSTRUCTION SET
MNE- FOR- OPCODE/
MON- MAT FMT/FT/
NAME IC OPERATION (in Verilog) FUNCT
Divide div R Lo=R[rs]/R[rt]; 0/–/–/1a
Hi=R[rs]%R[rt]
Divide Unsigned divu R Lo=R[rs]/R[rt]; (6) 0/–/–/1b
Hi=R[rs]%R[rt]
Multiply mult R {Hi,Lo}=R[rs]∗R[rt] 0/–/–/18
Multiply Unsigned multu R {Hi,Lo}=R[rs]∗R[rt] (6) 0/–/–/19
Branch On FP True bc1t FI if(FPCond) PC=PC+4+BranchAddr (4) 11/8/1/–
Branch On FP False bc1f FR if(!FPCond) PC=PC+4+BranchAddr (4) 11/8/0/–
FP Compare Single c.x.s∗ FR FPCond=(F[fs] op F[ft])?1:0 11/10/–/y
FP Compare Double c.x.d∗ FR FPCond=({F[fs],F[fs+1]} op {F[ft],F[ft+1]})?1:0 11/11/–/y

(x is eq, lt or le) (op is ==, < or <=) (y is 32, 3c or 3e)
FP Add Single add.s FR F[fd]=F[fs]+F[ft] 11/10/–/0
FP Divide Single div.s FR F[fd]=F[fs]/F[ft] 11/10/–/3
FP Multiply Single mul.s FR F[fd]=F[fs]∗F[ft] 11/10/–/2
FP Subtract Single sub.s FR F[fd]=F[fs]-F[ft] 11/10/–/1
FP Add Double add.d FR {F[fd],F[fd+1]}={F[fs],F[fs+1]}+{F[ft],F[ft+1]} 11/11/–/0
FP Divide Double div.d FR {F[fd],F[fd+1]}={F[fs],F[fs+1]}/{F[ft],F[ft+1]} 11/11/–/3
FP Multiply Double mul.d FR {F[fd],F[fd+1]}={F[fs],F[fs+1]}∗{F[ft],F[ft+1]} 11/11/–/2
FP Subtract Double sub.d FR {F[fd],F[fd+1]}={F[fs],F[fs+1]}-{F[ft],F[ft+1]} 11/11/–/1
Move From Hi mfhi R R[rd]=Hi 0/–/–/10
Move From Lo mflo R R[rd]=Lo 0/–/–/12
Move From Control mfc0 R R[rd]=CR[rs] 16/0/–/0
Load FP Single lwc1 I F[rt]=M[R[rs]+SignExtImm] (2) 31/–/–/–
Load FP Double ldc1 I F[rt]=M[R[rs]+SignExtImm]; (2) 35/–/–/–
F[rt+1]=M[R[rs]+SignExtImm+4]
Store FP Single swc1 I M[R[rs]+SignExtImm]=F[rt] (2) 39/–/–/–
Store FP Double sdc1 I M[R[rs]+SignExtImm]=F[rt]; (2) 3d/–/–/–
M[R[rs]+SignExtImm+4]=F[rt+1]

ASSEMBLER DIRECTIVES
.data [addr]∗ Subsequent items are stored in the data segment
.kdata [addr]∗ Subsequent items are stored in the kernel data segment
.ktext [addr]∗ Subsequent items are stored in the kernel text segment
.text [addr]∗ Subsequent items are stored in the text

starting at [addr] if specified
.ascii str Store string str in memory, but do not null-terminate it
.asciiz str Store string str in memory and null-terminate it
.byte b1 , . . . , bn Store the n values in successive bytes of memory
.double d1 , . . . , dn Store the n floating-point double precision numbers in successive memory locations
.float f1 , . . . , f1 Store the n floating-point single precision numbers in successive memory locations
.half h1 , . . . , hn Store the n 16-bit quantities in successive memory halfwords
.word w1 , . . . , wn Store the n 32-bit quantities in successive memory words
.space n Allocate n bytes of space in the current segment
.extern symsize Declare that the datum stored at sym is size bytes large and is a global label
.globl sym Declare that label sym is global and can be referenced from other files
.align n Align the next datum on a 2n byte boundary, until the next .data or .kdata directive
.set at Tells SPIM to complain if subsequent instructions use $at
.set noat prevents SPIM from complaining if subsequent instructions use $at

SYSCALLS EXCEPTION CODES


SERVICE $v0 ARGS RESULT Number Name Cause of Exception
print_int 1 integer $a0 0 Int Interrupt (hardware)
print_float 2 float $f12 4 AdEL Address Error Exception (load or instruction
print_double 3 double $f12/$f13 fetch)
print_string 4 string $a0 5 AdES Address Error Exception (store)
read_int 5 integer (in $v0) 6 IBE Bus Error on Instruction Fetch
read_float 6 float (in $f0) 7 DBE Bus Error on Load or Store
read_double 7 double (in $f0) 8 Sys Syscall Exception
read_string 8 buf $a0, buflen $a1 9 Bp Breakpoint Exception
sbrk 9 amount $a address (in $v0) 10 RI Reserved Instruction Exception
exit 10 11 CpU Coprocessor Unimplemented
12 Ov Arithmetic Overflow Exception
13 Tr Trap
15 FPE Floating Point Exception
[1] Patterson, David A; Hennessy, John J.: Computer Organization and Design, 3rd Edition. Morgan Kaufmann Publishers. San Francisco, 2005.

Copyright c 2007 Jan Wätzig, Staatliche Studienakademie Dresden (www.ba-dresden.de/∼jan)


This reference card may be used for educational purposes only.
Un vrai langage de programmation : MIPS
Schéma physique d’un CPU

ALU registres
Mémoire vive (RAM)

Unité de contrôle

CPU Périphériques

Schéma de fonctionnement du CPU : cycle d’instruction (Von Neumann)

Lecture Lecture Rangement


RAM de l’ins-
truction
de l’opé-
rande
de l’opé-
rande

Calcul de Calcul de Calcul de


Décodage Opération
l’adresse l’adresse l’adresse
CPU de l’ins-
de l’ins-
truction
d’opé-
sur les
données
de l’opé-
truction rande rande

RAM
— Elle contient les données et les programmes, sous forme numérique
— Un chiffre binaire (0 ou 1) s’appelle un bit (binary digit)
— Découpée par blocs de 8 bits. Un bloc de 8 bits = un octet
— Dans la RAM, chacun des octets est indexé par un numéro : son adresse

registres
— chaque registre = 1 mémoire de 32 bits = 1 mot = 4 octets
— Registres spéciaux :
— CP : Compteur de Programme = adresse de l’instruction suivante
— RI : Registre d’Instruction = instruction courante
— 32 registres programmables accessibles par leur numéro ($0 à $31) ou leur nom
(cas particulier : $0 contient toujours la valeur 0 — son nom est $zero)

Langage MIPS
— Fichier texte = programme
— Etape d’assemblage → programme binaire chargé en mémoire
— .data
directive démarrant la zone mémoire réservée aux données
— .text
directive démarrant la zone mémoire réservée au programme
Dans la zone .text, chaque ligne correspond à une instruction du programme, et sera traduite par un
mot (32 bits) par l’assembleur.
Addition et soustraction
— opérandes et résultat sont des registres (pas d’accès à la RAM)
— Syntaxe des instructions : toujours de la forme

op rd, rs, rt

op : opération (désignée par son nom)


rd : registre « destination »
rs : registre contenant le 1er opérande de l’opération (« source 1 »)
rt : registre contenant le 2d opérande de l’opération (« source 2 »)
— exemples :

add $v0, $s0, $s1 # stocke dans $v0 la somme des contenus de $s0 et de $s1
add $2 , $16, $17 # pareil, en désignant les registres par leur numéro
sub $t1, $t2, $t3 # stocke dans $t1 la différence ($t2 - $t3)
addu $v0, $s0, $s1 # comme add, sans plantage si dépassement
subu $t1, $t2, $t3 # comme sub, sans plantage si dépassement

— version avec « immediate » (constante) : le second opérande est un immédiat au lieu d’être le contenu
d’un registre

addi $v0, $zero, 17 # stocke dans $v0 la somme de $zero (= 0) et de 17


subi $v1, $v0, 5 # stocke dans $v1 la différence ($v0 - 5)

Exercice 1. Programmer en mips les calculs suivants (le résultat devra se trouver dans $v0) :
— 900
— 19 + 98
— (19 + 91) − (28 + 82)

Chargement et stockage (RAM ←→ registre)


— Pour transférer un mot, il faut préciser :
— Un registre : cible ou source de la donnée
— Une adresse mémoire (plus subtil)
— Un registre contient l’adresse de base
— On souhaite souvent se décaler d’une constante (offset) par rapport à l’adresse de base.
— L’adresse en RAM est la somme de l’adresse de base et de l’offset
— Syntaxe de l’instruction de chargement : toujours de la forme

op rt, offset(rs)

op : opération (désignée par son nom)


rt : registre de « source » du stockage ou « destination » du chargement
offset : décalage numérique en octets
rs : registre contenant l’adresse de base
— Chargement d’une adresse dans un registre
— dans le programme MIPS, utilisation d’un label pour donner un nom symbolique à l’adresse
de la ligne (dans le code assemblé) : un nom de label, suivi du signe « : ». Ex :

label1:
un_nom_de_label_quelconque:

— chargement de l’adresse d’un label dans un registre rd :

la rd, label

— Instructions de chargement (RAM → registres : lb, lbu, lw


— Instructions de stockage (registres → RAM) : sb, sw.
— Exemples :

.data
label_octets: .byte -1, 30, -1 # trois octets (-1, 30, -1)
label_mots: .word 1900, 123 # deux mots (1900, 123) (← huit octets)
.text
la $s0, label_octets # charge l'adresse label_octets dans $s0
lb $t1, 0($s0) # charge -1 dans le registre $t1
lb $t2, 1($s0) # charge 30 dans le registre $t2
lbu $t3, 2($s0) # charge 255 dans le registre $t3
la $s1, label_mots # charge l'adresse label_mots dans $s1
lw $t4, 0($s1) # charge 1900 dans $t4
lw $t5, 4($s1) # charge 123 dans $t5
sb $t2, 0($s1) # stocke l'octet 30 dans la RAM (à label_mots)
sw $t4, 0($s0) # stocke le mot 1900 en RAM (à label_octets)

Exercice 2. Faire un programme qui calcule res = 2a + b, où a, b et res sont des labels dans la
zone .data, désignant chacun un mot de valeur initiale respective 950, 123 et 0.

Branchements
— Branchement si égaux

beq rs, rt, label

beq : pour branch if registers are equal


Signifie : si (rs = rt) sauter vers label
— Branchement si différents

bne rs, rt, label

bne : pour branch if registers are not equal


Signifie : si (rs 6= rt) sauter vers label
— Sauts inconditionnel

j label # équivalent à : beq $0, $0, label


jr rs # idem, sauf que l'adresse du saut est dans un registre rs
Exercice 3. Faire un programme qui calcule res = a × b, où a, b et res sont des labels dans la
zone .data, désignant chacun un mot de valeur initiale respective 950, 123 et 0. On considère
toutes les valeurs comme des entiers non signés (i.e. positifs ou nuls).

— Traitement des inégalités

slt rd, rs, rt

slt : pour Set Less Than


Signifie : si (rs < rt) mettre 1 dans rd, sinon mettre 0 dans rd
Exemples :

lab1: slt $t2, $t0, $t1 # si $t0 < $t1,


bne $t2, $0, lab10 # aller à lab10
lab2: slt $t2, $s1, $s2 # si $s1 >= $s2, (¬ $s1 < $s2)
beq $t2, $0, lab1 # aller à lab1

Exercice 4. Faire un programme qui transforme le mot stocké au label blip en sa valeur absolue.

Exercice 5. Faire un programme qui calcule le quotient et le reste de ab . a, b, quotient et reste


sont des labels de mots positifs ou nuls dans la zone .data.

Algorithme :
1. initialisation : $s1 ← a , $s2 ← 0
2. tant que $s1 >= b, mettre à jour :
$s1 ← $s1 - b
$s2 ← $s2 + 1
3. terminaison : quotient ← $s2, reste ← $s1

Entrées / Sorties
— Voir la partie SYSCALLS de la feuille de référence.
Exemples :

.data
chaine: .asciiz "ab12" # 5 octets : 97, 98, 49, 50, 0
octets: .byte 97, 98, 49, 50, 0 # 5 octets : 97, 98, 49, 50, 0
espace: .space 200 # 200 octets non initialisés
.text
addi $v0, $0, 1 # code de syscall : 1 = print_int
addi $a0, $0, 199 # argument de syscall : 199
syscall # → affiche 199 à l'écran
addi $v0, $0, 4 # code de syscall : 4 = print_string
la $a0, octets # argument de syscall : adresse octets
syscall # → affiche ab12 à l'écran
addi $v0, $0, 8 # code de syscall : 8 = read_string
la $a0, espace # arg1 de syscall : adresse espace
addi $a1, $0, 200 # arg2 de syscall : 200
syscall # lit une chaîne de caractères au clavier
# (jusqu'à Entrée ou au max 200 caractères)
# et stocke les codes ascii (octets)
# à partir du label "espace"
Sous-programmes

variables i, j, k
... | MIPS : on suppose que
k ← mult(i,j) # mult = algorithme paramétré | « mult » est le label
j ← mult(k,k) # qui « renvoie » un résultat | d'un code
i ← i + j # | effectuant la multiplication

Problèmes :
— comment passer des arguments
— comment récupérer le résultat
— à la fin de l’exécution de « mult », vers quelle adresse faire le saut de « retour » ? (dépend de l’adresse
du saut « aller »)
— mult peut modifier le contenu des registres, or on a besoin de conserver la valeur de i pour l’addition
finale

saut vers un sous-programme

1012 jal label # jal : 1. place l'adresse de retour (1016) dans $ra
1016 ... # 2. place l'adresse « label » dans CP (i.e. saut)

jal : pour Jump And Link


Signifie : enregistre l’adresse de l’instruction suivante dans $ra ($31) puis
Le saut de « retour », à la fin de la procédure mult, utilise :

jr $ra

Arguments et valeur de retour : conventions de registres


Adresse de retour $ra
Arguments $a0, $a1, $a2, $a3
Valeur(s) de retour $v0, $v1
Registres sauvegardés $s0, $s1 ... $s7

Exemple :

algo somme(i,j) : | programme principal :


retourne (i + j) | calcule : somme(1,2) + somme(3,4) → $v0

somme: add $v0, $a0, $a1 main:


jr $ra addi $a0, $0, 1 # arg.1 = 1
addi $a1, $0, 2 # arg.2 = 2
jal somme # somme(1,2) → $v0
add $s0, $0, $v0 # $v0 → $s0
addi $a0, $0, 3 # arg.1 = 3
addi $a1, $0, 4 # arg.2 = 4
jal somme # somme(3,4) → $v0
addi $v0, $s0, $v0 # $s0 + $v0 → $v0
Sous-programmes imbriqués Exemple : mult récursif :
mrec: bne $a1, $0, jpos
algo mrec(i,j) : add $v0, $0, $0 # si $a1 = 0, retourner 0
si j = 0, retourner 0 jr $ra
sinon, jpos: addi $a1, $a1, -1 #
retourner : jal mrec # mrec(i,j-1) → $v0
mrec(i, j-1) + i ret: add $v0, $v0, $a0 # $v0 + i → $v0
jr $ra

— L’adresse de retour de l’appel initial de mrec a été placée dans $ra, mais cette valeur va être écrasée
par l’adresse ret dès le premier appel récursif.
— Il est donc nécessaire de sauvegarder l’adresse de retour de mrec avant l’appel récursif.

Utilisation de la pile

Allocation mémoire Pile


Adresses
$sp → 7fff ffffhex ...
pile = stack hautes
argument 6
argument 5
$fp →
Registres La pile
$gp → 1000 8000hex Sauvegardés croît
static = .data
1000 0000hex
.text Variables
pc → 0040 0000hex Locales
Réservée $sp →
Adresses
basses
— Un registre dédié $sp qui pointe toujours vers le dernier espace utilisé de la mémoire
— Pour utiliser la pile, on décrémente ce registre du nombre d’octets nécessaires au stockage des
informations que l’on veut sauvegarder
— Les arguments d’un sous-programme peuvent être placés sur le haut de la pile avant l’« appel » (si
$a0, $a1, $a2 et $a3 ne suffisent pas, ou ne conviennent pas, par exemple quand les arguments ne
sont pas des mots de 32 bits)
— A la sortie d’un sous-programme, celui-ci peut placer sa valeur de retour au sommet de la pile de
l’appelant, si $v0 et $v1 ne suffisent pas ou ne conviennent pas
— A la sortie d’un sous-programme, celui-ci doit restituer les valeurs de tous les registres sauvegardés
($s0 à $s7, ainsi que $sp) à l’appelant, telles qu’elles étaient à l’entrée

mrec: addi $sp, $sp, -4 # empiler $ra jpos: addi $a1, $a1, -1 #
sw $ra, 0($sp) jal mrec # mrec(i,j-1)
bne $a1, $0, jpos add $v0, $v0, $a0 # $v0 + i
add $v0, $0, $0 # si $a1 = 0, ret: lw $ra, 0($sp) # dépiler $ra
j ret # aller en ret addi $sp, $sp, 4 # restituer $sp
jr $ra

Exercice 6. (a) implanter une factorielle récursive,


(b) f (0) = 0, f (1) = 1, f (i)i≥2 = f (i − 2) + f (i − 1)

You might also like