Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions 7/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.29)
project(syspro_cpp)

set(CMAKE_CXX_STANDARD 17)

add_executable(syspro_cpp
src/main.cpp
src/emulator.cpp
src/Jmpz.cpp
src/Mov.cpp
src/Add.cpp
src/Sub.cpp
src/Mul.cpp
src/Div.cpp
src/Load.cpp
src/Store.cpp
src/Jmp.cpp)

target_include_directories(syspro_cpp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
32 changes: 32 additions & 0 deletions 7/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Here is an simple Very Reduced Instruction Set Computer (vrisc) architecture.
It has only four integer registers `R0`, `R1`, `R2`, `R3`. And also has `1024` RAM memory cells.

The instruction set of vrisc assembly is:

| Instruction | Semantics |
| ----------- | --------- |
| `Mov Ri Rj` | `Ri = Rj` |
| `Mov Ri x ` | `Ri = x` |
| `Add Ri Rj` | `Ri += Rj` |
| `Add Ri x` | `Ri += x` |
| `Sub Ri Rj` | `Ri -= Rj` |
| `Sub Ri x` | `Ri -= x` |
| `Mul Ri Rj` | `Ri *= Rj` |
| `Mul Ri x` | `Ri *= x` |
| `Div Ri Rj` | `Ri /= Rj` |
| `Div Ri x` | `Ri /= x` |
| `Load Ri x` | `Ri = Mem[x]` |
| `Store Ri x` | `Mem[x] = Ri` |
| `Jmp x` | `pc = x` |
| `Jmpz x` | `pc = if R0 == 0 then pc = x else pc++` |

Where `x` is an immediate.

Your task is to write a simple emulator of this architecture.
The emulator must be implemented in the OOP paradigm.
In file `emulator.cpp` you can find the template for your solution.
File contains the base class of all instructions `Instruction`. All other instructions should be derived from it.
At the end of the emulation emulator should return value on the `R0` register.
Feel free to modify this source.

Don't forget about tests!
10 changes: 10 additions & 0 deletions 7/factorial.vrisc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Mov R0 5
Mov R1 1
Mov Jmpz 6

Mul R1 R0
Sub R0 1
Jmp 2

Mov R0 R1

15 changes: 15 additions & 0 deletions 7/include/Add.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#include "emulator.h"

namespace Emulator {
class Add : public Instruction {
Reg dst, src_reg;
int src_imm;
bool is_immediate;

public:
Add(Reg dst, Reg src);
Add(Reg dst, int imm);
void eval(EmulatorState& emul) override;
};
}
15 changes: 15 additions & 0 deletions 7/include/Div.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#include "emulator.h"

namespace Emulator {
class Div : public Instruction {
Reg dst, src_reg;
int src_imm;
bool is_immediate;

public:
Div(Reg dst, Reg src);
Div(Reg dst, int imm);
void eval(EmulatorState& emul) override;
};
}
12 changes: 12 additions & 0 deletions 7/include/Jmp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once
#include "emulator.h"

namespace Emulator {
class Jmp : public Instruction {
int src;

public:
explicit Jmp(int src);
void eval(EmulatorState& emul) override;
};
}
12 changes: 12 additions & 0 deletions 7/include/Jmpz.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once
#include "emulator.h"

namespace Emulator {
class Jmpz : public Instruction {
int src;

public:
explicit Jmpz(int src);
void eval(EmulatorState& emul) override;
};
}
13 changes: 13 additions & 0 deletions 7/include/Load.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once
#include "emulator.h"

namespace Emulator {
class Load : public Instruction {
Reg dst;
int src;

public:
Load(Reg dst, int src);
void eval(EmulatorState& emul) override;
};
}
15 changes: 15 additions & 0 deletions 7/include/Mov.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#include "emulator.h"

namespace Emulator {
class Mov : public Instruction {
Reg dst, src_reg;
int src_imm;
bool is_immediate;

public:
Mov(Reg dst, Reg src);
Mov(Reg dst, int imm);
void eval(EmulatorState& emul) override;
};
}
15 changes: 15 additions & 0 deletions 7/include/Mul.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#include "emulator.h"

namespace Emulator {
class Mul : public Instruction {
Reg dst, src_reg;
int src_imm;
bool is_immediate;

public:
Mul(Reg dst, Reg src);
Mul(Reg dst, int imm);
void eval(EmulatorState& emul) override;
};
}
13 changes: 13 additions & 0 deletions 7/include/Store.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once
#include "emulator.h"

namespace Emulator {
class Store : public Instruction {
int dst;
Reg src;

public:
Store(Reg src, int dst);
void eval(EmulatorState& emul) override;
};
}
15 changes: 15 additions & 0 deletions 7/include/Sub.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#include "emulator.h"

namespace Emulator {
class Sub : public Instruction {
Reg dst, src_reg;
int src_imm;
bool is_immediate;

public:
Sub(Reg dst, Reg src);
Sub(Reg dst, int imm);
void eval(EmulatorState& emul) override;
};
}
34 changes: 34 additions & 0 deletions 7/include/emulator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once
#include <optional>
#include <vector>
#include <string>

namespace Emulator {

enum Reg {
R0, R1, R2, R3
};

struct EmulatorState {
static const size_t regs_size = 4;
static const size_t mem_size = 1024;

std::vector<int> _registers{regs_size};
std::vector<int> _mem{mem_size};

size_t _pc = 0;
};

class Instruction {
public:
virtual void eval(EmulatorState& emul) = 0;
virtual ~Instruction() = default;
};

std::optional<Reg> strtoreg(const std::string& str);
std::vector<Instruction*> parse(const std::string& program);
int emulate(const std::string& program_text);
}

std::vector<std::string> split(const std::string& s, char delim);
std::optional<std::string> readStringFromFile(const std::string& filename);
14 changes: 14 additions & 0 deletions 7/src/Add.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "Add.h"

namespace Emulator {
Add::Add(Reg dst, Reg src) : dst(dst), src_reg(src), src_imm(0), is_immediate(false) {}
Add::Add(Reg dst, int imm) : dst(dst), src_reg(R0), src_imm(imm), is_immediate(true) {}

void Add::eval(EmulatorState& emul) {
if (is_immediate) {
emul._registers[dst] += src_imm;
} else {
emul._registers[dst] += emul._registers[src_reg];
}
}
}
14 changes: 14 additions & 0 deletions 7/src/Div.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "Div.h"

namespace Emulator {
Div::Div(Reg dst, Reg src) : dst(dst), src_reg(src), src_imm(0), is_immediate(false) {}
Div::Div(Reg dst, int imm) : dst(dst), src_reg(R0), src_imm(imm), is_immediate(true) {}

void Div::eval(EmulatorState& emul) {
if (is_immediate) {
emul._registers[dst] /= src_imm;
} else {
emul._registers[dst] /= emul._registers[src_reg];
}
}
}
9 changes: 9 additions & 0 deletions 7/src/Jmp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "Jmp.h"

namespace Emulator {
Jmp::Jmp(int src) : src(src) {}

void Jmp::eval(EmulatorState& emul) {
emul._pc = src;
}
}
9 changes: 9 additions & 0 deletions 7/src/Jmpz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "Jmpz.h"

namespace Emulator {
Jmpz::Jmpz(int src) : src(src) {}

void Jmpz::eval(EmulatorState& emul) {
emul._pc = (emul._registers[R0] == 0) ? src : (emul._pc + 1);
}
}
9 changes: 9 additions & 0 deletions 7/src/Load.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "Load.h"

namespace Emulator {
Load::Load(Reg dst, int src) : dst(dst), src(src) {}

void Load::eval(EmulatorState& emul) {
emul._registers[dst] = emul._mem[src];
}
}
14 changes: 14 additions & 0 deletions 7/src/Mov.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "Mov.h"

namespace Emulator {
Mov::Mov(Reg dst, Reg src) : dst(dst), src_reg(src), src_imm(0), is_immediate(false) {}
Mov::Mov(Reg dst, int imm) : dst(dst), src_reg(R0), src_imm(imm), is_immediate(true) {}

void Mov::eval(EmulatorState& emul) {
if (is_immediate) {
emul._registers[dst] = src_imm;
} else {
emul._registers[dst] = emul._registers[src_reg];
}
}
}
14 changes: 14 additions & 0 deletions 7/src/Mul.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "Mul.h"

namespace Emulator {
Mul::Mul(Reg dst, Reg src) : dst(dst), src_reg(src), src_imm(0), is_immediate(false) {}
Mul::Mul(Reg dst, int imm) : dst(dst), src_reg(R0), src_imm(imm), is_immediate(true) {}

void Mul::eval(EmulatorState& emul) {
if (is_immediate) {
emul._registers[dst] *= src_imm;
} else {
emul._registers[dst] *= emul._registers[src_reg];
}
}
}
9 changes: 9 additions & 0 deletions 7/src/Store.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "Store.h"

namespace Emulator {
Store::Store(Reg src, int dst) : dst(dst), src(src) {}

void Store::eval(EmulatorState& emul) {
emul._mem[dst] = emul._registers[src];
}
}
14 changes: 14 additions & 0 deletions 7/src/Sub.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "Sub.h"

namespace Emulator {
Sub::Sub(Reg dst, Reg src) : dst(dst), src_reg(src), src_imm(0), is_immediate(false) {}
Sub::Sub(Reg dst, int imm) : dst(dst), src_reg(R0), src_imm(imm), is_immediate(true) {}

void Sub::eval(EmulatorState& emul) {
if (is_immediate) {
emul._registers[dst] -= src_imm;
} else {
emul._registers[dst] -= emul._registers[src_reg];
}
}
}
Loading