#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" #include "linker.h" /* initialisation de la MP avec un malloc fermeture du prog et free catch du ctrl-c */ int HasToRun = 1, HasToReset; Uint32 base_addr = 0; Uint32 LireInstruction(void) { return (LD(LireRegistrePC())); } void IncrementeCompteurOrdinal(void) { EcrireRegistrePC(AdditionNonSigne(LireRegistrePC(), 1)); } Uint32 Adresse(Uint32 u, Uint32 instruction) { Uint32 tmp; switch (champ(u, 2)) { case 0: exception(1, _("Adresse: Call With Invalid r/m Field State ( r/m=00 )")); return (0); case 1: tmp = LireInstruction(); IncrementeCompteurOrdinal(); return (tmp); case 2: return (LireRegistre(Champ3(instruction))); /* Adresse dans registre */ case 3: tmp = LireRegistre(Champ3(instruction)) + LireInstruction(); /* Adresse dans registre + decalage de nouvelle instruction */ IncrementeCompteurOrdinal(); return (tmp); default: exception(1, _("Adresse: Unmatched Addr Field")); return (0); } } void Initialisation(void) { int i; for (i = 0; i < TAILLE_MEMOIRE; i++) Reset(&memoire_principale[i]); InitRegistres(); /* initialisation des registres */ EcrireRegistreSP(ADD_SP); /* initialisation du stack pointer */ } void DecodeExec(Uint32 instruction, Uint32 entrypoint) { Uint32 champ_registre_resultat, val1, val2, resultat; int test1, test2; Uint32 val; /* valeur qui va etre stockée */ if (Opcode(instruction) & 0x80) { fpu(Opcode(instruction)); } else { switch (Opcode(instruction)) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: /* 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 (Opcode(instruction) < 6) { 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 { val2 = LireInstruction(); /* Deuxième entier, stocké après l'instruction, qui va etre utilisé dans l'opération */ IncrementeCompteurOrdinal(); } } 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; } } if ((Opcode(instruction) & 2) && !(Opcode(instruction & 3))) { EcrireRegistreRG(resultat); EcrireRegistreRD(SecondResult); } else { 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[cond] */ case 11: switch (champ(Extension(instruction), 4)) { case 0: if (Champ1(instruction) == Champ2(instruction)) { test1 = 1; } else { 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) { Uint32 tmp; tmp = LireInstruction(); if (Opcode(instruction) & 1) { tmp += LireRegistrePC(); } EcrireRegistrePC(tmp); } break; case 12: /* JMP */ case 13: if (ValeurBit(Extension(instruction), 0) == 0) { /* RET */ EcrireRegistreSP(AdditionNonSigne(LireRegistreSP(), Champ1(instruction))); EcrireRegistreSP(AdditionNonSigne(LireRegistreSP(), 1)); EcrireRegistrePC(LD(LireRegistreSP())); } else if (ValeurBit(Extension(instruction), 1) == 0) { /* JMP */ if (ValeurBit(Extension(instruction), 2) == 0) { EcrireRegistrePC(LireRegistre(Champ1(instruction))); } else { EcrireRegistrePC(LireInstruction()); } } else { /* CALL */ ST(LireRegistreSP(), LireRegistrePC()); EcrireRegistreSP(SoustractionNonSigne(LireRegistreSP(), 1)); if (ValeurBit(Extension(instruction), 2) == 0) { EcrireRegistrePC(LireRegistre(Champ1(instruction))); } else { EcrireRegistrePC(LireInstruction()); } } break; case 14: /* PUSH */ if (ValeurBit(Extension(instruction), 0) == 0) val = LireRegistre(Champ1(instruction)); else { val = LireInstruction(); IncrementeCompteurOrdinal(); } ST(LireRegistreSP(), val); EcrireRegistreSP(SoustractionNonSigne(LireRegistreSP(), 1)); break; case 15: /* POP */ EcrireRegistreSP(AdditionNonSigne(LireRegistreSP(), 1)); EcrireRegistre(Champ1(instruction), LD(LireRegistreSP())); break; case 127: /* HALT-RESET */ if (ValeurBit(Extension(instruction), 0)) { HasToRun = 0; /* Halt */ } else { HasToReset = 1; /* Reset */ ResetRegistres(); } break; default: exception(1, _("DecodeExec: Invalid Opcode")); } } } void Traitement(Uint32 entrypoint) { /* ******************** FIXMI ************************* */ Uint32 instruction; while (HasToRun) { EcrireRegistrePC(entrypoint); HasToRun = 1; HasToReset = 0; while ((HasToRun) && (!HasToReset)) { instruction = LireInstruction(); IncrementeCompteurOrdinal(); DecodeExec(instruction, entrypoint); } } } 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(); } void ChargeBinaire(char * filename) { FILE * file; char message[BUFSIZ]; Uint32 entrypoint, nb, ns, nbss, nr; Uint32 * relocation_table; int i; file = openfilereading(filename); if (readword(file)==0x58454e4e) { /*verification de la signature*/ sprintf(message,_("Total Size Of The Binary File: %d"),readword(file)); pushcontext(message); nb=readword(file); /* taille du segment text */ ns=readword(file); /* taille des donnes statiques */ nbss=readword(file); /* taille des donnees non init */ nr=readword(file); /* taille de la table de relogement */ relocation_table=Emalloc(nr); for (i=0;i