J'ai avancé dans mon assembleur. C'est une grosse escroquerie ce truc, franchement si ça marche on peut me décerner la palme du bourrin
En fait le truc c'est que mon jeu d'instructions est tellement minimal qu'il n'est vraiment pas orthogonal. Prenons une instruction CPU bien pourrie: le branchement conditionnel (B[xx] ra, rb, saut_relatif_si_succès avec xx code de condition). Déjà il y a pour 14 bits d'opérande (sur 16), donc seulement 3 pour l'offset de branchement, c'est-à-dire [-4 .. +3].
Maintenant j'écris ceci:
:a
BRA :b
MOV r0, 0
BNE r0, 0, :a
:b
NOP
Le machin va me générer cela (il va mettre le 0 dans un registre, at, car BNE s'attend à ça seulement):
0000 BRA 3 ; @0008
0002 MOV r0, 0
0004 MOV at, 0
0006 BNE r0, at, -4 ; @0000
0008 NOP
Mais remplaçons bêtement le MOV r0, 0 par MOV r0, -1, qui ne peut plus être fait en une instruction:
0000 BRA 5 ; @000c
0002 MOV r0, 255 (-1)
0004 EXT r0
0006 MOV at, 0
0008 BEQ r0, at, 1 ; @000a
000a BRA -6 ; @0000
000c NOP
(pendant l'exécution d'une instruction, pc vaut 'adresse de l'instruction exécutée' + 2. BRA -6 équivaut à SUB pc, 12)
Cette fois le le BNE est remplacé par un BEQ (inverse) qui skippe un branchement standard pour revenir plus haut. En fait tout le code a bougé, puisque l'instruction devenant plus grande car le label n'était pas assez proche, tout le reste du code est décalé, et et d'autres sauts peuvent éventuellement devenir à leur tour trop gros et nécessiter des instructions supplémentaires.
Bref -> grosse boucle while (des trucs ont bougé) { génère du code en fonction des labels actuels et ajuste la position des labels en fonction du nouveau code } comme un méga bourrin, et si un jour ça bloque on remplacera par un for