initial
This commit is contained in:
commit
8054ac43ac
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.o
|
||||
*.asm
|
||||
main
|
23
Makefile
Normal file
23
Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
CXXFLAGS = -O0 -g -Wall -Wextra -Werror -Wpedantic -std=c++20 -Wno-error=unused-parameter -Wno-error=unused-but-set-variable -fPIE
|
||||
LDFLAGS =
|
||||
|
||||
TARGET =
|
||||
CXX = $(TARGET)g++
|
||||
|
||||
OBJS = main.o fromstring.o addressing_mode.o codec.o parser.o
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
all: main
|
||||
|
||||
%.o: %.cc $(HEADERS) Makefile
|
||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
main: $(OBJS)
|
||||
$(CXX) $(LDFLAGS) $^ -o $@
|
||||
|
||||
clean:
|
||||
rm -f *.o *.elf *.bin *.out *.imem *.hex
|
||||
|
||||
.SUFFIXES:
|
||||
.INTERMEDIATE:
|
||||
.PHONY: all clean %.dump
|
35
addressing_mode.cc
Normal file
35
addressing_mode.cc
Normal file
@ -0,0 +1,35 @@
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "addressing_mode.hh"
|
||||
#include "isa.hh"
|
||||
|
||||
static bool is_uint16(ssize_t n) { return n >= 0 && n <= 65535; }
|
||||
|
||||
static bool is_uint8(ssize_t n) { return n >= 0 && n <= 255; }
|
||||
|
||||
static bool is_int8(ssize_t n) { return n >= -128 && n <= 127; }
|
||||
|
||||
static bool always_valid(ssize_t _) { return true; }
|
||||
|
||||
std::unordered_map<isa::mode, addressing_mode_t>& addressing_mode() {
|
||||
static std::unordered_map<isa::mode, addressing_mode_t> _ = {
|
||||
{isa::mode::A, { .len = 2, .valid = is_uint16 }},
|
||||
{isa::mode::AII, { .len = 2, .valid = is_uint16 }},
|
||||
{isa::mode::AIX, { .len = 2, .valid = is_uint16 }},
|
||||
{isa::mode::AIY, { .len = 2, .valid = is_uint16 }},
|
||||
{isa::mode::AI, { .len = 2, .valid = is_uint16 }},
|
||||
{isa::mode::ACC, { .len = 0, .valid = always_valid }},
|
||||
{isa::mode::IMM, { .len = 1, .valid = is_uint8 }},
|
||||
{isa::mode::I, { .len = 0, .valid = always_valid }},
|
||||
{isa::mode::R, { .len = 1, .valid = is_int8 }},
|
||||
{isa::mode::S, { .len = 0, .valid = always_valid }},
|
||||
{isa::mode::ZP, { .len = 1, .valid = is_uint8 }},
|
||||
{isa::mode::ZPII, { .len = 1, .valid = is_uint8 }},
|
||||
{isa::mode::ZPX, { .len = 1, .valid = is_uint8 }},
|
||||
{isa::mode::ZPY, { .len = 1, .valid = is_uint8 }},
|
||||
{isa::mode::ZPI, { .len = 1, .valid = is_uint8 }},
|
||||
{isa::mode::ZPIY, { .len = 1, .valid = is_uint8 }},
|
||||
};
|
||||
return _;
|
||||
}
|
13
addressing_mode.hh
Normal file
13
addressing_mode.hh
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "isa.hh"
|
||||
|
||||
struct addressing_mode_t {
|
||||
size_t len;
|
||||
std::function<bool(ssize_t)> valid;
|
||||
};
|
||||
|
||||
std::unordered_map<isa::mode, addressing_mode_t>& addressing_mode();
|
30
assembler.hh
Normal file
30
assembler.hh
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "isa.hh"
|
||||
|
||||
namespace assembler {
|
||||
struct literal_t {
|
||||
ssize_t num;
|
||||
};
|
||||
|
||||
struct reference_t {
|
||||
size_t symbol;
|
||||
};
|
||||
|
||||
struct implied_t {
|
||||
};
|
||||
|
||||
struct instruction_t {
|
||||
std::optional<size_t> symbol;
|
||||
isa::op op;
|
||||
isa::mode mode;
|
||||
std::variant<literal_t, reference_t, implied_t> value;
|
||||
size_t location;
|
||||
};
|
||||
|
||||
using program_t = std::vector<instruction_t>;
|
||||
}
|
563
codec.cc
Normal file
563
codec.cc
Normal file
@ -0,0 +1,563 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
|
||||
#include "codec.hh"
|
||||
#include "isa.hh"
|
||||
|
||||
namespace codec {
|
||||
const std::map<std::tuple<isa::op, isa::mode>, uint8_t>& encode() {
|
||||
static const std::map<std::tuple<isa::op, isa::mode>, uint8_t> _ = {
|
||||
{{isa::op::BRK, isa::mode::S}, 0},
|
||||
{{isa::op::ORA, isa::mode::ZPX}, 1},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 2},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 3},
|
||||
{{isa::op::TSB, isa::mode::ZP}, 4},
|
||||
{{isa::op::ORA, isa::mode::ZP}, 5},
|
||||
{{isa::op::ASL, isa::mode::ZP}, 6},
|
||||
{{isa::op::RMB0, isa::mode::ZP}, 7},
|
||||
{{isa::op::PHP, isa::mode::S}, 8},
|
||||
{{isa::op::ORA, isa::mode::IMM}, 9},
|
||||
{{isa::op::ASL, isa::mode::A}, 10},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 11},
|
||||
{{isa::op::TSB, isa::mode::A}, 12},
|
||||
{{isa::op::ORA, isa::mode::A}, 13},
|
||||
{{isa::op::ASL, isa::mode::A}, 14},
|
||||
{{isa::op::BBR0, isa::mode::R}, 15},
|
||||
|
||||
{{isa::op::BPL, isa::mode::R}, 16},
|
||||
{{isa::op::ORA, isa::mode::ZPIY}, 17},
|
||||
{{isa::op::ORA, isa::mode::ZPI}, 18},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 19},
|
||||
{{isa::op::TRB, isa::mode::ZP}, 20},
|
||||
{{isa::op::ORA, isa::mode::ZPX}, 21},
|
||||
{{isa::op::ASL, isa::mode::ZPX}, 22},
|
||||
{{isa::op::RMB1, isa::mode::ZP}, 23},
|
||||
{{isa::op::CLC, isa::mode::I}, 24},
|
||||
{{isa::op::ORA, isa::mode::AIY}, 25},
|
||||
{{isa::op::INC, isa::mode::A}, 26},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 27},
|
||||
{{isa::op::TRB, isa::mode::A}, 28},
|
||||
{{isa::op::ORA, isa::mode::AIX}, 29},
|
||||
{{isa::op::ASL, isa::mode::AIX}, 30},
|
||||
{{isa::op::BBR1, isa::mode::R}, 31},
|
||||
|
||||
{{isa::op::JSR, isa::mode::A}, 32},
|
||||
{{isa::op::AND, isa::mode::ZPII}, 33},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 34},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 35},
|
||||
{{isa::op::BIT, isa::mode::ZP}, 36},
|
||||
{{isa::op::AND, isa::mode::ZP}, 37},
|
||||
{{isa::op::ROL, isa::mode::ZP}, 38},
|
||||
{{isa::op::RMB2, isa::mode::ZP}, 39},
|
||||
{{isa::op::PLP, isa::mode::S}, 40},
|
||||
{{isa::op::AND, isa::mode::IMM}, 41},
|
||||
{{isa::op::ROL, isa::mode::A}, 42},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 43},
|
||||
{{isa::op::BIT, isa::mode::A}, 44},
|
||||
{{isa::op::AND, isa::mode::A}, 45},
|
||||
{{isa::op::ROL, isa::mode::A}, 46},
|
||||
{{isa::op::BBR2, isa::mode::R}, 47},
|
||||
|
||||
{{isa::op::BMI, isa::mode::R}, 48},
|
||||
{{isa::op::AND, isa::mode::ZPIY}, 49},
|
||||
{{isa::op::AND, isa::mode::ZPI}, 50},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 51},
|
||||
{{isa::op::BIT, isa::mode::ZPX}, 52},
|
||||
{{isa::op::AND, isa::mode::ZPX}, 53},
|
||||
{{isa::op::ROL, isa::mode::ZPX}, 54},
|
||||
{{isa::op::RMB3, isa::mode::ZP}, 55},
|
||||
{{isa::op::SEC, isa::mode::I}, 56},
|
||||
{{isa::op::AND, isa::mode::AIY}, 57},
|
||||
{{isa::op::DEC, isa::mode::A}, 58},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 59},
|
||||
{{isa::op::BIT, isa::mode::AIX}, 60},
|
||||
{{isa::op::AND, isa::mode::AIX}, 61},
|
||||
{{isa::op::ROL, isa::mode::AIX}, 62},
|
||||
{{isa::op::BBR3, isa::mode::R}, 63},
|
||||
|
||||
{{isa::op::RTI, isa::mode::S}, 64},
|
||||
{{isa::op::EOR, isa::mode::ZPII}, 65},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 66},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 67},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 68},
|
||||
{{isa::op::EOR, isa::mode::ZP}, 69},
|
||||
{{isa::op::LSR, isa::mode::ZP}, 70},
|
||||
{{isa::op::RMB4, isa::mode::ZP}, 71},
|
||||
{{isa::op::PHA, isa::mode::S}, 72},
|
||||
{{isa::op::EOR, isa::mode::IMM}, 73},
|
||||
{{isa::op::LSR, isa::mode::A}, 74},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 75},
|
||||
{{isa::op::JMP, isa::mode::A}, 76},
|
||||
{{isa::op::EOR, isa::mode::A}, 77},
|
||||
{{isa::op::LSR, isa::mode::A}, 78},
|
||||
{{isa::op::BBR4, isa::mode::R}, 79},
|
||||
|
||||
{{isa::op::BVC, isa::mode::R}, 80},
|
||||
{{isa::op::EOR, isa::mode::ZPIY}, 81},
|
||||
{{isa::op::EOR, isa::mode::ZPI}, 82},
|
||||
{{isa::op::EOR, isa::mode::ZPX}, 83},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 84},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 85},
|
||||
{{isa::op::LSR, isa::mode::ZPX}, 86},
|
||||
{{isa::op::RMB5, isa::mode::ZP}, 87},
|
||||
{{isa::op::CLI, isa::mode::I}, 88},
|
||||
{{isa::op::EOR, isa::mode::AIY}, 89},
|
||||
{{isa::op::PHY, isa::mode::S}, 90},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 91},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 92},
|
||||
{{isa::op::EOR, isa::mode::AIX}, 93},
|
||||
{{isa::op::LSR, isa::mode::AIX}, 94},
|
||||
{{isa::op::BBR5, isa::mode::R}, 95},
|
||||
|
||||
{{isa::op::RTS, isa::mode::S}, 96},
|
||||
{{isa::op::ADC, isa::mode::ZPII}, 97},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 98},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 99},
|
||||
{{isa::op::STZ, isa::mode::ZP}, 100},
|
||||
{{isa::op::ADC, isa::mode::ZP}, 101},
|
||||
{{isa::op::ROR, isa::mode::ZP}, 102},
|
||||
{{isa::op::RMB6, isa::mode::ZP}, 103},
|
||||
{{isa::op::PLA, isa::mode::S}, 104},
|
||||
{{isa::op::ADC, isa::mode::IMM}, 105},
|
||||
{{isa::op::ROR, isa::mode::A}, 106},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 107},
|
||||
{{isa::op::JMP, isa::mode::AI}, 108},
|
||||
{{isa::op::ADC, isa::mode::A}, 109},
|
||||
{{isa::op::ROR, isa::mode::A}, 110},
|
||||
{{isa::op::BBR6, isa::mode::R}, 111},
|
||||
|
||||
{{isa::op::BVS, isa::mode::R}, 112},
|
||||
{{isa::op::ADC, isa::mode::ZPIY}, 113},
|
||||
{{isa::op::ADC, isa::mode::ZPI}, 114},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 115},
|
||||
{{isa::op::STZ, isa::mode::ZPX}, 116},
|
||||
{{isa::op::ADC, isa::mode::ZPX}, 117},
|
||||
{{isa::op::ROR, isa::mode::ZPX}, 118},
|
||||
{{isa::op::RMB7, isa::mode::ZP}, 119},
|
||||
{{isa::op::SEI, isa::mode::I}, 120},
|
||||
{{isa::op::ADC, isa::mode::AIY}, 121},
|
||||
{{isa::op::PLY, isa::mode::S}, 122},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 123},
|
||||
{{isa::op::JMP, isa::mode::AII}, 124},
|
||||
{{isa::op::ADC, isa::mode::AIX}, 125},
|
||||
{{isa::op::ROR, isa::mode::AIX}, 126},
|
||||
{{isa::op::BBR7, isa::mode::R}, 127},
|
||||
|
||||
{{isa::op::BRA, isa::mode::R}, 128},
|
||||
{{isa::op::STA, isa::mode::ZPII}, 129},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 130},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 131},
|
||||
{{isa::op::STY, isa::mode::ZP}, 132},
|
||||
{{isa::op::STA, isa::mode::ZP}, 133},
|
||||
{{isa::op::STX, isa::mode::ZP}, 134},
|
||||
{{isa::op::SMB0, isa::mode::ZP}, 135},
|
||||
{{isa::op::DEY, isa::mode::I}, 136},
|
||||
{{isa::op::BIT, isa::mode::IMM}, 137},
|
||||
{{isa::op::TXA, isa::mode::I}, 138},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 139},
|
||||
{{isa::op::STY, isa::mode::A}, 140},
|
||||
{{isa::op::STA, isa::mode::A}, 141},
|
||||
{{isa::op::STX, isa::mode::A}, 142},
|
||||
{{isa::op::BBS0, isa::mode::R}, 143},
|
||||
|
||||
{{isa::op::BCC, isa::mode::R}, 144},
|
||||
{{isa::op::STA, isa::mode::ZPIY}, 145},
|
||||
{{isa::op::STA, isa::mode::ZPI}, 146},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 147},
|
||||
{{isa::op::STY, isa::mode::ZPX}, 148},
|
||||
{{isa::op::STA, isa::mode::ZPX}, 149},
|
||||
{{isa::op::STX, isa::mode::ZPY}, 150},
|
||||
{{isa::op::SMB1, isa::mode::ZP}, 151},
|
||||
{{isa::op::TYA, isa::mode::I}, 152},
|
||||
{{isa::op::STA, isa::mode::AIY}, 153},
|
||||
{{isa::op::TXS, isa::mode::I}, 154},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 155},
|
||||
{{isa::op::STZ, isa::mode::A}, 156},
|
||||
{{isa::op::STA, isa::mode::AIX}, 157},
|
||||
{{isa::op::STZ, isa::mode::AIX}, 158},
|
||||
{{isa::op::BBS1, isa::mode::R}, 159},
|
||||
|
||||
{{isa::op::LDY, isa::mode::IMM}, 160},
|
||||
{{isa::op::LDA, isa::mode::ZPII}, 161},
|
||||
{{isa::op::LDX, isa::mode::IMM}, 162},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 163},
|
||||
{{isa::op::LDY, isa::mode::ZP}, 164},
|
||||
{{isa::op::LDA, isa::mode::ZP}, 165},
|
||||
{{isa::op::LDX, isa::mode::ZP}, 166},
|
||||
{{isa::op::SMB2, isa::mode::ZP}, 167},
|
||||
{{isa::op::TAY, isa::mode::I}, 168},
|
||||
{{isa::op::LDA, isa::mode::IMM}, 169},
|
||||
{{isa::op::TAX, isa::mode::I}, 170},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 171},
|
||||
{{isa::op::LDY, isa::mode::A}, 172},
|
||||
{{isa::op::LDA, isa::mode::A}, 173},
|
||||
{{isa::op::LDX, isa::mode::A}, 174},
|
||||
{{isa::op::BBS2, isa::mode::R}, 175},
|
||||
|
||||
{{isa::op::BCS, isa::mode::R}, 176},
|
||||
{{isa::op::LDA, isa::mode::ZPIY}, 177},
|
||||
{{isa::op::LDA, isa::mode::ZPI}, 178},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 179},
|
||||
{{isa::op::LDY, isa::mode::ZPX}, 180},
|
||||
{{isa::op::LDA, isa::mode::ZPX}, 181},
|
||||
{{isa::op::LDX, isa::mode::ZPY}, 182},
|
||||
{{isa::op::SMB3, isa::mode::ZP}, 183},
|
||||
{{isa::op::CLV, isa::mode::I}, 184},
|
||||
{{isa::op::LDA, isa::mode::AIY}, 185},
|
||||
{{isa::op::TSX, isa::mode::I}, 186},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 187},
|
||||
{{isa::op::LDY, isa::mode::AIX}, 188},
|
||||
{{isa::op::LDA, isa::mode::AIX}, 189},
|
||||
{{isa::op::LDX, isa::mode::AIY}, 190},
|
||||
{{isa::op::BBS3, isa::mode::R}, 191},
|
||||
|
||||
{{isa::op::CPY, isa::mode::IMM}, 192},
|
||||
{{isa::op::CMP, isa::mode::ZPII}, 193},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 194},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 195},
|
||||
{{isa::op::CPY, isa::mode::ZP}, 196},
|
||||
{{isa::op::CMP, isa::mode::ZP}, 197},
|
||||
{{isa::op::DEC, isa::mode::ZP}, 198},
|
||||
{{isa::op::SMB4, isa::mode::ZP}, 199},
|
||||
{{isa::op::INY, isa::mode::I}, 200},
|
||||
{{isa::op::CMP, isa::mode::IMM}, 201},
|
||||
{{isa::op::DEX, isa::mode::I}, 202},
|
||||
{{isa::op::WAI, isa::mode::I}, 203},
|
||||
{{isa::op::CPY, isa::mode::A}, 204},
|
||||
{{isa::op::CMP, isa::mode::A}, 205},
|
||||
{{isa::op::DEC, isa::mode::A}, 206},
|
||||
{{isa::op::BBS4, isa::mode::R}, 207},
|
||||
|
||||
{{isa::op::BNE, isa::mode::R}, 208},
|
||||
{{isa::op::CMP, isa::mode::ZPIY}, 209},
|
||||
{{isa::op::CMP, isa::mode::ZPI}, 210},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 211},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 212},
|
||||
{{isa::op::CMP, isa::mode::ZPX}, 213},
|
||||
{{isa::op::DEC, isa::mode::ZPX}, 214},
|
||||
{{isa::op::SMB5, isa::mode::ZP}, 215},
|
||||
{{isa::op::CLD, isa::mode::I}, 216},
|
||||
{{isa::op::CMP, isa::mode::AIY}, 217},
|
||||
{{isa::op::PHX, isa::mode::S}, 218},
|
||||
{{isa::op::STP, isa::mode::I}, 219},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 220},
|
||||
{{isa::op::CMP, isa::mode::AIX}, 221},
|
||||
{{isa::op::DEC, isa::mode::AIX}, 222},
|
||||
{{isa::op::BBS5, isa::mode::R}, 223},
|
||||
|
||||
{{isa::op::CPX, isa::mode::IMM}, 224},
|
||||
{{isa::op::SBC, isa::mode::ZPII}, 225},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 226},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 227},
|
||||
{{isa::op::CPX, isa::mode::ZP}, 228},
|
||||
{{isa::op::SBC, isa::mode::ZP}, 229},
|
||||
{{isa::op::INC, isa::mode::ZP}, 230},
|
||||
{{isa::op::SMB6, isa::mode::ZP}, 231},
|
||||
{{isa::op::INX, isa::mode::I}, 232},
|
||||
{{isa::op::SBC, isa::mode::IMM}, 233},
|
||||
{{isa::op::NOP, isa::mode::I}, 234},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 235},
|
||||
{{isa::op::CPX, isa::mode::A}, 236},
|
||||
{{isa::op::SBC, isa::mode::A}, 237},
|
||||
{{isa::op::INC, isa::mode::A}, 238},
|
||||
{{isa::op::BBS6, isa::mode::R}, 239},
|
||||
|
||||
{{isa::op::BEQ, isa::mode::R}, 240},
|
||||
{{isa::op::SBC, isa::mode::ZPIY}, 241},
|
||||
{{isa::op::SBC, isa::mode::ZPI}, 242},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 243},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 244},
|
||||
{{isa::op::SBC, isa::mode::ZPX}, 245},
|
||||
{{isa::op::INC, isa::mode::ZPX}, 246},
|
||||
{{isa::op::SMB7, isa::mode::ZP}, 247},
|
||||
{{isa::op::SED, isa::mode::I}, 248},
|
||||
{{isa::op::SBC, isa::mode::AIY}, 249},
|
||||
{{isa::op::PLX, isa::mode::S}, 250},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 251},
|
||||
//{{isa::op::O_INVALID, isa::mode::M_INVALID}, 252},
|
||||
{{isa::op::SBC, isa::mode::AIX}, 253},
|
||||
{{isa::op::INC, isa::mode::AIX}, 254},
|
||||
{{isa::op::BBS7, isa::mode::R}, 255},
|
||||
};
|
||||
return _;
|
||||
}
|
||||
|
||||
const std::map<uint8_t, std::tuple<isa::op, isa::mode>>& decode() {
|
||||
static const std::map<uint8_t, std::tuple<isa::op, isa::mode>> _ = {
|
||||
{0, {isa::op::BRK, isa::mode::S}},
|
||||
{1, {isa::op::ORA, isa::mode::ZPX}},
|
||||
//{2, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{3, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{4, {isa::op::TSB, isa::mode::ZP}},
|
||||
{5, {isa::op::ORA, isa::mode::ZP}},
|
||||
{6, {isa::op::ASL, isa::mode::ZP}},
|
||||
{7, {isa::op::RMB0, isa::mode::ZP}},
|
||||
{8, {isa::op::PHP, isa::mode::S}},
|
||||
{9, {isa::op::ORA, isa::mode::IMM}},
|
||||
{10, {isa::op::ASL, isa::mode::A}},
|
||||
//{11, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{12, {isa::op::TSB, isa::mode::A}},
|
||||
{13, {isa::op::ORA, isa::mode::A}},
|
||||
{14, {isa::op::ASL, isa::mode::A}},
|
||||
{15, {isa::op::BBR0, isa::mode::R}},
|
||||
|
||||
{16, {isa::op::BPL, isa::mode::R}},
|
||||
{17, {isa::op::ORA, isa::mode::ZPIY}},
|
||||
{18, {isa::op::ORA, isa::mode::ZPI}},
|
||||
//{19, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{20, {isa::op::TRB, isa::mode::ZP}},
|
||||
{21, {isa::op::ORA, isa::mode::ZPX}},
|
||||
{22, {isa::op::ASL, isa::mode::ZPX}},
|
||||
{23, {isa::op::RMB1, isa::mode::ZP}},
|
||||
{24, {isa::op::CLC, isa::mode::I}},
|
||||
{25, {isa::op::ORA, isa::mode::AIY}},
|
||||
{26, {isa::op::INC, isa::mode::A}},
|
||||
//{27, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{28, {isa::op::TRB, isa::mode::A}},
|
||||
{29, {isa::op::ORA, isa::mode::AIX}},
|
||||
{30, {isa::op::ASL, isa::mode::AIX}},
|
||||
{31, {isa::op::BBR1, isa::mode::R}},
|
||||
|
||||
{32, {isa::op::JSR, isa::mode::A}},
|
||||
{33, {isa::op::AND, isa::mode::ZPII}},
|
||||
//{34, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{35, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{36, {isa::op::BIT, isa::mode::ZP}},
|
||||
{37, {isa::op::AND, isa::mode::ZP}},
|
||||
{38, {isa::op::ROL, isa::mode::ZP}},
|
||||
{39, {isa::op::RMB2, isa::mode::ZP}},
|
||||
{40, {isa::op::PLP, isa::mode::S}},
|
||||
{41, {isa::op::AND, isa::mode::IMM}},
|
||||
{42, {isa::op::ROL, isa::mode::A}},
|
||||
//{43, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{44, {isa::op::BIT, isa::mode::A}},
|
||||
{45, {isa::op::AND, isa::mode::A}},
|
||||
{46, {isa::op::ROL, isa::mode::A}},
|
||||
{47, {isa::op::BBR2, isa::mode::R}},
|
||||
|
||||
{48, {isa::op::BMI, isa::mode::R}},
|
||||
{49, {isa::op::AND, isa::mode::ZPIY}},
|
||||
{50, {isa::op::AND, isa::mode::ZPI}},
|
||||
//{51, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{52, {isa::op::BIT, isa::mode::ZPX}},
|
||||
{53, {isa::op::AND, isa::mode::ZPX}},
|
||||
{54, {isa::op::ROL, isa::mode::ZPX}},
|
||||
{55, {isa::op::RMB3, isa::mode::ZP}},
|
||||
{56, {isa::op::SEC, isa::mode::I}},
|
||||
{57, {isa::op::AND, isa::mode::AIY}},
|
||||
{58, {isa::op::DEC, isa::mode::A}},
|
||||
//{59, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{60, {isa::op::BIT, isa::mode::AIX}},
|
||||
{61, {isa::op::AND, isa::mode::AIX}},
|
||||
{62, {isa::op::ROL, isa::mode::AIX}},
|
||||
{63, {isa::op::BBR3, isa::mode::R}},
|
||||
|
||||
{64, {isa::op::RTI, isa::mode::S}},
|
||||
{65, {isa::op::EOR, isa::mode::ZPII}},
|
||||
//{66, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{67, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{68, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{69, {isa::op::EOR, isa::mode::ZP}},
|
||||
{70, {isa::op::LSR, isa::mode::ZP}},
|
||||
{71, {isa::op::RMB4, isa::mode::ZP}},
|
||||
{72, {isa::op::PHA, isa::mode::S}},
|
||||
{73, {isa::op::EOR, isa::mode::IMM}},
|
||||
{74, {isa::op::LSR, isa::mode::A}},
|
||||
//{75, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{76, {isa::op::JMP, isa::mode::A}},
|
||||
{77, {isa::op::EOR, isa::mode::A}},
|
||||
{78, {isa::op::LSR, isa::mode::A}},
|
||||
{79, {isa::op::BBR4, isa::mode::R}},
|
||||
|
||||
{80, {isa::op::BVC, isa::mode::R}},
|
||||
{81, {isa::op::EOR, isa::mode::ZPIY}},
|
||||
{82, {isa::op::EOR, isa::mode::ZPI}},
|
||||
{83, {isa::op::EOR, isa::mode::ZPX}},
|
||||
//{84, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{85, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{86, {isa::op::LSR, isa::mode::ZPX}},
|
||||
{87, {isa::op::RMB5, isa::mode::ZP}},
|
||||
{88, {isa::op::CLI, isa::mode::I}},
|
||||
{89, {isa::op::EOR, isa::mode::AIY}},
|
||||
{90, {isa::op::PHY, isa::mode::S}},
|
||||
//{91, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{92, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{93, {isa::op::EOR, isa::mode::AIX}},
|
||||
{94, {isa::op::LSR, isa::mode::AIX}},
|
||||
{95, {isa::op::BBR5, isa::mode::R}},
|
||||
|
||||
{96, {isa::op::RTS, isa::mode::S}},
|
||||
{97, {isa::op::ADC, isa::mode::ZPII}},
|
||||
//{98, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{99, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{100, {isa::op::STZ, isa::mode::ZP}},
|
||||
{101, {isa::op::ADC, isa::mode::ZP}},
|
||||
{102, {isa::op::ROR, isa::mode::ZP}},
|
||||
{103, {isa::op::RMB6, isa::mode::ZP}},
|
||||
{104, {isa::op::PLA, isa::mode::S}},
|
||||
{105, {isa::op::ADC, isa::mode::IMM}},
|
||||
{106, {isa::op::ROR, isa::mode::A}},
|
||||
//{107, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{108, {isa::op::JMP, isa::mode::AI}},
|
||||
{109, {isa::op::ADC, isa::mode::A}},
|
||||
{110, {isa::op::ROR, isa::mode::A}},
|
||||
{111, {isa::op::BBR6, isa::mode::R}},
|
||||
|
||||
{112, {isa::op::BVS, isa::mode::R}},
|
||||
{113, {isa::op::ADC, isa::mode::ZPIY}},
|
||||
{114, {isa::op::ADC, isa::mode::ZPI}},
|
||||
//{115, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{116, {isa::op::STZ, isa::mode::ZPX}},
|
||||
{117, {isa::op::ADC, isa::mode::ZPX}},
|
||||
{118, {isa::op::ROR, isa::mode::ZPX}},
|
||||
{119, {isa::op::RMB7, isa::mode::ZP}},
|
||||
{120, {isa::op::SEI, isa::mode::I}},
|
||||
{121, {isa::op::ADC, isa::mode::AIY}},
|
||||
{122, {isa::op::PLY, isa::mode::S}},
|
||||
//{123, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{124, {isa::op::JMP, isa::mode::AII}},
|
||||
{125, {isa::op::ADC, isa::mode::AIX}},
|
||||
{126, {isa::op::ROR, isa::mode::AIX}},
|
||||
{127, {isa::op::BBR7, isa::mode::R}},
|
||||
|
||||
{128, {isa::op::BRA, isa::mode::R}},
|
||||
{129, {isa::op::STA, isa::mode::ZPII}},
|
||||
//{130, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{131, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{132, {isa::op::STY, isa::mode::ZP}},
|
||||
{133, {isa::op::STA, isa::mode::ZP}},
|
||||
{134, {isa::op::STX, isa::mode::ZP}},
|
||||
{135, {isa::op::SMB0, isa::mode::ZP}},
|
||||
{136, {isa::op::DEY, isa::mode::I}},
|
||||
{137, {isa::op::BIT, isa::mode::IMM}},
|
||||
{138, {isa::op::TXA, isa::mode::I}},
|
||||
//{139, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{140, {isa::op::STY, isa::mode::A}},
|
||||
{141, {isa::op::STA, isa::mode::A}},
|
||||
{142, {isa::op::STX, isa::mode::A}},
|
||||
{143, {isa::op::BBS0, isa::mode::R}},
|
||||
|
||||
{144, {isa::op::BCC, isa::mode::R}},
|
||||
{145, {isa::op::STA, isa::mode::ZPIY}},
|
||||
{146, {isa::op::STA, isa::mode::ZPI}},
|
||||
//{147, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{148, {isa::op::STY, isa::mode::ZPX}},
|
||||
{149, {isa::op::STA, isa::mode::ZPX}},
|
||||
{150, {isa::op::STX, isa::mode::ZPY}},
|
||||
{151, {isa::op::SMB1, isa::mode::ZP}},
|
||||
{152, {isa::op::TYA, isa::mode::I}},
|
||||
{153, {isa::op::STA, isa::mode::AIY}},
|
||||
{154, {isa::op::TXS, isa::mode::I}},
|
||||
//{155, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{156, {isa::op::STZ, isa::mode::A}},
|
||||
{157, {isa::op::STA, isa::mode::AIX}},
|
||||
{158, {isa::op::STZ, isa::mode::AIX}},
|
||||
{159, {isa::op::BBS1, isa::mode::R}},
|
||||
|
||||
{160, {isa::op::LDY, isa::mode::IMM}},
|
||||
{161, {isa::op::LDA, isa::mode::ZPII}},
|
||||
{162, {isa::op::LDX, isa::mode::IMM}},
|
||||
//{163, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{164, {isa::op::LDY, isa::mode::ZP}},
|
||||
{165, {isa::op::LDA, isa::mode::ZP}},
|
||||
{166, {isa::op::LDX, isa::mode::ZP}},
|
||||
{167, {isa::op::SMB2, isa::mode::ZP}},
|
||||
{168, {isa::op::TAY, isa::mode::I}},
|
||||
{169, {isa::op::LDA, isa::mode::IMM}},
|
||||
{170, {isa::op::TAX, isa::mode::I}},
|
||||
//{171, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{172, {isa::op::LDY, isa::mode::A}},
|
||||
{173, {isa::op::LDA, isa::mode::A}},
|
||||
{174, {isa::op::LDX, isa::mode::A}},
|
||||
{175, {isa::op::BBS2, isa::mode::R}},
|
||||
|
||||
{176, {isa::op::BCS, isa::mode::R}},
|
||||
{177, {isa::op::LDA, isa::mode::ZPIY}},
|
||||
{178, {isa::op::LDA, isa::mode::ZPI}},
|
||||
//{179, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{180, {isa::op::LDY, isa::mode::ZPX}},
|
||||
{181, {isa::op::LDA, isa::mode::ZPX}},
|
||||
{182, {isa::op::LDX, isa::mode::ZPY}},
|
||||
{183, {isa::op::SMB3, isa::mode::ZP}},
|
||||
{184, {isa::op::CLV, isa::mode::I}},
|
||||
{185, {isa::op::LDA, isa::mode::AIY}},
|
||||
{186, {isa::op::TSX, isa::mode::I}},
|
||||
//{187, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{188, {isa::op::LDY, isa::mode::AIX}},
|
||||
{189, {isa::op::LDA, isa::mode::AIX}},
|
||||
{190, {isa::op::LDX, isa::mode::AIY}},
|
||||
{191, {isa::op::BBS3, isa::mode::R}},
|
||||
|
||||
{192, {isa::op::CPY, isa::mode::IMM}},
|
||||
{193, {isa::op::CMP, isa::mode::ZPII}},
|
||||
//{194, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{195, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{196, {isa::op::CPY, isa::mode::ZP}},
|
||||
{197, {isa::op::CMP, isa::mode::ZP}},
|
||||
{198, {isa::op::DEC, isa::mode::ZP}},
|
||||
{199, {isa::op::SMB4, isa::mode::ZP}},
|
||||
{200, {isa::op::INY, isa::mode::I}},
|
||||
{201, {isa::op::CMP, isa::mode::IMM}},
|
||||
{202, {isa::op::DEX, isa::mode::I}},
|
||||
{203, {isa::op::WAI, isa::mode::I}},
|
||||
{204, {isa::op::CPY, isa::mode::A}},
|
||||
{205, {isa::op::CMP, isa::mode::A}},
|
||||
{206, {isa::op::DEC, isa::mode::A}},
|
||||
{207, {isa::op::BBS4, isa::mode::R}},
|
||||
|
||||
{208, {isa::op::BNE, isa::mode::R}},
|
||||
{209, {isa::op::CMP, isa::mode::ZPIY}},
|
||||
{210, {isa::op::CMP, isa::mode::ZPI}},
|
||||
//{211, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{212, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{213, {isa::op::CMP, isa::mode::ZPX}},
|
||||
{214, {isa::op::DEC, isa::mode::ZPX}},
|
||||
{215, {isa::op::SMB5, isa::mode::ZP}},
|
||||
{216, {isa::op::CLD, isa::mode::I}},
|
||||
{217, {isa::op::CMP, isa::mode::AIY}},
|
||||
{218, {isa::op::PHX, isa::mode::S}},
|
||||
{219, {isa::op::STP, isa::mode::I}},
|
||||
//{220, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{221, {isa::op::CMP, isa::mode::AIX}},
|
||||
{222, {isa::op::DEC, isa::mode::AIX}},
|
||||
{223, {isa::op::BBS5, isa::mode::R}},
|
||||
|
||||
{224, {isa::op::CPX, isa::mode::IMM}},
|
||||
{225, {isa::op::SBC, isa::mode::ZPII}},
|
||||
//{226, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{227, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{228, {isa::op::CPX, isa::mode::ZP}},
|
||||
{229, {isa::op::SBC, isa::mode::ZP}},
|
||||
{230, {isa::op::INC, isa::mode::ZP}},
|
||||
{231, {isa::op::SMB6, isa::mode::ZP}},
|
||||
{232, {isa::op::INX, isa::mode::I}},
|
||||
{233, {isa::op::SBC, isa::mode::IMM}},
|
||||
{234, {isa::op::NOP, isa::mode::I}},
|
||||
//{235, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{236, {isa::op::CPX, isa::mode::A}},
|
||||
{237, {isa::op::SBC, isa::mode::A}},
|
||||
{238, {isa::op::INC, isa::mode::A}},
|
||||
{239, {isa::op::BBS6, isa::mode::R}},
|
||||
|
||||
{240, {isa::op::BEQ, isa::mode::R}},
|
||||
{241, {isa::op::SBC, isa::mode::ZPIY}},
|
||||
{242, {isa::op::SBC, isa::mode::ZPI}},
|
||||
//{243, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{244, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{245, {isa::op::SBC, isa::mode::ZPX}},
|
||||
{246, {isa::op::INC, isa::mode::ZPX}},
|
||||
{247, {isa::op::SMB7, isa::mode::ZP}},
|
||||
{248, {isa::op::SED, isa::mode::I}},
|
||||
{249, {isa::op::SBC, isa::mode::AIY}},
|
||||
{250, {isa::op::PLX, isa::mode::S}},
|
||||
//{251, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
//{252, {isa::op::O_INVALID, isa::mode::M_INVALID}},
|
||||
{253, {isa::op::SBC, isa::mode::AIX}},
|
||||
{254, {isa::op::INC, isa::mode::AIX}},
|
||||
{255, {isa::op::BBS7, isa::mode::R}},
|
||||
};
|
||||
return _;
|
||||
}
|
||||
}
|
12
codec.hh
Normal file
12
codec.hh
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
|
||||
#include "isa.hh"
|
||||
|
||||
namespace codec {
|
||||
extern const std::map<std::tuple<isa::op, isa::mode>, uint8_t>& encode();
|
||||
const std::map<uint8_t, std::tuple<isa::op, isa::mode>>& decode();
|
||||
}
|
133
fromstring.cc
Normal file
133
fromstring.cc
Normal file
@ -0,0 +1,133 @@
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
#include "isa.hh"
|
||||
#include "mneumonic.hh"
|
||||
|
||||
namespace fromstring {
|
||||
const std::unordered_map<std::string_view, isa::op>& op() {
|
||||
static const std::unordered_map<std::string_view, isa::op> _ = {
|
||||
{mneumonic::op::ADC, isa::op::ADC},
|
||||
{mneumonic::op::AND, isa::op::AND},
|
||||
{mneumonic::op::ASL, isa::op::ASL},
|
||||
{mneumonic::op::BBR0, isa::op::BBR0},
|
||||
{mneumonic::op::BBR1, isa::op::BBR1},
|
||||
{mneumonic::op::BBR2, isa::op::BBR2},
|
||||
{mneumonic::op::BBR3, isa::op::BBR3},
|
||||
{mneumonic::op::BBR4, isa::op::BBR4},
|
||||
{mneumonic::op::BBR5, isa::op::BBR5},
|
||||
{mneumonic::op::BBR6, isa::op::BBR6},
|
||||
{mneumonic::op::BBR7, isa::op::BBR7},
|
||||
{mneumonic::op::BBS0, isa::op::BBS0},
|
||||
{mneumonic::op::BBS1, isa::op::BBS1},
|
||||
{mneumonic::op::BBS2, isa::op::BBS2},
|
||||
{mneumonic::op::BBS3, isa::op::BBS3},
|
||||
{mneumonic::op::BBS4, isa::op::BBS4},
|
||||
{mneumonic::op::BBS5, isa::op::BBS5},
|
||||
{mneumonic::op::BBS6, isa::op::BBS6},
|
||||
{mneumonic::op::BBS7, isa::op::BBS7},
|
||||
{mneumonic::op::BCC, isa::op::BCC},
|
||||
{mneumonic::op::BCS, isa::op::BCS},
|
||||
{mneumonic::op::BEQ, isa::op::BEQ},
|
||||
{mneumonic::op::BIT, isa::op::BIT},
|
||||
{mneumonic::op::BMI, isa::op::BMI},
|
||||
{mneumonic::op::BNE, isa::op::BNE},
|
||||
{mneumonic::op::BPL, isa::op::BPL},
|
||||
{mneumonic::op::BRA, isa::op::BRA},
|
||||
{mneumonic::op::BRK, isa::op::BRK},
|
||||
{mneumonic::op::BVC, isa::op::BVC},
|
||||
{mneumonic::op::BVS, isa::op::BVS},
|
||||
{mneumonic::op::CLC, isa::op::CLC},
|
||||
{mneumonic::op::CLD, isa::op::CLD},
|
||||
{mneumonic::op::CLI, isa::op::CLI},
|
||||
{mneumonic::op::CLV, isa::op::CLV},
|
||||
{mneumonic::op::CMP, isa::op::CMP},
|
||||
{mneumonic::op::CPX, isa::op::CPX},
|
||||
{mneumonic::op::CPY, isa::op::CPY},
|
||||
{mneumonic::op::DEC, isa::op::DEC},
|
||||
{mneumonic::op::DEX, isa::op::DEX},
|
||||
{mneumonic::op::DEY, isa::op::DEY},
|
||||
{mneumonic::op::EOR, isa::op::EOR},
|
||||
{mneumonic::op::INC, isa::op::INC},
|
||||
{mneumonic::op::INX, isa::op::INX},
|
||||
{mneumonic::op::INY, isa::op::INY},
|
||||
{mneumonic::op::JMP, isa::op::JMP},
|
||||
{mneumonic::op::JSR, isa::op::JSR},
|
||||
{mneumonic::op::LDA, isa::op::LDA},
|
||||
{mneumonic::op::LDX, isa::op::LDX},
|
||||
{mneumonic::op::LDY, isa::op::LDY},
|
||||
{mneumonic::op::LSR, isa::op::LSR},
|
||||
{mneumonic::op::NOP, isa::op::NOP},
|
||||
{mneumonic::op::ORA, isa::op::ORA},
|
||||
{mneumonic::op::PHA, isa::op::PHA},
|
||||
{mneumonic::op::PHP, isa::op::PHP},
|
||||
{mneumonic::op::PHX, isa::op::PHX},
|
||||
{mneumonic::op::PHY, isa::op::PHY},
|
||||
{mneumonic::op::PLA, isa::op::PLA},
|
||||
{mneumonic::op::PLP, isa::op::PLP},
|
||||
{mneumonic::op::PLX, isa::op::PLX},
|
||||
{mneumonic::op::PLY, isa::op::PLY},
|
||||
{mneumonic::op::RMB0, isa::op::RMB0},
|
||||
{mneumonic::op::RMB1, isa::op::RMB1},
|
||||
{mneumonic::op::RMB2, isa::op::RMB2},
|
||||
{mneumonic::op::RMB3, isa::op::RMB3},
|
||||
{mneumonic::op::RMB4, isa::op::RMB4},
|
||||
{mneumonic::op::RMB5, isa::op::RMB5},
|
||||
{mneumonic::op::RMB6, isa::op::RMB6},
|
||||
{mneumonic::op::RMB7, isa::op::RMB7},
|
||||
{mneumonic::op::ROL, isa::op::ROL},
|
||||
{mneumonic::op::ROR, isa::op::ROR},
|
||||
{mneumonic::op::RTI, isa::op::RTI},
|
||||
{mneumonic::op::RTS, isa::op::RTS},
|
||||
{mneumonic::op::SBC, isa::op::SBC},
|
||||
{mneumonic::op::SEC, isa::op::SEC},
|
||||
{mneumonic::op::SED, isa::op::SED},
|
||||
{mneumonic::op::SEI, isa::op::SEI},
|
||||
{mneumonic::op::SMB0, isa::op::SMB0},
|
||||
{mneumonic::op::SMB1, isa::op::SMB1},
|
||||
{mneumonic::op::SMB2, isa::op::SMB2},
|
||||
{mneumonic::op::SMB3, isa::op::SMB3},
|
||||
{mneumonic::op::SMB4, isa::op::SMB4},
|
||||
{mneumonic::op::SMB5, isa::op::SMB5},
|
||||
{mneumonic::op::SMB6, isa::op::SMB6},
|
||||
{mneumonic::op::SMB7, isa::op::SMB7},
|
||||
{mneumonic::op::STA, isa::op::STA},
|
||||
{mneumonic::op::STP, isa::op::STP},
|
||||
{mneumonic::op::STX, isa::op::STX},
|
||||
{mneumonic::op::STY, isa::op::STY},
|
||||
{mneumonic::op::STZ, isa::op::STZ},
|
||||
{mneumonic::op::TAX, isa::op::TAX},
|
||||
{mneumonic::op::TAY, isa::op::TAY},
|
||||
{mneumonic::op::TRB, isa::op::TRB},
|
||||
{mneumonic::op::TSB, isa::op::TSB},
|
||||
{mneumonic::op::TSX, isa::op::TSX},
|
||||
{mneumonic::op::TXA, isa::op::TXA},
|
||||
{mneumonic::op::TXS, isa::op::TXS},
|
||||
{mneumonic::op::TYA, isa::op::TYA},
|
||||
{mneumonic::op::WAI, isa::op::WAI},
|
||||
};
|
||||
return _;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string_view, isa::mode>& mode() {
|
||||
static const std::unordered_map<std::string_view, isa::mode> _ {
|
||||
{mneumonic::mode::A, isa::mode::A},
|
||||
{mneumonic::mode::AII, isa::mode::AII},
|
||||
{mneumonic::mode::AIX, isa::mode::AIX},
|
||||
{mneumonic::mode::AIY, isa::mode::AIY},
|
||||
{mneumonic::mode::AI, isa::mode::AI},
|
||||
{mneumonic::mode::ACC, isa::mode::ACC},
|
||||
{mneumonic::mode::IMM, isa::mode::IMM},
|
||||
{mneumonic::mode::I, isa::mode::I},
|
||||
{mneumonic::mode::R, isa::mode::R},
|
||||
{mneumonic::mode::S, isa::mode::S},
|
||||
{mneumonic::mode::ZP, isa::mode::ZP},
|
||||
{mneumonic::mode::ZPII, isa::mode::ZPII},
|
||||
{mneumonic::mode::ZPX, isa::mode::ZPX},
|
||||
{mneumonic::mode::ZPY, isa::mode::ZPY},
|
||||
{mneumonic::mode::ZPI, isa::mode::ZPI},
|
||||
{mneumonic::mode::ZPIY, isa::mode::ZPIY},
|
||||
};
|
||||
return _;
|
||||
}
|
||||
}
|
14
fromstring.hh
Normal file
14
fromstring.hh
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "isa.hh"
|
||||
#include "codec.hh"
|
||||
#include "mneumonic.hh"
|
||||
|
||||
namespace fromstring {
|
||||
const std::unordered_map<std::string_view, isa::op>& op();
|
||||
|
||||
const std::unordered_map<std::string_view, isa::mode>& mode();
|
||||
}
|
125
isa.hh
Normal file
125
isa.hh
Normal file
@ -0,0 +1,125 @@
|
||||
#pragma once
|
||||
|
||||
namespace isa {
|
||||
|
||||
enum class op {
|
||||
ADC,
|
||||
AND,
|
||||
ASL,
|
||||
BBR0,
|
||||
BBR1,
|
||||
BBR2,
|
||||
BBR3,
|
||||
BBR4,
|
||||
BBR5,
|
||||
BBR6,
|
||||
BBR7,
|
||||
BBS0,
|
||||
BBS1,
|
||||
BBS2,
|
||||
BBS3,
|
||||
BBS4,
|
||||
BBS5,
|
||||
BBS6,
|
||||
BBS7,
|
||||
BCC,
|
||||
BCS,
|
||||
BEQ,
|
||||
BIT,
|
||||
BMI,
|
||||
BNE,
|
||||
BPL,
|
||||
BRA,
|
||||
BRK,
|
||||
BVC,
|
||||
BVS,
|
||||
CLC,
|
||||
CLD,
|
||||
CLI,
|
||||
CLV,
|
||||
CMP,
|
||||
CPX,
|
||||
CPY,
|
||||
DEC,
|
||||
DEX,
|
||||
DEY,
|
||||
EOR,
|
||||
INC,
|
||||
INX,
|
||||
INY,
|
||||
JMP,
|
||||
JSR,
|
||||
LDA,
|
||||
LDX,
|
||||
LDY,
|
||||
LSR,
|
||||
NOP,
|
||||
ORA,
|
||||
PHA,
|
||||
PHP,
|
||||
PHX,
|
||||
PHY,
|
||||
PLA,
|
||||
PLP,
|
||||
PLX,
|
||||
PLY,
|
||||
RMB0,
|
||||
RMB1,
|
||||
RMB2,
|
||||
RMB3,
|
||||
RMB4,
|
||||
RMB5,
|
||||
RMB6,
|
||||
RMB7,
|
||||
ROL,
|
||||
ROR,
|
||||
RTI,
|
||||
RTS,
|
||||
SBC,
|
||||
SEC,
|
||||
SED,
|
||||
SEI,
|
||||
SMB0,
|
||||
SMB1,
|
||||
SMB2,
|
||||
SMB3,
|
||||
SMB4,
|
||||
SMB5,
|
||||
SMB6,
|
||||
SMB7,
|
||||
STA,
|
||||
STP,
|
||||
STX,
|
||||
STY,
|
||||
STZ,
|
||||
TAX,
|
||||
TAY,
|
||||
TRB,
|
||||
TSB,
|
||||
TSX,
|
||||
TXA,
|
||||
TXS,
|
||||
TYA,
|
||||
WAI,
|
||||
};
|
||||
|
||||
enum class mode {
|
||||
A, // Absolute a
|
||||
AII, // Absolute Indexed Indirect (a,x)
|
||||
AIX, // Absolute Indexed with X a,x
|
||||
AIY, // Absolute Indexed with Y a,y
|
||||
AI, // Absolute Indrect (a)
|
||||
ACC, // Accumulator A
|
||||
IMM, // Immediate #
|
||||
I, // Implied i
|
||||
R, // Program Counter Relative r
|
||||
S, // Stack s
|
||||
ZP, // Zero Page zp
|
||||
ZPII, // Zero Page Indexed Indirect (zp,x)
|
||||
ZPX, // Zero Page Indexed with X zp,x
|
||||
ZPY, // Zero Page Indexed with Y zp,y
|
||||
ZPI, // Zero Page Indirect (zp)
|
||||
ZPIY, // Zero Page Indirect Indexed with Y (zp),y
|
||||
};
|
||||
|
||||
}
|
137
main.cc
Normal file
137
main.cc
Normal file
@ -0,0 +1,137 @@
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "assembler.hh"
|
||||
#include "addressing_mode.hh"
|
||||
#include "codec.hh"
|
||||
#include "parser.hh"
|
||||
|
||||
using symbol_table_t = std::unordered_map<size_t, assembler::program_t::const_iterator>;
|
||||
|
||||
bool resolve_symbols(assembler::program_t& program, symbol_table_t& symbol_table)
|
||||
{
|
||||
size_t offset = 0;
|
||||
|
||||
for (auto ins = program.begin(); ins != program.end(); ins++) {
|
||||
if (ins->symbol != std::nullopt) {
|
||||
auto [_, ok] = symbol_table.insert({*(ins->symbol), ins});
|
||||
if (!ok) {
|
||||
std::cout << "duplicate symbol\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << *(ins->symbol) << ' ' << offset << '\n';
|
||||
}
|
||||
|
||||
ins->location = offset;
|
||||
|
||||
auto am_it = addressing_mode().find(ins->mode);
|
||||
assert (am_it != addressing_mode().end());
|
||||
offset += 1 + am_it->second.len;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void serialize_program(const assembler::program_t& program, const symbol_table_t &symbol_table, size_t link_location, std::ostream& out)
|
||||
{
|
||||
char buf[3];
|
||||
|
||||
for (auto ins = program.cbegin(); ins != program.cend(); ins++) {
|
||||
std::cerr << "enc " << (int)ins->op << ' ' << (int)ins->mode << '\n';
|
||||
auto opcode_it = codec::encode().find({ins->op, ins->mode});
|
||||
assert (opcode_it != codec::encode().end());
|
||||
|
||||
buf[0] = opcode_it->second;
|
||||
|
||||
auto am_it = addressing_mode().find(ins->mode);
|
||||
assert (am_it != addressing_mode().end());
|
||||
|
||||
auto get_value = [&]() -> ssize_t {
|
||||
if (std::holds_alternative<assembler::reference_t>(ins->value)) {
|
||||
assembler::reference_t ref = std::get<assembler::reference_t>(ins->value);
|
||||
auto sym_it = symbol_table.find(ref.symbol);
|
||||
assert (sym_it != symbol_table.end());
|
||||
auto ref_ins = sym_it->second;
|
||||
if (ins->mode == isa::mode::R) {
|
||||
std::cout << "relative\n";
|
||||
ssize_t offset = static_cast<ssize_t>(ref_ins->location) - static_cast<ssize_t>(ins->location + 2);
|
||||
return offset;
|
||||
} else {
|
||||
return ref_ins->location + link_location;
|
||||
}
|
||||
} else if (std::holds_alternative<assembler::literal_t>(ins->value)) {
|
||||
assembler::literal_t lit = std::get<assembler::literal_t>(ins->value);
|
||||
return lit.num;
|
||||
} else if (std::holds_alternative<assembler::implied_t>(ins->value)) {
|
||||
assert (std::holds_alternative<assembler::implied_t>(ins->value));
|
||||
} else {
|
||||
assert (false);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
size_t value = get_value();
|
||||
if (!am_it->second.valid(value)) {
|
||||
std::cout << "overflow at h" << std::hex << ins->location << '\n';
|
||||
}
|
||||
|
||||
std::cout << "value " << std::hex << value << ' ' << am_it->second.len << '\n';
|
||||
|
||||
if (am_it->second.len >= 2)
|
||||
buf[2] = (value >> 8) & 0xff;
|
||||
if (am_it->second.len >= 1)
|
||||
buf[1] = (value >> 0) & 0xff;
|
||||
|
||||
out.write(buf, 1 + am_it->second.len);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
if (argc < 3) {
|
||||
std::cerr << "argc < 3\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string input_filename {argv[1]};
|
||||
std::ifstream is {input_filename, std::ios::binary | std::ios::ate};
|
||||
if (!is.is_open()) {
|
||||
std::cerr << "failed to open " << input_filename << '\n';
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto size = is.tellg();
|
||||
std::string buf(size, '\0'); // construct string to stream size
|
||||
is.seekg(0);
|
||||
is.read(buf.data(), size);
|
||||
is.close();
|
||||
|
||||
|
||||
assembler::program_t program;
|
||||
symbol_table_t symbol_table;
|
||||
bool ok;
|
||||
|
||||
ok = parser::parse(buf, program);
|
||||
if (!ok)
|
||||
return -1;
|
||||
|
||||
ok = resolve_symbols(program, symbol_table);
|
||||
if (!ok)
|
||||
return -1;
|
||||
|
||||
|
||||
std::string output_filename {argv[2]};
|
||||
std::ofstream out {output_filename, std::ios::binary};
|
||||
if (!out.is_open()) {
|
||||
std::cerr << "failed to open " << output_filename << '\n';
|
||||
return -1;
|
||||
}
|
||||
|
||||
serialize_program(program, symbol_table, 0x8000, out);
|
||||
|
||||
out.close();
|
||||
return 0;
|
||||
}
|
127
mneumonic.hh
Normal file
127
mneumonic.hh
Normal file
@ -0,0 +1,127 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mneumonic {
|
||||
namespace mode {
|
||||
constexpr std::string_view A = "a";
|
||||
constexpr std::string_view AII = "(a,x)";
|
||||
constexpr std::string_view AIX = "a,x";
|
||||
constexpr std::string_view AIY = "a,y";
|
||||
constexpr std::string_view AI = "(a)";
|
||||
constexpr std::string_view ACC = "A";
|
||||
constexpr std::string_view IMM = "#";
|
||||
constexpr std::string_view I = "i";
|
||||
constexpr std::string_view R = "r";
|
||||
constexpr std::string_view S = "s";
|
||||
constexpr std::string_view ZP = "zp";
|
||||
constexpr std::string_view ZPII = "(zp,x)";
|
||||
constexpr std::string_view ZPX = "zp,x";
|
||||
constexpr std::string_view ZPY = "zp,y";
|
||||
constexpr std::string_view ZPI = "(zp)";
|
||||
constexpr std::string_view ZPIY = "(zp),y";
|
||||
}
|
||||
}
|
||||
|
||||
namespace mneumonic {
|
||||
namespace op {
|
||||
constexpr std::string_view ADC = "ADC";
|
||||
constexpr std::string_view AND = "AND";
|
||||
constexpr std::string_view ASL = "ASL";
|
||||
constexpr std::string_view BBR0 = "BBR0";
|
||||
constexpr std::string_view BBR1 = "BBR1";
|
||||
constexpr std::string_view BBR2 = "BBR2";
|
||||
constexpr std::string_view BBR3 = "BBR3";
|
||||
constexpr std::string_view BBR4 = "BBR4";
|
||||
constexpr std::string_view BBR5 = "BBR5";
|
||||
constexpr std::string_view BBR6 = "BBR6";
|
||||
constexpr std::string_view BBR7 = "BBR7";
|
||||
constexpr std::string_view BBS0 = "BBS0";
|
||||
constexpr std::string_view BBS1 = "BBS1";
|
||||
constexpr std::string_view BBS2 = "BBS2";
|
||||
constexpr std::string_view BBS3 = "BBS3";
|
||||
constexpr std::string_view BBS4 = "BBS4";
|
||||
constexpr std::string_view BBS5 = "BBS5";
|
||||
constexpr std::string_view BBS6 = "BBS6";
|
||||
constexpr std::string_view BBS7 = "BBS7";
|
||||
constexpr std::string_view BCC = "BCC";
|
||||
constexpr std::string_view BCS = "BCS";
|
||||
constexpr std::string_view BEQ = "BEQ";
|
||||
constexpr std::string_view BIT = "BIT";
|
||||
constexpr std::string_view BMI = "BMI";
|
||||
constexpr std::string_view BNE = "BNE";
|
||||
constexpr std::string_view BPL = "BPL";
|
||||
constexpr std::string_view BRA = "BRA";
|
||||
constexpr std::string_view BRK = "BRK";
|
||||
constexpr std::string_view BVC = "BVC";
|
||||
constexpr std::string_view BVS = "BVS";
|
||||
constexpr std::string_view CLC = "CLC";
|
||||
constexpr std::string_view CLD = "CLD";
|
||||
constexpr std::string_view CLI = "CLI";
|
||||
constexpr std::string_view CLV = "CLV";
|
||||
constexpr std::string_view CMP = "CMP";
|
||||
constexpr std::string_view CPX = "CPX";
|
||||
constexpr std::string_view CPY = "CPY";
|
||||
constexpr std::string_view DEC = "DEC";
|
||||
constexpr std::string_view DEX = "DEX";
|
||||
constexpr std::string_view DEY = "DEY";
|
||||
constexpr std::string_view EOR = "EOR";
|
||||
constexpr std::string_view INC = "INC";
|
||||
constexpr std::string_view INX = "INX";
|
||||
constexpr std::string_view INY = "INY";
|
||||
constexpr std::string_view JMP = "JMP";
|
||||
constexpr std::string_view JSR = "JSR";
|
||||
constexpr std::string_view LDA = "LDA";
|
||||
constexpr std::string_view LDX = "LDX";
|
||||
constexpr std::string_view LDY = "LDY";
|
||||
constexpr std::string_view LSR = "LSR";
|
||||
constexpr std::string_view NOP = "NOP";
|
||||
constexpr std::string_view ORA = "ORA";
|
||||
constexpr std::string_view PHA = "PHA";
|
||||
constexpr std::string_view PHP = "PHP";
|
||||
constexpr std::string_view PHX = "PHX";
|
||||
constexpr std::string_view PHY = "PHY";
|
||||
constexpr std::string_view PLA = "PLA";
|
||||
constexpr std::string_view PLP = "PLP";
|
||||
constexpr std::string_view PLX = "PLX";
|
||||
constexpr std::string_view PLY = "PLY";
|
||||
constexpr std::string_view RMB0 = "RMB0";
|
||||
constexpr std::string_view RMB1 = "RMB1";
|
||||
constexpr std::string_view RMB2 = "RMB2";
|
||||
constexpr std::string_view RMB3 = "RMB3";
|
||||
constexpr std::string_view RMB4 = "RMB4";
|
||||
constexpr std::string_view RMB5 = "RMB5";
|
||||
constexpr std::string_view RMB6 = "RMB6";
|
||||
constexpr std::string_view RMB7 = "RMB7";
|
||||
constexpr std::string_view ROL = "ROL";
|
||||
constexpr std::string_view ROR = "ROR";
|
||||
constexpr std::string_view RTI = "RTI";
|
||||
constexpr std::string_view RTS = "RTS";
|
||||
constexpr std::string_view SBC = "SBC";
|
||||
constexpr std::string_view SEC = "SEC";
|
||||
constexpr std::string_view SED = "SED";
|
||||
constexpr std::string_view SEI = "SEI";
|
||||
constexpr std::string_view SMB0 = "SMB0";
|
||||
constexpr std::string_view SMB1 = "SMB1";
|
||||
constexpr std::string_view SMB2 = "SMB2";
|
||||
constexpr std::string_view SMB3 = "SMB3";
|
||||
constexpr std::string_view SMB4 = "SMB4";
|
||||
constexpr std::string_view SMB5 = "SMB5";
|
||||
constexpr std::string_view SMB6 = "SMB6";
|
||||
constexpr std::string_view SMB7 = "SMB7";
|
||||
constexpr std::string_view STA = "STA";
|
||||
constexpr std::string_view STP = "STP";
|
||||
constexpr std::string_view STX = "STX";
|
||||
constexpr std::string_view STY = "STY";
|
||||
constexpr std::string_view STZ = "STZ";
|
||||
constexpr std::string_view TAX = "TAX";
|
||||
constexpr std::string_view TAY = "TAY";
|
||||
constexpr std::string_view TRB = "TRB";
|
||||
constexpr std::string_view TSB = "TSB";
|
||||
constexpr std::string_view TSX = "TSX";
|
||||
constexpr std::string_view TXA = "TXA";
|
||||
constexpr std::string_view TXS = "TXS";
|
||||
constexpr std::string_view TYA = "TYA";
|
||||
constexpr std::string_view WAI = "WAI";
|
||||
}
|
||||
}
|
261
parser.cc
Normal file
261
parser.cc
Normal file
@ -0,0 +1,261 @@
|
||||
#include <cassert>
|
||||
#include <string_view>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <variant>
|
||||
|
||||
#include "assembler.hh"
|
||||
#include "addressing_mode.hh"
|
||||
#include "fromstring.hh"
|
||||
#include "isa.hh"
|
||||
|
||||
static bool tokenize(std::string_view buf, std::function<bool(std::string_view, ssize_t, ssize_t)> cb)
|
||||
{
|
||||
auto it = buf.cbegin();
|
||||
std::optional<decltype(it)> token_begin = std::nullopt;
|
||||
|
||||
ssize_t row = 0;
|
||||
ssize_t col = 0;
|
||||
|
||||
while (it != buf.cend()) {
|
||||
auto c = *it;
|
||||
switch (c) {
|
||||
case '\n':
|
||||
case ' ':
|
||||
if (token_begin != std::nullopt) {
|
||||
bool ret = cb(buf.substr(*token_begin - buf.cbegin(), it - *token_begin), row, col);
|
||||
if (!ret) {
|
||||
// cb failed
|
||||
return false;
|
||||
}
|
||||
token_begin = std::nullopt;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (token_begin == std::nullopt) {
|
||||
token_begin = it;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '\n') {
|
||||
col = 0;
|
||||
row++;
|
||||
} else {
|
||||
col++;
|
||||
};
|
||||
it++;
|
||||
}
|
||||
|
||||
bool ret = cb("", row + 1, col);
|
||||
if (!ret) {
|
||||
// cb failed
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
namespace parser {
|
||||
enum class state {
|
||||
label_or_op,
|
||||
op,
|
||||
mode,
|
||||
value,
|
||||
comment,
|
||||
just_comment,
|
||||
};
|
||||
}
|
||||
|
||||
using symbol_strings_t = std::unordered_map<std::string_view, size_t>;
|
||||
|
||||
namespace parser {
|
||||
|
||||
bool parse(std::string_view buf, assembler::program_t& program)
|
||||
{
|
||||
size_t current_symbol = 0;
|
||||
symbol_strings_t ss;
|
||||
|
||||
parser::state state = parser::state::label_or_op;
|
||||
|
||||
auto get_symbol = [&](std::string_view s) {
|
||||
auto find = ss.find(s);
|
||||
if (find == ss.end()) {
|
||||
auto insert = ss.insert({s, current_symbol++});
|
||||
assert(insert.second);
|
||||
return (insert.first)->second;
|
||||
} else {
|
||||
return find->second;
|
||||
}
|
||||
};
|
||||
|
||||
assembler::instruction_t current_instruction;
|
||||
ssize_t current_row;
|
||||
|
||||
bool inside_comment = false;
|
||||
|
||||
bool parsed = tokenize(buf, [&](std::string_view s, ssize_t row, ssize_t col) -> bool {
|
||||
while (true) {
|
||||
switch (state) {
|
||||
case parser::state::label_or_op:
|
||||
{
|
||||
current_row = row;
|
||||
if (s.back() == ':') {
|
||||
std::string_view key = s.substr(0, s.length() - 1);
|
||||
auto symbol = get_symbol(key);
|
||||
std::cout << "label `" << symbol << "`\n";
|
||||
current_instruction.symbol = symbol;
|
||||
state = parser::state::op;
|
||||
return true;
|
||||
} else if (s.front() == ';') {
|
||||
state = parser::state::just_comment;
|
||||
continue;
|
||||
} else if (s.empty()) {
|
||||
// I hate myself for this dirty hack
|
||||
return true;
|
||||
} else {
|
||||
current_instruction.symbol = std::nullopt;
|
||||
[[fallthrough]];
|
||||
}
|
||||
}
|
||||
case parser::state::op:
|
||||
{
|
||||
assert(row == current_row);
|
||||
auto op_it = fromstring::op().find(s);
|
||||
if (op_it == fromstring::op().end()) {
|
||||
std::cout << "invalid op `" << s << "`\n";
|
||||
return false;
|
||||
} else {
|
||||
current_instruction.op = op_it->second;
|
||||
std::cout << "ok op `" << static_cast<int>(op_it->second) << "`\n";
|
||||
}
|
||||
state = parser::state::mode;
|
||||
return true;
|
||||
}
|
||||
case parser::state::mode:
|
||||
{
|
||||
assert(row == current_row);
|
||||
auto mode_it = fromstring::mode().find(s);
|
||||
if (mode_it == fromstring::mode().end()) {
|
||||
std::cout << "invalid mode `" << s << "`\n";
|
||||
return false;
|
||||
} else {
|
||||
current_instruction.mode = mode_it->second;
|
||||
std::cout << "ok mode `" << static_cast<int>(mode_it->second) << "`\n";
|
||||
}
|
||||
state = parser::state::value;
|
||||
return true;
|
||||
}
|
||||
case parser::state::value:
|
||||
{
|
||||
auto am_it = addressing_mode().find(current_instruction.mode);
|
||||
assert(am_it != addressing_mode().end());
|
||||
if (am_it->second.len == 0) {
|
||||
std::cout << "no value expected\n";
|
||||
assembler::implied_t i {};
|
||||
current_instruction.value = i;
|
||||
state = parser::state::comment;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(row == current_row);
|
||||
|
||||
auto parse_integer = [](std::string_view s, int base) -> std::optional<ssize_t> {
|
||||
std::string value_str {s.data() + 1, s.size() - 1};
|
||||
size_t pos;
|
||||
ssize_t value;
|
||||
value = std::stoll(value_str, &pos, base);
|
||||
if (pos != value_str.length())
|
||||
return std::nullopt;
|
||||
else
|
||||
return value;
|
||||
};
|
||||
|
||||
std::optional<ssize_t> literal;
|
||||
auto as_literal = [](ssize_t n) -> assembler::literal_t { return {n}; };
|
||||
switch (*s.cbegin()) {
|
||||
case 'h':
|
||||
{
|
||||
literal = parse_integer(s, 16);
|
||||
if (literal == std::nullopt) {
|
||||
std::cout << "invalid hex literal\n";
|
||||
}
|
||||
current_instruction.value = as_literal(*literal);
|
||||
std::cout << "value hex literal `" << *literal << "`\n";
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
{
|
||||
literal = parse_integer(s, 10);
|
||||
if (literal == std::nullopt) {
|
||||
std::cout << "invalid dec literal\n";
|
||||
return false;
|
||||
}
|
||||
current_instruction.value = as_literal(*literal);
|
||||
std::cout << "value dec literal `" << *literal << "`\n";
|
||||
break;
|
||||
}
|
||||
case ':':
|
||||
{
|
||||
std::string_view key = s.substr(1, s.length() - 1);
|
||||
assembler::reference_t reference = { get_symbol(key) };
|
||||
current_instruction.value = reference;
|
||||
std::cout << "value reference `" << reference.symbol << "`\n";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
std::cout << "invalid base\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
state = parser::state::comment;
|
||||
return true;
|
||||
}
|
||||
case parser::state::comment:
|
||||
{
|
||||
if (row != current_row) {
|
||||
std::cerr << "push " << (int)current_instruction.op << '\n';
|
||||
inside_comment = false;
|
||||
program.push_back(current_instruction);
|
||||
state = parser::state::label_or_op;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*s.cbegin() == ';') {
|
||||
inside_comment = true;
|
||||
return true;
|
||||
} else if (inside_comment) {
|
||||
return true;
|
||||
} else {
|
||||
std::cout << "expected comment\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case parser::state::just_comment:
|
||||
{
|
||||
if (row != current_row) {
|
||||
inside_comment = false;
|
||||
state = parser::state::label_or_op;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*s.cbegin() == ';') {
|
||||
inside_comment = true;
|
||||
return true;
|
||||
} else if (inside_comment) {
|
||||
return true;
|
||||
} else {
|
||||
std::cout << "expected comment\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
}
|
9
parser.hh
Normal file
9
parser.hh
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "assembler.hh"
|
||||
|
||||
namespace parser {
|
||||
bool parse(std::string_view buf, assembler::program_t& program);
|
||||
}
|
127
tostring.cc
Normal file
127
tostring.cc
Normal file
@ -0,0 +1,127 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "instruction.hh"
|
||||
#include "mneumonic.hh"
|
||||
|
||||
namespace tostring {
|
||||
const std::unordered_map<op_t, std::string_view> op {
|
||||
{op::ADC, mneumonic::op::ADC},
|
||||
{op::AND, mneumonic::op::AND},
|
||||
{op::ASL, mneumonic::op::ASL},
|
||||
{op::BBR0, mneumonic::op::BBR0},
|
||||
{op::BBR1, mneumonic::op::BBR1},
|
||||
{op::BBR2, mneumonic::op::BBR2},
|
||||
{op::BBR3, mneumonic::op::BBR3},
|
||||
{op::BBR4, mneumonic::op::BBR4},
|
||||
{op::BBR5, mneumonic::op::BBR5},
|
||||
{op::BBR6, mneumonic::op::BBR6},
|
||||
{op::BBR7, mneumonic::op::BBR7},
|
||||
{op::BBS0, mneumonic::op::BBS0},
|
||||
{op::BBS1, mneumonic::op::BBS1},
|
||||
{op::BBS2, mneumonic::op::BBS2},
|
||||
{op::BBS3, mneumonic::op::BBS3},
|
||||
{op::BBS4, mneumonic::op::BBS4},
|
||||
{op::BBS5, mneumonic::op::BBS5},
|
||||
{op::BBS6, mneumonic::op::BBS6},
|
||||
{op::BBS7, mneumonic::op::BBS7},
|
||||
{op::BCC, mneumonic::op::BCC},
|
||||
{op::BCS, mneumonic::op::BCS},
|
||||
{op::BEQ, mneumonic::op::BEQ},
|
||||
{op::BIT, mneumonic::op::BIT},
|
||||
{op::BMI, mneumonic::op::BMI},
|
||||
{op::BNE, mneumonic::op::BNE},
|
||||
{op::BPL, mneumonic::op::BPL},
|
||||
{op::BRA, mneumonic::op::BRA},
|
||||
{op::BRK, mneumonic::op::BRK},
|
||||
{op::BVC, mneumonic::op::BVC},
|
||||
{op::BVS, mneumonic::op::BVS},
|
||||
{op::CLC, mneumonic::op::CLC},
|
||||
{op::CLD, mneumonic::op::CLD},
|
||||
{op::CLI, mneumonic::op::CLI},
|
||||
{op::CLV, mneumonic::op::CLV},
|
||||
{op::CMP, mneumonic::op::CMP},
|
||||
{op::CPX, mneumonic::op::CPX},
|
||||
{op::CPY, mneumonic::op::CPY},
|
||||
{op::DEC, mneumonic::op::DEC},
|
||||
{op::DEX, mneumonic::op::DEX},
|
||||
{op::DEY, mneumonic::op::DEY},
|
||||
{op::EOR, mneumonic::op::EOR},
|
||||
{op::INC, mneumonic::op::INC},
|
||||
{op::INX, mneumonic::op::INX},
|
||||
{op::INY, mneumonic::op::INY},
|
||||
{op::JMP, mneumonic::op::JMP},
|
||||
{op::JSR, mneumonic::op::JSR},
|
||||
{op::LDA, mneumonic::op::LDA},
|
||||
{op::LDX, mneumonic::op::LDX},
|
||||
{op::LDY, mneumonic::op::LDY},
|
||||
{op::LSR, mneumonic::op::LSR},
|
||||
{op::NOP, mneumonic::op::NOP},
|
||||
{op::ORA, mneumonic::op::ORA},
|
||||
{op::PHA, mneumonic::op::PHA},
|
||||
{op::PHP, mneumonic::op::PHP},
|
||||
{op::PHX, mneumonic::op::PHX},
|
||||
{op::PHY, mneumonic::op::PHY},
|
||||
{op::PLA, mneumonic::op::PLA},
|
||||
{op::PLP, mneumonic::op::PLP},
|
||||
{op::PLX, mneumonic::op::PLX},
|
||||
{op::PLY, mneumonic::op::PLY},
|
||||
{op::RMB0, mneumonic::op::RMB0},
|
||||
{op::RMB1, mneumonic::op::RMB1},
|
||||
{op::RMB2, mneumonic::op::RMB2},
|
||||
{op::RMB3, mneumonic::op::RMB3},
|
||||
{op::RMB4, mneumonic::op::RMB4},
|
||||
{op::RMB5, mneumonic::op::RMB5},
|
||||
{op::RMB6, mneumonic::op::RMB6},
|
||||
{op::RMB7, mneumonic::op::RMB7},
|
||||
{op::ROL, mneumonic::op::ROL},
|
||||
{op::ROR, mneumonic::op::ROR},
|
||||
{op::RTI, mneumonic::op::RTI},
|
||||
{op::RTS, mneumonic::op::RTS},
|
||||
{op::SBC, mneumonic::op::SBC},
|
||||
{op::SEC, mneumonic::op::SEC},
|
||||
{op::SED, mneumonic::op::SED},
|
||||
{op::SEI, mneumonic::op::SEI},
|
||||
{op::SMB0, mneumonic::op::SMB0},
|
||||
{op::SMB1, mneumonic::op::SMB1},
|
||||
{op::SMB2, mneumonic::op::SMB2},
|
||||
{op::SMB3, mneumonic::op::SMB3},
|
||||
{op::SMB4, mneumonic::op::SMB4},
|
||||
{op::SMB5, mneumonic::op::SMB5},
|
||||
{op::SMB6, mneumonic::op::SMB6},
|
||||
{op::SMB7, mneumonic::op::SMB7},
|
||||
{op::STA, mneumonic::op::STA},
|
||||
{op::STP, mneumonic::op::STP},
|
||||
{op::STX, mneumonic::op::STX},
|
||||
{op::STY, mneumonic::op::STY},
|
||||
{op::STZ, mneumonic::op::STZ},
|
||||
{op::TAX, mneumonic::op::TAX},
|
||||
{op::TAY, mneumonic::op::TAY},
|
||||
{op::TRB, mneumonic::op::TRB},
|
||||
{op::TSB, mneumonic::op::TSB},
|
||||
{op::TSX, mneumonic::op::TSX},
|
||||
{op::TXA, mneumonic::op::TXA},
|
||||
{op::TXS, mneumonic::op::TXS},
|
||||
{op::TYA, mneumonic::op::TYA},
|
||||
{op::WAI, mneumonic::op::WAI},
|
||||
};
|
||||
|
||||
const std::unordered_map<amode_t, std::string_view> mode {
|
||||
{mode::A, mneumonic::mode::A},
|
||||
{mode::AII, mneumonic::mode::AII},
|
||||
{mode::AIX, mneumonic::mode::AIX},
|
||||
{mode::AIY, mneumonic::mode::AIY},
|
||||
{mode::AI, mneumonic::mode::AI},
|
||||
{mode::ACC, mneumonic::mode::ACC},
|
||||
{mode::IMM, mneumonic::mode::IMM},
|
||||
{mode::I, mneumonic::mode::I},
|
||||
{mode::R, mneumonic::mode::R},
|
||||
{mode::S, mneumonic::mode::S},
|
||||
{mode::ZP, mneumonic::mode::ZP},
|
||||
{mode::ZPII, mneumonic::mode::ZPII},
|
||||
{mode::ZPX, mneumonic::mode::ZPX},
|
||||
{mode::ZPY, mneumonic::mode::ZPY},
|
||||
{mode::ZPI, mneumonic::mode::ZPI},
|
||||
{mode::ZPIY, mneumonic::mode::ZPIY},
|
||||
};
|
||||
}
|
11
tostring.hh
Normal file
11
tostring.hh
Normal file
@ -0,0 +1,11 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "codec.hh"
|
||||
#include "mneumonic.hh"
|
||||
|
||||
namespace tostring {
|
||||
extern const std::unordered_map<op_t, std::string_view> op;
|
||||
|
||||
extern const std::unordered_map<amode_t, std::string_view> mode;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user