#include #ifdef HAVE_CONFIG_H #include "config.h" #else #define _(x) x #endif #include "alu.h" #include "simulator.h" #include "interne.h" #include "registre.h" #include "memoire.h" #include "fpu.h" #include "exceptions.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: exception(1, _("Adresse: Unmatched Addr Field")); } } void Initialisation(void) { int i; 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 */ 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 */ if (champ(Champ1(instruction), 2) == 0) {/* r/m de arg1 = 0 */ EcrireRegistre(Champ3(instruction), LireRegistre(Champ2(instruction))); } else { ST(Adresse(Champ1(instruction), instruction), LireRegistre(Champ2(instruction))); } } else {/* arg2 = imm32 */ if (champ(Champ1(instruction), 2) == 0) { /* r/m de arg1 = 0 */ EcrireRegistre(Champ3(instruction), LireInstruction()); IncrementeCompteurOrdinal(); } else { ST(Adresse(Champ1(instruction), instruction), LireInstruction()); IncrementeCompteurOrdinal(); } } } else { if (ValeurBit(Extension(instruction), 0) == 0) {/* arg2 = reg */ if (champ(Champ1(instruction), 2) == 0) {/* r/m de arg1 = 0 */ EcrireRegistre(Champ2(instruction), LireRegistre(Champ3(instruction))); } else { EcrireRegistre(Champ2(instruction), LD(Adresse(Champ1(instruction), instruction))); } } else {/* arg2 = imm32 */ exception(1,_("MOV: Memory to Memory Forbidden On This Type Of Processor")); } } 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 AfficheReg(void) // affiche reg { int i, j; 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");} void Debogueur(void) { AfficheReg();}