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