initial cpu structure :thonk:
Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
@@ -1,2 +1,7 @@
|
|||||||
BasedOnStyle: LLVM
|
BasedOnStyle: Mozilla
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
AlignConsecutiveAssignments: Consecutive
|
||||||
|
BreakAfterAttributes: Always
|
||||||
|
AllowShortEnumsOnASingleLine: False
|
@@ -1,10 +1,17 @@
|
|||||||
#include "matar.hh"
|
#include "emulator.hh"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
int
|
||||||
std::cout << "Hello" << std::endl;
|
main(int argc, const char* argv[]) {
|
||||||
if (run() > 0) {
|
if (argc != 2) {
|
||||||
std::cerr << "Crashed" << std::endl;
|
std::cerr << "Usage: " << argv[0] << " <file>" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
emulator::run(argv[1]);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Exception: " << e.what() << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,6 +10,6 @@ executable(
|
|||||||
meson.project_name(),
|
meson.project_name(),
|
||||||
target_sources,
|
target_sources,
|
||||||
link_with: target_deps,
|
link_with: target_deps,
|
||||||
include_directories: includes,
|
include_directories: inc,
|
||||||
install : true
|
install : true,
|
||||||
)
|
)
|
12
flake.nix
12
flake.nix
@@ -16,12 +16,12 @@
|
|||||||
eachSystem (system:
|
eachSystem (system:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
llvm = pkgs.llvmPackages;
|
llvm = pkgs.llvmPackages_16;
|
||||||
stdenv = llvm.libcxxStdenv;
|
stdenv = llvm.libcxxStdenv;
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [ meson ninja ];
|
nativeBuildInputs = with pkgs; [ meson ninja ];
|
||||||
in
|
in
|
||||||
{
|
rec {
|
||||||
packages = rec {
|
packages = rec {
|
||||||
matar = stdenv.mkDerivation rec {
|
matar = stdenv.mkDerivation rec {
|
||||||
name = "matar";
|
name = "matar";
|
||||||
@@ -44,7 +44,13 @@
|
|||||||
matar = pkgs.mkShell.override { inherit stdenv; } {
|
matar = pkgs.mkShell.override { inherit stdenv; } {
|
||||||
name = "matar";
|
name = "matar";
|
||||||
packages = nativeBuildInputs ++ (with pkgs; [
|
packages = nativeBuildInputs ++ (with pkgs; [
|
||||||
clang-tools
|
# dev tools
|
||||||
|
clang-tools_16
|
||||||
|
|
||||||
|
# other tools
|
||||||
|
valgrind
|
||||||
|
|
||||||
|
llvm.lldb
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
default = matar;
|
default = matar;
|
||||||
|
16
include/emulator.hh
Normal file
16
include/emulator.hh
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef EMULATOR_HH
|
||||||
|
#define EMULATOR_HH
|
||||||
|
|
||||||
|
// Why do I have a public API? We will know that in the future
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace emulator {
|
||||||
|
void
|
||||||
|
run(std::string filepath);
|
||||||
|
|
||||||
|
void
|
||||||
|
run(std::ifstream& ifile);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* EMULATOR_HH */
|
@@ -1,6 +0,0 @@
|
|||||||
#ifndef MATAR_HH
|
|
||||||
#define MATAR_HH
|
|
||||||
|
|
||||||
int run();
|
|
||||||
|
|
||||||
#endif /* MATAR_HH */
|
|
5
include/meson.build
Normal file
5
include/meson.build
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
headers = files(
|
||||||
|
'emulator.hh'
|
||||||
|
)
|
||||||
|
|
||||||
|
install_headers(headers, subdir: meson.project_name(), preserve_path: true)
|
@@ -6,10 +6,7 @@ project('matar', 'cpp',
|
|||||||
'optimization=3',
|
'optimization=3',
|
||||||
'cpp_std=c++20'])
|
'cpp_std=c++20'])
|
||||||
|
|
||||||
includes = include_directories('include')
|
inc = include_directories('include')
|
||||||
|
|
||||||
subdir('include')
|
subdir('include')
|
||||||
subdir('src')
|
subdir('src')
|
||||||
subdir('apps')
|
subdir('apps')
|
||||||
|
|
||||||
import('pkgconfig').generate(lib)
|
|
39
src/bits.hh
Normal file
39
src/bits.hh
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
using std::size_t;
|
||||||
|
|
||||||
|
template<std::integral Int>
|
||||||
|
inline bool
|
||||||
|
get_nth_bit(Int num, size_t n) {
|
||||||
|
return (1 && (num >> n));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::integral Int>
|
||||||
|
inline void
|
||||||
|
set_nth_bit(Int& num, size_t n) {
|
||||||
|
num |= (1 << n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::integral Int>
|
||||||
|
inline void
|
||||||
|
rst_nth_bit(Int& num, size_t n) {
|
||||||
|
num &= ~(1 << n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::integral Int>
|
||||||
|
inline void
|
||||||
|
chg_nth_bit(Int& num, size_t n, bool x) {
|
||||||
|
num ^= (num ^ -x) & 1 << n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// read range of bits from start to end inclusive
|
||||||
|
template<std::unsigned_integral Int>
|
||||||
|
inline Int
|
||||||
|
get_bit_range(Int& num, size_t start, size_t end) {
|
||||||
|
// NOTE: we do not require -1 if it is a signed integral (which it is not)
|
||||||
|
Int left = std::numeric_limits<Int>::digits - 1 - end;
|
||||||
|
return num << left >> (left + start);
|
||||||
|
}
|
14
src/bus.hh
Normal file
14
src/bus.hh
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Bus {
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Bus() = default;
|
||||||
|
Bus(std::istream& ifile)
|
||||||
|
: data(std::istreambuf_iterator<char>(ifile),
|
||||||
|
std::istreambuf_iterator<char>()) {}
|
||||||
|
};
|
61
src/cpu/arm/insruction.hh
Normal file
61
src/cpu/arm/insruction.hh
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
enum class ArmInstructionFormat {
|
||||||
|
DataProcessingAndFsrTransfer,
|
||||||
|
Multiply,
|
||||||
|
MultiplyLong,
|
||||||
|
SingleDataSwap,
|
||||||
|
BranchAndExchange,
|
||||||
|
HalfwordDataTransferRegisterOffset,
|
||||||
|
HalfwordDataTransferImmediateOffset,
|
||||||
|
SingleDataTransfer,
|
||||||
|
Undefined,
|
||||||
|
BlockDataTransfer,
|
||||||
|
Branch,
|
||||||
|
CoprocessorDataTransfer,
|
||||||
|
CoprocessorDataOperation,
|
||||||
|
CoprocessorRegisterTransfer,
|
||||||
|
SoftwareInterrupt
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Condition {
|
||||||
|
EQ = 0b0000,
|
||||||
|
NE = 0b0001,
|
||||||
|
CS = 0b0010,
|
||||||
|
CC = 0b0011,
|
||||||
|
MI = 0b0100,
|
||||||
|
PL = 0b0101,
|
||||||
|
VS = 0b0110,
|
||||||
|
VC = 0b0111,
|
||||||
|
HI = 0b1000,
|
||||||
|
LS = 0b1001,
|
||||||
|
GE = 0b1010,
|
||||||
|
LT = 0b1011,
|
||||||
|
GT = 0b1100,
|
||||||
|
LE = 0b1101,
|
||||||
|
AL = 0b1110
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class OpCode {
|
||||||
|
AND = 0b0000,
|
||||||
|
EOR = 0b0001,
|
||||||
|
SUB = 0b0010,
|
||||||
|
RSB = 0b0011,
|
||||||
|
ADD = 0b0100,
|
||||||
|
ADC = 0b0101,
|
||||||
|
SBC = 0b0110,
|
||||||
|
RSC = 0b0111,
|
||||||
|
TST = 0b1000,
|
||||||
|
TEQ = 0b1001,
|
||||||
|
CMP = 0b1010,
|
||||||
|
CMN = 0b1011,
|
||||||
|
ORR = 0b1100,
|
||||||
|
MOV = 0b1101,
|
||||||
|
BIC = 0b1110,
|
||||||
|
MVN = 0b1111
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Shift {
|
||||||
|
LSL = 0b00,
|
||||||
|
LSR = 0b01,
|
||||||
|
ASR = 0b10,
|
||||||
|
ROR = 0b11
|
||||||
|
};
|
2
src/cpu/arm/meson.build
Normal file
2
src/cpu/arm/meson.build
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
lib_sources += files(
|
||||||
|
)
|
106
src/cpu/cpu.cc
106
src/cpu/cpu.cc
@@ -1,6 +1,104 @@
|
|||||||
#include "cpu.hh"
|
#include "cpu.hh"
|
||||||
#include <iostream>
|
#include "cpu/utility.hh"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
namespace cpu {
|
/* change modes */
|
||||||
void run() { std::cout << "Hello from inside the CPU" << std::endl; }
|
void
|
||||||
} // namespace cpu
|
Cpu::chg_mode(Mode from, Mode to) {
|
||||||
|
if (from == to)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* TODO: replace visible registers with view once I understand how to
|
||||||
|
* concatenate views */
|
||||||
|
#define STORE_BANKED(mode, MODE) \
|
||||||
|
std::copy(gpr + GPR_##MODE##_BANKED_FIRST, \
|
||||||
|
gpr + GPR_##MODE##_BANKED_FIRST + GPR_##MODE##_BANKED_COUNT, \
|
||||||
|
gpr_banked.mode)
|
||||||
|
|
||||||
|
switch (from) {
|
||||||
|
case Mode::Fiq:
|
||||||
|
STORE_BANKED(fiq, FIQ);
|
||||||
|
spsr_banked.fiq = spsr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::Supervisor:
|
||||||
|
STORE_BANKED(svc, SVC);
|
||||||
|
spsr_banked.svc = spsr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::Abort:
|
||||||
|
STORE_BANKED(abt, ABT);
|
||||||
|
spsr_banked.abt = spsr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::Irq:
|
||||||
|
STORE_BANKED(irq, IRQ);
|
||||||
|
spsr_banked.irq = spsr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::Undefined:
|
||||||
|
STORE_BANKED(und, UND);
|
||||||
|
spsr_banked.und = spsr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::User:
|
||||||
|
case Mode::System:
|
||||||
|
STORE_BANKED(old, SYS_USR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RESTORE_BANKED(mode, MODE) \
|
||||||
|
std::copy(gpr_banked.mode, \
|
||||||
|
gpr_banked.mode + GPR_##MODE##_BANKED_COUNT, \
|
||||||
|
gpr + GPR_##MODE##_BANKED_FIRST)
|
||||||
|
|
||||||
|
switch (to) {
|
||||||
|
case Mode::Fiq:
|
||||||
|
RESTORE_BANKED(fiq, FIQ);
|
||||||
|
spsr = spsr_banked.fiq;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::Supervisor:
|
||||||
|
RESTORE_BANKED(svc, SVC);
|
||||||
|
spsr = spsr_banked.svc;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::Abort:
|
||||||
|
RESTORE_BANKED(abt, ABT);
|
||||||
|
spsr = spsr_banked.abt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::Irq:
|
||||||
|
RESTORE_BANKED(irq, IRQ);
|
||||||
|
spsr = spsr_banked.irq;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::Undefined:
|
||||||
|
RESTORE_BANKED(und, UND);
|
||||||
|
spsr = spsr_banked.und;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Mode::User:
|
||||||
|
case Mode::System:
|
||||||
|
STORE_BANKED(old, SYS_USR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef RESTORE_BANKED
|
||||||
|
|
||||||
|
cpsr.set_mode(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set register
|
||||||
|
inline uint32_t&
|
||||||
|
Cpu::operator[](size_t idx) {
|
||||||
|
// avoid unneeded complexity like index checks
|
||||||
|
return gpr[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
// get register
|
||||||
|
inline const uint32_t&
|
||||||
|
Cpu::operator[](size_t idx) const {
|
||||||
|
return gpr[idx];
|
||||||
|
}
|
||||||
|
@@ -1,7 +1,77 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ABSOLUTE "MADarchod"
|
#include "bus.hh"
|
||||||
|
#include "psr.hh"
|
||||||
|
|
||||||
namespace cpu {
|
#include <cstdint>
|
||||||
void run();
|
|
||||||
|
using std::size_t;
|
||||||
|
|
||||||
|
static constexpr size_t GPR_VISIBLE_COUNT = 16;
|
||||||
|
|
||||||
|
static constexpr size_t GPR_FIQ_BANKED_FIRST = 8;
|
||||||
|
static constexpr size_t GPR_FIQ_BANKED_COUNT = 7;
|
||||||
|
|
||||||
|
static constexpr size_t GPR_SVC_BANKED_FIRST = 13;
|
||||||
|
static constexpr size_t GPR_SVC_BANKED_COUNT = 2;
|
||||||
|
|
||||||
|
static constexpr size_t GPR_ABT_BANKED_FIRST = 13;
|
||||||
|
static constexpr size_t GPR_ABT_BANKED_COUNT = 2;
|
||||||
|
|
||||||
|
static constexpr size_t GPR_IRQ_BANKED_FIRST = 13;
|
||||||
|
static constexpr size_t GPR_IRQ_BANKED_COUNT = 2;
|
||||||
|
|
||||||
|
static constexpr size_t GPR_UND_BANKED_FIRST = 13;
|
||||||
|
static constexpr size_t GPR_UND_BANKED_COUNT = 2;
|
||||||
|
|
||||||
|
static constexpr size_t GPR_SYS_USR_BANKED_FIRST = 8;
|
||||||
|
static constexpr size_t GPR_SYS_USR_BANKED_COUNT = 7;
|
||||||
|
|
||||||
|
struct _GprBanked {
|
||||||
|
uint32_t fiq[GPR_FIQ_BANKED_COUNT];
|
||||||
|
uint32_t svc[GPR_SVC_BANKED_COUNT];
|
||||||
|
uint32_t abt[GPR_ABT_BANKED_COUNT];
|
||||||
|
uint32_t irq[GPR_IRQ_BANKED_COUNT];
|
||||||
|
uint32_t und[GPR_UND_BANKED_COUNT];
|
||||||
|
|
||||||
|
/* visible registers before the mode switch */
|
||||||
|
uint32_t old[GPR_SYS_USR_BANKED_COUNT];
|
||||||
|
};
|
||||||
|
typedef struct _GprBanked GprBanked;
|
||||||
|
|
||||||
|
struct _SpsrBanked {
|
||||||
|
Psr fiq;
|
||||||
|
Psr svc;
|
||||||
|
Psr abt;
|
||||||
|
Psr irq;
|
||||||
|
Psr und;
|
||||||
|
};
|
||||||
|
typedef struct _SpsrBanked SpsrBanked;
|
||||||
|
|
||||||
|
class Cpu {
|
||||||
|
uint32_t gpr[GPR_VISIBLE_COUNT]; // general purpose registers
|
||||||
|
GprBanked gpr_banked; // banked general purpose registers
|
||||||
|
SpsrBanked spsr_banked; // banked saved program status registers
|
||||||
|
Psr cpsr; // current program status register
|
||||||
|
Psr spsr; // status program status register
|
||||||
|
Bus bus;
|
||||||
|
|
||||||
|
void chg_mode(Mode from, Mode to);
|
||||||
|
|
||||||
|
uint32_t& operator[](size_t idx);
|
||||||
|
const uint32_t& operator[](size_t idx) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Cpu(Bus bus)
|
||||||
|
: gpr(0)
|
||||||
|
, gpr_banked({ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 } })
|
||||||
|
, spsr_banked({ 0, 0, 0, 0, 0 })
|
||||||
|
, cpsr(0)
|
||||||
|
, spsr(0)
|
||||||
|
, bus(bus) {
|
||||||
|
cpsr.set_mode(Mode::System);
|
||||||
|
cpsr.set_irq_disabled(true);
|
||||||
|
cpsr.set_fiq_disabled(true);
|
||||||
|
cpsr.set_state(State::Arm);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
lib_sources += files(
|
lib_sources += files(
|
||||||
'cpu.cc'
|
'cpu.cc'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
subdir('arm')
|
55
src/cpu/psr.hh
Normal file
55
src/cpu/psr.hh
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "bits.hh"
|
||||||
|
#include "utility.hh"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
static constexpr uint32_t PSR_CLEAR_RESERVED = 0xf00000ff;
|
||||||
|
static constexpr uint32_t PSR_CLEAR_MODE = 0x0b00000;
|
||||||
|
|
||||||
|
class Psr {
|
||||||
|
uint32_t psr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// clear the reserved bits i.e, [8:27]
|
||||||
|
Psr(uint32_t raw) { psr = raw & PSR_CLEAR_RESERVED; }
|
||||||
|
|
||||||
|
// Mode : [4:0]
|
||||||
|
Mode mode() const { return static_cast<Mode>(psr & ~PSR_CLEAR_MODE); }
|
||||||
|
void set_mode(Mode mode) {
|
||||||
|
psr &= PSR_CLEAR_MODE;
|
||||||
|
psr |= static_cast<uint32_t>(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// State : [5]
|
||||||
|
bool state() const { return get_nth_bit(psr, 5); }
|
||||||
|
void set_state(State state) {
|
||||||
|
chg_nth_bit(psr, 5, static_cast<bool>(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_SET_NTH_BIT_FUNCTIONS(name, n) \
|
||||||
|
bool name() const { return get_nth_bit(psr, n); } \
|
||||||
|
void set_##name(bool val) { chg_nth_bit(psr, n, val); }
|
||||||
|
|
||||||
|
// FIQ disable : [6]
|
||||||
|
GET_SET_NTH_BIT_FUNCTIONS(fiq_disabled, 6)
|
||||||
|
|
||||||
|
// IRQ disable : [7]
|
||||||
|
GET_SET_NTH_BIT_FUNCTIONS(irq_disabled, 7)
|
||||||
|
|
||||||
|
// Reserved bits : [27:8]
|
||||||
|
|
||||||
|
// Overflow flag : [28]
|
||||||
|
GET_SET_NTH_BIT_FUNCTIONS(v, 28);
|
||||||
|
|
||||||
|
// Carry flag : [29]
|
||||||
|
GET_SET_NTH_BIT_FUNCTIONS(c, 29);
|
||||||
|
|
||||||
|
// Zero flag : [30]
|
||||||
|
GET_SET_NTH_BIT_FUNCTIONS(z, 30);
|
||||||
|
|
||||||
|
// Negative flag : [30]
|
||||||
|
GET_SET_NTH_BIT_FUNCTIONS(n, 31);
|
||||||
|
|
||||||
|
#undef GET_SET_NTH_BIT_FUNCTIONS
|
||||||
|
};
|
17
src/cpu/utility.hh
Normal file
17
src/cpu/utility.hh
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
/* M[4:0] in PSR */
|
||||||
|
User = 0b10000,
|
||||||
|
Fiq = 0b10001,
|
||||||
|
Irq = 0b10010,
|
||||||
|
Supervisor = 0b10011,
|
||||||
|
Abort = 0b10111,
|
||||||
|
Undefined = 0b11011,
|
||||||
|
System = 0b11111,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class State {
|
||||||
|
Arm = 0,
|
||||||
|
Thumb = 1
|
||||||
|
};
|
24
src/emulator.cc
Normal file
24
src/emulator.cc
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include "emulator.hh"
|
||||||
|
#include "bus.hh"
|
||||||
|
#include "cpu/cpu.hh"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace emulator {
|
||||||
|
void
|
||||||
|
run(std::ifstream& ifile) {
|
||||||
|
Bus bus(ifile);
|
||||||
|
Cpu cpu(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run(std::string filepath) {
|
||||||
|
std::ifstream ifile(filepath, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
if (!ifile.is_open()) {
|
||||||
|
throw std::ios::failure("No such file exists", std::error_code());
|
||||||
|
}
|
||||||
|
|
||||||
|
run(ifile);
|
||||||
|
ifile.close();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +0,0 @@
|
|||||||
#include "matar.hh"
|
|
||||||
#include "cpu/cpu.hh"
|
|
||||||
|
|
||||||
int run() {
|
|
||||||
cpu::run();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,5 +1,5 @@
|
|||||||
lib_sources = files(
|
lib_sources = files(
|
||||||
'matar.cc'
|
'emulator.cc'
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('cpu')
|
subdir('cpu')
|
||||||
@@ -7,6 +7,8 @@ subdir('cpu')
|
|||||||
lib = library(
|
lib = library(
|
||||||
meson.project_name(),
|
meson.project_name(),
|
||||||
lib_sources,
|
lib_sources,
|
||||||
include_directories: includes,
|
include_directories: inc,
|
||||||
install: true
|
install: true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import('pkgconfig').generate(lib)
|
Reference in New Issue
Block a user