diff --git a/miniCPU.c b/miniCPU.c
new file mode 100644
index 0000000000000000000000000000000000000000..e0adb3ae5897cf74cbea986bdfc00b23abbca929
--- /dev/null
+++ b/miniCPU.c
@@ -0,0 +1,549 @@
+/*
+ * -------------------------- TP du module Archi -------------------------
+ *
+ * ATTENTION : un outil de détection de plagiat logiciel sera utilisé lors de la correction, vous avez donc tout intérêt à effectuer un travail PERSONNEL
+ *
+ * Un mot/registre de NBITS bits (par défaut NBITS=16) est représenté par un tableau d'entiers égaux à 0 ou 1.
+ * Une ALU est représentée par une structure ALU, avec registre accumulateur et registre d'état.
+ * Un CPU (très très simplifié) est représenté par une ALU et quelques registres nécessaires pour stocker les résultats intermédiaires.
+ *
+ * Certaines fonctions vous sont fournies, d'autres sont à implanter ou à compléter, de préférence dans l'ordre où elles sont indiquées.
+ * Il vous est fortement conseillé de lire attentivement l'ensemble des commentaires.
+ *
+ * Parmi les opérations arithmétiques et logiques, seules 4 opérations de base sont directement fournies par l'ALU, les autres doivent être décrites comme des algorithmes
+ * travaillant à l'aide des opérateurs de base de l'ALU simplifiée et pouvant utiliser les registres du CPU.
+ *
+ * La fonction main() vous permet de tester au fur et à mesure les fonctions que vous implantez.
+ *
+ * ----------------------------------------------------------------------------------------------
+ *
+ * author: B. Girau
+ * version: 2021-22
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdbool.h>
+
+
+
+#define NBITS 8  // attention, votre programme doit pouvoir être adapté à d'autres tailles juste en modifiant la valeur de cette constante
+// en ayant toujours NBITS < 32
+
+/////////////////////////////////////////////////////////
+// définition de types
+/////////////////////////////////////////////////////////
+
+typedef struct {
+  int* accu;
+  int* flags; // indicateurs ZF CF OF NF
+} ALU;
+
+typedef struct {
+  ALU alu;
+  int* R0;
+  int* R1;
+  int* R2;
+} CPU;
+
+/////////////////////////////////////////////////////////
+// fonctions d'initialisation
+/////////////////////////////////////////////////////////
+
+/*
+ * allocation d'un mot entier de NBITS bits initialisé à 0
+ */
+int* word() {
+  int* tab;
+  int i;
+  tab=(int*)malloc(NBITS*sizeof(int));
+  for(i=0;i<NBITS;i++) tab[i]=0;
+  // poids faible : tab[0]
+  // poids fort : tab[NBITS-1]
+  return tab;
+}
+
+/*
+ * Initialisation du mot (mot de NBITS bits, codant un entier en Cà2) avec une valeur entière.
+ */
+void setValue(int* word,int n) {
+  int n_low = n & 0x7FFFFFFF;
+  // revient à mettre à 0 le bit de poids fort en 32 bits
+  // on peut alors travailler sur la partie positive du codage de n
+  // remarque : si n est bien codable en Ca2 sur NBITS, et si n est négatif, on récupère quand même le codage de n sur NBITS en Ca2 en prenant les NBITS de poids faible de n_low
+  
+  // à compléter
+  for (int a = 0; a < NBITS; ++a){
+    word[a] = 0;
+  }
+  int i = 0;
+  while(n_low != 0){
+    word[i] = n_low % 2;
+    n_low /= 2;
+    i +=1;  
+  }
+
+  int indice = 0;
+  if (n < 0){
+    for (int i = 0; i < NBITS; i++){
+      if (word[i] == 1){
+        indice = i;
+      }
+    }
+    for (int j = indice + 1; j < NBITS; ++j){
+      if(word[j] == 1){
+        word[j] = 0;
+      }else if(word[j] == 0){
+        word[j] = 1;
+      }
+    }
+  }
+  
+  
+}
+
+/*
+ * instanciation d'un mot de NBITS bits initialisé avec la valeur n
+ */
+int* initWord(int n) {
+  int* tab=word();
+  setValue(tab,n) ;
+  return tab;
+}
+    
+/*
+ * Initialisation du mot (mot de NBITS bits) par recopie des bits du mot en paramètre.
+ */
+void copyValue(int* word,int* src) {
+    // à compléter
+    for (int i =0; i < NBITS; ++i){
+      word[i] = src[i];
+    }
+}
+
+/*
+ * instanciation d'un mot de NBITS bits initialisé par recopie d'un mot
+ */
+int* copyWord(int* src) {
+  int* tab=word();
+  copyValue(tab,src) ;
+  return tab;
+}
+
+/*
+ * initialise l'ALU
+ */
+ALU initALU() {
+  ALU res;
+  res.accu=word();
+  res.flags=(int*)malloc(4*sizeof(int));
+  return res;
+}
+
+/*
+ * initialise le CPU
+ */
+CPU initCPU() {
+  CPU res;
+  res.alu=initALU();
+  res.R0=(int*)malloc(NBITS*sizeof(int));
+  res.R1=(int*)malloc(NBITS*sizeof(int));
+  res.R2=(int*)malloc(NBITS*sizeof(int));
+  return res;
+}
+
+/////////////////////////////////////////////////////////
+// fonctions de lecture
+/////////////////////////////////////////////////////////
+
+/*
+ * Retourne la valeur entière signée représentée par le mot (complément à 2).
+ */    
+int intValue(int* word) {
+    int res = 0;
+    int p = 1;
+    for(int i =0; i < NBITS - 1; ++i){
+      res += word[i] * p;
+       p *=2;
+    }
+    res += word[NBITS - 1] * (-p);
+    return res;
+}
+
+/*
+ * Retourne une chaîne de caractères décrivant les NBITS bits
+ */
+char* toString(int* word) {
+  int i,j=0;
+  char* s=(char*)malloc((2+NBITS)*sizeof(char));
+  for (i=NBITS-1;i>=0;i--) {
+    if (word[i]==1) s[j]='1';
+    else s[j]='0';
+    j++;
+  }
+  s[j]=0;
+  return s;
+}
+
+/*
+ * Retourne l'écriture des indicateurs associés à l'ALU.
+ */
+char* flagsToString(ALU alu) {
+  char *string=(char*)malloc(10*sizeof(char));
+  sprintf(string,"z%dc%do%dn%d",alu.flags[0],alu.flags[1],alu.flags[2],alu.flags[3]);
+  return string;
+}
+
+/*
+ * affiche à l'écran le contenu d'une ALU
+ */
+void printing(ALU alu) {
+    // à compléter
+    printf("ALU.acc =%s\nALU.flags =%s\n", toString(alu.accu), flagsToString(alu));
+}
+
+/////////////////////////////////////////////////////////
+// fonctions de manipulations élémentaires
+/////////////////////////////////////////////////////////
+
+/*
+ * Mise à la valeur b du bit spécifié dans le mot
+ */
+void set(int* word,int bitIndex,int b) {
+  if ((bitIndex > NBITS-1) || (bitIndex < 0)) 
+    printf("valeur d'index incorrecte\n");
+  word[bitIndex] = b ;
+}
+
+/*
+ * Retourne la valeur du bit spécifié dans le mot
+ */
+int get(int* word,int bitIndex) {
+  if ((bitIndex > NBITS-1) || (bitIndex < 0)) 
+    printf("valeur d'index incorrecte\n");
+  return word[bitIndex] ;
+}
+
+/*
+ * Positionne l'indicateur ZF en fonction de l'état de l'accumulateur
+ */
+void setZ(ALU alu) {
+  // à compléter
+  int i = 0;
+  while (i < NBITS && alu.accu[i] == 0){
+    i += 1;
+  }
+  if (i == NBITS){
+    set(alu.flags, 0, 1);
+  }else{
+    set(alu.flags, 0, 0);
+  }
+
+  // alu.flags[0] = (intValue(alu.accu) == 0)
+}
+
+/////////////////////////////////////////////////////////
+// opérateurs de base de l'ALU
+// IMPORTANT : les indicateurs doivent être mis à jour
+/////////////////////////////////////////////////////////
+
+/*
+ * Stocke le paramètre dans le registre accumulateur
+ */
+void pass(ALU alu,int* B) {
+  // à compléter
+  copyValue(alu.accu, B);
+  setZ(alu);
+  alu.flags[1] = 0; // pas de carry
+  alu.flags[2] = 0; // ni overflow
+  alu.flags[3] = alu.accu[NBITS - 1];
+}
+
+/*
+ * Effectue un NAND (NON-ET) entre le contenu de l'accumulateur et le paramètre.
+ */
+void nand(ALU alu,int* B) {
+  // à compléter
+  for (int i =0; i < NBITS; i++){
+    set(alu.accu, i, !(get(alu.accu, i) && get(B, i)));
+  }
+  setZ(alu);
+  alu.flags[1] = 0; // pas de carry
+  alu.flags[2] = 0; // ni overflow
+  alu.flags[3] = alu.accu[NBITS - 1];
+}
+
+/*
+ * Décale le contenu de l'accumulateur de 1 bit vers la droite
+ */
+void shift(ALU alu) {
+  int tab[NBITS];
+  copyValue(tab, alu.accu);
+  for (int i = NBITS - 2; i >= 0; i--) // bit poid faible indice 0
+  {
+    set(alu.accu, i, tab[i+1]); // le decalage a droite est equivalent au decalage a gauche du tableau
+  }
+  set(alu.accu, NBITS - 1, 0);  // La derniere case(poid fort) on rajoute ensuite un 0
+  setZ(alu);
+  alu.flags[1] = 0; // pas de carry
+  alu.flags[2] = 0; // ni overflow
+  alu.flags[3] = alu.accu[NBITS - 1];
+}
+
+/*
+ * module Full Adder : a+b+c_in = s + 2 c_out
+ * retourne un tableau contenant s et c_out
+ */
+int* fullAdder(int a,int b,int c_in) {
+  int* res=(int*)malloc(2*sizeof(int));
+  // à compléter
+  res[0] = (a + b + c_in) % 2; // elimine 2*c_out ms la valeur de s fixe car((0 ou 1) % 2 == 0 ou 1)
+  res[1] = (a+b+c_in - res[0]) / 2; // Module FA
+  return res;
+}
+
+/*
+ * Additionne le paramètre au contenu de l'accumulateur (addition entière Cà2).
+ * Les indicateurs sont positionnés conformément au résultat de l'opération.
+ */
+void add(ALU alu,int* B) {
+  // à compléter
+  int *res = (int*)malloc(2*sizeof(int));
+  int carry = 0;
+  for (int i =0; i < NBITS; i++){
+    res = fullAdder(get(alu.accu, i), get(B, i), carry);
+    set(alu.accu, i, res[0]);
+    carry = res[1]; 
+  }
+  setZ(alu);
+  alu.flags[1] = carry;
+  alu.flags[2] = (carry && alu.accu[NBITS - 1]); // on a un overflow si on a une carry et un bit à 1
+  alu.flags[3] = alu.accu[NBITS - 1];
+
+}
+
+////////////////////////////////////////////////////////////////////
+// Opérations logiques :
+////////////////////////////////////////////////////////////////////
+
+/*
+ * Négation.
+ */
+void not(CPU cpu){
+  // à compléter
+  nand(cpu.alu, cpu.alu.accu);
+}
+
+/*
+ * Et.
+ */
+void and(CPU cpu,int* B) {
+  // à compléter
+  nand(cpu.alu, B);
+  not(cpu); // ET == !!ET
+}
+
+
+/*
+ * Ou.
+ */
+void or(CPU cpu,int* B) {
+  for (int i =0; i < NBITS; ++i){
+    set(cpu.alu.accu, i, get(cpu.alu.accu, i) || get(B, i));
+  }
+}
+
+/*
+ * Xor.
+ */
+void xor(CPU cpu,int* B) {
+  for (int i =0; i < NBITS; ++i){
+    set(cpu.alu.accu, i, get(cpu.alu.accu, i) ^ get(B, i));
+  }
+}
+
+/*
+ * Décale le receveur de |n| positions.
+ * Le décalage s'effectue vers la gauche si n>0 vers la droite dans le cas contraire.
+ * C'est un décalage logique (pas de report du bit de signe dans les positions 
+ * libérées en cas de décalage à droite).
+ * L'indicateur CF est positionné avec le dernier bit "perdu".
+ */
+void logicalShift(CPU cpu,int n) {
+  // à compléter
+  int i = n;
+  while (i != 0){
+    if (n <= 0){
+      shift(cpu.alu);
+      ++i;
+    }else{
+      add(cpu.alu, cpu.alu.accu);
+      --i;
+    }
+  }
+}
+
+/////////////////////////////////////////////////////////
+// Opérations arithmétiques entières
+/////////////////////////////////////////////////////////
+
+/*
+ * Opposé.
+ */
+void opp(CPU cpu) {
+  // à compléter
+  for (int i = 0; i < NBITS; i++){
+    set(cpu.alu.accu, i, !get(cpu.alu.accu, i));
+  }
+}
+
+/*
+ * Soustraction.
+ */
+void sub(CPU cpu,int* B) {
+  // à compléter
+  int v = intValue(B);
+  int *tmp = (int*)malloc(sizeof(int));
+  setValue(tmp, -v);
+  add(cpu.alu, tmp); 
+}
+
+/*
+ * Multiplication.
+ */
+void mul(CPU cpu,int* B) {
+  // à compléter
+  int v = intValue(B); 
+  if (v < 0){
+    opp(cpu);   // si le B est negatif on fait l'opposé du contenu de cpu
+    v = -v;
+  }
+  for (int i =0; i < v; i++){
+    add(cpu.alu, cpu.alu.accu); // ensuite on additionne B fois la valeur du cpu avec lui meme
+  }
+}
+
+/////////////////////////////////////////////////////////
+// Programme de test
+/////////////////////////////////////////////////////////
+
+int main(int argc,char *argv[]) {
+  
+  /*
+    Ce programme est fourni à titre d'exemple pour permettre de tester simplement vos fonctions.
+    Il vous est bien entendu possible de le modifier/compléter, ou encore d'écrire vos propres fonctions de test.
+   */
+  
+  int* operand;
+  ALU alu;
+  CPU cpu;
+  
+  int chosenInt,integer ;
+  int go_on = 1 ;
+  
+  char* menu =     
+    "              Programme de test\n\n0  Quitter\n1  setValue(operande,int)\n2  pass(alu,operande)\n3  printing(alu)\n4  afficher toString(operande)\n5  afficher intValue(operande)\n6  afficher intValue(accu)\n7  accu=nand(accu,operande)\n8  accu=add(accu,operande)\n9  accu=sub(accu,operande)\n10 accu=and(accu,operande)\n11 accu=or(accu,operande)\n12 accu=xor(accu,operande)\n13 accu=not(accu)\n14 accu=opp(accu)\n15 accu=shift(accu)\n16 accu=logicalShift(accu,int)\n17 accu=mul(accu,operande)\n\n" ;
+  
+  char* invite = "--> Quel est votre choix  ? " ;
+  
+  printf("%s",menu) ; 
+
+  operand=word();
+  cpu=initCPU();
+  alu=cpu.alu;
+  
+  while (go_on==1) {
+    printf("%s",invite);
+    scanf("%d",&chosenInt);
+    switch (chosenInt) {
+    case 0 : 
+      go_on = 0 ;
+      break ;
+    case 1 :
+      printf("Entrez un nombre :"); 
+      scanf("%d",&integer);
+      setValue(operand,integer);
+      break ;
+    case 2 : 
+      pass(alu,operand);
+      break ;
+    case 3 : 
+      printing(alu);
+      break ;
+    case 4 : 
+      printf("%s\n",toString(operand));
+      break ;
+    case 5 : 
+      printf("intValue(operand)=%d\n",intValue(operand));
+      break ;
+    case 6 : 
+      printf("intValue(accu)=%d\n",intValue(alu.accu));
+      break ;
+    case 7 : 
+      nand(alu,operand);
+      printf("apres nand(), accu = ");
+      printing(alu);
+      break ;
+    case 8 : 
+      add(alu,operand);
+      printf("apres add(), accu = ");
+      printing(alu);
+      break ;
+    case 9 : 
+      sub(cpu,operand);
+      printf("apres sub(), A = ");
+      printing(alu);
+      break ;
+    case 10 : 
+      and(cpu,operand);
+      printf("apres and(), A = ");
+      printing(alu);
+      break ;
+    case 11 : 
+      or(cpu,operand);
+      printf("apres or(), A = ");
+      printing(alu);
+      break ;
+    case 12 : 
+      xor(cpu,operand);
+      printf("apres xor(), A = ");
+      printing(alu);
+      break ;
+    case 13 : 
+      not(cpu);
+      printf("apres not(), A = ");
+      printing(alu);
+      break ;
+    case 14 : 
+      opp(cpu);
+      printf("apres opp(), A = ");
+      printing(alu);
+      break ;
+    case 15 : 
+      shift(alu);
+      printf("apres shift(), A = ");
+      printing(alu);
+      break ;
+    case 16 : 
+      printf("Entrez un entier :") ;
+      scanf("%d",&integer);
+      logicalShift(cpu,integer);
+      printf("apres logicalshift(%d), A = ",integer);
+      printing(alu);
+      break ;
+    case 17 : 
+      mul(cpu,operand);
+      printf("apres mul(), A = ");
+      printing(alu);
+      break ;
+    default : 
+      printf("Choix inexistant !!!!\n");
+      printf("%s",menu);
+    }
+  }
+  printf("Au revoir et a bientot\n");
+  return 0;
+}
+
+
+