/*
* main.cc
*
* Assembler for PDP-8 Virtual Machine
*
* Created on: Mar 16, 2010
* Author: matthew
*/
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <vector>
#include <string.h>
#include <sstream>
#include "myLib.h"
using namespace std;
void compile(vector<instruction> &code, vector<message> &report)
{
ostringstream output;
int n,bit4, bit3=0;
string op_code;
//Check START
if(code[0].word[0]!="START")
{
c_error(report, 0, "START expected.");
}
//Compile code
for(int a=1; a<code.size()-1; a++)
{
//Set operation code
if(code[a].word[0]=="AND")
{
op_code="000";
}
else if(code[a].word[0]=="TAD")
{
op_code="001";
}
else if(code[a].word[0]=="ISZ")
{
op_code="010";
}
else if(code[a].word[0]=="DCA")
{
op_code="011";
}
else if(code[a].word[0]=="JMS")
{
op_code="100";
}
else if(code[a].word[0]=="JMP")
{
op_code="101";
}
else if(code[a].word[0]=="OUT")
{
op_code="110";
}
else if(code[a].word[0]=="HLT")
{
output<<"111";
output<<"110000010";
continue;
}
else if(code[a].word[0]=="CLA")
{
output<<"111";
output<<"010000000";
continue;
}
else if(code[a].word[0]=="CMA")
{
output<<"111";
output<<"000100000";
continue;
}
else if(code[a].word[0]=="IAC")
{
output<<"111";
output<<"000000001";
continue;
}
else if(code[a].word[0]=="CLL")
{
output<<"111";
output<<"001000000";
continue;
}
else if(code[a].word[0]=="CML")
{
output<<"111";
output<<"000010000";
continue;
}
else if(code[a].word[0]=="RAR")
{
output<<"111";
output<<"000001000";
continue;
}
else if(code[a].word[0]=="RAL")
{
output<<"111";
output<<"000000100";
continue;
}
else if(code[a].word[0]=="RTR")
{
output<<"111";
output<<"000001010";
continue;
}
else if(code[a].word[0]=="RTL")
{
output<<"111";
output<<"000000110";
continue;
}
else if(code[a].word[0]=="SZA")
{
output<<"111";
output<<"100100000";
continue;
}
else if(code[a].word[0]=="SZL")
{
output<<"111";
output<<"100011000";
continue;
}
//Return error if the operation is unknown
else
{
c_error(report, a, code[a].word[0]+" unknown instruction.");
continue;
}
//Check number of arguments
if(code[a].word.size()!=2)
{
c_error(report, a, code[a].word[0]+" requires 1 argument.");
continue;
}
//Check if the reference is direct and set bit 3
if(code[a].word[1][0]=='$')bit3=1;
else bit3=0;
n = atoi(code[a].word[1].c_str()+bit3);
//TODO: create variables and handle direct addresses
//Check if the address is valid
if((n>0 && n<129 && n>>0))
{
//check if the address is in the same page as the instruction
bit4 = bit_4(code[a].line, n);
if(bit4==-1)
c_error(report, a, "this operation cannot directly access address ");
//Now assembly instruction
output<<op_code;
output<<bit3;
output<<bit4;
output<<binary(n);
}
//Report an error if not
else
{
c_error(report, a, code[a].word[1]+" invalid address.");
}
}
//Check END
if(code[code.size()-1].word[0]!="END")
{
c_error(report, code.size()-1, "END expected.");
}
if(report.size()==0)
{
ofstream binfile;
binfile.open("bin.txt");
if(binfile.good())
{
binfile<<output.str();
debug_message("Binary file successfully assembled.");
}
else
{
error("Cannot create binary file file.");
}
binfile.close();
}
}
int main()
{
ifstream sourcefile;
ofstream binfile;
int linenum=0;
vector<message>report;
vector<instruction>code;
//Open source file
sourcefile.open("source.txt");
if(sourcefile.good())
{
debug_message("Source file successfully opened.");
}
else
{
error("Cannot open source file.");
}
//Read source file and create source code structure
while(!sourcefile.eof())
{
char line[50], *command;
bool flag=false;
instruction i;
//Read line from source file
sourcefile.getline(line, 50);
//Split string into words
command = strtok (line," \t");
if(command!=NULL)flag=true;
while (command != NULL)
{
//Create instruction
i.word.push_back(command);
command = strtok (NULL, " \t");
}
//Flag ignores blank lines
if(flag)
{
//Add line number to instruction
i.line=linenum++;
//Add instruction to source code
code.push_back(i);
}
}
//Close source file
sourcefile.close();
cout<<endl<<"SOURCE CODE:"<<endl<<endl;
//Compile source
compile(code, report);
//Print code
for(int a=0; a<code.size(); a++)
{
cout<<code[a].line<<" ";
for(int b=0; b<code[a].word.size(); b++)
{
cout<<code[a].word[b]<< " ";
}
cout<<endl;
}
show_report(report);
return 0;
}