#pragma once #include #include #include #include #include #include #include #include "app/emu/cpu/internal/opcodes.h" namespace yaze { namespace app { namespace emu { class AsmParser { public: std::vector Parse(const std::string& instruction) { std::smatch match; if (!std::regex_match(instruction, match, instruction_regex_)) { throw std::runtime_error("Invalid instruction format: " + instruction); } std::string mnemonic = match[1]; std::string addressing_mode = match[2]; std::string operand = match[3]; std::string lookup_string = mnemonic.substr(0, 3); auto opcode_entry = mnemonic_to_opcode_.find(mnemonic); if (opcode_entry == mnemonic_to_opcode_.end()) { throw std::runtime_error( "Unknown mnemonic or addressing mode: " + mnemonic + addressing_mode); } std::vector bytes = {opcode_entry->second}; // AppendOperandBytes(bytes, operand, addressing_mode); return bytes; } void CreateInternalOpcodeMap() { for (const auto& opcode_entry : opcode_to_mnemonic) { std::string name = opcode_entry.second; uint8_t opcode = opcode_entry.first; mnemonic_to_opcode_[name] = opcode; } } private: void AppendOperandBytes(std::vector& bytes, const std::string& operand, const std::string& addressing_mode) { if (addressing_mode == ".b") { bytes.push_back(static_cast(std::stoi(operand, nullptr, 16))); } else if (addressing_mode == ".w") { uint16_t word_operand = static_cast(std::stoi(operand, nullptr, 16)); bytes.push_back(static_cast(word_operand & 0xFF)); bytes.push_back(static_cast((word_operand >> 8) & 0xFF)); } else if (addressing_mode == ".l") { uint32_t long_operand = static_cast(std::stoul(operand, nullptr, 16)); bytes.push_back(static_cast(long_operand & 0xFF)); bytes.push_back(static_cast((long_operand >> 8) & 0xFF)); bytes.push_back(static_cast((long_operand >> 16) & 0xFF)); } } enum class AddressingMode { kAbsolute, kAbsoluteLong, kAbsoluteIndexedIndirect, kAbsoluteIndexedX, kAbsoluteIndexedY, kAbsoluteIndirect, kAbsoluteIndirectLong, kAbsoluteLongIndexedX, kAccumulator, kBlockMove, kDirectPage, kDirectPageIndexedX, kDirectPageIndexedY, kDirectPageIndirect, kDirectPageIndirectIndexedY, kDirectPageIndirectLong, kDirectPageIndirectLongIndexedY, kDirectPageIndirectIndexedX, kDirectPageIndirectLongIndexedX, kImmediate, kImplied, kProgramCounterRelative, kProgramCounterRelativeLong, kStackRelative, kStackRelativeIndirectIndexedY, kStackRelativeIndirectIndexedYLong, kStack, kStackRelativeIndexedY, }; AddressingMode InferAddressingModeFromOperand(const std::string& operand) { if (operand[0] == '$') { return AddressingMode::kAbsolute; } else if (operand[0] == '#') { return AddressingMode::kImmediate; } else { return AddressingMode::kImplied; } } const std::regex instruction_regex_{R"((\w+)\s*(\.\w)?\s*(\$\w+|\#\w+|\w+))"}; std::unordered_map mnemonic_to_opcode_; }; } // namespace emu } // namespace app } // namespace yaze