#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 */ 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 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(); }