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