diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/alu.c | 22 | ||||
-rw-r--r-- | lib/archi.c | 349 | ||||
-rw-r--r-- | lib/interne.c | 94 | ||||
-rw-r--r-- | lib/memoire.c | 33 | ||||
-rw-r--r-- | lib/registre.c | 166 |
5 files changed, 664 insertions, 0 deletions
diff --git a/lib/alu.c b/lib/alu.c new file mode 100644 index 0000000..b394b09 --- /dev/null +++ b/lib/alu.c @@ -0,0 +1,22 @@ +#include "alu.h"
+ +// rajouter les overflow... +
+/*****************************************/
+/** **/
+/** GESTION DE L'UNITE DE CALCUL **/
+/** **/
+/*****************************************/
+
+Uint32 AdditionNonSigne(Uint32 a, Uint32 b) { return (a + b); }
+Uint32 AdditionSigne(Uint32 a, Uint32 b) { return (a + b); }
+Uint32 SoustractionNonSigne(Uint32 a, Uint32 b) { return (a - b); }
+Uint32 SoustractionSigne(Uint32 a, Uint32 b) { return (a - b); }
+Uint32 MultiplicationNonSigne(Uint32 a, Uint32 b) { return (a * b); }
+Uint32 MultiplicationSigne(Uint32 a, Uint32 b) { return (a * b); }
+Uint32 DivisionNonSigne(Uint32 a, Uint32 b) { return (a / b); }
+Uint32 DivisionSigne(Uint32 a, Uint32 b) { return (a / b); }
+Uint32 AND(Uint32 a, Uint32 b) { return (a & b); }
+Uint32 OR(Uint32 a, Uint32 b) { return (a | b); }
+Uint32 SHL(Uint32 a) { return (a >> 1); }
+Uint32 SHR(Uint32 a) { return (a << 1); }
diff --git a/lib/archi.c b/lib/archi.c new file mode 100644 index 0000000..cb8bb4a --- /dev/null +++ b/lib/archi.c @@ -0,0 +1,349 @@ +#include <stdio.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif + +#include "alu.h" +#include "registre.h" +#include "memoire.h" +#include "fpu.h" + + + + +// a modifier : Adresse switch 0 c faux +// CALL RET ??? +// verifier le reste + +// initialisation de la MP avec un malloc +// fermeture du prog et free +// catch du ctrl-c + +Uint32 LireInstruction(void) +{ + return (LD(LireRegistrePC())); +} + +void IncrementeCompteurOrdinal(void) +{ + EcrireRegistrePC(AdditionNonSigne(LireRegistrePC(), 1)); +} + +Uint32 Adresse(Uint32 u, Uint32 instruction) +{ + switch (champ(u, 2)) { + case 0: + return (LireRegistre(Champ3(instruction))); /* directement registre A CORRIGER */ + case 1: + IncrementeCompteurOrdinal(); + return (LireInstruction()); + case 2: + return (LireRegistre(Champ3(instruction))); /* Adresse dans registre */ + case 3: + IncrementeCompteurOrdinal(); + return (LireRegistre(Champ3(instruction)) + LireInstruction()); /* Adresse dans registre + decalage de nouvelle instruction */ + default: /* Il exige une loge... */ + return (0); + } +} + +void Initialisation(void) +{ + int i; + + Reset(&Err_Mem); + Reset(&Err_Reg); + for (i = 0; i < TAILLE_MEMOIRE; i++) + Reset(&memoire_principale[i]); + EcrireRegistrePP(ADD_PP); +} + +void Decode(Uint32 instruction) +{ + Uint32 champ_registre_resultat, val1, val2, resultat; + + if (Opcode(instruction) & 0x80) { + fpu(Opcode(instruction)); + } else { + switch (Opcode(instruction)) { + case (0 || 1 || 2 || 3 || 4 || 5):{ + /* ALU */ + champ_registre_resultat = Champ1(instruction); /* Champ du registre dans lequel va etre stocké le résultat */ + val1 = LireRegistre(Champ2(instruction)); /* Premier entier qui va etre utilisé dans l'opération */ + if (ValeurBit(Extension(instruction), 0) == 0) + val2 = LireRegistre(Champ3(instruction)); /* Deuxième entier, stocké dans un registre, qui va etre utilisé dans l'opération */ + else { + IncrementeCompteurOrdinal(); + val2 = LireInstruction(); /* Deuxième entier, stocké après l'instruction, qui va etre utilisé dans l'opération */ + } + if (ValeurBit(Extension(instruction), 1) == 0) /* Teste si l'opération est signée ou pas */ + switch (Opcode(instruction)) { + case 0: + resultat = AdditionNonSigne(val1, val2); + break; + case 1: + resultat = SoustractionNonSigne(val1, val2); + break; + case 2: + resultat = MultiplicationNonSigne(val1, val2); + break; + case 3: + resultat = DivisionNonSigne(val1, val2); + break; + case 4: + resultat = AND(val1, val2); + break; + case 5: + resultat = OR(val1, val2); + break; + case 6: + resultat = SHL(val1); + break; + case 7: + resultat = SHR(val1); + break; + } else + switch (Opcode(instruction)) { + case 0: + resultat = AdditionSigne(val1, val2); + break; + case 1: + resultat = SoustractionSigne(val1, val2); + break; + case 2: + resultat = MultiplicationSigne(val1, val2); + break; + case 3: + resultat = DivisionSigne(val1, val2); + break; + case 4: + resultat = AND(val1, val2); + break; + case 5: + resultat = OR(val1, val2); + break; + case 6: + resultat = SHL(val1); + break; + case 7: + resultat = SHR(val1); + break; + } + EcrireRegistre(champ_registre_resultat, resultat); /* On écrit le résultat dans le registre de sortie */ + break; + } + case 8:{ /* MOV <=> il exige une loge en losange ou la sauje jonche les sieges */ + if (ValeurBit(Extension(instruction), 4) == 1) /* MOV conditionnel */ + if (ValeurBit(Extension(instruction), 5) == 0) /* Test normal */ + switch (champ(Extension(instruction) >> 2, 4)) { /* teste les bits 2 et 3 */ + case 0: + if (Overflow() == 1) + goto fin; + case 1: + if (Zero() == 1) + goto fin; + case 2: + if (Sign() == 1) + goto fin; + case 3: + if (Parity() == 1) + goto fin; + } else /* Negation du test */ + switch (champ(Extension(instruction) >> 2, 4)) { /* teste les bits 2 et 3 */ + case 0: + if (Overflow() == 0) + goto fin; + case 1: + if (Zero() == 0) + goto fin; + case 2: + if (Sign() == 0) + goto fin; + case 3: + if (Parity() == 0) + goto fin; + } + /* Pas de MOV conditionnel */ + if (ValeurBit(Extension(instruction), 1) == 0) /* Mov arg1 arg2 */ + if (ValeurBit(Extension(instruction), 0) == 0) /* arg2 = reg */ + EcrireRegistre(Champ1(instruction), LireRegistre(Champ2(instruction))); + else /* arg2 = imm32 */ if (champ(Champ2(instruction), 4) == 0) + EcrireRegistre(Champ1(instruction), + Adresse(Champ2(instruction), instruction)); + else + EcrireRegistre(Champ1(instruction), + LD(Adresse(Champ2(instruction), instruction))); + else /* Mov arg2 arg1 */ if (ValeurBit(Extension(instruction), 0) == 0) /* arg2 = reg */ + EcrireRegistre(Champ2(instruction), LireRegistre(Champ1(instruction))); + else /* arg1 = imm32 */ if (champ(Champ2(instruction), 4) == 0) + ST(Adresse(Champ2(instruction), instruction), + LireRegistre(Champ1(instruction))); + else + ST(Adresse(Champ2(instruction), instruction), + LireRegistre(Champ1(instruction))); + fin: + break; + } + case 9:{ /* NOP */ + /* Instruction nulle */ + break; + } + case 10: /* J */ + case 11:{ + int test1, test2; + + switch (champ(Extension(instruction), 4)) { + case 0: + test1 = LireRegistre(Champ1(instruction)) == LireRegistre(Champ2(instruction)); + break; + case 1: + test1 = LireRegistre(Champ1(instruction)) != LireRegistre(Champ2(instruction)); + break; + case 2: + test1 = LireRegistre(Champ1(instruction)) < LireRegistre(Champ2(instruction)); + break; + case 3: + test1 = LireRegistre(Champ1(instruction)) <= LireRegistre(Champ2(instruction)); + break; + } + switch (champ(Extension(instruction) >> 2, 4)) { + case 0: + test2 = Overflow(); + break; + case 1: + test2 = Zero(); + break; + case 2: + test2 = Sign(); + break; + case 3: + test2 = Parity(); + break; + } + switch (champ(Extension(instruction) >> 4, 4)) { + case 0: + test1 = test1; + break; + case 1: + test1 = test1 || test2; + break; + case 2: + test1 = test1 && !test2; + break; + case 3: + test1 = test1 || !test2; + break; + } + if (test1) { + IncrementeCompteurOrdinal(); + if (Opcode(instruction) == 10) + EcrireRegistrePC(LireInstruction()); + else + EcrireRegistrePC(AdditionNonSigne(LireRegistrePC(), LireInstruction())); + } + break; + } + case (12): /* JMP *//* Kris Kross */ + case (13): + if (ValeurBit(Extension(instruction), 0) == 0) { + ; /* RET */ + } else if (ValeurBit(Extension(instruction), 1) == 0) ; /* JMP */ + else; /* CALL */ + + break; + case 14:{ /* PUSH */ + Uint32 val; /* valeur qui va etre stockée */ + + EcrireRegistrePP(SoustractionNonSigne(LireRegistrePP(), 1)); /* On pointe sur un emplacement vide */ + if (ValeurBit(Extension(instruction), 0) == 0) + val = LireRegistre(Champ1(instruction)); + else { + IncrementeCompteurOrdinal(); + val = LireInstruction(); + } + ST(LireRegistrePP(), val); + break; + } + case 15:{ /* POP */ + EcrireRegistre(Champ1(instruction), LireRegistrePP()); + EcrireRegistrePP(AdditionNonSigne(LireRegistrePP(), 1)); + break; + } + case 127:{ /* HALT-RESET */ + if (ValeurBit(Extension(instruction), 0)) + getc(stdin); /* Halt */ + else + Initialisation(); /* Reset */ + break; + } + default:{ + printf("soja"); + } + } + } +} +void Traitement(void) +{ + Uint32 instruction; + + while (!0) { + instruction = LireInstruction(); + Decode(instruction); + IncrementeCompteurOrdinal(); + } +} + +void Debogueur(void) // transformer en affiche reg +{ + int i,j; + +/* gotoxy(1, 1); + printf("Etat des registres classiques Etat des registres"); + gotoxy(1, 2); + printf(" speciaux "); + gotoxy(1, 11); + printf(" Instruction a decoder"); + gotoxy(1, 14); + printf(" Prochaine instruction"); + for (i = 1; i <= 16; i++) { + gotoxy(1, i + 2); + printf("r%2d:%9d", i - 1, registre[i - 1]); + } + for (i = 17; i <= 32; i++) { + gotoxy(17, i - 16 + 2); + printf("r%2d:%9d", i - 1, registre[i - 1]); + } + gotoxy(40, 4); + printf("Rg :%9d", LireRegistreRG()); + gotoxy(40, 5); + printf("Rd :%9d", LireRegistreRD()); + gotoxy(40, 6); + printf("PC :%9d", LireRegistrePC()); + gotoxy(40, 7); + printf("Flag :%9d", LireRegistreFLAG()); + gotoxy(40, 12); + printf(" %9d", LireInstruction()); + registre[REG_PC]++; + gotoxy(40, 15); + printf(" %9d", LireInstruction()); + registre[REG_PC]--; + getc(stdin); +*/ + for (i=0; i<=3; i++) { + for (j=1; j<=8;j++) { + printf(" R%02d ", (i*8+j)); + } + printf("\n"); + for (j=1; j<=8;j++) { + printf("%08lX ", (registre[i*8+j-1])); + } + printf("\n"); + + } + printf("Rg: %08lX | Rd: %08lX | Flag: %08lX | PC: %08lX\n", LireRegistreRG(), LireRegistreRD(), LireRegistreFLAG(),registre[REG_PC]); + printf("\n"); +} + diff --git a/lib/interne.c b/lib/interne.c new file mode 100644 index 0000000..bdab97e --- /dev/null +++ b/lib/interne.c @@ -0,0 +1,94 @@ +#include <stdio.h> +#include "interne.h" +#include "archi.h" + +// mettre des exceptions dans les fcns ci dessous a la place de GestionErreurs + +void GestionErreurs(void) +{ +} + +void Reset(Uint32 * i) +{ /* met tous les bits d'un mot à zéro */ + *i &= 0; +} /* Ok */ + +void Set(Uint32 * i) +{ /* met le bit de poids faible à 1 */ + *i &= 1; +} /* Ok */ + +/* Met le bit 'position' à zéro */ +void ResetBit(Uint32 * i, int position) +{ + if (position < 0 || position > 31) { + GestionErreurs(); + } else { + Uint32 aux = VAL_MAX - (1 << position); + + *i &= aux; + } +} /* Ok */ + +/* Met le bit 'position' à un */ +void SetBit(Uint32 * i, int position) +{ + if (position < 0 || position > 31) { + GestionErreurs(); + } else { + Uint32 aux = 1 << position; + + *i |= aux; + } +} /* Ok */ + +/* Donne la valeur du bit 'position' */ +int ValeurBit(Uint32 nombre, int position) +{ + if (position < 0 || position > 31) { + GestionErreurs(); + return (-1); + } + return ((nombre >> position) & 1); +} /* Ok */ + +/* Affiche tous les bits d'un mot */ +void Uint32toBin(Uint32 i) +{ + int k; + + for (k = 31; k >= 0; k--) + printf("%d", ValeurBit(i, k)); + printf("\n"); +} /* Ok */ + +/* Extrait un champ dans un mot */ +Uint32 champ(Uint32 nombre, int taille) +{ + return (nombre & (taille - 1)); +} /* Ok */ + +Uint32 Opcode(Uint32 ins) +{ + return (champ(ins >> 0, 256)); +} /* Ok */ + +Uint32 Extension(Uint32 ins) +{ + return (champ(ins >> 8, 64)); +} /* Ok */ + +Uint32 Champ1(Uint32 ins) +{ + return (champ(ins >> 14, 64)); +} /* Ok */ + +Uint32 Champ2(Uint32 ins) +{ + return (champ(ins >> 20, 64)); +} /* Ok */ + +Uint32 Champ3(Uint32 ins) +{ + return (champ(ins >> 26, 64)); +} /* Ok */ diff --git a/lib/memoire.c b/lib/memoire.c new file mode 100644 index 0000000..c8dd6a4 --- /dev/null +++ b/lib/memoire.c @@ -0,0 +1,33 @@ +#include "memoire.h" +#include "interne.h" +#include "archi.h" + +/*****************************************/ +/** **/ +/** GESTION DE LA MEMOIRE PRINCIPALE **/ +/** **/ +/*****************************************/ + +/* Lit le mot qui se trouve à l'offset 'offset' en mémoire */ +Uint32 LD(Uint32 offset) +{ + Uint32 i; + + Reset(&i); + if (offset < 0 || offset >= TAILLE_MEMOIRE) { + Set(&Err_Mem); + return (i); + } else { + i = memoire_principale[offset]; + return (i); + } +} + +/* Ecrit le mot 'valeur' à l'offset 'offset' en mémoire */ +void ST(Uint32 offset, Uint32 valeur) +{ + if (offset < 0 || offset >= TAILLE_MEMOIRE) + Set(&Err_Mem); + else + memoire_principale[offset] = valeur; +} diff --git a/lib/registre.c b/lib/registre.c new file mode 100644 index 0000000..f97595d --- /dev/null +++ b/lib/registre.c @@ -0,0 +1,166 @@ +#include "registre.h" +#include "interne.h" +#include "archi.h" + +/*****************************************/ +/** **/ +/** GESTION DES REGISTRES **/ +/** **/ +/*****************************************/ + +Uint32 LireRegistreRG(void) +{ + return (registre[REG_RG]); +} + +Uint32 LireRegistreRD(void) +{ + return (registre[REG_RD]); +} + +Uint32 LireRegistrePC(void) +{ + return (registre[REG_PC]); +} + +Uint32 LireRegistreFLAG(void) +{ + return (registre[REG_FLAG]); +} + +Uint32 LireRegistrePP(void) +{ + return (registre[REG_PUSHPOP]); +} + +void EcrireRegistreRG(Uint32 val) +{ + registre[REG_RG] = val; +} + +void EcrireRegistreRD(Uint32 val) +{ + registre[REG_RD] = val; +} + +void EcrireRegistrePC(Uint32 val) +{ + registre[REG_PC] = val; +} + +void EcrireRegistreFLAG(Uint32 val) +{ + registre[REG_FLAG] = val; +} + +void EcrireRegistrePP(Uint32 val) +{ + registre[REG_PUSHPOP] = val; +} + +/* Lit le mot qui se trouve dans le registre 'numero_registre' */ +Uint32 LireRegistre(Uint32 champ_registre) +{ + Uint32 i; + + if (ValeurBit(champ_registre, 5) == 0) { /* Test du bit S */ + Reset(&i); + if (champ_registre < 0 || champ_registre >= NB_REGISTRES_UTILISABLES) { /* Si on voudrait diminuer le nombre de registres */ + Set(&Err_Reg); /* Il n'y a que 32 registres */ + return (i); + } + i = registre[champ_registre]; /* Registre classique */ + return (i); + } else /* Registre spécial */ + switch (champ(champ_registre, 4)) { + case 0: + return (LireRegistreRG()); + case 1: + return (LireRegistreRD()); + case 2: + return (LireRegistrePC()); + case 3: + return (LireRegistreFLAG()); + default:{ + Set(&Err_Reg); + return (0); + } + } +} + +/* Ecrit le mot 'valeur' dans le registre 'numero_registre' */ +void EcrireRegistre(Uint32 champ_registre, Uint32 valeur) +{ + Uint32 i; + + if (ValeurBit(champ_registre, 5) == 0) { /* Test du bit S */ + Reset(&i); + if (champ_registre < 0 || champ_registre >= NB_REGISTRES_UTILISABLES) + Set(&Err_Reg); /* Il n'y a que 32 registres */ + else + registre[champ_registre] = valeur; /* Registre classique */ + } else /* Registre spécial */ + switch (champ(champ_registre, 4)) { + case 0: + EcrireRegistreRG(valeur); + case 1: + EcrireRegistreRD(valeur); + case 2: + EcrireRegistrePC(valeur); + case 3: + EcrireRegistreFLAG(valeur); + default: + Set(&Err_Reg); + } +} + +int Overflow(void) +{ + return (ValeurBit(LireRegistreFLAG(), 0)); +} +int Zero(void) +{ + return (ValeurBit(LireRegistreFLAG(), 1)); +} +int Sign(void) +{ + return (ValeurBit(LireRegistreFLAG(), 2)); +} +int Parity(void) +{ + return (ValeurBit(LireRegistreFLAG(), 3)); +} + +void SetOverflow(void) +{ + registre[REG_FLAG] |= 1; +} +void SetZero(void) +{ + registre[REG_FLAG] |= 2; +} +void SetSign(void) +{ + registre[REG_FLAG] |= 4; +} +void SetParity(void) +{ + registre[REG_FLAG] |= 8; +} + +void ResetOverflow(void) +{ + registre[REG_FLAG] &= (VAL_MAX - 1); +} +void ResetZero(void) +{ + registre[REG_FLAG] &= (VAL_MAX - 2); +} +void ResetSign(void) +{ + registre[REG_FLAG] &= (VAL_MAX - 4); +} +void ResetParity(void) +{ + registre[REG_FLAG] &= (VAL_MAX - 8); +} |