cpu: fix changing modes

Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
2024-06-11 23:23:48 +05:30
parent 9e6b121918
commit f34efb183f
3 changed files with 34 additions and 12 deletions

View File

@@ -21,12 +21,12 @@ class Cpu {
static constexpr uint8_t GPR_COUNT = 16;
static constexpr uint8_t GPR_FIQ_FIRST = 8;
static constexpr uint8_t GPR_SVC_FIRST = 13;
static constexpr uint8_t GPR_ABT_FIRST = 13;
static constexpr uint8_t GPR_IRQ_FIRST = 13;
static constexpr uint8_t GPR_UND_FIRST = 13;
static constexpr uint8_t GPR_SYS_USR_FIRST = 8;
static constexpr uint8_t GPR_FIQ_FIRST = 8;
static constexpr uint8_t GPR_SVC_FIRST = 13;
static constexpr uint8_t GPR_ABT_FIRST = 13;
static constexpr uint8_t GPR_IRQ_FIRST = 13;
static constexpr uint8_t GPR_UND_FIRST = 13;
static constexpr uint8_t GPR_OLD_FIRST = 8;
std::shared_ptr<Bus> bus;
std::array<uint32_t, GPR_COUNT> gpr; // general purpose registers
@@ -54,7 +54,7 @@ class Cpu {
std::array<uint32_t, GPR_COUNT - GPR_UND_FIRST - 1> und;
// visible registers before the mode switch
std::array<uint32_t, GPR_COUNT - GPR_SYS_USR_FIRST> old;
std::array<uint32_t, GPR_COUNT - GPR_OLD_FIRST - 1> old;
} gpr_banked; // banked general purpose registers
struct {

View File

@@ -1,11 +1,9 @@
#include "cpu/cpu.hh"
#include "cpu/arm/instruction.hh"
#include "cpu/thumb/instruction.hh"
#include "util/bits.hh"
#include "util/log.hh"
#include <algorithm>
#include <cstdio>
#include <type_traits>
namespace matar {
Cpu::Cpu(const Bus& bus) noexcept
@@ -39,13 +37,16 @@ Cpu::chg_mode(const Mode to) {
* concatenate views */
#define STORE_BANKED(mode, MODE) \
std::copy(gpr.begin() + GPR_##MODE##_FIRST, \
gpr.begin() + gpr.size() - 1, \
gpr.end() - 1, \
gpr_banked.mode.begin())
switch (from) {
case Mode::Fiq:
STORE_BANKED(fiq, FIQ);
spsr_banked.fiq = spsr;
std::copy(gpr_banked.old.begin(),
gpr_banked.old.end() - 2, // dont copy R13 and R14
gpr.begin() + GPR_OLD_FIRST);
break;
case Mode::Supervisor:
@@ -70,10 +71,15 @@ Cpu::chg_mode(const Mode to) {
case Mode::User:
case Mode::System:
STORE_BANKED(old, SYS_USR);
// we only take care of r13 and r14, because FIQ takes care of the
// rest
gpr_banked.old[5] = gpr[13];
gpr_banked.old[6] = gpr[14];
break;
}
#undef STORE_BANKED
#define RESTORE_BANKED(mode, MODE) \
std::copy(gpr_banked.mode.begin(), \
gpr_banked.mode.end(), \
@@ -83,6 +89,9 @@ Cpu::chg_mode(const Mode to) {
case Mode::Fiq:
RESTORE_BANKED(fiq, FIQ);
spsr = spsr_banked.fiq;
std::copy(gpr.begin() + GPR_FIQ_FIRST,
gpr.end() - 2, // dont copy R13 and R14
gpr_banked.old.begin());
break;
case Mode::Supervisor:
@@ -107,13 +116,17 @@ Cpu::chg_mode(const Mode to) {
case Mode::User:
case Mode::System:
STORE_BANKED(old, SYS_USR);
gpr[13] = gpr_banked.old[5];
gpr[14] = gpr_banked.old[6];
break;
}
#undef RESTORE_BANKED
cpsr.set_mode(to);
glogger.info_bold("Mode changed from {:b} to {:b}",
static_cast<uint32_t>(from),
static_cast<uint32_t>(to));
}
void

View File

@@ -48,6 +48,15 @@ class Logger {
}
}
template<typename... Args>
void info_bold(const std::format_string<Args...>& fmt, Args&&... args) {
if (level & static_cast<uint8_t>(LogLevel::Info)) {
print(stream, "{}{}[INFO] ", ansi::WHITE, ansi::BOLD);
log(fmt, std::forward<Args>(args)...);
print(stream, ansi::RESET);
}
}
template<typename... Args>
void warn(const std::format_string<Args...>& fmt, Args&&... args) {
if (level & static_cast<uint8_t>(LogLevel::Warn)) {