first commit

This commit is contained in:
2024-10-22 16:42:28 +02:00
commit 8a98e89c51
12 changed files with 5501958 additions and 0 deletions

37
.clang-format Normal file
View File

@@ -0,0 +1,37 @@
Language: Cpp
BasedOnStyle: LLVM
AlignAfterOpenBracket: DontAlign
BreakConstructorInitializers: AfterColon
ConstructorInitializerAllOnOneLineOrOnePerLine: true
PointerAlignment: Left
SortIncludes: true
SpacesBeforeTrailingComments: 2
UseTab: Always
MaxEmptyLinesToKeep: 5
TabWidth: 4
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
IndentWidth: 4
IndentCaseLabels: true
ColumnLimit: 135
AlwaysBreakTemplateDeclarations: Yes
AllowShortFunctionsOnASingleLine: Empty
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
# Xmake cache
.xmake/
build/
# MacOS Cache
.DS_Store

13
.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,13 @@
{
"configurations": [
{
"name": "Blitz",
"cppStandard": "c++17",
"includePath": [
"include"
],
"compileCommands": ".vscode/compile_commands.json"
}
],
"version": 4
}

11
.vscode/compile_commands.json vendored Normal file
View File

@@ -0,0 +1,11 @@
[
{
"directory": "/home/simon/Programmation/Assembleur",
"arguments": ["/usr/bin/gcc", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-DNDEBUG", "-o", "build/.objs/Assembleur/linux/x86_64/release/src/main.cpp.o", "src/main.cpp"],
"file": "src/main.cpp"
},
{
"directory": "/home/simon/Programmation/Assembleur",
"arguments": ["/usr/bin/gcc", "-c", "-m64", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-O3", "-DNDEBUG", "-o", "build/.objs/Assembleur/linux/x86_64/release/src/Assembleur.cpp.o", "src/Assembleur.cpp"],
"file": "src/Assembleur.cpp"
}]

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"stdexcept": "cpp"
}
}

176
src/Assembleur.cpp Normal file
View File

@@ -0,0 +1,176 @@
#include "Assembleur.h"
#include <map>
#include <sstream>
#include <stdexcept>
enum TypeArithmetique {
Add = 0,
Sub,
And,
Or,
Xor,
Sl,
Sr,
Not,
};
enum TypeMemoire {
Str = 0,
Ld,
};
enum TypeSautControle {
Jump = 0,
Jequ,
Jneq,
Jsup,
Jinf,
Call,
Ret,
};
static std::map<std::string, Instruction> INSTRUCTION_KEYS = {
{"add", {Arithmetique, Add}},
{"sub", {Arithmetique, Sub}},
{"and", {Arithmetique, And}},
{"or", {Arithmetique, Or}},
{"xor", {Arithmetique, Xor}},
{"sl", {Arithmetique, Sl}},
{"sr", {Arithmetique, Sr}},
{"str", {Memoire, Str}},
{"ld", {Memoire, Ld}},
{"jmp", {SautControle, Jump}},
{"jequ", {SautControle, Jequ}},
{"jneq", {SautControle, Jneq}},
{"jsup", {SautControle, Jsup}},
{"jinf", {SautControle, Jinf}},
{"call", {SautControle, Call}},
{"ret", {SautControle, Ret}},
};
std::uint32_t Assembleur::ParseLabel(const std::string& a_Label) {
auto it = m_Labels.find(a_Label);
if (it == m_Labels.end()) {
throw std::runtime_error("Label " + a_Label + " not found !");
}
return it->second;
}
void Assembleur::AddLabel(const std::string& a_Label, std::uint32_t a_Line) {
m_Labels.insert({a_Label, a_Line});
}
std::uint32_t Assembleur::IToInt(Instruction a_Instruction) {
return static_cast<std::uint32_t>(a_Instruction.m_Instruction) << 30 | static_cast<std::uint32_t>(a_Instruction.m_SubInstruction)
<< 28;
}
std::uint32_t Assembleur::ParseOperation(Instruction a_Instruction, std::uint32_t a_R1, std::uint32_t a_R2, std::uint32_t a_R3) {
return IToInt(a_Instruction) | a_R1 << 23 | a_R2 << 20 | a_R3 << 17;
}
std::uint32_t Assembleur::ParseOperationImmediate(
Instruction a_Instruction, std::uint32_t a_R1, std::uint32_t a_R2, std::uint32_t a_C1) {
return IToInt(a_Instruction) | 1 << 26 | a_R1 << 23 | a_R2 << 20 | a_C1;
}
std::uint32_t Assembleur::ParseJump(Instruction a_Instruction, const std::string& a_Label) {
return IToInt(a_Instruction) | a_Instruction.m_Line - ParseLabel(a_Label);
}
std::uint32_t Assembleur::ParseJump(Instruction a_Instruction, std::uint8_t a_R1, std::uint8_t a_R2, const std::string& a_Label) {
return IToInt(a_Instruction) | a_R1 << 24 | a_R2 << 21 | a_Instruction.m_Line - ParseLabel(a_Label);
}
std::uint32_t Assembleur::ParseJump(Instruction a_Instruction) {
return IToInt(a_Instruction);
}
std::uint32_t Assembleur::ParseIO(Instruction a_Instruction, std::uint32_t a_R1, std::uint32_t a_R2, std::uint32_t a_R3) {
return IToInt(a_Instruction) | a_R1 << 24 | a_R2 << 21 | a_R3 << 18;
}
static std::uint32_t ParseRegistry(const std::string& a_Str) {
if (a_Str.at(0) != 'R')
throw std::runtime_error("Registry " + a_Str + " not found !");
return std::stoi(a_Str.substr(1));
}
static bool IsConstant(const std::string& a_Str) {
return a_Str.at(0) == '#';
}
static std::uint32_t ParseConstant(const std::string& a_Str) {
if (a_Str.at(0) != '#')
throw std::runtime_error("Registry " + a_Str + " not found !");
return std::stoi(a_Str.substr(1));
}
std::uint32_t Assembleur::ParseInstruction(const std::string& a_Str, std::uint32_t a_Line, std::uint32_t a_RealLine) {
std::stringstream ss{a_Str};
std::string ins;
ss >> ins;
auto it = INSTRUCTION_KEYS.find(ins);
if (it == INSTRUCTION_KEYS.end()) {
throw std::runtime_error("[Line " + std::to_string(a_RealLine) + "] " + "Instruction \"" + ins + "\" not found !");
}
Instruction instruction = it->second;
instruction.m_Line = a_Line;
try {
switch (instruction.m_Instruction) {
case Arithmetique: {
std::string R1, R2, R3;
ss >> R1 >> R2 >> R3;
if (IsConstant(R3)) {
return ParseOperationImmediate(instruction, ParseRegistry(R1), ParseRegistry(R2), ParseConstant(R3));
} else {
return ParseOperation(instruction, ParseRegistry(R1), ParseRegistry(R2), ParseRegistry(R3));
}
}
case Memoire: {
std::string R1, R2, R3;
ss >> R1 >> R2 >> R3;
return ParseIO(instruction, ParseRegistry(R1), ParseRegistry(R2), ParseRegistry(R3));
}
case SautControle: {
switch (instruction.m_SubInstruction) {
case Ret:
return ParseJump(instruction);
case Call:
case Jump: {
std::string label;
ss >> label;
return ParseJump(instruction, label);
}
case Jequ:
case Jneq:
case Jsup:
case Jinf: {
std::string R1, R2, label;
ss >> R1 >> R2 >> label;
return ParseJump(instruction, ParseRegistry(R1), ParseRegistry(R2), label);
}
}
}
}
} catch (std::runtime_error& e) {
throw std::runtime_error("[Line " + std::to_string(a_RealLine) + "] " + e.what());
}
return 0;
}

44
src/Assembleur.h Normal file
View File

@@ -0,0 +1,44 @@
#pragma once
#include <cstdint>
#include <map>
#include <string>
enum TypeInstruction : std::uint8_t {
Arithmetique = 0,
Memoire = 1,
SautControle = 3,
};
struct Instruction {
TypeInstruction m_Instruction;
std::uint8_t m_SubInstruction;
std::uint32_t m_Line;
};
class Assembleur {
private:
std::map<std::string, std::uint32_t> m_Labels;
public:
void AddLabel(const std::string& a_Label, std::uint32_t a_Line);
std::uint32_t ParseInstruction(const std::string& a_Str, std::uint32_t a_Line, std::uint32_t a_RealLine);
private:
std::uint32_t ParseLabel(const std::string& a_Label);
std::uint32_t IToInt(Instruction a_Instruction);
std::uint32_t ParseOperation(Instruction a_Instruction, std::uint32_t a_R1, std::uint32_t a_R2, std::uint32_t a_R3);
std::uint32_t ParseOperationImmediate(Instruction a_Instruction, std::uint32_t a_R1, std::uint32_t a_R2, std::uint32_t a_C1);
std::uint32_t ParseJump(Instruction a_Instruction, const std::string& a_Label);
std::uint32_t ParseJump(Instruction a_Instruction, std::uint8_t a_R1, std::uint8_t a_R2, const std::string& a_Label);
std::uint32_t ParseJump(Instruction a_Instruction);
std::uint32_t ParseIO(Instruction a_Instruction, std::uint32_t a_R1, std::uint32_t a_R2, std::uint32_t a_R3);
};

53
src/main.cpp Normal file
View File

@@ -0,0 +1,53 @@
#include <fstream>
#include <iostream>
#include <vector>
#include "Assembleur.h"
using BinaryData = std::vector<std::uint32_t>;
static BinaryData ParseFile(const std::string& fileName) {
std::ifstream file{fileName};
std::uint32_t lineNumber = 0, realLineNumber = 0;
std::string line;
Assembleur assembleur;
BinaryData output;
while (getline(file, line)) {
lineNumber++;
realLineNumber++;
if (line.find(":") != std::string::npos) {
std::string label = line.substr(0, line.size() - 1);
assembleur.AddLabel(label, lineNumber);
lineNumber--;
} else {
output.push_back(assembleur.ParseInstruction(line, lineNumber, realLineNumber));
}
}
return output;
}
static void OutputFile(const BinaryData& a_Data, const std::string& fileName) {
std::ofstream file {fileName};
file.write(reinterpret_cast<const char*>(a_Data.data()), a_Data.size() * sizeof(a_Data.at(0)));
}
int main(int argc, char** argv) {
try {
auto output = ParseFile("test.asm");
OutputFile(output, "test.bin");
} catch (std::runtime_error& e) {
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}

20
test.asm Normal file
View File

@@ -0,0 +1,20 @@
operations:
add R1 R2 R3
sub R1 R2 #69
and R1 R2 R3
xor R1 R2 R3
or R1 R2 R3
sl R1 R2 R3
sr R1 R2 R3
io:
str R1 R2 R3
ld R1 R2 R3
sauts:
jmp operations
jequ R1 R2 io
jneq R1 R2 sauts
jsup R1 R2 operations
jinf R1 R2 io
controle:
call io
ret

BIN
test.bin Normal file

Binary file not shown.

5501515
test.txt Normal file

File diff suppressed because it is too large Load Diff

76
xmake.lua Normal file
View File

@@ -0,0 +1,76 @@
add_rules("mode.debug", "mode.release")
target("Assembleur")
set_kind("binary")
add_files("src/*.cpp")
set_rundir(".")
--
-- If you want to known more usage about xmake, please see https://xmake.io
--
-- ## FAQ
--
-- You can enter the project directory firstly before building project.
--
-- $ cd projectdir
--
-- 1. How to build project?
--
-- $ xmake
--
-- 2. How to configure project?
--
-- $ xmake f -p [macosx|linux|iphoneos ..] -a [x86_64|i386|arm64 ..] -m [debug|release]
--
-- 3. Where is the build output directory?
--
-- The default output directory is `./build` and you can configure the output directory.
--
-- $ xmake f -o outputdir
-- $ xmake
--
-- 4. How to run and debug target after building project?
--
-- $ xmake run [targetname]
-- $ xmake run -d [targetname]
--
-- 5. How to install target to the system directory or other output directory?
--
-- $ xmake install
-- $ xmake install -o installdir
--
-- 6. Add some frequently-used compilation flags in xmake.lua
--
-- @code
-- -- add debug and release modes
-- add_rules("mode.debug", "mode.release")
--
-- -- add macro definition
-- add_defines("NDEBUG", "_GNU_SOURCE=1")
--
-- -- set warning all as error
-- set_warnings("all", "error")
--
-- -- set language: c99, c++11
-- set_languages("c99", "c++11")
--
-- -- set optimization: none, faster, fastest, smallest
-- set_optimize("fastest")
--
-- -- add include search directories
-- add_includedirs("/usr/include", "/usr/local/include")
--
-- -- add link libraries and search directories
-- add_links("tbox")
-- add_linkdirs("/usr/local/lib", "/usr/lib")
--
-- -- add system link libraries
-- add_syslinks("z", "pthread")
--
-- -- add compilation and link flags
-- add_cxflags("-stdnolib", "-fno-strict-aliasing")
-- add_ldflags("-L/usr/local/lib", "-lpthread", {force = true})
--
-- @endcode
--