# Assembleur
pour assembler un fichier:
- depuis ce dossier
  `cargo run --release -p asm fichierentre [fichiersortie]`
- depuis le sous dossier asm
  `cargo run --release fichierentre [fichiersortie]`

syntaxe supplémentaire supportée:
- `let rx label`
  assigne l'adresse de label a rx
- `D valeur`
  rentre la donné brute égale à la valeur (immédiate ou addresse de label)
  (pour mettre des données dans le fichier et pas du code executable)
- `eint` Active les interruptions
- `dint` Desactive les interruptions
- `swi`  Active l'interruption swi
- `reti` Retourne depuis le handler d'interruption
- `umull` multiplication non signée usuelle
- `umulh` multiplication non signée, moitié haute du résultat 64 bits
- `smull` et `sumlh` versions signée de la multiplication
- `div`   division non signée
- `mod`   modulo non signé

# Simulateur
## pour lancer la simulation:
- depuis ce dossier
 `cargo run --release -p simu fichierentre`
- depuis le sous dossier simu
  `cargo run --release fichierentre`

Pour rajouter le support de multiplication/division: rajouter --features=div_mul

### instruction spéciale:
halt (jump 0) met le programme en pause, mais on peut se reveiller par des interuptions
call 0 termine l'exécution du simulateur

## mmio:
- 0x01000000 à 0x0112c000 : Écran en lecture/écriture. un pixel par 32bits, de gauche a droite puis de bas en haut.
Format de pixel en 0BGR, 4 bits par couleur.
Passage au format RGBA (a pour alpha) avec la feature rgba
- 0x01200000 : Clavier (scancode) (lecture seule)
- 0x01200004 : Horloge (millisecondes écoulé depuis le début de la simulation, wrappe tout les 49 jours) (lecture seule)
- 0x01200008 : Boutons de la souris (OR des boutons préssés)  Gauche = 1, Droit=2, Clic Molette = 3, Autres non testé (lecture seule)
- 0x0120000c : Position horizontale de la souris (en pixels, -1 si hors de l'écran) (lecture seule)
- 0x01200010 : Position verticale de la souris (en pixels, -1 si hors de l'écran) (lecture seule)
- 0x01201000 : Activation des Interupts de MMIO. Remis a zero par `dint`. Attention, Écrire ici sans activer les interruptions va bloquer les intéruptions et l'affichage (écriture seule)

## Interuptions:
Si les interruptions sont activées (avec eint), qu'il y a une raison de faire une interruption,
et qu'on n'est pas déjà dans une routine d'interruption de priorité >=,
alors le cpu effectue les actions suivantes:

Finis l'instruction en cours si c'est une interruption externe
si interruption a des arguments, les mets dans les registres par ordre croissant,
Mets PC a (priorité de l'intéruption)*4 (instruction n°priorité)

Cela veut dire que votre début de programme, si vous voulez utiliser les interruption, doit être une table de jump vers les handler correspondant

Pour sortir d'une interuption, utilisez `reti`
*Il FAUT sortir avec un reti*

*Les interuptions utilisent la stack, donc lorsque les interuptions sont activés, il est interdit de stocker des information au dessus du pointeur de stack.
de même, `reti` ne peut pas être appellé par une sous fonction appellée depuis l'interrupt handler*

Les intéruptions et leurs arguments, par priorité croissante:
### 0: Point d'entrée
  C'est ici que le programme commence. Seul cas d'utilisation
### 1: MMIO
  Doivent être activé par le MMIO a l'adresse 0x01201000, en y écrivant le OR des (1<<identifiant)
  On toujours pour argument (r0) leur identifiant
  Les mmio corespondant sont modifié avant d'entrer dans l'intéruption, et TOUT LES MMIO d'une interuption active sont bloqués tant qu'on n'est pas sorti
  - 1 : Clavier
  - 2 : Boutons de la souris
  - 3 : Mouvements de la souris
  - 4 : Écran (rien n'est modifié, attend la sortie de l'intéruption pour afficher une frame)
### 2: SWI
  Pas d'argument

### 3: Division par zero
  2 arguments: numéro de registre de sortie et valeur du dividende.
  lors de l'appel a reti, attend que r0 n'ai pas été modifié et un retour dans r1.
  la registre de destination prend la valeur retourné dans r1
### 4: Load/Store illégal
  Un load store a été fait a une adresse non multiple de 4
  3 aruments:
  si c'est un load:  0, addresse, numéro de registre de retour
  si c'est un store: 1, addresse, valeure a stocker
  ne modifiez pas r0, et dans le cas des load, r2. (ou restaurez avant le reti)
  Si c'est un load, le registre destination prendra la valeur de retour, attendue dans r1
### 5: Unsupported Opcode
  Une division multiplication alors qu'elle ne sont pas activées
  4 arguments:
  indice de registre de retour, argument 1, argument 2, fonction
  Même mode de retour que la division par zero
### 6: Instruction Illégale
  Une instruction non légale, ou un load / store a une adresse non mappé.
  1 argument: l'opcode de l'instruction associé
  Il est fortement recommendé d'utiliser cette intéruption pour afficher du debug, puis de quitter le programme, mais il est possible
  de continuer a l'instruction suivante à l'aide d'un `reti`
