1

Implement JMP instructions and fix a parsing bug, when MOV is called with a register as source

This commit is contained in:
2023-03-21 17:14:40 +01:00
parent 664c28f635
commit b9898e0a8d
5 changed files with 91 additions and 21 deletions

View File

@ -0,0 +1,11 @@
//
// Created by christoph on 21.03.23.
//
#include "JumpNode.h"
JumpNode::JumpNode(JumpNode::JumpOperation operation) : operation(operation) {}
uint8_t JumpNode::compile() const {
return (CONDITION & 0b11) << 6 | (operation & 0b111);
}

34
src/ast/nodes/JumpNode.h Normal file
View File

@ -0,0 +1,34 @@
//
// Created by christoph on 21.03.23.
//
#ifndef LOGISIMASSEMBLER_JUMPNODE_H
#define LOGISIMASSEMBLER_JUMPNODE_H
#include "../Node.h"
class JumpNode : public Node {
public:
enum JumpOperation : uint8_t {
NEVER,
EQUAL_ZERO,
LESS_ZERO,
LESS_EQUAL_ZERO,
ALWAYS,
NOT_ZERO,
GREATER_ZERO,
GREATER_EQUAL_ZERO
};
public:
JumpNode(JumpOperation operation);
~JumpNode() override = default;
[[nodiscard]] auto compile() const -> uint8_t override;
private:
JumpOperation operation;
};
#endif //LOGISIMASSEMBLER_JUMPNODE_H

View File

@ -45,9 +45,10 @@ auto is_alphabetical(const char character) -> bool {
}
auto is_mnemonic(const Token &token) -> bool {
// TODO: Add other mnemonics
// TODO: Move this to a separate header
const std::vector<std::string> mnemonics = {"MOV",
"ADD"};
"AND", "OR", "NAND", "NOR", "ADD", "SUB",
"JEQ", "JLE", "JLEQ", "JNEQ", "JGR", "JGEQ"};
return std::find(mnemonics.begin(), mnemonics.end(), static_cast<std::string_view>(token))
!= mnemonics.end();

View File

@ -6,13 +6,13 @@
#include "../ast/nodes/MovNode.h"
#include "../ast/nodes/ConstNode.h"
#include "../ast/nodes/AluNode.h"
#include <map>
#include "../ast/nodes/JumpNode.h"
// ! Helper Functions
// ! Public Functions
Parser::Parser(const std::vector<Token> &tokens) : tokens(tokens), position(tokens.begin()) {}
Parser::Parser(const std::vector<Token> &tokens) : position(tokens.begin()) {}
auto Parser::parse() -> std::unique_ptr<Node> {
while (peek().getType() != Token::END) {
@ -20,16 +20,7 @@ auto Parser::parse() -> std::unique_ptr<Node> {
throw "Parser Error: Expected Mnemonic!";
}
// TODO: Put these functions in a map, mapped to the mnemonic name string
if (static_cast<std::string_view>(peek()) == "MOV") {
mov();
continue;
}
if (static_cast<std::string_view>(peek()) == "ADD") {
alu();
continue;
}
eaters[static_cast<std::string>(peek())](*this);
}
return std::move(ast);
@ -54,19 +45,17 @@ void Parser::mov() {
uint8_t source = 0; // Load from reg0
if (peek().getType() == Token::NUMBER) {
ast->addChild(std::move(std::make_unique<ConstNode>(static_cast<uint8_t>(peek())))); // Load constant to reg0
} else if (peek().getType() == Token::IDENTIFIER) {
source = static_cast<uint8_t>(peek());
} else if (peek().getType() == Token::IDENTIFIER && static_cast<std::string_view>(peek().subtoken(0, 3)) == "reg") {
source = static_cast<uint8_t>(peek().subtoken(3, 1));
} else {
throw "Parser Error: Expected Constant or Register!";
}
get(); // Eat source
const Token identifier = peek().subtoken(0, 3);
const Token reg = peek().subtoken(3, 1); // Get reg number
if (peek().getType() != Token::IDENTIFIER || static_cast<std::string_view>(identifier) != "reg") {
if (peek().getType() != Token::IDENTIFIER || static_cast<std::string_view>(peek().subtoken(0, 3)) != "reg") {
throw "Parser Error: Expected Register!";
}
auto target = static_cast<uint8_t>(reg);
auto target = static_cast<uint8_t>(peek().subtoken(3, 1));
get(); // Eat target
ast->addChild(std::move(std::make_unique<MovNode>(source, target)));
@ -89,3 +78,21 @@ void Parser::alu() {
ast->addChild(std::move(std::make_unique<AluNode>(aluMap[static_cast<std::string>(get())]))); // Eat alu
}
void Parser::jmp() {
std::map<std::string, JumpNode::JumpOperation> jmpMap = {{"JEQ", JumpNode::EQUAL_ZERO},
{"JLE", JumpNode::LESS_ZERO},
{"JLEQ", JumpNode::LESS_EQUAL_ZERO},
{"JNEQ", JumpNode::NOT_ZERO},
{"JGR", JumpNode::GREATER_ZERO},
{"JGEQ", JumpNode::GREATER_EQUAL_ZERO}};
if (peek().getType() != Token::MNEMONIC) {
throw "Parser Error: Expected Mnemonic!";
}
if (!jmpMap.contains(static_cast<std::string>(peek()))) {
throw "Parser Error: Invalid JMP operation!";
}
ast->addChild(std::move(std::make_unique<JumpNode>(jmpMap[static_cast<std::string>(get())]))); // Eat jmp
}

View File

@ -7,6 +7,8 @@
#include <memory>
#include <vector>
#include <map>
#include <functional>
#include "../lexer/Token.h"
#include "../ast/Node.h"
#include "../ast/nodes/RootNode.h"
@ -28,10 +30,25 @@ private:
void alu();
void jmp();
private:
const std::vector<Token> &tokens;
std::vector<Token>::const_iterator position;
std::unique_ptr<Node> ast = std::make_unique<RootNode>();
std::map<std::string, std::function<void(Parser &)>> eaters = {{"MOV", &Parser::mov},
{"AND", &Parser::alu},
{"OR", &Parser::alu},
{"NAND", &Parser::alu},
{"NOR", &Parser::alu},
{"ADD", &Parser::alu},
{"SUB", &Parser::alu},
{"JEQ", &Parser::jmp},
{"JLE", &Parser::jmp},
{"JLEQ", &Parser::jmp},
{"JNEQ", &Parser::jmp},
{"JGR", &Parser::jmp},
{"JGEQ", &Parser::jmp}};
};
#endif //LOGISIMASSEMBLER_PARSER_H