/*
/*                   A Simple 32-bit  Computer
/*                            HEXY-32
/*
/*                         Brought to you 
/*
/*                              By
/*                    
/*                 YOUR VERY OWN ENEE350 INSTRUCTOR
/*
/*             This  computer program simulates the fetch,decode
/*              and execute cycles of a simple 32-bit computer
/*                             
/*
/*              HEXY-32  has the following registers:
/*                  
/*                    
/*                       A:    32 bits
/*                       B:    32 bits
/*                       MDR:  32 bits
/*                       MAR:  24 bits
/*                       IR:   32 bits
/*                       PC:   24 bits
/*
/*    Its instruction repertoire consists of the following instructions
/*  
/*     Register Instructions
/*     CLA: Clear A          Opcode: 0000 0 0  ----- A = 0              HexCode: 00
/*     CLB: Clear B          Opcode: 0000 0 1  ----- B = 0              HexCode: 04
/*     INA: Incre A          Opcode: 0001 0 0  ----- A = A+1            HexCode: 10    
/*     INB: Incre B          Opcode: 0001 0 1  ----- B = B+1            HexCode: 14
/*     CMA: Compl A          Opcode: 0010 0 0  ----- A = ~A             HexCode: 20
/*     CMB: Compl B          Opcode: 0010 0 1  ----- B = ~B             HexCode: 24
/*     ORA: Or    A,B        Opcode: 0011 0 0  ----- A = A | B          HexCode: 30
/*     ORB: Or    B,A        Opcode: 0011 0 1  ----- B = A | B          HexCode: 34
/*     ANA: And   A,B        Opcode: 0100 0 0  ----- A = A & B          HexCode: 40
/*     ANB: And   B,A        Opcode: 0100 0 1  ----- B = A & B          HexCode: 44
/*     ADA: Add   A,B        Opcode: 0101 0 0  ----- A = A + B          HexCode: 50
/*     ADB: Add   B,A        Opcode: 0101 0 1  ----- B = A + B          HexCode: 54
/*     SRA: Shfr  A          Opcode: 0110 0 0  ----- A = A >> 1         HexCode: 60
/*     SRB: Shfr  B          Opcode: 0110 0 1  ----- B = B >> 1         HexCode: 64
/*     SLA: Shfl  A          Opcode: 0111 0 0  ----- A = A << 1         HexCode: 70
/*     SLB: Shfl  B          Opcode: 0111 0 1  ----- A = A << 1         HexCode: 74
/*
/*     Memory Reference Instructions
/*
/*     CLM: Clear M          Opcode: 0000 1 -  ----- M = 0              HexCode: 08,09,0A
/*     INM: Incre M          Opcode: 0001 1 -  ----- M = M+1            HexCode: 18,19,1A
/*     CMM: Compl M          Opcode: 0010 1 -  ----- M = ~M             HexCode: 28,29,2A
/*     OMA: Or    A,M        Opcode: 0011 1 0  ----- A = M | A          HexCode: 38,39,3A
/*     OMB: Or    B,M        Opcode: 0011 1 1  ----- B = M | B          HexCode: 3C,3D,3E
/*     AMA: And   A,M        Opcode: 0100 1 0  ----- A = M & A          HexCode: 48,49,4A
/*     AMB: And   B,M        Opcode: 0100 1 1  ----- B = M & B          HexCode: 4C,4D,4E
/*     MAA: Add   A,M        Opcode: 0101 1 0  ----- A = M + A          HexCode: 58,59,5A
/*     MAB: Add   B,M        Opcode: 0101 1 1  ----- B = M + B          HexCode: 5C,5D,5E
/*     SRM: Shfr  M          Opcode: 0110 1 -  ----- M = M >> 1         HexCode: 68,69,6A
/*     SLM: Shfl  M          Opcode: 0111 1 -  ----- M = M << 1         HexCode: 78,79,7A
/*     LDA  Load  A,M        Opcode: 1000 1 0  ----- A = M              HexCode: 88,89,8A
/*     LDB  Load  B,M        Opcode: 1000 1 1  ----- B = M              HexCode: 8C,8D,8E
/*     STA  Stor  A,M        Opcode: 1001 1 0  ----- M = A              HexCode: 98,99,9A
/*     STB  Stor  B,M        Opcode: 1001 1 1  ----- M = B              HexCode: 9C,9D,9E

/*     Branch Instructions
/*
/*     BAA: jmp              Opcode: 1010 - -  ----- PC=Br.Ad           HexCode: A8,A9,AA
/*     BPA: Br+   A          Opcode: 1011 - 0  ----- PC=(A>0)&Br.Ad     HexCode: B8,B9,BA   
/*     BPB: Br+   B          Opcode: 1011 - 1  ----- PC=(B>0)&Br.Ad     HexCode: BC,BD,BE
/*     BZA: Br0   A          Opcode: 1100 - 0  ----- PC=(A==0)&Br.Ad    HexCode: C8,C9,CA
/*     BZB: Br0   B          Opcode: 1100 - 1  ----- PC=(B==0)&Br.Ad    HexCode: CC,CD,CE
/*     HLT  Halt             Opcode: 1101 - -  ----- reset = 1          HexCode: D0

/*               Operand or Branch address computation
/*
/*                    Immediate: MDR = IR[8:31]
/*                    Direct:    MDR = MEM[IR[8:31]]
/*                    Indirect   MDR = MEM[MEM[IR[8:31]]
/*  
/*               Programs are entered and displayed in hex code.
/*
/*       Please communicate all your questions and comments to            
/*          
/*                        A. Yavuz Oruc
/*                          Professor
/*                   University of Maryland
/*                   College Park, MD 20742
/*                    E-mail: yavuz@eng.umd.edu
/*
/*                        November 1997                       
*/

typedef struct 
{
unsigned long int    MDR;
unsigned long int    MAR;
unsigned long int    PC;
unsigned long int    IR;
unsigned long int    R;
unsigned long int    A;
unsigned long int    B;   
unsigned long int    MEMORY[8192];
short                opcode;
short                addrtype;
Boolean              regtype;
Boolean              optype;
Boolean              S;
Boolean              C;
Boolean              V;
Boolean              Z;
Boolean              datavalid;
Boolean              read;
Boolean              write;
Boolean              reset;
} ENEE350Global;


#include <iostream.h>  
#include <stdio.h>
#include <limits.h>  

ENEE350Global   g;

void initialize (void);
unsigned long int EffOperand (void);

void main(void)
{unsigned long int address = 0, i = 0,  action = 0; 
  unsigned long int pcstr,location,location1,location2;

do
{    initialize();
     g.reset = 0;
     cout << "Type 0 to enter a program, 1 to display registers, 2 to display memory: ";
     cin >> action;
     cout << "\n";
     
if(action == 0)
{

 cout << "Enter your program's starting address: ";
 cin >> g.PC;
 address =g.PC;
 pcstr=address;
    do 
    {cout << "Enter instruction  "   << address -g.PC << "\n";
    cout << "Or type -1 to end your program: ";
    scanf("%lX",&(g.MEMORY[address]));
    address = address + 1;
    }
    while (  ((g.MEMORY)[address-1] !=  -1 ) && (address < 1024));

if (address >= 1024)
cout << "Memory overflow";

cout << "\nHere is your program: \n\n";
for (i = g.PC; i< address-1; i++)
{ cout << "Location " << i << ": ";  printf("%08lX",g.MEMORY[i]); cout << "\n";}
cout << "\n Now load your data  or type -1 to end your loading \n\n";
do 
{cout << "Location: ";
scanf("%lX",&location);
// cin >> location;
if (location >= pcstr && location <= g.PC)
{cout << "Illegal location \n";}
else if (location != -1)
{
cout << "Data: ";
// cin >>  (g.MEMORY)[location];
scanf("%lX",&(g.MEMORY[location])); 
 }
}
while ( location !=  -1 );

cout << "\nHere is the flow of execution of your program:\n\n";
i=1;
while (g.reset == 0)
{       //Fetch Step
 cout << "Cycle " << i << ":  ";
 i= i+1;
 
        g.MAR =  g.PC;//Load next instruction's address into MAR
        g.PC =   g.PC +1; //Increment PC
        g.read = 1; //Fetch the next Instruction into MDR 
        cout << "read = "   << (short) g.read; cout << ", ";
        g.MDR =  g.MEMORY[g.MAR]; 
        g.read = 0;
        g.IR = g.MDR;//Load the instruction into IR
        g.opcode = (g.IR >> 28) & 15; //Decode Step
        g.optype = (g.IR >> 27) & 1;
        g.regtype = (Boolean) (g.IR >> 26) & (unsigned long int) 1;
        
        cout << "PC = ";  printf("%08lX",g.PC);  cout << ", ";  
        cout << "IR = ";  printf("%08lX",g.IR);  cout << ", ";  
     
     switch(g.opcode) 
         {
          case  0://Clear
          if (!g.optype) 
          {
          if (!g.regtype) 
           {g.A  = 0;} //CLA
           else 
           {g.B  = 0;} //CLB
           }
          else
          {
          g.MAR =  EffOperand(); //Direct or indirect operand
          g.MDR = 0;
          g.write = 1;
          cout << "write = " << (short) g.write; cout << ", ";  
          g.MEMORY[g.MAR] = g.MDR; //CLM
          g.write = 0; 
          }
          g.S = 0; g.Z = 1; g.V = 0; g.C = 0;
         break;
          
         case  1://Increment
         if (!g.optype) 
         {
         if (!g.regtype) 
         {g.A  = g.A + 1;  //INA
          g.S = (&g.A)[0];   //Set Flags
         if (g.A == 0) {g.C = 1; g.Z = 1; g.V = (&g.A)[0];} 
            else {g.C = 0; g.Z = 0; g.V = 0;}
         }
         else 
         {g.B  = g.B + 1; //INB
          g.S = g.B >> 31;
         if (g.B == 0) {g.C = 1; g.Z = 1; g.V = (&g.B)[0];}
            else {g.C = 0; g.Z = 0; g.V = 0; }
         }
         }
         else
         {
         g.MAR =  EffOperand(); //Direct or indirect operand
         g.MDR = g.MEMORY[g.MAR];
         g.MDR = g.MDR + 1; //INM
         g.write = 1;
         cout << "write = " << (short) g.write; cout << ", "; 
         g.MEMORY[g.MAR] = g.MDR; 
         g.write =  0; 
         g.S = g.MDR >> 31; //Set Flags
         if (g.MDR == 0) {g.C = 1; g.Z = 1; g.V = (&g.MDR)[0];} 
            else {g.C = 0; g.Z = 0; g.V = 0;}
         }
         break;

         case  2://Complement
         if (!g.optype) 
         {
         if (!g.regtype) 
         {g.A  = ~g.A;  //CMA
          g.S = g.A >> 31;
          if (g.A == 0) g.Z = 1;  else g.Z = 0;   
         }
         else 
          {g.B  = ~g.B; //CMB
           g.S = g.B >> 31;
          if (g.B == 0) g.Z = 1;  else g.Z = 0;   
          } 
         }
         else
         {
         g.MAR =  EffOperand(); //Direct or indirect operand
         g.MDR = g.MEMORY[g.MAR];
         g.MDR = ~g.MDR;
         g.write = 1;
         cout << "write = " << (short) g.write; cout << ", "; 
         g.MEMORY[g.MAR] = g.MDR; 
         g.write = 0;
         g.S = g.MDR >> 31;
         if (g.MDR == 0) g.Z = 1;  else g.Z = 0;   
         }
         g.C = 0; g.V = 0; 
         break;
        
         case  3://Or
         if (!g.optype) 
         { if (!g.regtype) 
             {g.A  = g.A | g.B; //ORA
              g.S = g.A >> 31;
              if (g.A == 0) g.Z = 1;             
             }
           else 
             {
             g.B  = g.A | g.B; //ORB  
             g.S = g.B >> 31;
             if (g.B == 0) g.Z = 1; else g.Z = 0;

             }    
         }
         else
         { g.MDR = EffOperand();
           if (!g.regtype) 
           { g.A  = g.A | g.MDR; //OMA
             g.S = g.A >> 31;
          if (g.A == 0) g.Z = 1; else g.Z = 0;

           }
            else 
           { g.B  = g.B | g.MDR; //OMB
             g.S = g.B >> 31;
            if (g.B == 0) g.Z = 1; else g.Z = 0;
           }
         } 
         g.C = 0; g.V = 0; 
          break;  

         case  4://And
         if (!g.optype) 
         { if (!g.regtype) 
             {g.A  = g.A & g.B; //ANA
              g.S = g.A >> 31;
              if (g.A == 0) g.Z = 1;  else g.Z = 0;           
             }
           else 
             {
             g.B  = g.A & g.B; //ANB  
             g.S = g.B >> 31;
             if (g.B == 0) g.Z = 1; else g.Z = 0;

             }    
         }
         else
         { g.MDR = EffOperand();
           if (!g.regtype) 
           { g.A  = g.A & g.MDR; //AMA
             g.S = g.A >> 31;
          if (g.A == 0) g.Z = 1;  else g.Z = 0;   

           }
            else 
           { g.B  = g.B & g.MDR; //AMB
             g.S = g.B >> 31;
            if (g.B == 0) g.Z = 1;  else g.Z = 0;   
           }
         } 
         g.C = 0; g.V = 0; 
          break;  


         case  5://Add
         if (!g.optype) 
         {              
           g.C = ((&g.A)[0] == 1) && ((&g.B)[0] == 1) || 
                 (((&g.A)[0] == 1) || ((&g.B)[0] == 1)) 
                 && (g.A & 0x7FFFFFFF) + (g.B & 0x7FFFFFFF) >= 0x80000000;   //Set Carry  
           g.V =(&g.A)[0]  & (&g.A)[0]  & (!(&g.A) +(&g.B)[0]) || 
               (!(&g.A)[0]) & (!(&g.B)[0]) & ((&g.A)[0] +(&g.B)[0]) ; //Set Overflow
                                                
          if (!g.regtype) 
             {
              g.A  = g.A + g.B; //ADA
              g.S = g.A >> 31;
              if (g.A == 0) g.Z = 1; else g.Z = 0;  
                         
             }
           else 
             {
             g.B  = g.A + g.B; //ADB  
             g.S = g.B >> 31;
             if (g.B == 0) g.Z = 1; else g.Z = 0; 

             }    
         }
         else
         { g.MDR = EffOperand();
           if (!g.regtype) 
           { 
           g.C = ((&g.A)[0] == 1) && ((&g.B)[0] == 1) || 
                 (((&g.A)[0] == 1) || ((&g.B)[0] == 1)) 
                 && (g.A & 0x7FFFFFFF) + (g.B & 0x7FFFFFFF) >= 0x80000000;   //Set Carry  
           g.V =(&g.A)[0]  & (&g.A)[0]  & (!(&g.A) +(&g.B)[0]) || 
               (!(&g.A)[0]) & (!(&g.B)[0]) & ((&g.A)[0] +(&g.B)[0]) ; //Set Overflow
                                     
           g.A  = g.A + g.MDR; //MAA
             g.S = g.A >> 31;
          if (g.A == 0) g.Z = 1;

           }
            else 
           { 
           g.C = ((&g.A)[0] == 1) && ((&g.B)[0] == 1) || 
                 (((&g.A)[0] == 1) || ((&g.B)[0] == 1)) 
                 && (g.A & 0x7FFFFFFF) + (g.B & 0x7FFFFFFF) >= 0x80000000;   //Set Carry  
           g.V =(&g.A)[0]  & (&g.A)[0]  & (!(&g.A) +(&g.B)[0]) || 
               (!(&g.A)[0]) & (!(&g.B)[0]) & ((&g.A)[0] +(&g.B)[0]) ; //Set Overflow
                            
           g.B  = g.B + g.MDR; //MAB
             g.S = g.B >> 31;
            if (g.B == 0) g.Z = 1;
           }
         } 
          break;  


 
         
          case 6://Shift Right
          if (!g.optype) 
          { if (!g.regtype) g.A  = g.A >> 1;
            else g.B  =  g.B >> 1;
          }
          else
          {
           g.MAR =  EffOperand();//Direct or indirect operand
           g.read = 1;
           g.MDR =  g.MEMORY[g.MAR];
           g.read = 0;
           g.MDR = g.MDR >> 1;
           g.write = 1;
           cout << "write = " << (short) g.write; cout << ", ";
           g.MEMORY[g.MAR] = g.MDR;  
           g.write = 0;   
          }
          break;
          
          case 7: //Shift Left
          if (!g.optype) 
          { if (!g.regtype) g.A  = g.A << 1;
            else g.B  =  g.B << 1;
          }
          else
          {
            g.MAR =  EffOperand();//Direct or indirect operand
            g.read = 1;
            g.MDR =  g.MEMORY[g.MAR];
            g.read = 0;
            g.MDR  =  g.MDR << 1;
            g.write = 1;
            cout << "write = " << (short) g.write; cout << ", ";
            g.MEMORY[g.MAR] = g.MDR;  
            g.write = 0;   

          }
          break;
                 
          case  8://Load
          g.MDR = EffOperand();
          if (!g.regtype) g.A  = g.MDR;       
          else g.B = g.MDR;       
          break;
                  
          case  9://Store
          if (!g.regtype) g.MDR  = g.A;   
          else {g.MDR = g.B;}     
          g.MAR =  EffOperand();//Direct or indirect operand
          g.write =1; 
          cout << "write = " << (short) g.write; cout << ", ";
          g.MEMORY[g.MAR] =  g.MDR; //Write
          g.write = 0;    
          break;

          case 10: //Branch
           g.MDR = EffOperand();
           g.PC = g.MDR;
          break;
          
          case 11: //Branch if A (or B)  > 0
          if  ((!g.regtype && (g.A > 0)) || (g.regtype && (g.B > 0)) )
          {
           g.MDR = EffOperand();            
           g.PC = g.MDR;
          }
          break;

          case 12: //Branch if A (or B)  == 0
          if  ((!g.regtype && (g.A == 0)) || (g.regtype && (g.B == 0)) )
          {
           g.MDR = EffOperand();            
           g.PC = g.MDR;
          }
          break;
          
                      
         case 13: //Halt
         g.reset =1;
         break;
      
         case 14: 
         break;  //This is left for you to expand on
      
         case 15: 
         break;  //This is left for you to expand on  
      }
     
 cout << "A = ";   printf("%08lX",g.A);  cout << ", ";  
 cout << "B = ";  printf("%08lX",g.B);  cout << ", ";  
 cout << "Z = " << (short) g.Z; cout << ", ";
 cout << "S = " << (short) g.S << "\n";
 cout << "C = " << (short) g.C; cout << ", ";
 cout << "V = " << (short) g.V << "\n";
 cout << "MAR = ";  printf("%08lX",g.MAR);  cout << ", ";  
 cout << "MDR = ";   printf("%08lX",g.MDR);  cout << ", ";  
 cout << "reset = " << (short) g.reset << "\n\n";

}
}
if (action == 1)
{
 cout << "A = ";   printf("%08lX",g.A);  cout << ", ";  
 cout << "B = ";  printf("%08lX",g.B);  cout << ", ";  
 cout << "Z = " << (short) g.Z; cout << ", ";
 cout << "S = " << (short) g.S << "\n";
 cout << "C = " << (short) g.C; cout << ", ";
 cout << "V = " << (short) g.V << "\n";
 cout << "MAR = ";  printf("%08lX",g.MAR);  cout << ", ";  
 cout << "MDR = ";   printf("%08lX",g.MDR);  cout << ", ";  
 cout << "PC = ";  printf("%08lX",g.PC);  cout << ", ";  
 cout << "IR = ";    printf("%08lX",g.IR);  cout << ", ";  
 cout << "reset = " << (short) g.reset << "\n\n";
}

if(action == 2)
{cout << "Enter the first address: ";
scanf("%lX",&location1);
// cin >> location1;
 cout << "Enter the last address: ";
scanf("%lX",&location2);
// cin >> location2;
 cout << "\n";
 for (i = location1; i <= location2; i++)
 {cout <<  "Location " << i << " : "; printf("%08lX",g.MEMORY[i]); cout << "\n";}
 cout << "\n";
}
}
while (1);
}

void initialize(void)
{g.PC =   0;
 g.A =   0;
 g.B =   0;
 g.MAR =  0;
 g.MDR =   0;
 g.IR =   0;
 g.reset = 0;
 g.opcode =0;
}

unsigned long int EffOperand(void)

/*This function computes the effective operand .
 The effective operand is interpreted as follows:
   
   CLM,INM,CMM,SRM,SLM: The effective operand is direct or indirect.
   
   OMA,OMB,ADA,ADB,MAA,MAB: The effective operand is immediate, direct or indirect.
   
   LDA,LDM: The effective operand is immediate, direct or indirect.
   
   STA,STB: The effective operand is direct or indirect.
   
   BAA,BPA,BPB,BZA,BZB: The effective address is immediate, direct or indirect.
*/
 { 
 unsigned int operand;
 g.addrtype = (g.IR >> 24) & 3;
 
 operand =  g.IR & 0xFFFFFF;
  
 switch(g.addrtype)
 {case 0://Immediate operand
  
  break;
  
  case 1: //Direct operand
  
   if (operand <= 8191)
   {g.read =1;
   cout << "read = "   << (short) g.read; cout << ", ";
   operand = g.MEMORY[operand];
   g.read = 0;
   }
   else
   cout << "Memory Overflow ";
  break;
  
  case 2: //Indirect operand
   if (operand <= 8191)
   {g.read =1;
   cout << "read = "   << (short) g.read; cout << ", ";
   operand = g.MEMORY[operand];
   g.read = 0;
   if (operand <= 8191)
   {g.read =1;
   cout << "read = "   << (short) g.read; cout << ", ";
   operand = g.MEMORY[operand];
   g.read = 0;
   }
   else 
   cout << "Memory Overflow ";   
   }
   else
   cout << "Memory Overflow ";  
   break;
  }

  return operand;
  }



Return to my home page

Return to software page