/*
* Author: Pawel Jablonski
* E-mail: pj@xirx.net
* WWW: xirx.net
* GIT: git.xirx.net
*
* License: You can use this code however you like
* but leave information about the original author.
* Code is free for non-commercial and commercial use.
*/
#include "asm.h"
//! Constructor for assembler start functions
Asm::Asm()
{
}
/**
* Compile the kernel
*
* @param inputFile Name of the input source file
* @param outputFile Name of the output binary file
* @param outputMapFile Name of the output map file
*
* @return Status of compilation
*/
bool Asm::compileRom(const QString &inputFile, const QString &outputFile, const QString &outputMapFile)
{
return(this->compile(DataList::Mode::Rom, inputFile, outputFile, outputMapFile));
}
/**
* Compile the application
*
* @param inputFile Name of the input source file
* @param outputFile Name of the output binary file
*
* @return Status of compilation
*/
bool Asm::compileApp(const QString &inputFile, const QString &outputFile)
{
return(this->compile(DataList::Mode::App, inputFile, outputFile));
}
/**
* Compile the source
*
* @param mode Mode of compilation
* @param inputFile Name of the input source file
* @param outputFile Name of the output binary file
* @param outputMapFile Name of the output map file
*
* @return Status of compilation
*/
bool Asm::compile(DataList::Mode mode, QString inputFile, QString outputFile, QString outputMapFile)
{
QTextStream out(stdout);
DataList dataList(mode);
Parser parser(dataList);
if(!parser.parseFile(inputFile))
{
out << "ERROR: Parsing error\n\n";
return(-1);
}
Compiler compiler(dataList);
this->initInstructions(compiler);
if(!compiler.compile())
{
out << "ERROR: Compilation error\n\n";
return(-1);
}
Linker linker(dataList);
if(!linker.link())
{
out << "ERROR: Linking error\n\n";
return(-1);
}
if(!linker.saveFile(outputFile, outputMapFile))
{
out << "ERROR: Failed to save file\n\n";
return(-1);
}
out << "OK: The file was saved successfully\n\n";
return(0);
}
/**
* Init the instruction list for the compiler
*
* @param compiler Compiler to which the instructions will be added
*/
void Asm::initInstructions(Compiler &compiler)
{
// LOAD_I + RPC+1
compiler.addInstruction(Instruction("nop", 0b00000000));
// LOAD_I + RPC
compiler.addInstruction(Instruction("halt", 0b11111111));
// LOAD_I + STORE + RPC+1
compiler.addInstruction(Instruction("ldf", 0b00000100, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("ldr", 0b00001000, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("str", 0b00001100, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("mov", 0b10000000, Instruction::Arg::ABXY, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("in", 0b00010000, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("out", 0b00010100, Instruction::Arg::ABXY));
// LOAD_I + ALU + RPC+1
compiler.addInstruction(Instruction("cmp", 0b11100000, Instruction::Arg::AB, Instruction::Arg::ABXY));
// LOAD_I + ALU + STORE + RPC+1
compiler.addInstruction(Instruction("inc", 0b00011000, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("incc", 0b01110000, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("dec", 0b00011100, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("decc", 0b01110100, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("not", 0b00100000, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("add", 0b10010000, Instruction::Arg::AB, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("addc", 0b10011000, Instruction::Arg::AB, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("sub", 0b10100000, Instruction::Arg::AB, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("subc", 0b10101000, Instruction::Arg::AB, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("and", 0b10110000, Instruction::Arg::AB, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("or", 0b10111000, Instruction::Arg::AB, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("xor", 0b11000000, Instruction::Arg::AB, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("shl", 0b01111000, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("clr", 0b11001000, Instruction::Arg::ABXY));
// LOAD_I + 8x ALU + STORE + RPC+1
compiler.addInstruction(Instruction("shr", 0b01111100, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("swap", 0b01101100, Instruction::Arg::ABXY));
// LOAD_I + PC+1 + STORE + RPC+1
compiler.addInstruction(Instruction("mov", 0b00100100, Instruction::Arg::Val256, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("out", 0b00000010, Instruction::Arg::Val256));
// LOAD_I + PC+1 + LOAD_D + STORE + RPC+1
compiler.addInstruction(Instruction("str", 0b00000001, Instruction::Arg::Val256));
// LOAD_I + PC+1 + LOAD_D + ALU + RPC+1
compiler.addInstruction(Instruction("cmp", 0b00101000, Instruction::Arg::Val256, Instruction::Arg::ABXY));
// LOAD_I + PC+1 + LOAD_D + ALU + STORE + RPC+1
compiler.addInstruction(Instruction("add", 0b00101100, Instruction::Arg::Val256, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("addc", 0b00110000, Instruction::Arg::Val256, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("sub", 0b00110100, Instruction::Arg::Val256, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("subc", 0b00111000, Instruction::Arg::Val256, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("and", 0b00111100, Instruction::Arg::Val256, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("or", 0b01000000, Instruction::Arg::Val256, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("xor", 0b01000100, Instruction::Arg::Val256, Instruction::Arg::ABXY));
// LOAD_I + PC+1 + LOAD_MAL + PC+1 + LOAD_MAH + STORE + RPC+1
compiler.addInstruction(Instruction("ldf", 0b01011000, Instruction::Arg::Addr, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("ldr", 0b01011100, Instruction::Arg::Addr, Instruction::Arg::ABXY));
compiler.addInstruction(Instruction("str", 0b01100000, Instruction::Arg::ABXY, Instruction::Arg::Addr));
// LOAD_I + PC+1 + LOAD_D + PC+1 + LOAD_MAL + PC+1 + LOAD_MAH + STORE + RPC+1
compiler.addInstruction(Instruction("str", 0b00000011, Instruction::Arg::Val256, Instruction::Arg::Addr));
// LOAD_I + LOAD + LOAD + RPC+1 + LOAD_I + LOAD + RPC+1
compiler.addInstruction(Instruction("xchg", 0b11010000, Instruction::Arg::ABXY, Instruction::Arg::ABXY, Instruction::Arg::None, 0b11001100, Instruction::Arg::ABXY));
// LOAD_I + PC+1 + LOAD_MAL + PC+1 + LOAD_MAH + 3x STORE + RPC+1
compiler.addInstruction(Instruction("xchg", 0b01001000, Instruction::Arg::Addr, Instruction::Arg::ABXY));
// LOAD_I + PC+1 + LOAD_PCL + PC+1 + LOAD_PCH + STORE + RESET
compiler.addInstruction(Instruction("jmp", 0b11110000, Instruction::Arg::Addr));
// LOAD_I + PC+1 + LOAD_D + PC+1 + LOAD_PCH + STORE + RESET
// + PC+1 + PC+1 + RPC+1
compiler.addInstruction(Instruction("je", 0b11111000, Instruction::Arg::Addr));
compiler.addInstruction(Instruction("jne", 0b11111001, Instruction::Arg::Addr));
compiler.addInstruction(Instruction("jg", 0b11111010, Instruction::Arg::Addr));
compiler.addInstruction(Instruction("jge", 0b11111011, Instruction::Arg::Addr));
compiler.addInstruction(Instruction("jl", 0b11111100, Instruction::Arg::Addr));
compiler.addInstruction(Instruction("jle", 0b11111101, Instruction::Arg::Addr));
// LOAD_I + STORE + SP-1 + RPC+1
compiler.addInstruction(Instruction("push", 0b01100100, Instruction::Arg::ABXY));
// LOAD_I + SP+1 + STORE + RPC+1
compiler.addInstruction(Instruction("pop", 0b01101000, Instruction::Arg::ABXY));
// LOAD_I + STORE + SP-1 + STORE + SP-1 + PC+1 + LOAD_D + PC+1 + LOAD_PCH + STORE + RESET
compiler.addInstruction(Instruction("call", 0b11110001, Instruction::Arg::Addr));
// LOAD_I + SP+1 + STORE + SP+1 + STORE + RESET
compiler.addInstruction(Instruction("ret", 0b11110010));
// LOAD_I + ALU + PC+1 + PC+1 + RPC+1
// + ALU + STORE + PC+1 + LOAD_D + PC+1 + LOAD_PCH + STORE + RESET
compiler.addInstruction(Instruction("loope", 0b11101000, Instruction::Arg::AB, Instruction::Arg::ABXY, Instruction::Arg::Addr));
// LOAD_I + ALU + STORE + PC+1 + PC+1 + PC+1 + RPC+1
// + ALU + STORE + PC+1 + LOAD_D + PC+1 + LOAD_PCH + STORE + RESET
compiler.addInstruction(Instruction("loope", 0b01001100, Instruction::Arg::Val256, Instruction::Arg::ABXY, Instruction::Arg::Addr));
// LOAD_I + ALU STORE + PC+1 + PC+1 + RPC+1
// + ALU + STORE + PC+1 + LOAD_D + PC+1 + LOAD_PCH + STORE + RESET
compiler.addInstruction(Instruction("loopz", 0b11110100, Instruction::Arg::ABXY, Instruction::Arg::Addr));
}