2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,5 +3,5 @@ result
|
|||||||
build/
|
build/
|
||||||
.cache/
|
.cache/
|
||||||
*~
|
*~
|
||||||
#*#
|
\#*\#
|
||||||
.#*
|
.#*
|
||||||
|
13
README.md
13
README.md
@@ -5,18 +5,21 @@ But if you are curious (probably not), read ahead
|
|||||||
# Dependencies
|
# Dependencies
|
||||||
## Tested toolchains
|
## Tested toolchains
|
||||||
|
|
||||||
- LLVM 16.0.6
|
- LLVM 18.1.7
|
||||||
- GCC 12.3.0
|
- GCC 14.1.0
|
||||||
|
|
||||||
In theory, any toolchain supporting at least the C++20 standard should work.
|
In theory, any toolchain supporting at least the c++23 standard should work.
|
||||||
I am using LLVM's clang and libcxx as the primary toolchain.
|
I am using LLVM's clang and libcxx as the primary toolchain.
|
||||||
|
|
||||||
## Static libraries
|
## Static libraries
|
||||||
|
|
||||||
| Name | Version | Required? |
|
| Name | Version | Required? |
|
||||||
|:------:|:----------|:---------:|
|
|:------:|:----------|:---------:|
|
||||||
| fmt | >= 10.1.1 | yes |
|
|
||||||
| catch2 | >= 3.4 | for tests |
|
| catch2 | >= 3.4 | for tests |
|
||||||
|
|
||||||
This goes without saying but using a different toolchain to compile these libraries before linking probably won't work.
|
This goes without saying but using a different toolchain to compile these libraries before linking probably won't work.
|
||||||
I will add meson wrap support once LLVM 17 is out, since I want to get rid of fmt.
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
# LOG
|
||||||
|
- June 11, 2024: After almost an year, I have come back to this silly abandoned project, will probably complete it soon.
|
||||||
|
30
flake.lock
generated
30
flake.lock
generated
@@ -5,11 +5,11 @@
|
|||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1693611461,
|
"lastModified": 1717285511,
|
||||||
"narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=",
|
"narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca",
|
"rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1695806987,
|
"lastModified": 1717868076,
|
||||||
"narHash": "sha256-fX5kGs66NZIxCMcpAGIpxuftajHL8Hil1vjHmjjl118=",
|
"narHash": "sha256-c83Y9t815Wa34khrux81j8K8ET94ESmCuwORSKm2bQY=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "f3dab3509afca932f3f4fd0908957709bb1c1f57",
|
"rev": "cd18e2ae9ab8e2a0a8d715b60c91b54c0ac35ff9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -36,20 +36,14 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-lib": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"dir": "lib",
|
"lastModified": 1717284937,
|
||||||
"lastModified": 1693471703,
|
"narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=",
|
||||||
"narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=",
|
"type": "tarball",
|
||||||
"owner": "NixOS",
|
"url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85",
|
|
||||||
"type": "github"
|
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"dir": "lib",
|
"type": "tarball",
|
||||||
"owner": "NixOS",
|
"url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz"
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fmt/ostream.h>
|
|
||||||
|
|
||||||
namespace matar {
|
namespace matar {
|
||||||
enum class ShiftType {
|
enum class ShiftType {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
#include "cpu/alu.hh"
|
#include "cpu/alu.hh"
|
||||||
#include "cpu/psr.hh"
|
#include "cpu/psr.hh"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fmt/ostream.h>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
namespace matar {
|
namespace matar {
|
||||||
@@ -215,7 +215,7 @@ struct Instruction {
|
|||||||
Instruction(uint32_t insn);
|
Instruction(uint32_t insn);
|
||||||
Instruction(Condition condition, InstructionData data)
|
Instruction(Condition condition, InstructionData data)
|
||||||
: condition(condition)
|
: condition(condition)
|
||||||
, data(data){};
|
, data(data) {};
|
||||||
|
|
||||||
void exec(Cpu& cpu);
|
void exec(Cpu& cpu);
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fmt/ostream.h>
|
|
||||||
|
|
||||||
namespace matar {
|
namespace matar {
|
||||||
enum class Mode {
|
enum class Mode {
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
#include "cpu/alu.hh"
|
#include "cpu/alu.hh"
|
||||||
#include "cpu/psr.hh"
|
#include "cpu/psr.hh"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fmt/ostream.h>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
namespace matar {
|
namespace matar {
|
||||||
|
19
meson.build
19
meson.build
@@ -4,28 +4,11 @@ project('matar', 'cpp',
|
|||||||
default_options : ['warning_level=3',
|
default_options : ['warning_level=3',
|
||||||
'werror=true',
|
'werror=true',
|
||||||
'optimization=3',
|
'optimization=3',
|
||||||
'cpp_std=c++20',
|
'cpp_std=c++23',
|
||||||
'default_library=static'])
|
'default_library=static'])
|
||||||
|
|
||||||
compiler = meson.get_compiler('cpp')
|
compiler = meson.get_compiler('cpp')
|
||||||
|
|
||||||
'''
|
|
||||||
TODO: use <print> and <format> instead of libfmt once LLVM 17 is out
|
|
||||||
|
|
||||||
if compiler.has_argument('-std=c++2c')
|
|
||||||
add_global_arguments('-std=c++2c', language: 'cpp')
|
|
||||||
elif compiler.has_argument('-std=c++23')
|
|
||||||
add_global_arguments('-std=c++23', language: 'cpp')
|
|
||||||
elif compiler.has_argument('-std=c++2b')
|
|
||||||
add_global_arguments('-std=c++2b', language: 'cpp')
|
|
||||||
elif compiler.has_argument('-std=c++20')
|
|
||||||
add_global_arguments('-std=c++20', language: 'cpp')
|
|
||||||
else
|
|
||||||
error(compiler.get_id() + ' ' + compiler.version() + 'does not meet the compiler requirements')
|
|
||||||
endif
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
subdir('include')
|
subdir('include')
|
||||||
subdir('src')
|
subdir('src')
|
||||||
subdir('apps')
|
subdir('apps')
|
||||||
|
@@ -1,17 +1,10 @@
|
|||||||
{ ... }: {
|
{ ... }: {
|
||||||
perSystem = { pkgs, src, ... }:
|
perSystem = { pkgs, src, ... }:
|
||||||
let
|
let
|
||||||
llvm = pkgs.llvmPackages_16;
|
llvm = pkgs.llvmPackages_18;
|
||||||
stdenv = llvm.libcxxStdenv;
|
stdenv = llvm.libcxxStdenv;
|
||||||
|
|
||||||
libraries = with pkgs; [
|
libraries = with pkgs; [
|
||||||
((pkgs.fmt.override {
|
|
||||||
inherit stdenv;
|
|
||||||
enableShared = false;
|
|
||||||
}).overrideAttrs (oa: {
|
|
||||||
cmakeFlags = oa.cmakeFlags ++ [ "-DFMT_TEST=off" ];
|
|
||||||
})).dev
|
|
||||||
|
|
||||||
(catch2_3.override { inherit stdenv; }).out
|
(catch2_3.override { inherit stdenv; }).out
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
@@ -19,7 +12,7 @@
|
|||||||
packages.matar-clang = pkgs.callPackage ./build.nix { inherit src libraries stdenv; };
|
packages.matar-clang = pkgs.callPackage ./build.nix { inherit src libraries stdenv; };
|
||||||
devShells.matar-clang = pkgs.callPackage ./shell.nix {
|
devShells.matar-clang = pkgs.callPackage ./shell.nix {
|
||||||
inherit libraries stdenv;
|
inherit libraries stdenv;
|
||||||
tools = with pkgs; [ (clang-tools_16.override { enableLibcxx = true; }) ];
|
tools = with pkgs; [ (clang-tools_18.override { enableLibcxx = true; }) ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
{ ... }: {
|
{ ... }: {
|
||||||
perSystem = { pkgs, src, ... }:
|
perSystem = { pkgs, src, ... }:
|
||||||
let
|
let
|
||||||
|
stdenv = pkgs.gcc14Stdenv;
|
||||||
|
|
||||||
libraries = with pkgs; [
|
libraries = with pkgs; [
|
||||||
(pkgs.fmt.override { enableShared = false; }).dev
|
(catch2_3.override { inherit stdenv; }).out
|
||||||
catch2_3.out
|
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages.matar = pkgs.callPackage ./build.nix { inherit src libraries; };
|
packages.matar = pkgs.callPackage ./build.nix { inherit src libraries stdenv; };
|
||||||
devShells.matar = pkgs.callPackage ./shell.nix { inherit libraries; };
|
devShells.matar = pkgs.callPackage ./shell.nix { inherit libraries stdenv; };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include "cpu/alu.hh"
|
#include "cpu/alu.hh"
|
||||||
#include "util/bits.hh"
|
#include "util/bits.hh"
|
||||||
|
#include <bit>
|
||||||
|
|
||||||
namespace matar {
|
namespace matar {
|
||||||
uint32_t
|
uint32_t
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
#include "cpu/arm/instruction.hh"
|
#include "cpu/arm/instruction.hh"
|
||||||
#include "util/bits.hh"
|
#include "util/bits.hh"
|
||||||
|
#include <format>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace matar::arm {
|
namespace matar::arm {
|
||||||
std::string
|
std::string
|
||||||
@@ -9,15 +11,15 @@ Instruction::disassemble() {
|
|||||||
return std::visit(
|
return std::visit(
|
||||||
overloaded{
|
overloaded{
|
||||||
[condition](BranchAndExchange& data) {
|
[condition](BranchAndExchange& data) {
|
||||||
return fmt::format("BX{} R{:d}", condition, data.rn);
|
return std::format("BX{} R{:d}", condition, data.rn);
|
||||||
},
|
},
|
||||||
[condition](Branch& data) {
|
[condition](Branch& data) {
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"B{}{} 0x{:06X}", (data.link ? "L" : ""), condition, data.offset);
|
"B{}{} 0x{:06X}", (data.link ? "L" : ""), condition, data.offset);
|
||||||
},
|
},
|
||||||
[condition](Multiply& data) {
|
[condition](Multiply& data) {
|
||||||
if (data.acc) {
|
if (data.acc) {
|
||||||
return fmt::format("MLA{}{} R{:d},R{:d},R{:d},R{:d}",
|
return std::format("MLA{}{} R{:d},R{:d},R{:d},R{:d}",
|
||||||
condition,
|
condition,
|
||||||
(data.set ? "S" : ""),
|
(data.set ? "S" : ""),
|
||||||
data.rd,
|
data.rd,
|
||||||
@@ -25,7 +27,7 @@ Instruction::disassemble() {
|
|||||||
data.rs,
|
data.rs,
|
||||||
data.rn);
|
data.rn);
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("MUL{}{} R{:d},R{:d},R{:d}",
|
return std::format("MUL{}{} R{:d},R{:d},R{:d}",
|
||||||
condition,
|
condition,
|
||||||
(data.set ? "S" : ""),
|
(data.set ? "S" : ""),
|
||||||
data.rd,
|
data.rd,
|
||||||
@@ -34,7 +36,7 @@ Instruction::disassemble() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[condition](MultiplyLong& data) {
|
[condition](MultiplyLong& data) {
|
||||||
return fmt::format("{}{}{}{} R{:d},R{:d},R{:d},R{:d}",
|
return std::format("{}{}{}{} R{:d},R{:d},R{:d},R{:d}",
|
||||||
(data.uns ? 'U' : 'S'),
|
(data.uns ? 'U' : 'S'),
|
||||||
(data.acc ? "MLAL" : "MULL"),
|
(data.acc ? "MLAL" : "MULL"),
|
||||||
condition,
|
condition,
|
||||||
@@ -46,7 +48,7 @@ Instruction::disassemble() {
|
|||||||
},
|
},
|
||||||
[](Undefined) { return std::string("UND"); },
|
[](Undefined) { return std::string("UND"); },
|
||||||
[condition](SingleDataSwap& data) {
|
[condition](SingleDataSwap& data) {
|
||||||
return fmt::format("SWP{}{} R{:d},R{:d},[R{:d}]",
|
return std::format("SWP{}{} R{:d},R{:d},[R{:d}]",
|
||||||
condition,
|
condition,
|
||||||
(data.byte ? "B" : ""),
|
(data.byte ? "B" : ""),
|
||||||
data.rd,
|
data.rd,
|
||||||
@@ -62,18 +64,18 @@ Instruction::disassemble() {
|
|||||||
expression = "";
|
expression = "";
|
||||||
} else {
|
} else {
|
||||||
expression =
|
expression =
|
||||||
fmt::format(",{}#{:d}", (data.up ? '+' : '-'), *offset);
|
std::format(",{}#{:d}", (data.up ? '+' : '-'), *offset);
|
||||||
}
|
}
|
||||||
} else if (const Shift* shift = std::get_if<Shift>(&data.offset)) {
|
} else if (const Shift* shift = std::get_if<Shift>(&data.offset)) {
|
||||||
// Shifts are always immediate in single data transfer
|
// Shifts are always immediate in single data transfer
|
||||||
expression = fmt::format(",{}R{:d},{} #{:d}",
|
expression = std::format(",{}R{:d},{} #{:d}",
|
||||||
(data.up ? '+' : '-'),
|
(data.up ? '+' : '-'),
|
||||||
shift->rm,
|
shift->rm,
|
||||||
stringify(shift->data.type),
|
stringify(shift->data.type),
|
||||||
shift->data.operand);
|
shift->data.operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"{}{}{}{} R{:d},[R{:d}{}]{}",
|
"{}{}{}{} R{:d},[R{:d}{}]{}",
|
||||||
(data.load ? "LDR" : "STR"),
|
(data.load ? "LDR" : "STR"),
|
||||||
condition,
|
condition,
|
||||||
@@ -91,15 +93,15 @@ Instruction::disassemble() {
|
|||||||
if (data.offset == 0) {
|
if (data.offset == 0) {
|
||||||
expression = "";
|
expression = "";
|
||||||
} else {
|
} else {
|
||||||
expression = fmt::format(
|
expression = std::format(
|
||||||
",{}#{:d}", (data.up ? '+' : '-'), data.offset);
|
",{}#{:d}", (data.up ? '+' : '-'), data.offset);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
expression =
|
expression =
|
||||||
fmt::format(",{}R{:d}", (data.up ? '+' : '-'), data.offset);
|
std::format(",{}R{:d}", (data.up ? '+' : '-'), data.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"{}{}{}{} R{:d},[R{:d}{}]{}",
|
"{}{}{}{} R{:d},[R{:d}{}]{}",
|
||||||
(data.load ? "LDR" : "STR"),
|
(data.load ? "LDR" : "STR"),
|
||||||
condition,
|
condition,
|
||||||
@@ -115,12 +117,12 @@ Instruction::disassemble() {
|
|||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++) {
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
if (get_bit(data.regs, i))
|
if (get_bit(data.regs, i))
|
||||||
fmt::format_to(std::back_inserter(regs), "R{:d},", i);
|
std::format_to(std::back_inserter(regs), "R{:d},", i);
|
||||||
};
|
};
|
||||||
|
|
||||||
regs.pop_back();
|
regs.pop_back();
|
||||||
|
|
||||||
return fmt::format("{}{}{}{} R{:d}{},{{{}}}{}",
|
return std::format("{}{}{}{} R{:d}{},{{{}}}{}",
|
||||||
(data.load ? "LDM" : "STM"),
|
(data.load ? "LDM" : "STM"),
|
||||||
condition,
|
condition,
|
||||||
(data.up ? 'I' : 'D'),
|
(data.up ? 'I' : 'D'),
|
||||||
@@ -132,12 +134,12 @@ Instruction::disassemble() {
|
|||||||
},
|
},
|
||||||
[condition](PsrTransfer& data) {
|
[condition](PsrTransfer& data) {
|
||||||
if (data.type == PsrTransfer::Type::Mrs) {
|
if (data.type == PsrTransfer::Type::Mrs) {
|
||||||
return fmt::format("MRS{} R{:d},{}",
|
return std::format("MRS{} R{:d},{}",
|
||||||
condition,
|
condition,
|
||||||
data.operand,
|
data.operand,
|
||||||
(data.spsr ? "SPSR_all" : "CPSR_all"));
|
(data.spsr ? "SPSR_all" : "CPSR_all"));
|
||||||
} else {
|
} else {
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"MSR{} {}_{},{}{}",
|
"MSR{} {}_{},{}{}",
|
||||||
condition,
|
condition,
|
||||||
(data.spsr ? "SPSR" : "CPSR"),
|
(data.spsr ? "SPSR" : "CPSR"),
|
||||||
@@ -153,9 +155,9 @@ Instruction::disassemble() {
|
|||||||
|
|
||||||
if (const uint32_t* operand =
|
if (const uint32_t* operand =
|
||||||
std::get_if<uint32_t>(&data.operand)) {
|
std::get_if<uint32_t>(&data.operand)) {
|
||||||
op_2 = fmt::format("#{:d}", *operand);
|
op_2 = std::format("#{:d}", *operand);
|
||||||
} else if (const Shift* shift = std::get_if<Shift>(&data.operand)) {
|
} else if (const Shift* shift = std::get_if<Shift>(&data.operand)) {
|
||||||
op_2 = fmt::format("R{:d},{} {}{:d}",
|
op_2 = std::format("R{:d},{} {}{:d}",
|
||||||
shift->rm,
|
shift->rm,
|
||||||
stringify(shift->data.type),
|
stringify(shift->data.type),
|
||||||
(shift->data.immediate ? '#' : 'R'),
|
(shift->data.immediate ? '#' : 'R'),
|
||||||
@@ -165,7 +167,7 @@ Instruction::disassemble() {
|
|||||||
switch (data.opcode) {
|
switch (data.opcode) {
|
||||||
case OpCode::MOV:
|
case OpCode::MOV:
|
||||||
case OpCode::MVN:
|
case OpCode::MVN:
|
||||||
return fmt::format("{}{}{} R{:d},{}",
|
return std::format("{}{}{} R{:d},{}",
|
||||||
stringify(data.opcode),
|
stringify(data.opcode),
|
||||||
condition,
|
condition,
|
||||||
(data.set ? "S" : ""),
|
(data.set ? "S" : ""),
|
||||||
@@ -175,13 +177,13 @@ Instruction::disassemble() {
|
|||||||
case OpCode::TEQ:
|
case OpCode::TEQ:
|
||||||
case OpCode::CMP:
|
case OpCode::CMP:
|
||||||
case OpCode::CMN:
|
case OpCode::CMN:
|
||||||
return fmt::format("{}{} R{:d},{}",
|
return std::format("{}{} R{:d},{}",
|
||||||
stringify(data.opcode),
|
stringify(data.opcode),
|
||||||
condition,
|
condition,
|
||||||
data.rn,
|
data.rn,
|
||||||
op_2);
|
op_2);
|
||||||
default:
|
default:
|
||||||
return fmt::format("{}{}{} R{:d},R{:d},{}",
|
return std::format("{}{}{} R{:d},R{:d},{}",
|
||||||
stringify(data.opcode),
|
stringify(data.opcode),
|
||||||
condition,
|
condition,
|
||||||
(data.set ? "S" : ""),
|
(data.set ? "S" : ""),
|
||||||
@@ -191,11 +193,11 @@ Instruction::disassemble() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[condition](SoftwareInterrupt) {
|
[condition](SoftwareInterrupt) {
|
||||||
return fmt::format("SWI{}", condition);
|
return std::format("SWI{}", condition);
|
||||||
},
|
},
|
||||||
[condition](CoprocessorDataTransfer& data) {
|
[condition](CoprocessorDataTransfer& data) {
|
||||||
std::string expression = fmt::format(",#{:d}", data.offset);
|
std::string expression = std::format(",#{:d}", data.offset);
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"{}{}{} p{:d},c{:d},[R{:d}{}]{}",
|
"{}{}{} p{:d},c{:d},[R{:d}{}]{}",
|
||||||
(data.load ? "LDC" : "STC"),
|
(data.load ? "LDC" : "STC"),
|
||||||
condition,
|
condition,
|
||||||
@@ -207,7 +209,7 @@ Instruction::disassemble() {
|
|||||||
(data.pre ? (data.write ? "!" : "") : expression));
|
(data.pre ? (data.write ? "!" : "") : expression));
|
||||||
},
|
},
|
||||||
[condition](CoprocessorDataOperation& data) {
|
[condition](CoprocessorDataOperation& data) {
|
||||||
return fmt::format("CDP{} p{},{},c{},c{},c{},{}",
|
return std::format("CDP{} p{},{},c{},c{},c{},{}",
|
||||||
condition,
|
condition,
|
||||||
data.cpn,
|
data.cpn,
|
||||||
data.cp_opc,
|
data.cp_opc,
|
||||||
@@ -217,7 +219,7 @@ Instruction::disassemble() {
|
|||||||
data.cp);
|
data.cp);
|
||||||
},
|
},
|
||||||
[condition](CoprocessorRegisterTransfer& data) {
|
[condition](CoprocessorRegisterTransfer& data) {
|
||||||
return fmt::format("{}{} p{},{},R{},c{},c{},{}",
|
return std::format("{}{} p{},{},R{},c{},c{},{}",
|
||||||
(data.load ? "MRC" : "MCR"),
|
(data.load ? "MRC" : "MCR"),
|
||||||
condition,
|
condition,
|
||||||
data.cpn,
|
data.cpn,
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include "cpu/thumb/instruction.hh"
|
#include "cpu/thumb/instruction.hh"
|
||||||
#include "util/bits.hh"
|
#include "util/bits.hh"
|
||||||
|
#include <format>
|
||||||
|
|
||||||
namespace matar::thumb {
|
namespace matar::thumb {
|
||||||
std::string
|
std::string
|
||||||
@@ -7,14 +8,14 @@ Instruction::disassemble(uint32_t pc) {
|
|||||||
return std::visit(
|
return std::visit(
|
||||||
overloaded{
|
overloaded{
|
||||||
[](MoveShiftedRegister& data) {
|
[](MoveShiftedRegister& data) {
|
||||||
return fmt::format("{} R{:d},R{:d},#{:d}",
|
return std::format("{} R{:d},R{:d},#{:d}",
|
||||||
stringify(data.opcode),
|
stringify(data.opcode),
|
||||||
data.rd,
|
data.rd,
|
||||||
data.rs,
|
data.rs,
|
||||||
data.offset);
|
data.offset);
|
||||||
},
|
},
|
||||||
[](AddSubtract& data) {
|
[](AddSubtract& data) {
|
||||||
return fmt::format("{} R{:d},R{:d},{}{:d}",
|
return std::format("{} R{:d},R{:d},{}{:d}",
|
||||||
stringify(data.opcode),
|
stringify(data.opcode),
|
||||||
data.rd,
|
data.rd,
|
||||||
data.rs,
|
data.rs,
|
||||||
@@ -22,27 +23,27 @@ Instruction::disassemble(uint32_t pc) {
|
|||||||
data.offset);
|
data.offset);
|
||||||
},
|
},
|
||||||
[](MovCmpAddSubImmediate& data) {
|
[](MovCmpAddSubImmediate& data) {
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"{} R{:d},#{:d}", stringify(data.opcode), data.rd, data.offset);
|
"{} R{:d},#{:d}", stringify(data.opcode), data.rd, data.offset);
|
||||||
},
|
},
|
||||||
[](AluOperations& data) {
|
[](AluOperations& data) {
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"{} R{:d},R{:d}", stringify(data.opcode), data.rd, data.rs);
|
"{} R{:d},R{:d}", stringify(data.opcode), data.rd, data.rs);
|
||||||
},
|
},
|
||||||
[](HiRegisterOperations& data) {
|
[](HiRegisterOperations& data) {
|
||||||
if (data.opcode == HiRegisterOperations::OpCode::BX) {
|
if (data.opcode == HiRegisterOperations::OpCode::BX) {
|
||||||
return fmt::format("{} R{:d}", stringify(data.opcode), data.rs);
|
return std::format("{} R{:d}", stringify(data.opcode), data.rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"{} R{:d},R{:d}", stringify(data.opcode), data.rd, data.rs);
|
"{} R{:d},R{:d}", stringify(data.opcode), data.rd, data.rs);
|
||||||
},
|
},
|
||||||
|
|
||||||
[](PcRelativeLoad& data) {
|
[](PcRelativeLoad& data) {
|
||||||
return fmt::format("LDR R{:d},[PC,#{:d}]", data.rd, data.word);
|
return std::format("LDR R{:d},[PC,#{:d}]", data.rd, data.word);
|
||||||
},
|
},
|
||||||
[](LoadStoreRegisterOffset& data) {
|
[](LoadStoreRegisterOffset& data) {
|
||||||
return fmt::format("{}{} R{:d},[R{:d},R{:d}]",
|
return std::format("{}{} R{:d},[R{:d},R{:d}]",
|
||||||
(data.load ? "LDR" : "STR"),
|
(data.load ? "LDR" : "STR"),
|
||||||
(data.byte ? "B" : ""),
|
(data.byte ? "B" : ""),
|
||||||
data.rd,
|
data.rd,
|
||||||
@@ -51,11 +52,11 @@ Instruction::disassemble(uint32_t pc) {
|
|||||||
},
|
},
|
||||||
[](LoadStoreSignExtendedHalfword& data) {
|
[](LoadStoreSignExtendedHalfword& data) {
|
||||||
if (!data.s && !data.h) {
|
if (!data.s && !data.h) {
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"STRH R{:d},[R{:d},R{:d}]", data.rd, data.rb, data.ro);
|
"STRH R{:d},[R{:d},R{:d}]", data.rd, data.rb, data.ro);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt::format("{}{} R{:d},[R{:d},R{:d}]",
|
return std::format("{}{} R{:d},[R{:d},R{:d}]",
|
||||||
(data.s ? "LDS" : "LDR"),
|
(data.s ? "LDS" : "LDR"),
|
||||||
(data.h ? 'H' : 'B'),
|
(data.h ? 'H' : 'B'),
|
||||||
data.rd,
|
data.rd,
|
||||||
@@ -63,7 +64,7 @@ Instruction::disassemble(uint32_t pc) {
|
|||||||
data.ro);
|
data.ro);
|
||||||
},
|
},
|
||||||
[](LoadStoreImmediateOffset& data) {
|
[](LoadStoreImmediateOffset& data) {
|
||||||
return fmt::format("{}{} R{:d},[R{:d},#{:d}]",
|
return std::format("{}{} R{:d},[R{:d},#{:d}]",
|
||||||
(data.load ? "LDR" : "STR"),
|
(data.load ? "LDR" : "STR"),
|
||||||
(data.byte ? "B" : ""),
|
(data.byte ? "B" : ""),
|
||||||
data.rd,
|
data.rd,
|
||||||
@@ -71,33 +72,33 @@ Instruction::disassemble(uint32_t pc) {
|
|||||||
data.offset);
|
data.offset);
|
||||||
},
|
},
|
||||||
[](LoadStoreHalfword& data) {
|
[](LoadStoreHalfword& data) {
|
||||||
return fmt::format("{} R{:d},[R{:d},#{:d}]",
|
return std::format("{} R{:d},[R{:d},#{:d}]",
|
||||||
(data.load ? "LDRH" : "STRH"),
|
(data.load ? "LDRH" : "STRH"),
|
||||||
data.rd,
|
data.rd,
|
||||||
data.rb,
|
data.rb,
|
||||||
data.offset);
|
data.offset);
|
||||||
},
|
},
|
||||||
[](SpRelativeLoad& data) {
|
[](SpRelativeLoad& data) {
|
||||||
return fmt::format("{} R{:d},[SP,#{:d}]",
|
return std::format("{} R{:d},[SP,#{:d}]",
|
||||||
(data.load ? "LDR" : "STR"),
|
(data.load ? "LDR" : "STR"),
|
||||||
data.rd,
|
data.rd,
|
||||||
data.word);
|
data.word);
|
||||||
},
|
},
|
||||||
[](LoadAddress& data) {
|
[](LoadAddress& data) {
|
||||||
return fmt::format("ADD R{:d},{},#{:d}",
|
return std::format("ADD R{:d},{},#{:d}",
|
||||||
data.rd,
|
data.rd,
|
||||||
(data.sp ? "SP" : "PC"),
|
(data.sp ? "SP" : "PC"),
|
||||||
data.word);
|
data.word);
|
||||||
},
|
},
|
||||||
[](AddOffsetStackPointer& data) {
|
[](AddOffsetStackPointer& data) {
|
||||||
return fmt::format("ADD SP,#{:d}", data.word);
|
return std::format("ADD SP,#{:d}", data.word);
|
||||||
},
|
},
|
||||||
[](PushPopRegister& data) {
|
[](PushPopRegister& data) {
|
||||||
std::string regs;
|
std::string regs;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++) {
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
if (get_bit(data.regs, i))
|
if (get_bit(data.regs, i))
|
||||||
fmt::format_to(std::back_inserter(regs), "R{:d},", i);
|
std::format_to(std::back_inserter(regs), "R{:d},", i);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.load) {
|
if (data.load) {
|
||||||
@@ -106,14 +107,14 @@ Instruction::disassemble(uint32_t pc) {
|
|||||||
else
|
else
|
||||||
regs.pop_back();
|
regs.pop_back();
|
||||||
|
|
||||||
return fmt::format("POP {{{}}}", regs);
|
return std::format("POP {{{}}}", regs);
|
||||||
} else {
|
} else {
|
||||||
if (data.pclr)
|
if (data.pclr)
|
||||||
regs += "LR";
|
regs += "LR";
|
||||||
else
|
else
|
||||||
regs.pop_back();
|
regs.pop_back();
|
||||||
|
|
||||||
return fmt::format("PUSH {{{}}}", regs);
|
return std::format("PUSH {{{}}}", regs);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[](MultipleLoad& data) {
|
[](MultipleLoad& data) {
|
||||||
@@ -121,31 +122,31 @@ Instruction::disassemble(uint32_t pc) {
|
|||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++) {
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
if (get_bit(data.regs, i))
|
if (get_bit(data.regs, i))
|
||||||
fmt::format_to(std::back_inserter(regs), "R{:d},", i);
|
std::format_to(std::back_inserter(regs), "R{:d},", i);
|
||||||
};
|
};
|
||||||
|
|
||||||
regs.pop_back();
|
regs.pop_back();
|
||||||
|
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"{} R{}!,{{{}}}", (data.load ? "LDMIA" : "STMIA"), data.rb, regs);
|
"{} R{}!,{{{}}}", (data.load ? "LDMIA" : "STMIA"), data.rb, regs);
|
||||||
},
|
},
|
||||||
[](SoftwareInterrupt& data) {
|
[](SoftwareInterrupt& data) {
|
||||||
return fmt::format("SWI {:d}", data.vector);
|
return std::format("SWI {:d}", data.vector);
|
||||||
},
|
},
|
||||||
[pc](ConditionalBranch& data) {
|
[pc](ConditionalBranch& data) {
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"B{} #{:d}",
|
"B{} #{:d}",
|
||||||
stringify(data.condition),
|
stringify(data.condition),
|
||||||
static_cast<int32_t>(data.offset + pc + 2 * INSTRUCTION_SIZE));
|
static_cast<int32_t>(data.offset + pc + 2 * INSTRUCTION_SIZE));
|
||||||
},
|
},
|
||||||
[pc](UnconditionalBranch& data) {
|
[pc](UnconditionalBranch& data) {
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"B #{:d}",
|
"B #{:d}",
|
||||||
static_cast<int32_t>(data.offset + pc + 2 * INSTRUCTION_SIZE));
|
static_cast<int32_t>(data.offset + pc + 2 * INSTRUCTION_SIZE));
|
||||||
},
|
},
|
||||||
[](LongBranchWithLink& data) {
|
[](LongBranchWithLink& data) {
|
||||||
// duh this manual be empty for H = 0
|
// duh this manual be empty for H = 0
|
||||||
return fmt::format(
|
return std::format(
|
||||||
"BL{} #{:d}", (data.high ? "H" : ""), data.offset);
|
"BL{} #{:d}", (data.high ? "H" : ""), data.offset);
|
||||||
},
|
},
|
||||||
[](auto) { return std::string("unknown instruction"); } },
|
[](auto) { return std::string("unknown instruction"); } },
|
||||||
|
@@ -8,12 +8,6 @@ subdir('cpu')
|
|||||||
|
|
||||||
lib_cpp_args = []
|
lib_cpp_args = []
|
||||||
|
|
||||||
fmt = dependency('fmt', version : '>=10.1.0', static: true)
|
|
||||||
if not fmt.found()
|
|
||||||
fmt = dependency('fmt', version : '>=10.1.0', static: false)
|
|
||||||
lib_cpp_args += '-DFMT_HEADER_ONLY'
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('disassembler')
|
if get_option('disassembler')
|
||||||
lib_cpp_args += '-DDISASSEMBLER'
|
lib_cpp_args += '-DDISASSEMBLER'
|
||||||
endif
|
endif
|
||||||
@@ -21,7 +15,6 @@ endif
|
|||||||
lib = library(
|
lib = library(
|
||||||
meson.project_name(),
|
meson.project_name(),
|
||||||
lib_sources,
|
lib_sources,
|
||||||
dependencies: [fmt],
|
|
||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
install: true,
|
install: true,
|
||||||
cpp_args: lib_cpp_args
|
cpp_args: lib_cpp_args
|
||||||
|
@@ -35,6 +35,6 @@ inline Int
|
|||||||
bit_range(Int num, size_t start, size_t end) {
|
bit_range(Int num, size_t start, size_t end) {
|
||||||
// NOTE: we do not require -1 if it is a signed integral
|
// NOTE: we do not require -1 if it is a signed integral
|
||||||
Int left =
|
Int left =
|
||||||
std::numeric_limits<Int>::digits - (std::is_unsigned<Int>::value) - end;
|
std::numeric_limits<Int>::digits - (!std::is_signed<Int>::value) - end;
|
||||||
return static_cast<Int>(num << left) >> (left + start);
|
return static_cast<Int>(num << left) >> (left + start);
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#include <fmt/core.h>
|
#include <format>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// Why I wrote this myself? I do not know
|
// Why I wrote this myself? I do not know
|
||||||
@@ -110,7 +110,7 @@ sha256(std::array<uint8_t, N>& data) {
|
|||||||
|
|
||||||
for (j = 0; j < 8; j++)
|
for (j = 0; j < 8; j++)
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
fmt::format_to(std::back_inserter(string),
|
std::format_to(std::back_inserter(string),
|
||||||
"{:02x}",
|
"{:02x}",
|
||||||
((h[j] >> (24 - i * 8)) & 0xFF));
|
((h[j] >> (24 - i * 8)) & 0xFF));
|
||||||
|
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/loglevel.hh"
|
#include "util/loglevel.hh"
|
||||||
#include <fmt/ostream.h>
|
#include <print>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace logging {
|
namespace logging {
|
||||||
namespace ansi {
|
namespace ansi {
|
||||||
@@ -14,7 +13,7 @@ static constexpr auto BOLD = "\033[1m";
|
|||||||
static constexpr auto RESET = "\033[0m";
|
static constexpr auto RESET = "\033[0m";
|
||||||
}
|
}
|
||||||
|
|
||||||
using fmt::print;
|
using std::print;
|
||||||
|
|
||||||
class Logger {
|
class Logger {
|
||||||
using LogLevel = matar::LogLevel;
|
using LogLevel = matar::LogLevel;
|
||||||
@@ -27,12 +26,12 @@ class Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void log(const fmt::format_string<Args...>& fmt, Args&&... args) {
|
void log(const std::format_string<Args...>& fmt, Args&&... args) {
|
||||||
fmt::println(stream, fmt, std::forward<Args>(args)...);
|
std::println(stream, fmt, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void debug(const fmt::format_string<Args...>& fmt, Args&&... args) {
|
void debug(const std::format_string<Args...>& fmt, Args&&... args) {
|
||||||
if (level & static_cast<uint8_t>(LogLevel::Debug)) {
|
if (level & static_cast<uint8_t>(LogLevel::Debug)) {
|
||||||
print(stream, "{}{}[DEBUG] ", ansi::MAGENTA, ansi::BOLD);
|
print(stream, "{}{}[DEBUG] ", ansi::MAGENTA, ansi::BOLD);
|
||||||
log(fmt, std::forward<Args>(args)...);
|
log(fmt, std::forward<Args>(args)...);
|
||||||
@@ -41,7 +40,7 @@ class Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void info(const fmt::format_string<Args...>& fmt, Args&&... args) {
|
void info(const std::format_string<Args...>& fmt, Args&&... args) {
|
||||||
if (level & static_cast<uint8_t>(LogLevel::Info)) {
|
if (level & static_cast<uint8_t>(LogLevel::Info)) {
|
||||||
print(stream, "{}[INFO] ", ansi::WHITE);
|
print(stream, "{}[INFO] ", ansi::WHITE);
|
||||||
log(fmt, std::forward<Args>(args)...);
|
log(fmt, std::forward<Args>(args)...);
|
||||||
@@ -50,7 +49,7 @@ class Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void warn(const fmt::format_string<Args...>& fmt, Args&&... args) {
|
void warn(const std::format_string<Args...>& fmt, Args&&... args) {
|
||||||
if (level & static_cast<uint8_t>(LogLevel::Warn)) {
|
if (level & static_cast<uint8_t>(LogLevel::Warn)) {
|
||||||
print(stream, "{}[WARN] ", ansi::YELLOW);
|
print(stream, "{}[WARN] ", ansi::YELLOW);
|
||||||
log(fmt, std::forward<Args>(args)...);
|
log(fmt, std::forward<Args>(args)...);
|
||||||
@@ -59,7 +58,7 @@ class Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void error(const fmt::format_string<Args...>& fmt, Args&&... args) {
|
void error(const std::format_string<Args...>& fmt, Args&&... args) {
|
||||||
if (level & static_cast<uint8_t>(LogLevel::Error)) {
|
if (level & static_cast<uint8_t>(LogLevel::Error)) {
|
||||||
print(stream, "{}{}[ERROR] ", ansi::RED, ansi::BOLD);
|
print(stream, "{}{}[ERROR] ", ansi::RED, ansi::BOLD);
|
||||||
log(fmt, std::forward<Args>(args)...);
|
log(fmt, std::forward<Args>(args)...);
|
||||||
|
Reference in New Issue
Block a user