/*****************************************************************************/
/* VESP COMPUTER-2.0M(Microprogrammed version) *
/* Author: A. Yavuz Oruc *
/* Copyright © 2000,2004. *
/* Sabatech Corporation (www.sabatech.com) *
/* All rights reserved. *
/*Copying and compiling this program for personal use is permitted. However, *
/*no part of this program may be reproduced or distributed in any form or *
/*by any means, or stored in a database or retrieval system, without the *
/*prior written permission of the Author and Sabatech Corporation. * *
/*Neither Sabatech nor the Author makes any direct or implied claims * *
/*that this program will work accurately and/or generate correct results, * *
/*In addition, they provide no warranties direct or implied that using * *
/*this program on any computer will be safe in so far as guarding against *
/*destroying and/or deleting any information, data, code, program or file *
/*that may be stored in the memory of user's computer. *
/*****************************************************************************/
/* Please communicate all your questions and comments to */
/* A. Yavuz Oruc at yavuz@sabatech.com */
/*--------------------Changes and additions in this version-------------------*/
/* This is the 1st microprogrammed version of vesp 2.0 */
/* Warning!!!! This program overwrites any data in the filename which is */
/* specified at the console in response to the prompt for saving a vesp */
/* program. Save at your own risk!!!!! */
/******************************************************************************/
/* This computer program simulates the fetch,decode
/* and execute cycles of a hypothetical 16-bit computer,
/* called VESP (_V_Ery _Simple _Processor)
/* Revised to reduce the address field to 12 bits. 2/13/03
/* VESP has the following registers on which it executes 8 instructions:
/* A: 16 bits (Implicit) It refers to location 0 in VESP's memory
/* B: 16 bits (Implicit) It refers to location 1 in VESP's memory
/* IX: 16 bits (Implicit) It refers to location 2 in VESP's memory
/* IR: 16 bits
/* MAR: 12 bits
/* PC: 12 bits
/* Its instruction repertoire consists of the following instructions:
/* ADD: Add Opcode: 0000 ----- A = A+B HexCode: 0
/* CMP: Compl Opcode: 0001 ----- A = ~A HexCode: 1
/* LDA: Load Opcode: 0010 ----- M[IR[4:15] ] = M[MAR+1] HexCode: 2
/* MOV: Move Opcode: 0011 ----- M[IR[4:15] ] = M[M[MAR+1][3:15]] HexCode: 3
/* JMP Jump Opcode: 0100 ----- PC = IR[4:15] HexCode: 4
/* JEZ: Jump if A=0 Opcode: 0101 ----- If (A = 0) PC = IR[4:15] HexCode: 5
/* JPS: Jump if A=+ Opcode: 0110 ----- If (A > 0) PC = IR[4:15] HexCode: 6
/* HLT: Halt Opcode: 0111 ----- reset = 1 HexCode: 7
/* INC: Increment Opcode: 1000 ----- A = A + 1
/* DEC: Decrement Opcode: 1001 ----- A = A - 1
/* AND: And Opcode: 1010 ----- A = A & B
/* IOR: Or Opcode: 1011 ----- A = A | B
/* SHL: Shift left Opcode: 1100 ----- A << 1
/* SHR: Shift right Opcode: 1101 ----- A >> 1
/* MXF Move from w/IX Opcode: 1110 ----- M[IR[3:15]] = M[IX]; IX = IX + 1;HexCode: E
/* MXT Move to w/IX Opcode: 1111 ----- M[IX] = M[IR[3:15]]; IX = IX + 1;HexCode: F
/* Programs are entered and displayed in hex code. */
#include <iostream.h>
#include <iomanip.h>
#include <stdio.h>
#include <limits.h>
void initialize(void); int readprogram(void);
void displayprogram(int progend);
void displayregisters(void); void displaymemory(void);
void maincycle(int trace); void fetch(void);
void decode(void); void execute(void);
void microsequencer(void); void loadmicrostore(void);
//AYO: Define the registers of the architecture.
typedef struct
{unsigned short MAR,PC,IR,MDR;
unsigned long clock;
short MEMORY[8192],S,C,F,Z,reset,add,cmp,lda,mov,jmp,jez,jps,hlt,inc,dec,lnd,lor,shl,shr,mxf,mxt;
short memory_read;
} architecture; architecture vesp;
typedef struct
{short MAR, PC, MIR, clock;
short ABUS, BBUS, OBUS;
char RET_SET;
short add_address, comp_address, load_address,move_address,jump_address,branchzero_address,
branchgreater_address,branchhalt_address, branchinc_address,branchdec_address,branchand_address,
branchzor_address,branchshl_address,branchshr_address,branchmxf_address,branchmxt_address;
short MICSTORE[4096];
} micarchitecture; micarchitecture micro_vesp;
int j=1;
int main(void)
{int address = 0,i = 0,action,action2,progend;
initialize();//AYO: Initialize all the registers.
cout << "\nWelcome to Vesp 2.0\n\n";
while(1) {vesp.reset = false; //AYO: vesp keeps running unless it is reset.
//AYO: Input program, diplay registers or memory
cin.clear();
cout << "\nType \n 0 to enter a program\n "
<< "1 to display registers\n 2 to display memory: ";
cin >> action2;
cin.clear();
cout << "\n";
//AYO: Read the program, display it, and execute it.
if(action2 == 0)
{progend = readprogram(); displayprogram(progend);
//AYO: Step through or execute the program.
while(vesp.reset == 0)
{cout << "\nEnter 0 if you wish to execute the program, 1 to step it, ";
cout << "2 to exit to the main menu: ";
cin.clear(); cin >> action2;
switch(action2)
{case 0: cout << "Enter 0 for a brief trace 1 for long trace: "; cin.clear(); cin >> action;
cout << "\n";
while(vesp.reset == 0) maincycle(action); break;
case 1: maincycle(1); break;
case 2: vesp.reset = true; break;
}
}
//AYO: Display the number of instructions and clock cycles executed.
if(action2 != 2)
{cout << "The number of instructions executed = " << dec << j-1 << "\n";
cout << "The number of clock cycles used = " << dec << vesp.clock << "\n";
j = 1; vesp.clock = 0;
}
}
if (action2 == 1) displayregisters();
if (action2 == 2) displaymemory();
//if (action == 3) readprogram();
}
}
void initialize(void)
{vesp.PC = vesp.MEMORY[0] = vesp.MEMORY[1] = vesp.IR = 0;
vesp.reset = 0; vesp.clock = 0;
loadmicrostore();
}
int readprogram(void)
{int address,instruction,progend,action;
char filename[16]; FILE *file;
do{ cout << "Enter your program's starting "
<< "address ( >= 3) as a 3-digit hex number: ";
cin >> hex >> vesp.PC;
} while (vesp.PC < 3);
address = vesp.PC;
cout << "Enter 0 to type in your program or 1 to read it from a file: ";
cin >> action;
if(action != 0)
{cout << "Enter the file name: "; cin >> filename;
if( (file = fopen(filename,"r")) != NULL)
{
while (fscanf(file,"%x",&instruction) != EOF && address < 8192 )
{
vesp.MEMORY[address] = instruction; address = address + 1;
/* cout << hex << address << "\n"; */
}
}
fclose(file);
}
else
do {cin.clear();
cout << "Enter instruction "
<< (address -vesp.PC)
<< " using a 4-digit hex number" << "\n";
cout << "Or type -1 to end your program: ";
cin >> hex >> instruction; //AYO: read it in hex.
vesp.MEMORY[address] = instruction;
address = address + 1;
}
while ( ( vesp.MEMORY[address-1] != -1 ) && (address < 8192)); //AYO: -1 marks the end.
if (address >= 4096)
{cout << "Memory overflow,"
<< "Please quit from the file menu and restart me!";
return address-1;}
progend = address - 1;
//save the program into a file
cout << "Enter 0 to continue, 1 to save your program into a file: ";
cin >> action;
if(action == 1)
{cout << "Enter the file name: "; cin >> filename;
if( (file = fopen(filename,"w")) != NULL)
{address = vesp.PC;
while (address < progend )
{
fprintf(file,"%4X\n",vesp.MEMORY[address]); //fputs("\n",file);
address = address + 1;
}
}
fclose(file);
}
return progend;
}
void displayprogram(int progend)
{int i;
cout << "\nHere is your program: \n\n";
for (i = vesp.PC; i<= progend; i++)
{
cout << "Location "; cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << i << ": "; //AYO: display it in uppercase hex.
cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << (0x0000FFFF & vesp.MEMORY[i]) << "\n";
}
}
void displayregisters(void)
{
cout << "A = "; cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << (0x0000FFFF & vesp.MEMORY[0])<< ", ";
cout << "B = "; cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << (0x0000FFFF & vesp.MEMORY[1])<< ", ";
cout << "Z = " << vesp.Z << ", ";
cout << "S = " << vesp.S << ", ";
cout << "C = " << vesp.C << ", ";
cout << "F = " << vesp.F << "\n";
cout << "MAR = "; cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << vesp.MAR << ", ";
cout << "PC = "; cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << vesp.PC << ", ";
cout << "IR = "; cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << vesp.IR << ", ";
cout << "reset = " << vesp.reset << "\n";
}
void displaymemory(void)
{int location1,location2,i;
cout << "Enter the first address (3 hex digits): ";
cin.clear();
cin >> hex >> location1;
cin.clear();
cout << "Enter the last address: (3 hex digits): ";
cin.clear();
cin >> hex >> location2;
cin.clear();
for (i = location1; i <= location2; i++)
{cout << "Location "; cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << i << " : ";
cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << (0x0000FFFF & vesp.MEMORY[i]); cout << "\n";
}
}
void maincycle(int trace)
{ cout << "Machine Cycle " << j << ": ";
j = j+1;
//AYO: Fetch Step
cout << "PC = "; cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << (vesp.PC & 0x0FFF) << ", ";
cout << "\nFETCH SUBCYCLE\n";
fetch();
cout << "\nClock cycle = " << vesp.clock << "\n";
//AYO: Decode Step
cout << "DECODE SUBCYCLE\n";
decode();
cout << "Clock cycle = " << vesp.clock << "\n";
//AYO: Execute Step
cout << "EXECUTE SUBCYCLE";
vesp.add = vesp.cmp = 0;
execute();
cout << "\nClock cycle = " << vesp.clock << "\n\n";
//AYO: Display the registers
if(trace == 1)
{
displayregisters();
cout << "add = " << vesp.add << " ";
cout << "complement = " << vesp.cmp << "\n\n";
if( (vesp.IR >> 12 ) == 2 || (vesp.IR >> 12 ) == 3)
{cout << "Memory[";
cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << (vesp.IR & 0x0FFF) << "] = ";
cout.fill('0'); cout.width(4); cout.setf(ios::uppercase);
cout << hex << (0x0000FFFF & vesp.MEMORY[vesp.IR & 0x0FFF])<< "\n\n";
}
}
}
void fetch(void)
{ //clock cycle 1. Load next instruction's address into MAR.
vesp.MAR = vesp.PC; vesp.clock = vesp.clock +1;
vesp.PC = vesp.PC +1; //Increment PC.
//clock cycle 2. Fetch the next Instruction into IR
cout << "MAR = "; printf("%04X",vesp.MAR); cout << ", ";
vesp.IR = vesp.MEMORY[vesp.MAR]; vesp.clock = vesp.clock +1;
cout << "IR = "; printf("%04X",vesp.IR); cout << ", ";
}
void decode(void)
{cout << "Decoded instruction is: ";
switch( vesp.IR >> 12)
{//Add //Complement
case 0: cout << "ADD\n"; break; case 1: cout << "CMP\n"; break;
//Load //Move
case 2: cout << "LDA\n"; break; case 3: cout << "MOV\n"; break;
//Jump //Jump if A = 0
case 4: cout << "JMP\n"; break; case 5: cout << "JEZ\n"; break;
//Jump if A > 0 //Halt
case 6: cout << "JPS\n"; break; case 7: cout << "HLT\n"; break;
//Increment //Decrement
case 8: cout << "INC\n"; break; case 9: cout << "DEC\n"; break;
//And //Or
case 10: cout << "AND\n"; break; case 11: cout << "IOR\n"; break;
//Shift left //Shift right
case 12: cout << "SHL\n"; break; case 13: cout << "SHR\n"; break;
//Add with IX+ //Add with IX-
case 14: cout << "MXP\n"; break; case 15: cout << "MXM\n"; break;
}
}
void execute(void)
{
switch(vesp.IR >> 12)
{//clock cycle 3.
//Add
case 0: // set micro_PC to add microcode and call microsequencer
micro_vesp.PC = micro_vesp.add_address; break;
//Complement
case 1: // set micro_PC to complement microcode and call microsequencer
micro_vesp.PC = micro_vesp.comp_address; break;
//Load
case 2: // set micro_PC to load microcode and call microsequencer
micro_vesp.PC = micro_vesp.load_address; break;
//Move
case 3: // set micro_PC to move microcode and call microsequencer
micro_vesp.PC = micro_vesp.move_address; break;
//Jump
case 4: // set micro_PC to jump microcode and call microsequencer
micro_vesp.PC = micro_vesp.jump_address; break;
//Branch if A = 0
case 5: // set micro_PC to branch if A=0 microcode and call microsequencer
micro_vesp.PC = micro_vesp.branchzero_address; break;
//Branch if A is > 0
case 6: // set micro_PC to branch if A>0 microcode and call microsequencer
micro_vesp.PC = micro_vesp.branchgreater_address; break;
//Halt
case 7: // set micro_PC to halt microcode and call microsequencer
micro_vesp.PC = micro_vesp.halt_address;break;
//Increment
case 8: // set micro_PC to increment microcode and call microsequencer
micro_vesp.PC = micro_vesp.inc_address;break;
//Decrement
case 9: // set micro_PC to decrement microcode and call microsequencer
micro_vesp.PC = micro_vesp.dec_address;break;
//AND
case 10: // set micro_PC to AND microcode and call microsequencer
micro_vesp.PC = micro_vesp.and_address;break;
//OR
case 11: // set micro_PC to OR microcode and call microsequencer
micro_vesp.PC = micro_vesp.or_address;break;
//Shift left
case 12: // set micro_PC to shift left microcode and call microsequencer
micro_vesp.PC = micro_vesp.shl_address;break;
//Shift right
case 13: // set micro_PC to shift right microcode and call microsequencer
micro_vesp.PC = micro_vesp.shr_address;break;
//MXF
case 14: // set micro_PC to MXF microcode and call microsequencer
micro_vesp.PC = micro_vesp.mxf_address;break;
//MXT
case 15: // set micro_PC to MXT microcode and call microsequencer
micro_vesp.PC = micro_vesp.mxt_address;break;
}
micro_vesp.RET_SET = 0;
microsequencer();
}
void microsequencer()
{
while(micro_vesp.RET_SET == 0)
{
/* Step 1: Read the next microinstruction into MIR */
micro_vesp.MAR = micro_vesp.PC; micro_vesp.PC = micro_vesp.PC + 1;
micro_vesp.MIR = micro_vesp.MICSTORE[micro_vesp.MAR];
/*
Step 2: Decode and execute the microinstruction
*/
switch(micro_vesp.MIR & 0xC000)
{
case 0x0000: // transfer µ-microinstruction
switch(micro_vesp.MIR & 0x3800) //ABUS select
{
case 0x0000: micro_vesp.ABUS = 0; break; //select 0 into the ABUS
case 0x0800: micro_vesp.ABUS = vesp.MEMORY[0]; break; //select A into the ABUS
case 0x1000: micro_vesp.ABUS = vesp.PC; break; //select PC into the ABUS
case 0x1800: micro_vesp.ABUS = vesp.IR; break; //select IR into the ABUS
}
switch(micro_vesp.MIR & 0x3800) //BBUS select
{
case 0x0000: micro_vesp.BBUS = vesp.MDR; break; //select MDR into the ABUS
case 0x0100: micro_vesp.BBUS = vesp.MAR; break; //select MAR into the ABUS
case 0x0200: micro_vesp.BBUS = vesp.MEMORY[1]; break; //select B into the ABUS
case 0x0300: micro_vesp.BBUS = 1; break; //select 1 into the ABUS
}
switch(micro_vesp.MIR & 0x00F0) /* Function select */
{
case 0x0000: micro_vesp.OBUS = micro_vesp.ABUS; break;
case 0x0001: micro_vesp.OBUS = micro_vesp.BBUS; break;
case 0x0002: micro_vesp.OBUS = micro_vesp.ABUS + micro_vesp.BBUS;
//Set the overflow flag
vesp.F =
(micro_vesp.ABUS && 0x8000 == 0) &&
(micro_vesp.BBUS && 0x8000 == 0) &&
(micro_vesp.OBUS && 0x8000 == 0x8000)
||
(micro_vesp.ABUS &&0x8000 == 0x8000 ) &&
(micro_vesp.BBUS &&0x8000 == 0x8000 ) &&
(micro_vesp.OBUS &&0x8000 == 0);
//Set the carry flag
vesp.C = (micro_vesp.ABUS && 0x8000 == 0x8000) &&(micro_vesp.BBUS && 0x8000 == 0x8000);
//Set the sign flag
vesp.S = micro_vesp.OBUS 0x8000;
//Set the zero flag
vesp.Z = (micro_vesp.OBUS == 0);
break;
case 0x0003: micro_vesp.OBUS = ~micro_vesp.ABUS; break;
case 0x0004: micro_vesp.OBUS = ~micro_vesp.BBUS; break;
case 0x0005: micro_vesp.OBUS = micro_vesp.ABUS & micro_vesp.BBUS; break;
case 0x0006: micro_vesp.OBUS = micro_vesp.ABUS | micro_vesp.BBUS; break;
case 0x0007: micro_vesp.OBUS = micro_vesp.ABUS >> 1; break;
case 0x0008: micro_vesp.OBUS = micro_vesp.ABUS << 1; break;
case 0x0009: micro_vesp.OBUS = ~micro_vesp.ABUS + micro_vesp.BBUS << 1; break;
}
switch(micro_vesp.MIR & 0x000F) /* Destination select */
{
case 0x0000: vesp.MEMORY[0] = micro_vesp.OBUS;
vesp.Z = (micro_vesp.OBUS == 0); break; //save into A
vesp.S = micro_vesp.OBUS 0x8000;
case 0x0001: vesp.PC = micro_vesp.OBUS; break;
case 0x0002: vesp.IR = micro_vesp.OBUS; break;
case 0x0003: vesp.MEMORY[2] = micro_vesp.OBUS; break;
case 0x0004: vesp.MDR = micro_vesp.OBUS; break;
case 0x0005: vesp.MAR = micro_vesp.OBUS; break;
case 0x0006: vesp.MEMORY[1] = micro_vesp.OBUS; break; //save into B
case 0x0007: vesp.RET_SET = micro_vesp.OBUS; break; //set/clear RET_SET.
case 0x0008: vesp.C = micro_vesp.OBUS &0x0001; break; //set/clear C.
case 0x0009: vesp.Z = micro_vesp.OBUS &0x0001; break; //set/clear Z.
case 0x000A: vesp.S = micro_vesp.OBUS &0x0001; break; //set/clear S.
case 0x000B: vesp.F = micro_vesp.OBUS &0x0001; break; //set/clear F.
case 0x000C: vesp.memory_read=micro_vesp.OBUS &0x0001; break; //For memory read;
case 0x000D: break; //TBD
case 0x000E: break; //TBD
case 0x000F: break; //TBD
}
break;
case 0x4000: // branch µ-microinstruction
switch(vesp_micro.MIR & 0x0000E000)
{
case 0x00000000:
/* branch if A is positive*/
if(vesp.S == 0 && vesp.Z != 1 && (vesp_micro.MIR & 0x00001000) == 0x00001000)
vesp_micro.MAR = 0x00000FFF & vesp_micro.MIR;
else vesp_micro.MAR = vesp_micro.MAR + 1;
break;
case 0x00001000:
/* branch if A is negative */
if(vesp.S == 1 && (vesp_micro.MIR & 0x00001000) == 0x00001000)
vesp_micro.MAR = 0x00000FFF & vesp_micro.MIR;
else vesp_micro.MAR = vesp_micro.MAR + 1;
break;
case 0x00002000:
/* branch if A is 0 */
if(vesp.Z == 1 && (vesp_micro.MIR & 0x00001000) == 0x00001000)
vesp_micro.MAR = 0x00000FFF & vesp_micro.MIR;
else vesp_micro.MAR = vesp_micro.MAR + 1;
break;
/* always branch */
if ( (vesp_micro.MIR & 0x00001000) == 0x00001000)
vesp_micro.MAR = 0x00000FFF & vesp_micro.MIR;
else vesp_micro.MAR = vesp_micro.MAR + 1;
break;
case 0x00007000: return 1; /* exit */
}
}
micro_vesp.clock = micro_vesp.clock +1;
}
void loadmicrostore(void)
{//ABUS Source Map------ABUS = 0, A, PC, IR, IX
//BBUS Source Map------BBUS = MDR, MAR, B,1
//OBUS Function S----- OBUS = A, B, A+B, ~A, ~B, A & B, A|B, A >> 1, A << 1,~A + B
//OBUS DestinationS--- IX,A,PC,MAR,MDR,IR,B,RET_SET,vesp.C,vesp.Z,vesp.S, vesp.F,
//memory_read,memory_write
//initialize the instruction micro-routines' starting addresses
micro_vesp.add_address = 0;
micro_vesp.comp_address = 2;
micro_vesp.load_address = 4;
/*
// begin add
Machine code:
Add
case 0:
temp = A + B; vesp.clock = vesp.clock +1;
if(A > 0 && B > 0 && temp < 0 ||
A < 0 && B < 0 && temp >= 0)
vesp.F = 1; else vesp.F = 0; //AYO: Set Overflow Flag
if (A < 0 && B < 0 || temp > 0 &&
(A < 0 && B > 0 || A > 0 && B < 0))
vesp.C = 1; else vesp.C = 0; //AYO: Set Carry Flag
A = temp; vesp.MEMORY[0] = A; //Save the sum in MEMORY[0]
//AYO: Set Zero Flag
if(A == 0) vesp.Z = 1; else vesp.Z = 0;
//AYO: Set Sign Flag
vesp.S = (A & 0x8000 ) >> 15; vesp.add = 1; break;
Flags are done in the microsequencer
*/
// ABUS = A; BBUS = B; OBUS = ABUS + BBUS; A = OBUS;
micro_vesp.MICSTORE[0x000] = 0x0A20 //00 00 1 010 0010 0000;
// BBUS = 1; OBUS = BBUS; RET_SET = OBUS;
micro_vesp.MICSTORE[0x001] = 0x0317;//00 00 0 011 0001 0111 ;
/end ad
//begin complement
/*
Machine code:
Complement
case 1: A = ~A; vesp.MEMORY[0] = A;
vesp.clock = vesp.clock +1;
if(A == 0) vesp.Z = 1; else vesp.Z = 0;
vesp.S = (A & 0x8000 ) >> 15;
vesp.cmp = 1; break;
Flags are done in the microsequencer
*/
// ABUS = A; BBUS = N/A; OBUS = ~ABUS; A = OBUS;
micro_vesp.MICSTORE[0x002] = 0x0830 //00 00 1 xxx 0011 0000;
// BBUS = 1; OBUS = BBUS; RET_SET = OBUS;
micro_vesp.MICSTORE[0x003] = 0x0317;//00 00 0 011 0001 0111 ;
//end complement
//begin load
/*
Machine code:
case 2: vesp.MAR += 1;
vesp.clock = vesp.clock +1;
vesp.MDR = vesp.MEMORY[vesp.MAR];
vesp.MAR = vesp.IR&0x0FFF; //without an extra clock
vesp.clock = vesp.clock +1;
vesp.MEMORY[vesp.MAR] = vesp.MDR;
vesp.clock = vesp.clock +1; vesp.lda = 1;
//AYO: Set Zero Flag
if(vesp.MAR == 0 && A == 0) vesp.Z = 1; else vesp.Z = 0;
//AYO: Set Sign Flag
if(vesp.MAR == 0)
vesp.S = (A & 0x8000 ) >> 15;
vesp.PC = vesp.PC + 1; break;
*/
//increment MAR
// ABUS = 0; BBUS = MAR; OBUS = ~ABUS + BBUS; MAR = OBUS;
micro_vesp.MICSTORE[0x004] = 0x0193 //00 00 0 001 1001 0011;
/issue a read
// ABUS = N/A; BBUS = 1; OBUS = BBUS; vesp.memory_read = OBUS;
micro_vesp.MICSTORE[0x005] = 0x03AC;//00 00 0 011 1010 1100 ;
//wait for 1 clock cycle after issuing read
(this brings the operand in memory into MDR after 1 clock)
// ABUS = 0; OBUS = ABUS; RET_SET = OBUS;
micro_vesp.MICSTORE[0x006] = 0x0007;//00 00 0 xxx 0000 0111 ;
//copy the address in IR into MAR
ABUS = IR, BBUS = N/A; OBUS = ABUS; MAR = OBUS
micro_vesp.MICSTORE[0x007] = 0x1807;//00 01 1 xxx 0000 0111 ;
//issue a write
//ABUS = N/A; BBUS = 1; OBUS = BBUS; vesp.memory_write = OBUS;
micro_vesp.MICSTORE[0x008] = 0x03AD;//00 00 0 011 1010 1101 ;
//wait for 1 clock cycle after issuing write
(this writes the operand from MDR into memory after 1 clock)
// ABUS = 0; BBUS = N/A; OBUS = ABUS; RET_SET = OBUS;
micro_vesp.MICSTORE[0x009] = 0x0007;//00 00 0 xxx 0000 0111 ;
//increment PC
// ABUS = PC; BBUS = 1; OBUS = ABUS + BBUS; PC = OBUS;
micro_vesp.MICSTORE[0x00A] = 0x1322;//00 01 0 011 0010 010 ;
//exit
// BBUS = 1; OBUS = BBUS; RET_SET = OBUS;
micro_vesp.MICSTORE[0x00B] = 0x0317;//00 01 1 011 0010 0111 ;
//end load
/*
//Move
Machine code:
case 3: vesp.MAR += 1;
vesp.clock = vesp.clock +1;
vesp.MDR = vesp.MEMORY[vesp.MAR];
vesp.clock = vesp.clock +1;
vesp.MAR = vesp.MDR;
vesp.clock = vesp.clock +1;
vesp.MDR = vesp.MEMORY[vesp.MAR];
vesp.MAR = vesp.IR&0x0FFF; //without an extra clock
vesp.clock = vesp.clock +1;
vesp.MEMORY[vesp.MAR] = vesp.MDR;
vesp.clock = vesp.clock + 1; vesp.mov = 1;
//AYO: Set Zero Flag
if(vesp.MAR == 0 && A == 0) vesp.Z = 1; else vesp.Z = 0;
//AYO: Set Sign Flag
if(vesp.MAR == 0)
vesp.S = (A & 0x8000 ) >> 15;
vesp.PC = vesp.PC + 1; break;
*/
//begin move
//move (left for you to complete as part of assignment 3)
//end move
// beginjump
/*
Machine code:
case 4: vesp.PC = vesp.IR & 0x1FFF; vesp.jmp = 1;
vesp.clock = vesp.clock +1; break;
*/
//end jump
//jump if A = 0
case 5: if (A == 0)
{vesp.PC = vesp.IR & 0x0FFF;} vesp.jez = 1;
vesp.clock = vesp.clock +1; break;
//Jump if A is > 0
case 6: if (A > 0)
{vesp.PC = vesp.IR & 0x0FFF;} vesp.jps = 1;
vesp.clock = vesp.clock +1; break;
//Halt
case 7: vesp.reset = true; vesp.clock = vesp.clock +1; break;
//INC
case 8:
temp = A + 1; vesp.clock = vesp.clock +1;
if(A > 0 && B > 0 && temp < 0 ||
A < 0 && B < 0 && temp >= 0)
vesp.F = 1; else vesp.F = 0; //AYO: Set Overflow Flag
if (A < 0 && B < 0 || temp > 0 &&
(A < 0 && B > 0 || A > 0 && B < 0))
vesp.C = 1; else vesp.C = 0; //AYO: Set Carry Flag
A = temp; vesp.MEMORY[0] = A; //Save the sum in MEMORY[0]
//AYO: Set Zero Flag
if(A == 0) vesp.Z = 1; else vesp.Z = 0;
//AYO: Set Sign Flag
vesp.S = (A & 0x8000 ) >> 15; vesp.inc = 1; break;
//AYO: In this implementation, vesp.inc is just symbolically set to 1.
//In a bus implementation, the input bus must be loaded with 1 and the
//vesp's computation engine must be programmed to add its operands.
//DEC
case 9:
temp = A - 1; vesp.clock = vesp.clock +1;
if(A > 0 && B > 0 && temp < 0 ||
A < 0 && B < 0 && temp >= 0)
vesp.F = 1; else vesp.F = 0; //AYO: Set Overflow Flag
if (A < 0 && B < 0 || temp > 0 &&
(A < 0 && B > 0 || A > 0 && B < 0))
vesp.C = 1; else vesp.C = 0; //AYO: Set Carry Flag
A = temp; vesp.MEMORY[0] = A; //Save the sum in MEMORY[0]
//AYO: Set Zero Flag
if(A == 0) vesp.Z = 1; else vesp.Z = 0;
//AYO: Set Sign Flag
vesp.S = (A & 0x8000 ) >> 15; vesp.dec = 1; break;
//AYO: In this implementation, vesp.dec is just symbolically set to 1.
//In a bus implementation, the input bus must be loaded with 1 and complemented;
// carry-in must be set to vesp.dec, and the vesp's computation engine
// must be programmed to add its operands.
//AND
case 10:
temp = A & B; vesp.clock = vesp.clock +1;
A = temp; vesp.MEMORY[0] = A; //Save the sum in MEMORY[0]
//AYO: Set Zero Flag
if(A == 0) vesp.Z = 1; else vesp.Z = 0; vesp.lnd = 1; break;
//IOR
case 11:
temp = A | B; vesp.clock = vesp.clock +1;
A = temp; vesp.MEMORY[0] = A; //Save the sum in MEMORY[0]
//AYO: Set Zero Flag
if(A == 0) vesp.Z = 1; else vesp.Z = 0; vesp.lor = 1; break;
//SHL
case 12:
temp = A << 1; vesp.clock = vesp.clock +1;
A = temp; vesp.MEMORY[0] = A; //Save the sum in MEMORY[0]
//AYO: Set Zero Flag
if(A == 0) vesp.Z = 1; else vesp.Z = 0;
//AYO: Set Sign Flag
vesp.S = (A & 0x8000 ) >> 15; vesp.shl = 1; break;
//SHR
case 13:
temp = A >> 1; vesp.clock = vesp.clock +1;
A = temp; vesp.MEMORY[0] = A; //Save the sum in MEMORY[0]
//AYO: Set Zero Flag
if(A == 0) vesp.Z = 1; else vesp.Z = 0;
//AYO: Set Sign Flag
vesp.S = (A & 0x8000 ) >> 15; vesp.shr = 1; break;
//MXF (index is used to copy a list of operands into a location one at a time.)
case 14:
vesp.MAR = IX; // read the next operand
vesp.clock = vesp.clock +1;
vesp.MDR = vesp.MEMORY[vesp.MAR];
vesp.MAR = vesp.IR&0x0FFF; //without an extra clock
vesp.clock = vesp.clock +1;
vesp.MEMORY[vesp.MAR] = vesp.MDR; // move the operand to the specified address
IX++; //without an extra clock
vesp.clock = vesp.clock +1;
//AYO: Set Zero Flag
if(A == 0) vesp.Z = 1; else vesp.Z = 0;
//AYO: Set Sign Flag
vesp.S = (A & 0x8000 ) >> 15; vesp.mxf = 1; break;
//MXT (index is used to copy an operand to a set of locations one at a time.)
case 15:
vesp.MAR = vesp.IR&0x0FFF; // read the operand
vesp.clock = vesp.clock +1;
vesp.MDR = vesp.MEMORY[vesp.MAR];
vesp.MAR = IX; //without an extra clock
vesp.clock = vesp.clock +1;
vesp.MEMORY[vesp.MAR] = vesp.MDR; //move the operand to the next location
IX++; //without an extra clock
vesp.clock = vesp.clock +1;
//AYO: Set Zero Flag
if(A == 0) vesp.Z = 1; else vesp.Z = 0;
//AYO: Set Sign Flag
vesp.S = (A & 0x8000 ) >> 15; vesp.mxt = 1; break;
}
}
|