refactor: make linter happy
also add a few unused coprocessor instructions Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
		
							
								
								
									
										8
									
								
								.clang-tidy
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.clang-tidy
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					Checks: '
 | 
				
			||||||
 | 
					  , clang-analyzer-*
 | 
				
			||||||
 | 
					  , cppcoreguidelines-*
 | 
				
			||||||
 | 
					  , -cppcoreguidelines-avoid-magic-numbers
 | 
				
			||||||
 | 
					  , -cppcoreguidelines-pro-bounds-constant-array-index
 | 
				
			||||||
 | 
					  , -cppcoreguidelines-macro-usage
 | 
				
			||||||
 | 
					  , -cppcoreguidelines-avoid-const-or-ref-data-members
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
							
								
								
									
										28
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					name: matar
 | 
				
			||||||
 | 
					on: [push, pull_request, workflow_dispatch]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					env:
 | 
				
			||||||
 | 
					  BUILDDIR: build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  build:
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					      - uses: cachix/install-nix-action@v20
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          extra_nix_config: |
 | 
				
			||||||
 | 
					            auto-optimise-store = true
 | 
				
			||||||
 | 
					            experimental-features = nix-command flakes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: meson build
 | 
				
			||||||
 | 
					        run: nix develop -c meson setup $BUILDDIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: clang-format check
 | 
				
			||||||
 | 
					        run: nix develop -c ninja clang-format-check -C $BUILDDIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: clang-tidy check
 | 
				
			||||||
 | 
					        run: nix develop -c ninja clang-tidy -C $BUILDDIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: ninja compile
 | 
				
			||||||
 | 
					        run: nix develop -c ninja -C $BUILDDIR
 | 
				
			||||||
@@ -8,10 +8,12 @@
 | 
				
			|||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NOLINTBEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, const char* argv[]) {
 | 
					main(int argc, const char* argv[]) {
 | 
				
			||||||
    std::vector<uint8_t> rom;
 | 
					    std::vector<uint8_t> rom;
 | 
				
			||||||
    std::array<uint8_t, Memory::BIOS_SIZE> bios;
 | 
					    std::array<uint8_t, Memory::BIOS_SIZE> bios = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto usage = [argv]() {
 | 
					    auto usage = [argv]() {
 | 
				
			||||||
        std::cerr << "Usage: " << argv[0] << " <file> [-b <bios>]" << std::endl;
 | 
					        std::cerr << "Usage: " << argv[0] << " <file> [-b <bios>]" << std::endl;
 | 
				
			||||||
@@ -85,3 +87,5 @@ main(int argc, const char* argv[]) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NOLINTEND
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
      systems = [
 | 
					      systems = [
 | 
				
			||||||
        "x86_64-linux"
 | 
					        "x86_64-linux"
 | 
				
			||||||
        "aarch64-linux"
 | 
					        "aarch64-linux"
 | 
				
			||||||
        "i686-linux"
 | 
					 #       "i686-linux"
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      eachSystem = with nixpkgs.lib; f: foldAttrs mergeAttrs { }
 | 
					      eachSystem = with nixpkgs.lib; f: foldAttrs mergeAttrs { }
 | 
				
			||||||
        (map (s: mapAttrs (_: v: { ${s} = v; }) (f s)) systems);
 | 
					        (map (s: mapAttrs (_: v: { ${s} = v; }) (f s)) systems);
 | 
				
			||||||
@@ -53,10 +53,6 @@
 | 
				
			|||||||
            packages = nativeBuildInputs ++ (with pkgs; [
 | 
					            packages = nativeBuildInputs ++ (with pkgs; [
 | 
				
			||||||
              # dev tools
 | 
					              # dev tools
 | 
				
			||||||
              clang-tools_16
 | 
					              clang-tools_16
 | 
				
			||||||
 | 
					 | 
				
			||||||
              # other tools
 | 
					 | 
				
			||||||
              valgrind
 | 
					 | 
				
			||||||
              llvm.lldb
 | 
					 | 
				
			||||||
            ]);
 | 
					            ]);
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
          default = matar;
 | 
					          default = matar;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,6 +40,12 @@ enum class Condition {
 | 
				
			|||||||
    AL = 0b1110
 | 
					    AL = 0b1110
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// https://fmt.dev/dev/api.html#std-ostream-support
 | 
				
			||||||
 | 
					std::ostream&
 | 
				
			||||||
 | 
					operator<<(std::ostream& os, const Condition cond);
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct fmt::formatter<Condition> : ostream_formatter {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class OpCode {
 | 
					enum class OpCode {
 | 
				
			||||||
    AND = 0b0000,
 | 
					    AND = 0b0000,
 | 
				
			||||||
    EOR = 0b0001,
 | 
					    EOR = 0b0001,
 | 
				
			||||||
@@ -68,6 +74,6 @@ enum class ShiftType {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// https://fmt.dev/dev/api.html#std-ostream-support
 | 
					// https://fmt.dev/dev/api.html#std-ostream-support
 | 
				
			||||||
std::ostream&
 | 
					std::ostream&
 | 
				
			||||||
operator<<(std::ostream& os, const Condition cond);
 | 
					operator<<(std::ostream& os, const ShiftType cond);
 | 
				
			||||||
template<>
 | 
					template<>
 | 
				
			||||||
struct fmt::formatter<Condition> : ostream_formatter {};
 | 
					struct fmt::formatter<ShiftType> : ostream_formatter {};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,10 +7,10 @@
 | 
				
			|||||||
using namespace logger;
 | 
					using namespace logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Cpu::Cpu(Bus& bus)
 | 
					Cpu::Cpu(Bus& bus)
 | 
				
			||||||
  : gpr(0)
 | 
					  : bus(std::make_shared<Bus>(bus))
 | 
				
			||||||
 | 
					  , gpr({ 0 })
 | 
				
			||||||
  , cpsr(0)
 | 
					  , cpsr(0)
 | 
				
			||||||
  , spsr(0)
 | 
					  , spsr(0)
 | 
				
			||||||
  , bus(std::make_shared<Bus>(bus))
 | 
					 | 
				
			||||||
  , gpr_banked({ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 } })
 | 
					  , gpr_banked({ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 } })
 | 
				
			||||||
  , spsr_banked({ 0, 0, 0, 0, 0 }) {
 | 
					  , spsr_banked({ 0, 0, 0, 0, 0 }) {
 | 
				
			||||||
    cpsr.set_mode(Mode::System);
 | 
					    cpsr.set_mode(Mode::System);
 | 
				
			||||||
@@ -18,20 +18,25 @@ Cpu::Cpu(Bus& bus)
 | 
				
			|||||||
    cpsr.set_fiq_disabled(true);
 | 
					    cpsr.set_fiq_disabled(true);
 | 
				
			||||||
    cpsr.set_state(State::Arm);
 | 
					    cpsr.set_state(State::Arm);
 | 
				
			||||||
    log_info("CPU successfully initialised");
 | 
					    log_info("CPU successfully initialised");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // PC is always two instructions ahead in the pipeline
 | 
				
			||||||
 | 
					    pc += 2 * ARM_INSTRUCTION_SIZE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* change modes */
 | 
					/* change modes */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
Cpu::chg_mode(Mode from, Mode to) {
 | 
					Cpu::chg_mode(const Mode to) {
 | 
				
			||||||
 | 
					    Mode from = cpsr.mode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (from == to)
 | 
					    if (from == to)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TODO: replace visible registers with view once I understand how to
 | 
					/* TODO: replace visible registers with view once I understand how to
 | 
				
			||||||
 * concatenate views */
 | 
					 * concatenate views */
 | 
				
			||||||
#define STORE_BANKED(mode, MODE)                                               \
 | 
					#define STORE_BANKED(mode, MODE)                                               \
 | 
				
			||||||
    std::copy(gpr + GPR_##MODE##_BANKED_FIRST,                                 \
 | 
					    std::copy(gpr.begin() + GPR_##MODE##_FIRST,                                \
 | 
				
			||||||
              gpr + GPR_##MODE##_BANKED_FIRST + GPR_##MODE##_BANKED_COUNT,     \
 | 
					              gpr.begin() + GPR_COUNT - 1,                                     \
 | 
				
			||||||
              gpr_banked.mode)
 | 
					              gpr_banked.mode.begin())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (from) {
 | 
					    switch (from) {
 | 
				
			||||||
        case Mode::Fiq:
 | 
					        case Mode::Fiq:
 | 
				
			||||||
@@ -66,9 +71,9 @@ Cpu::chg_mode(Mode from, Mode to) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define RESTORE_BANKED(mode, MODE)                                             \
 | 
					#define RESTORE_BANKED(mode, MODE)                                             \
 | 
				
			||||||
    std::copy(gpr_banked.mode,                                                 \
 | 
					    std::copy(gpr_banked.mode.begin(),                                         \
 | 
				
			||||||
              gpr_banked.mode + GPR_##MODE##_BANKED_COUNT,                     \
 | 
					              gpr_banked.mode.end(),                                           \
 | 
				
			||||||
              gpr + GPR_##MODE##_BANKED_FIRST)
 | 
					              gpr.begin() + GPR_##MODE##_FIRST)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (to) {
 | 
					    switch (to) {
 | 
				
			||||||
        case Mode::Fiq:
 | 
					        case Mode::Fiq:
 | 
				
			||||||
@@ -109,11 +114,15 @@ Cpu::chg_mode(Mode from, Mode to) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
Cpu::step() {
 | 
					Cpu::step() {
 | 
				
			||||||
    uint32_t insn = 0xffffffff;
 | 
					    uint32_t cur_pc = pc - 2 * ARM_INSTRUCTION_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (cpsr.state() == State::Arm) {
 | 
					    if (cpsr.state() == State::Arm) {
 | 
				
			||||||
        std::string disassembled = exec_arm(insn);
 | 
					        log_info("{:#034b}", bus->read_word(cur_pc));
 | 
				
			||||||
        log_info("{:#010X} : {}", gpr[15], disassembled);
 | 
					
 | 
				
			||||||
        gpr[15] += ARM_INSTRUCTION_SIZE;
 | 
					        std::string disassembled = exec_arm(bus->read_word(cur_pc));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        log_info("{:#010X} : {}", cur_pc, disassembled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pc += ARM_INSTRUCTION_SIZE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,40 +13,32 @@ class Cpu {
 | 
				
			|||||||
    void step();
 | 
					    void step();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
    static constexpr size_t GPR_FIQ_BANKED_FIRST = 8;
 | 
					    static constexpr size_t GPR_COUNT = 16;
 | 
				
			||||||
    static constexpr size_t GPR_FIQ_BANKED_COUNT = 7;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static constexpr size_t GPR_SVC_BANKED_FIRST = 13;
 | 
					    static constexpr size_t GPR_FIQ_FIRST     = 8;
 | 
				
			||||||
    static constexpr size_t GPR_SVC_BANKED_COUNT = 2;
 | 
					    static constexpr size_t GPR_SVC_FIRST     = 13;
 | 
				
			||||||
 | 
					    static constexpr size_t GPR_ABT_FIRST     = 13;
 | 
				
			||||||
 | 
					    static constexpr size_t GPR_IRQ_FIRST     = 13;
 | 
				
			||||||
 | 
					    static constexpr size_t GPR_UND_FIRST     = 13;
 | 
				
			||||||
 | 
					    static constexpr size_t GPR_SYS_USR_FIRST = 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static constexpr size_t GPR_ABT_BANKED_FIRST = 13;
 | 
					    std::shared_ptr<Bus> bus;
 | 
				
			||||||
    static constexpr size_t GPR_ABT_BANKED_COUNT = 2;
 | 
					    std::array<uint32_t, GPR_COUNT> gpr; // general purpose registers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static constexpr size_t GPR_VISIBLE_COUNT = 16;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint32_t gpr[GPR_VISIBLE_COUNT]; // general purpose registers
 | 
					 | 
				
			||||||
    Psr cpsr; // current program status register
 | 
					    Psr cpsr; // current program status register
 | 
				
			||||||
    Psr spsr; // status program status register
 | 
					    Psr spsr; // status program status register
 | 
				
			||||||
    std::shared_ptr<Bus> bus;
 | 
					
 | 
				
			||||||
 | 
					    uint32_t& pc = gpr[15];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        uint32_t fiq[GPR_FIQ_BANKED_COUNT];
 | 
					        std::array<uint32_t, GPR_COUNT - GPR_FIQ_FIRST - 1> fiq;
 | 
				
			||||||
        uint32_t svc[GPR_SVC_BANKED_COUNT];
 | 
					        std::array<uint32_t, GPR_COUNT - GPR_SVC_FIRST - 1> svc;
 | 
				
			||||||
        uint32_t abt[GPR_ABT_BANKED_COUNT];
 | 
					        std::array<uint32_t, GPR_COUNT - GPR_ABT_FIRST - 1> abt;
 | 
				
			||||||
        uint32_t irq[GPR_IRQ_BANKED_COUNT];
 | 
					        std::array<uint32_t, GPR_COUNT - GPR_IRQ_FIRST - 1> irq;
 | 
				
			||||||
        uint32_t und[GPR_UND_BANKED_COUNT];
 | 
					        std::array<uint32_t, GPR_COUNT - GPR_UND_FIRST - 1> und;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // visible registers before the mode switch
 | 
					        // visible registers before the mode switch
 | 
				
			||||||
        uint32_t old[GPR_SYS_USR_BANKED_COUNT];
 | 
					        std::array<uint32_t, GPR_COUNT - GPR_SYS_USR_FIRST> old;
 | 
				
			||||||
    } gpr_banked; // banked general purpose registers
 | 
					    } gpr_banked; // banked general purpose registers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
@@ -57,6 +49,6 @@ class Cpu {
 | 
				
			|||||||
        Psr und;
 | 
					        Psr und;
 | 
				
			||||||
    } spsr_banked; // banked saved program status registers
 | 
					    } spsr_banked; // banked saved program status registers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void chg_mode(Mode from, Mode to);
 | 
					    void chg_mode(const Mode to);
 | 
				
			||||||
    std::string exec_arm(uint32_t insn);
 | 
					    std::string exec_arm(const uint32_t insn);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,25 +5,27 @@
 | 
				
			|||||||
#include <cstdint>
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace logger;
 | 
					using namespace logger;
 | 
				
			||||||
 | 
					using std::array;
 | 
				
			||||||
 | 
					using stringv = std::string_view;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string
 | 
					std::string
 | 
				
			||||||
Cpu::exec_arm(uint32_t insn) {
 | 
					Cpu::exec_arm(const uint32_t insn) {
 | 
				
			||||||
    Condition cond = static_cast<Condition>(get_bit_range(insn, 28, 31));
 | 
					    Condition cond = static_cast<Condition>(get_bit_range(insn, 28, 31));
 | 
				
			||||||
    std::string disassembled;
 | 
					    std::string disassembled;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto pc_error = [](uint8_t r, const char* syn) {
 | 
					    auto pc_error = [](uint8_t r, stringv syn) {
 | 
				
			||||||
        if (r == 15)
 | 
					        if (r == 15)
 | 
				
			||||||
            log_error("Using PC (R15) as operand in {}", syn);
 | 
					            log_error("Using PC (R15) as operand in {}", syn);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto pc_undefined = [](uint8_t r, const char* syn) {
 | 
					    auto pc_undefined = [](uint8_t r, stringv syn) {
 | 
				
			||||||
        if (r == 15)
 | 
					        if (r == 15)
 | 
				
			||||||
            log_warn("Using PC (R15) as operand in {}", syn);
 | 
					            log_warn("Using PC (R15) as operand in {}", syn);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Branch and exhcange
 | 
					    // Branch and exhcange
 | 
				
			||||||
    if ((insn & 0x0FFFFFF0) == 0x012FFF10) {
 | 
					    if ((insn & 0x0FFFFFF0) == 0x012FFF10) {
 | 
				
			||||||
        static constexpr char syn[] = "BX";
 | 
					        static constexpr stringv syn = "BX";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint8_t rn = insn & 0b1111;
 | 
					        uint8_t rn = insn & 0b1111;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -38,16 +40,16 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
            cpsr.set_state(state);
 | 
					            cpsr.set_state(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // copy to PC
 | 
					            // copy to PC
 | 
				
			||||||
            gpr[15] = gpr[rn];
 | 
					            pc = gpr[rn];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // ignore [1:0] bits for arm and 0 bit for thumb
 | 
					            // ignore [1:0] bits for arm and 0 bit for thumb
 | 
				
			||||||
            rst_nth_bit(gpr[15], 0);
 | 
					            rst_nth_bit(pc, 0);
 | 
				
			||||||
            if (state == State::Arm)
 | 
					            if (state == State::Arm)
 | 
				
			||||||
                rst_nth_bit(gpr[15], 1);
 | 
					                rst_nth_bit(pc, 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // Branch
 | 
					        // Branch
 | 
				
			||||||
    } else if ((insn & 0x0E000000) == 0x0A000000) {
 | 
					    } else if ((insn & 0x0E000000) == 0x0A000000) {
 | 
				
			||||||
        static constexpr char syn[] = "B";
 | 
					        static constexpr stringv syn = "B";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool link       = get_nth_bit(insn, 24);
 | 
					        bool link       = get_nth_bit(insn, 24);
 | 
				
			||||||
        uint32_t offset = get_bit_range(insn, 0, 23);
 | 
					        uint32_t offset = get_bit_range(insn, 0, 23);
 | 
				
			||||||
@@ -63,14 +65,14 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
                offset |= 0xFC000000;
 | 
					                offset |= 0xFC000000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (link)
 | 
					            if (link)
 | 
				
			||||||
                gpr[14] = gpr[15] - ARM_INSTRUCTION_SIZE;
 | 
					                gpr[14] = pc - ARM_INSTRUCTION_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            gpr[15] += offset;
 | 
					            pc += offset - ARM_INSTRUCTION_SIZE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Multiply
 | 
					        // Multiply
 | 
				
			||||||
    } else if ((insn & 0x0FC000F0) == 0x00000090) {
 | 
					    } else if ((insn & 0x0FC000F0) == 0x00000090) {
 | 
				
			||||||
        static constexpr char syn[2][4] = { "MUL", "MLA" };
 | 
					        static constexpr array<stringv, 2> syn = { "MUL", "MLA" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint8_t rm = get_bit_range(insn, 0, 3);
 | 
					        uint8_t rm = get_bit_range(insn, 0, 3);
 | 
				
			||||||
        uint8_t rs = get_bit_range(insn, 8, 11);
 | 
					        uint8_t rs = get_bit_range(insn, 8, 11);
 | 
				
			||||||
@@ -117,8 +119,9 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        // Multiply long
 | 
					        // Multiply long
 | 
				
			||||||
    } else if ((insn & 0x0F8000F0) == 0x00800090) {
 | 
					    } else if ((insn & 0x0F8000F0) == 0x00800090) {
 | 
				
			||||||
        static constexpr char syn[2][2][6] = { { "SMULL", "SMLAL" },
 | 
					        static constexpr array<array<stringv, 2>, 2> syn = {
 | 
				
			||||||
                                               { "UMULL", "UMLAL" } };
 | 
					            { { "SMULL", "SMLAL" }, { "UMULL", "UMLAL" } }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint8_t rm   = get_bit_range(insn, 0, 3);
 | 
					        uint8_t rm   = get_bit_range(insn, 0, 3);
 | 
				
			||||||
        uint8_t rs   = get_bit_range(insn, 8, 11);
 | 
					        uint8_t rs   = get_bit_range(insn, 8, 11);
 | 
				
			||||||
@@ -157,7 +160,7 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
                gpr[rdhi] = get_bit_range(eval, 32, 63);
 | 
					                gpr[rdhi] = get_bit_range(eval, 32, 63);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                int64_t eval = static_cast<uint64_t>(gpr[rm]) *
 | 
					                int64_t eval = static_cast<int64_t>(gpr[rm]) *
 | 
				
			||||||
                                 static_cast<int64_t>(gpr[rs]) +
 | 
					                                 static_cast<int64_t>(gpr[rs]) +
 | 
				
			||||||
                               (a ? static_cast<int64_t>(gpr[rdhi]) << 32 |
 | 
					                               (a ? static_cast<int64_t>(gpr[rdhi]) << 32 |
 | 
				
			||||||
                                      static_cast<int64_t>(gpr[rdlo])
 | 
					                                      static_cast<int64_t>(gpr[rdlo])
 | 
				
			||||||
@@ -178,7 +181,7 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Single data swap
 | 
					        // Single data swap
 | 
				
			||||||
    } else if ((insn & 0x0FB00FF0) == 0x01000090) {
 | 
					    } else if ((insn & 0x0FB00FF0) == 0x01000090) {
 | 
				
			||||||
        static constexpr char syn[] = "SWP";
 | 
					        static constexpr stringv syn = "SWP";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint8_t rm = get_bit_range(insn, 0, 3);
 | 
					        uint8_t rm = get_bit_range(insn, 0, 3);
 | 
				
			||||||
        uint8_t rd = get_bit_range(insn, 12, 15);
 | 
					        uint8_t rd = get_bit_range(insn, 12, 15);
 | 
				
			||||||
@@ -206,7 +209,7 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
        // TODO: create abstraction to reuse for block data and single data
 | 
					        // TODO: create abstraction to reuse for block data and single data
 | 
				
			||||||
        // transfer
 | 
					        // transfer
 | 
				
			||||||
    } else if ((insn & 0x0E000090) == 0x00000090) {
 | 
					    } else if ((insn & 0x0E000090) == 0x00000090) {
 | 
				
			||||||
        static constexpr char syn[2][4] = { "STR", "LDR" };
 | 
					        static constexpr array<stringv, 2> syn_ = { "STR", "LDR" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint8_t rm      = get_bit_range(insn, 0, 3);
 | 
					        uint8_t rm      = get_bit_range(insn, 0, 3);
 | 
				
			||||||
        uint8_t h       = get_nth_bit(insn, 5);
 | 
					        uint8_t h       = get_nth_bit(insn, 5);
 | 
				
			||||||
@@ -218,20 +221,20 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
        bool imm        = get_nth_bit(insn, 22);
 | 
					        bool imm        = get_nth_bit(insn, 22);
 | 
				
			||||||
        bool u          = get_nth_bit(insn, 23);
 | 
					        bool u          = get_nth_bit(insn, 23);
 | 
				
			||||||
        bool p          = get_nth_bit(insn, 24);
 | 
					        bool p          = get_nth_bit(insn, 24);
 | 
				
			||||||
        uint32_t offset;
 | 
					        uint32_t offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string syn =
 | 
				
			||||||
 | 
					          fmt::format("{}{}{}", syn_[l], (s ? "S" : ""), (h ? 'H' : 'B'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!p && w)
 | 
					        if (!p && w)
 | 
				
			||||||
            log_error("Write-back enabled with post-indexing in {}", syn[l]);
 | 
					            log_error("Write-back enabled with post-indexing in {}", syn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (s && !l)
 | 
					        if (s && !l)
 | 
				
			||||||
            log_error("Signed data found in {}", syn[l]);
 | 
					            log_error("Signed data found in {}", syn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (w)
 | 
					        if (w)
 | 
				
			||||||
            pc_error(rn, syn[l]);
 | 
					            pc_error(rn, syn);
 | 
				
			||||||
        pc_error(rm, syn[l]);
 | 
					        pc_error(rm, syn);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (rd == 15 && !l && s && h)
 | 
					 | 
				
			||||||
            ;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            offset = (imm ? get_bit_range(insn, 8, 11) << 4 | rm : gpr[rm]);
 | 
					            offset = (imm ? get_bit_range(insn, 8, 11) << 4 | rm : gpr[rm]);
 | 
				
			||||||
@@ -241,8 +244,8 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
                                                 (imm ? offset : rm));
 | 
					                                                 (imm ? offset : rm));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            disassembled = fmt::format(
 | 
					            disassembled = fmt::format(
 | 
				
			||||||
              "{}{}{}{} R{:d}{}",
 | 
					              "{}{}{}{} R{:d},{}",
 | 
				
			||||||
              syn[l],
 | 
					              syn_[l],
 | 
				
			||||||
              cond,
 | 
					              cond,
 | 
				
			||||||
              (s ? "S" : ""),
 | 
					              (s ? "S" : ""),
 | 
				
			||||||
              (h ? 'H' : 'B'),
 | 
					              (h ? 'H' : 'B'),
 | 
				
			||||||
@@ -254,7 +257,10 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (cpsr.condition(cond)) {
 | 
					        if (cpsr.condition(cond)) {
 | 
				
			||||||
            uint32_t address = (u ? gpr[rn] + offset : gpr[rn] - offset);
 | 
					            uint32_t address = gpr[rn];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (p)
 | 
				
			||||||
 | 
					                address += (u ? offset : -offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // load
 | 
					            // load
 | 
				
			||||||
            if (l) {
 | 
					            if (l) {
 | 
				
			||||||
@@ -287,7 +293,92 @@ Cpu::exec_arm(uint32_t insn) {
 | 
				
			|||||||
                    bus->write_halfword(address, gpr[rd]);
 | 
					                    bus->write_halfword(address, gpr[rd]);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!p)
 | 
				
			||||||
 | 
					                address += (u ? offset : -offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!p || w)
 | 
				
			||||||
 | 
					                gpr[rn] = address;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Software Interrupt
 | 
				
			||||||
 | 
					        // What to do here?
 | 
				
			||||||
 | 
					    } else if ((insn & 0x0F000000) == 0x0F000000) {
 | 
				
			||||||
 | 
					        static constexpr stringv syn = "SWI";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (cpsr.condition(cond)) {
 | 
				
			||||||
 | 
					            chg_mode(Mode::Supervisor);
 | 
				
			||||||
 | 
					            pc   = 0x08;
 | 
				
			||||||
 | 
					            spsr = cpsr;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        disassembled = fmt::format("{}{} 0", syn, cond);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Coprocessor data transfer
 | 
				
			||||||
 | 
					    } else if ((insn & 0x0E000000) == 0x0C000000) {
 | 
				
			||||||
 | 
					        static constexpr array<stringv, 2> syn = { "STC", "LDC" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [[maybe_unused]] uint8_t offset = get_bit_range(insn, 0, 7);
 | 
				
			||||||
 | 
					        uint8_t cpn                     = get_bit_range(insn, 8, 11);
 | 
				
			||||||
 | 
					        uint8_t crd                     = get_bit_range(insn, 12, 15);
 | 
				
			||||||
 | 
					        [[maybe_unused]] uint8_t rn     = get_bit_range(insn, 16, 19);
 | 
				
			||||||
 | 
					        bool l                          = get_nth_bit(insn, 20);
 | 
				
			||||||
 | 
					        [[maybe_unused]] bool w         = get_nth_bit(insn, 21);
 | 
				
			||||||
 | 
					        bool n                          = get_nth_bit(insn, 22);
 | 
				
			||||||
 | 
					        [[maybe_unused]] bool u         = get_nth_bit(insn, 23);
 | 
				
			||||||
 | 
					        [[maybe_unused]] bool p         = get_nth_bit(insn, 24);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        disassembled = fmt::format(
 | 
				
			||||||
 | 
					          "{}{}{} p{},c{},{}", syn[l], cond, (n ? "L" : ""), cpn, crd, "a.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        log_error("Unimplemented instruction: {}", syn[l]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Coprocessor data operation
 | 
				
			||||||
 | 
					    } else if ((insn & 0x0F000010) == 0x0E000000) {
 | 
				
			||||||
 | 
					        static constexpr stringv syn = "CDP";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint8_t crm    = get_bit_range(insn, 0, 4);
 | 
				
			||||||
 | 
					        uint8_t cp     = get_bit_range(insn, 5, 7);
 | 
				
			||||||
 | 
					        uint8_t cpn    = get_bit_range(insn, 8, 11);
 | 
				
			||||||
 | 
					        uint8_t crd    = get_bit_range(insn, 12, 15);
 | 
				
			||||||
 | 
					        uint8_t crn    = get_bit_range(insn, 16, 19);
 | 
				
			||||||
 | 
					        uint8_t cp_opc = get_bit_range(insn, 20, 23);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        disassembled = fmt::format("{}{} p{},{},c{},c{},c{},{}",
 | 
				
			||||||
 | 
					                                   syn,
 | 
				
			||||||
 | 
					                                   cond,
 | 
				
			||||||
 | 
					                                   cpn,
 | 
				
			||||||
 | 
					                                   cp_opc,
 | 
				
			||||||
 | 
					                                   crd,
 | 
				
			||||||
 | 
					                                   crn,
 | 
				
			||||||
 | 
					                                   crm,
 | 
				
			||||||
 | 
					                                   cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        log_error("Unimplemented instruction: {}", syn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Coprocessor register transfer
 | 
				
			||||||
 | 
					    } else if ((insn & 0x0F000010) == 0x0E000010) {
 | 
				
			||||||
 | 
					        static constexpr array<stringv, 2> syn = { "MCR", "MRC" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint8_t crm    = get_bit_range(insn, 0, 4);
 | 
				
			||||||
 | 
					        uint8_t cp     = get_bit_range(insn, 5, 7);
 | 
				
			||||||
 | 
					        uint8_t cpn    = get_bit_range(insn, 8, 11);
 | 
				
			||||||
 | 
					        uint8_t rd     = get_bit_range(insn, 12, 15);
 | 
				
			||||||
 | 
					        uint8_t crn    = get_bit_range(insn, 16, 19);
 | 
				
			||||||
 | 
					        bool l         = get_nth_bit(insn, 20);
 | 
				
			||||||
 | 
					        uint8_t cp_opc = get_bit_range(insn, 21, 23);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        disassembled = fmt::format("{}{} p{},{},c{},c{},c{},{}",
 | 
				
			||||||
 | 
					                                   syn[l],
 | 
				
			||||||
 | 
					                                   cond,
 | 
				
			||||||
 | 
					                                   cpn,
 | 
				
			||||||
 | 
					                                   cp_opc,
 | 
				
			||||||
 | 
					                                   rd,
 | 
				
			||||||
 | 
					                                   crn,
 | 
				
			||||||
 | 
					                                   crm,
 | 
				
			||||||
 | 
					                                   cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        log_error("Unimplemented instruction: {}", syn[l]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return disassembled;
 | 
					    return disassembled;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,9 +2,8 @@
 | 
				
			|||||||
#include "util/bits.hh"
 | 
					#include "util/bits.hh"
 | 
				
			||||||
#include "util/log.hh"
 | 
					#include "util/log.hh"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Psr::Psr(uint32_t raw) {
 | 
					Psr::Psr(uint32_t raw)
 | 
				
			||||||
    psr = raw & PSR_CLEAR_RESERVED;
 | 
					  : psr(raw & PSR_CLEAR_RESERVED) {}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Mode
 | 
					Mode
 | 
				
			||||||
Psr::mode() const {
 | 
					Psr::mode() const {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,3 +32,23 @@ operator<<(std::ostream& os, const Condition cond) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return os;
 | 
					    return os;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::ostream&
 | 
				
			||||||
 | 
					operator<<(std::ostream& os, const ShiftType shift_type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CASE(type)                                                             \
 | 
				
			||||||
 | 
					    case ShiftType::type:                                                      \
 | 
				
			||||||
 | 
					        os << #type;                                                           \
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (shift_type) {
 | 
				
			||||||
 | 
					        CASE(LSL)
 | 
				
			||||||
 | 
					        CASE(LSR)
 | 
				
			||||||
 | 
					        CASE(ASR)
 | 
				
			||||||
 | 
					        CASE(ROR)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef CASE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,6 +40,12 @@ enum class Condition {
 | 
				
			|||||||
    AL = 0b1110
 | 
					    AL = 0b1110
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// https://fmt.dev/dev/api.html#std-ostream-support
 | 
				
			||||||
 | 
					std::ostream&
 | 
				
			||||||
 | 
					operator<<(std::ostream& os, const Condition cond);
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct fmt::formatter<Condition> : ostream_formatter {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class OpCode {
 | 
					enum class OpCode {
 | 
				
			||||||
    AND = 0b0000,
 | 
					    AND = 0b0000,
 | 
				
			||||||
    EOR = 0b0001,
 | 
					    EOR = 0b0001,
 | 
				
			||||||
@@ -68,6 +74,6 @@ enum class ShiftType {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// https://fmt.dev/dev/api.html#std-ostream-support
 | 
					// https://fmt.dev/dev/api.html#std-ostream-support
 | 
				
			||||||
std::ostream&
 | 
					std::ostream&
 | 
				
			||||||
operator<<(std::ostream& os, const Condition cond);
 | 
					operator<<(std::ostream& os, const ShiftType cond);
 | 
				
			||||||
template<>
 | 
					template<>
 | 
				
			||||||
struct fmt::formatter<Condition> : ostream_formatter {};
 | 
					struct fmt::formatter<ShiftType> : ostream_formatter {};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cstdint>
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@@ -33,9 +34,9 @@ typedef struct {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t entrypoint;
 | 
					    uint32_t entrypoint;
 | 
				
			||||||
    char title[12];
 | 
					    std::string title;
 | 
				
			||||||
 | 
					    std::string title_code;
 | 
				
			||||||
    UniqueCode unique_code;
 | 
					    UniqueCode unique_code;
 | 
				
			||||||
    char title_code[2];
 | 
					 | 
				
			||||||
    I18n i18n;
 | 
					    I18n i18n;
 | 
				
			||||||
    uint8_t version;
 | 
					    uint8_t version;
 | 
				
			||||||
    BootMode multiboot;
 | 
					    BootMode multiboot;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,14 +10,14 @@ using namespace logger;
 | 
				
			|||||||
Memory::Memory(std::array<uint8_t, BIOS_SIZE>&& bios,
 | 
					Memory::Memory(std::array<uint8_t, BIOS_SIZE>&& bios,
 | 
				
			||||||
               std::vector<uint8_t>&& rom) noexcept
 | 
					               std::vector<uint8_t>&& rom) noexcept
 | 
				
			||||||
  : bios(std::move(bios))
 | 
					  : bios(std::move(bios))
 | 
				
			||||||
  , board_wram(0)
 | 
					  , board_wram({ 0 })
 | 
				
			||||||
  , chip_wram(0)
 | 
					  , chip_wram({ 0 })
 | 
				
			||||||
  , palette_ram(0)
 | 
					  , palette_ram({ 0 })
 | 
				
			||||||
  , vram(0)
 | 
					  , vram({ 0 })
 | 
				
			||||||
  , oam_obj_attr(0)
 | 
					  , oam_obj_attr({ 0 })
 | 
				
			||||||
  , rom(std::move(rom)) {
 | 
					  , rom(std::move(rom)) {
 | 
				
			||||||
    std::string bios_hash = crypto::sha256(bios.data(), bios.size());
 | 
					    std::string bios_hash = crypto::sha256(this->bios);
 | 
				
			||||||
    static constexpr char expected_hash[] =
 | 
					    static constexpr std::string_view expected_hash =
 | 
				
			||||||
      "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570";
 | 
					      "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (bios_hash != expected_hash) {
 | 
					    if (bios_hash != expected_hash) {
 | 
				
			||||||
@@ -137,7 +137,7 @@ Memory::parse_header() {
 | 
				
			|||||||
        log_info("HEADER: BIOS debugger bits not set to 0");
 | 
					        log_info("HEADER: BIOS debugger bits not set to 0");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // game info
 | 
					    // game info
 | 
				
			||||||
    std::copy(&rom[0xA0], &rom[0xA0 + 12], header.title);
 | 
					    header.title = std::string(&rom[0xA0], &rom[0xA0 + 12]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (rom[0xAC]) {
 | 
					    switch (rom[0xAC]) {
 | 
				
			||||||
        case 'A':
 | 
					        case 'A':
 | 
				
			||||||
@@ -172,8 +172,7 @@ Memory::parse_header() {
 | 
				
			|||||||
            log_error("HEADER: invalid unique code: {}", rom[0xAC]);
 | 
					            log_error("HEADER: invalid unique code: {}", rom[0xAC]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    header.title_code[0] = rom[0xAD];
 | 
					    header.title_code = std::string(&rom[0xAD], &rom[0xAE]);
 | 
				
			||||||
    header.title_code[1] = rom[0xAE];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (rom[0xAF]) {
 | 
					    switch (rom[0xAF]) {
 | 
				
			||||||
        case 'J':
 | 
					        case 'J':
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ class Memory {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define DECL_MEMORY(name, ident, start, end)                                   \
 | 
					#define DECL_MEMORY(name, ident, start, end)                                   \
 | 
				
			||||||
    MEMORY_REGION(name, start, end)                                            \
 | 
					    MEMORY_REGION(name, start, end)                                            \
 | 
				
			||||||
    uint8_t ident[name##_END - name##_START + 1];
 | 
					    std::array<uint8_t, name##_END - name##_START + 1> ident;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MEMORY_REGION(BIOS, 0x00000000, 0x00003FFF)
 | 
					    MEMORY_REGION(BIOS, 0x00000000, 0x00003FFF)
 | 
				
			||||||
    std::array<uint8_t, BIOS_SIZE> bios;
 | 
					    std::array<uint8_t, BIOS_SIZE> bios;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,6 @@ lib_sources = files(
 | 
				
			|||||||
  'bus.cc'
 | 
					  'bus.cc'
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
subdir('util')
 | 
					 | 
				
			||||||
subdir('cpu')
 | 
					subdir('cpu')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fmt = dependency('fmt', version : '>=10.1.0')
 | 
					fmt = dependency('fmt', version : '>=10.1.0')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,54 +3,55 @@
 | 
				
			|||||||
#include <fmt/ostream.h>
 | 
					#include <fmt/ostream.h>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace logger {
 | 
					using fmt::print;
 | 
				
			||||||
inline std::ostream& stream = std::clog;
 | 
					using std::clog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace logger {
 | 
				
			||||||
namespace ansi {
 | 
					namespace ansi {
 | 
				
			||||||
static constexpr char RED[]     = "\033[31m";
 | 
					static constexpr std::string_view RED     = "\033[31m";
 | 
				
			||||||
static constexpr char YELLOW[]  = "\033[33m";
 | 
					static constexpr std::string_view YELLOW  = "\033[33m";
 | 
				
			||||||
static constexpr char MAGENTA[] = "\033[35m";
 | 
					static constexpr std::string_view MAGENTA = "\033[35m";
 | 
				
			||||||
static constexpr char WHITE[]   = "\033[37m";
 | 
					static constexpr std::string_view WHITE   = "\033[37m";
 | 
				
			||||||
static constexpr char BOLD[]    = "\033[1m";
 | 
					static constexpr std::string_view BOLD    = "\033[1m";
 | 
				
			||||||
static constexpr char RESET[]   = "\033[0m";
 | 
					static constexpr std::string_view RESET   = "\033[0m";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename... Args>
 | 
					template<typename... Args>
 | 
				
			||||||
inline void
 | 
					inline void
 | 
				
			||||||
log_raw(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
					log_raw(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
				
			||||||
    fmt::println(stream, fmt, std::forward<Args>(args)...);
 | 
					    fmt::println(clog, fmt, std::forward<Args>(args)...);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename... Args>
 | 
					template<typename... Args>
 | 
				
			||||||
inline void
 | 
					inline void
 | 
				
			||||||
log_debug(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
					log_debug(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
				
			||||||
    fmt::print(stream, "{}{}[DEBUG] ", ansi::MAGENTA, ansi::BOLD);
 | 
					    print(clog, "{}{}[DEBUG] ", ansi::MAGENTA, ansi::BOLD);
 | 
				
			||||||
    log_raw(fmt, std::forward<Args>(args)...);
 | 
					    log_raw(fmt, std::forward<Args>(args)...);
 | 
				
			||||||
    fmt::print(stream, ansi::RESET);
 | 
					    print(clog, ansi::RESET);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename... Args>
 | 
					template<typename... Args>
 | 
				
			||||||
inline void
 | 
					inline void
 | 
				
			||||||
log_info(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
					log_info(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
				
			||||||
    fmt::print(stream, "{}[INFO] ", ansi::WHITE);
 | 
					    print(clog, "{}[INFO] ", ansi::WHITE);
 | 
				
			||||||
    log_raw(fmt, std::forward<Args>(args)...);
 | 
					    log_raw(fmt, std::forward<Args>(args)...);
 | 
				
			||||||
    fmt::print(stream, ansi::RESET);
 | 
					    print(clog, ansi::RESET);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename... Args>
 | 
					template<typename... Args>
 | 
				
			||||||
inline void
 | 
					inline void
 | 
				
			||||||
log_warn(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
					log_warn(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
				
			||||||
    fmt::print(stream, "{}[WARN] ", ansi::YELLOW);
 | 
					    print(clog, "{}[WARN] ", ansi::YELLOW);
 | 
				
			||||||
    log_raw(fmt, std::forward<Args>(args)...);
 | 
					    log_raw(fmt, std::forward<Args>(args)...);
 | 
				
			||||||
    fmt::print(stream, ansi::RESET);
 | 
					    print(clog, ansi::RESET);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename... Args>
 | 
					template<typename... Args>
 | 
				
			||||||
inline void
 | 
					inline void
 | 
				
			||||||
log_error(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
					log_error(const fmt::format_string<Args...>& fmt, Args&&... args) {
 | 
				
			||||||
    fmt::print(stream, "{}{}[ERROR] ", ansi::RED, ansi::BOLD);
 | 
					    print(clog, "{}{}[ERROR] ", ansi::RED, ansi::BOLD);
 | 
				
			||||||
    log_raw(fmt, std::forward<Args>(args)...);
 | 
					    log_raw(fmt, std::forward<Args>(args)...);
 | 
				
			||||||
    fmt::print(stream, ansi::RESET);
 | 
					    print(clog, ansi::RESET);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +0,0 @@
 | 
				
			|||||||
lib_sources += files(
 | 
					 | 
				
			||||||
  'utils.cc'
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
@@ -1,113 +0,0 @@
 | 
				
			|||||||
#include "utils.hh"
 | 
					 | 
				
			||||||
#include <bit>
 | 
					 | 
				
			||||||
#include <iomanip>
 | 
					 | 
				
			||||||
#include <sstream>
 | 
					 | 
				
			||||||
#include <vector>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace crypto {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using std::rotr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::string
 | 
					 | 
				
			||||||
sha256(const uint8_t* data, const size_t size) {
 | 
					 | 
				
			||||||
    // Assuming 1 byte = 8 bits
 | 
					 | 
				
			||||||
    std::stringstream string;
 | 
					 | 
				
			||||||
    size_t k = 512 - (size * 8 + 65) % 512;
 | 
					 | 
				
			||||||
    size_t L = size + (65 + k) / 8;
 | 
					 | 
				
			||||||
    size_t i, j;
 | 
					 | 
				
			||||||
    bool c = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static constexpr uint32_t K[64] = {
 | 
					 | 
				
			||||||
        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
 | 
					 | 
				
			||||||
        0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
 | 
					 | 
				
			||||||
        0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
 | 
					 | 
				
			||||||
        0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
 | 
					 | 
				
			||||||
        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
 | 
					 | 
				
			||||||
        0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
 | 
					 | 
				
			||||||
        0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
 | 
					 | 
				
			||||||
        0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
 | 
					 | 
				
			||||||
        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
 | 
					 | 
				
			||||||
        0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
 | 
					 | 
				
			||||||
        0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint32_t h[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
 | 
					 | 
				
			||||||
                      0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (i = 0; i < L; i += 64) {
 | 
					 | 
				
			||||||
        size_t n = (size > i ? size - i : 0);
 | 
					 | 
				
			||||||
        uint32_t h0[8];
 | 
					 | 
				
			||||||
        uint32_t w[64] = { 0 };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (n == 64)
 | 
					 | 
				
			||||||
            c = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (n >= 64) {
 | 
					 | 
				
			||||||
            for (j = 0; j < 16; j++) {
 | 
					 | 
				
			||||||
                w[j] = data[i + j * 4] << 24 | data[i + j * 4 + 1] << 16 |
 | 
					 | 
				
			||||||
                       data[i + j * 4 + 2] << 8 | data[i + j * 4 + 3];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            uint8_t cur[64] = { 0 };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (n) {
 | 
					 | 
				
			||||||
                std::copy(data + i, data + size, cur);
 | 
					 | 
				
			||||||
                cur[n] = 0x80;
 | 
					 | 
				
			||||||
            } else if (c) {
 | 
					 | 
				
			||||||
                cur[n] = 0x80;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (n < 54) {
 | 
					 | 
				
			||||||
                for (j = 56; j < 64; j++) {
 | 
					 | 
				
			||||||
                    cur[j] = (size * 8 >> ((63 - j) * 8)) & 0xFF;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for (j = 0; j < 16; j++) {
 | 
					 | 
				
			||||||
                w[j] = cur[j * 4] << 24 | cur[j * 4 + 1] << 16 |
 | 
					 | 
				
			||||||
                       cur[j * 4 + 2] << 8 | cur[j * 4 + 3];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (j = 16; j < 64; j++) {
 | 
					 | 
				
			||||||
            uint32_t s0 =
 | 
					 | 
				
			||||||
              rotr(w[j - 15], 7) ^ rotr(w[j - 15], 18) ^ (w[j - 15] >> 3);
 | 
					 | 
				
			||||||
            uint32_t s1 =
 | 
					 | 
				
			||||||
              rotr(w[j - 2], 17) ^ rotr(w[j - 2], 19) ^ (w[j - 2] >> 10);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            w[j] = w[j - 16] + w[j - 7] + s0 + s1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::copy(h, h + 8, h0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (j = 0; j < 64; j++) {
 | 
					 | 
				
			||||||
            uint32_t s1  = rotr(h0[4], 6) ^ rotr(h0[4], 11) ^ rotr(h0[4], 25);
 | 
					 | 
				
			||||||
            uint32_t ch  = (h0[4] & h0[5]) ^ (~h0[4] & h0[6]);
 | 
					 | 
				
			||||||
            uint32_t t1  = h0[7] + s1 + ch + K[j] + w[j];
 | 
					 | 
				
			||||||
            uint32_t s0  = rotr(h0[0], 2) ^ rotr(h0[0], 13) ^ rotr(h0[0], 22);
 | 
					 | 
				
			||||||
            uint32_t maj = (h0[0] & h0[1]) ^ (h0[0] & h0[2]) ^ (h0[1] & h0[2]);
 | 
					 | 
				
			||||||
            uint32_t t2  = s0 + maj;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            h0[7] = h0[6];
 | 
					 | 
				
			||||||
            h0[6] = h0[5];
 | 
					 | 
				
			||||||
            h0[5] = h0[4];
 | 
					 | 
				
			||||||
            h0[4] = h0[3] + t1;
 | 
					 | 
				
			||||||
            h0[3] = h0[2];
 | 
					 | 
				
			||||||
            h0[2] = h0[1];
 | 
					 | 
				
			||||||
            h0[1] = h0[0];
 | 
					 | 
				
			||||||
            h0[0] = t1 + t2;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (j = 0; j < 8; j++)
 | 
					 | 
				
			||||||
            h[j] += h0[j];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    string << std::hex << std::setfill('0');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (j = 0; j < 8; j++)
 | 
					 | 
				
			||||||
        for (i = 0; i < 4; i++)
 | 
					 | 
				
			||||||
            string << std::setw(2) << ((h[j] >> (24 - i * 8)) & 0xFF);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return string.str();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,10 +1,121 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <bit>
 | 
				
			||||||
 | 
					#include <fmt/core.h>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Why I wrote this myself? I do not know
 | 
					// Why I wrote this myself? I do not know
 | 
				
			||||||
// I will off myself 😹😹😹😹
 | 
					// I will off myself 😹😹😹😹
 | 
				
			||||||
namespace crypto {
 | 
					namespace crypto {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using std::rotr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename std::size_t N>
 | 
				
			||||||
std::string
 | 
					std::string
 | 
				
			||||||
sha256(const uint8_t* data, const size_t size);
 | 
					sha256(std::array<uint8_t, N>& data) {
 | 
				
			||||||
 | 
					    // Assuming 1 byte = 8 bits
 | 
				
			||||||
 | 
					    std::string string;
 | 
				
			||||||
 | 
					    size_t k = 512 - (N * 8 + 65) % 512;
 | 
				
			||||||
 | 
					    size_t L = N + (65 + k) / 8;
 | 
				
			||||||
 | 
					    size_t i = 0, j = 0;
 | 
				
			||||||
 | 
					    bool c = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static constexpr std::array<uint32_t, 64> K = {
 | 
				
			||||||
 | 
					        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
 | 
				
			||||||
 | 
					        0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
 | 
				
			||||||
 | 
					        0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
 | 
				
			||||||
 | 
					        0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
 | 
				
			||||||
 | 
					        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
 | 
				
			||||||
 | 
					        0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
 | 
				
			||||||
 | 
					        0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
 | 
				
			||||||
 | 
					        0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
 | 
				
			||||||
 | 
					        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
 | 
				
			||||||
 | 
					        0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
 | 
				
			||||||
 | 
					        0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::array<uint32_t, 8> h = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372,
 | 
				
			||||||
 | 
					                                  0xa54ff53a, 0x510e527f, 0x9b05688c,
 | 
				
			||||||
 | 
					                                  0x1f83d9ab, 0x5be0cd19 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < L; i += 64) {
 | 
				
			||||||
 | 
					        size_t n = (N > i ? N - i : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::array<uint32_t, 8> h0 = { 0 };
 | 
				
			||||||
 | 
					        std::array<uint32_t, 64> w = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (n == 64)
 | 
				
			||||||
 | 
					            c = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (n >= 64) {
 | 
				
			||||||
 | 
					            for (j = 0; j < 16; j++) {
 | 
				
			||||||
 | 
					                w[j] = data[i + j * 4] << 24 | data[i + j * 4 + 1] << 16 |
 | 
				
			||||||
 | 
					                       data[i + j * 4 + 2] << 8 | data[i + j * 4 + 3];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            std::array<uint32_t, 64> cur = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (n) {
 | 
				
			||||||
 | 
					                std::copy(data.begin() + i, data.begin() + N, cur.begin());
 | 
				
			||||||
 | 
					                cur[n] = 0x80;
 | 
				
			||||||
 | 
					            } else if (c) {
 | 
				
			||||||
 | 
					                cur[n] = 0x80;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (n < 54) {
 | 
				
			||||||
 | 
					                for (j = 56; j < 64; j++) {
 | 
				
			||||||
 | 
					                    cur[j] = (N * 8 >> ((63 - j) * 8)) & 0xFF;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (j = 0; j < 16; j++) {
 | 
				
			||||||
 | 
					                w[j] = cur[j * 4] << 24 | cur[j * 4 + 1] << 16 |
 | 
				
			||||||
 | 
					                       cur[j * 4 + 2] << 8 | cur[j * 4 + 3];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (j = 16; j < 64; j++) {
 | 
				
			||||||
 | 
					            uint32_t s0 =
 | 
				
			||||||
 | 
					              rotr(w[j - 15], 7) ^ rotr(w[j - 15], 18) ^ (w[j - 15] >> 3);
 | 
				
			||||||
 | 
					            uint32_t s1 =
 | 
				
			||||||
 | 
					              rotr(w[j - 2], 17) ^ rotr(w[j - 2], 19) ^ (w[j - 2] >> 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            w[j] = w[j - 16] + w[j - 7] + s0 + s1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::copy(h.begin(), h.end(), h0.begin());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (j = 0; j < 64; j++) {
 | 
				
			||||||
 | 
					            uint32_t s1  = rotr(h0[4], 6) ^ rotr(h0[4], 11) ^ rotr(h0[4], 25);
 | 
				
			||||||
 | 
					            uint32_t ch  = (h0[4] & h0[5]) ^ (~h0[4] & h0[6]);
 | 
				
			||||||
 | 
					            uint32_t t1  = h0[7] + s1 + ch + K[j] + w[j];
 | 
				
			||||||
 | 
					            uint32_t s0  = rotr(h0[0], 2) ^ rotr(h0[0], 13) ^ rotr(h0[0], 22);
 | 
				
			||||||
 | 
					            uint32_t maj = (h0[0] & h0[1]) ^ (h0[0] & h0[2]) ^ (h0[1] & h0[2]);
 | 
				
			||||||
 | 
					            uint32_t t2  = s0 + maj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            h0[7] = h0[6];
 | 
				
			||||||
 | 
					            h0[6] = h0[5];
 | 
				
			||||||
 | 
					            h0[5] = h0[4];
 | 
				
			||||||
 | 
					            h0[4] = h0[3] + t1;
 | 
				
			||||||
 | 
					            h0[3] = h0[2];
 | 
				
			||||||
 | 
					            h0[2] = h0[1];
 | 
				
			||||||
 | 
					            h0[1] = h0[0];
 | 
				
			||||||
 | 
					            h0[0] = t1 + t2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (j = 0; j < 8; j++)
 | 
				
			||||||
 | 
					            h[j] += h0[j];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (j = 0; j < 8; j++)
 | 
				
			||||||
 | 
					        for (i = 0; i < 4; i++)
 | 
				
			||||||
 | 
					            fmt::format_to(std::back_inserter(string),
 | 
				
			||||||
 | 
					                           "{:02x}",
 | 
				
			||||||
 | 
					                           ((h[j] >> (24 - i * 8)) & 0xFF));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user