M jasm/CMakeLists.txt +7 -0
@@ 25,6 25,13 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_
add_executable(jasm ${jasm_src})
+if (${MINGW})
+ add_custom_command(TARGET jasm POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different "/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libgcc_s_seh-1.dll" $<TARGET_FILE_DIR:jasm>
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different "/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++-6.dll" $<TARGET_FILE_DIR:jasm>
+ )
+endif()
+
set_property(TARGET jasm PROPERTY CXX_STANDARD 17)
set_property(TARGET jasm PROPERTY CXX_STANDARD_REQUIRED ON)
M jasm/assemble/assembler_impl/assembler_impl.cpp +16 -2
@@ 840,7 840,7 @@ Section *Assembler::find_section(uint64_
return nullptr;
}
-bool Assembler::progress_was_made()
+bool Assembler::progress_was_made(int pass)
{
// hash types
uint64_t storage_hash = _current_pass.types.hash();
@@ 862,6 862,20 @@ bool Assembler::progress_was_made()
_last_pass_hash = storage_hash;
+ if (pass > 101) {
+ _oscillating_state = true; // not really oscillating but forever mutating
+ if (_dump_symbols) {
+ // We have already done a pass with dump symbols turned on (to collect a reverse
+ // lookup for symbol names so report no more progress.
+ return false;
+ } else {
+ // Turn on dump symbols flag to start storing reverse lookups for symbols in the next pass.
+ _dump_symbols = true;
+ // Fake progress to get another pass
+ return true;
+ }
+ }
+
return true;
}
@@ 1347,7 1361,7 @@ void Assembler::assemble()
++pass;
- if (!progress_was_made())
+ if (!progress_was_made(pass))
break;
}
M jasm/assemble/assembler_impl/assembler_impl.h +6 -1
@@ 32,6 32,10 @@ namespace jasm
{
class ProcessorZ80;
}
+ namespace wdc65c02
+ {
+ class Processor65c02;
+ }
class HexSourceWriter;
@@ 59,6 63,7 @@ class Assembler
{
friend mos6502::Processor6502;
friend z80::ProcessorZ80;
+ friend wdc65c02::Processor65c02;
public:
Assembler(
@@ 1018,7 1023,7 @@ private:
void run_assembly_pass(bool generate, int pass);
- bool progress_was_made();
+ bool progress_was_made(int pass);
/// Tokenize, syntax analyze and parse a file.
void parse_file(bool generate, const std::string &filename, const SourceLocation *include_location);
M jasm/assemble/assembler_impl/syntax_impl.cpp +11 -3
@@ 1076,7 1076,8 @@ const SyntaxToken *Assembler::parse_defi
if (define.source_location.file_index != define.end_source_location.file_index) {
end_line = define.source_location.file_index + 1;
}
- _hex_source_writer->write_data(static_cast<uint32_t>(program_counter_before), &data[data_size_before], generated_size, define.source_location.file_index, define.source_location.row, end_line);
+ constexpr bool increase = true;
+ _hex_source_writer->write_data(static_cast<uint32_t>(program_counter_before), &data[data_size_before], increase, generated_size, define.source_location.file_index, define.source_location.row, end_line);
}
t = skip_to_end_of_define(t);
@@ 1701,8 1702,15 @@ const SyntaxToken *Assembler::parse_alig
case SectionType::Code:
{
// move program counter and add data accordingly
- auto &data = _section->generated_data(Section::Contents::DataDefinition);
- data.insert(data.end(), static_cast<size_t>(align_bytes), fill_byte);
+ if (generate) {
+ auto &data = _section->generated_data(Section::Contents::DataDefinition);
+ data.insert(data.end(), static_cast<size_t>(align_bytes), fill_byte);
+
+ if (_hex_source_writer != nullptr) {
+ constexpr bool increase = false;
+ _hex_source_writer->write_data(static_cast<uint32_t>(_program_counter.integer_value), &fill_byte, increase, core::unsign_cast(align_bytes), align_token.source_location.file_index, align_token.source_location.row, align_token.source_location.row + 1);
+ }
+ }
_program_counter.integer_value += align_bytes;
break;
}
M jasm/docs/jasm.md +36 -0
@@ 20,6 20,7 @@ This documentation covers the language a
* [Processor Support](#processor-support)
* [6502](#m6502)
+ * [65c02](#wdc65c02)
* [Z80](#z80)
* [Starter Guide](#starter-guide)
* [Basic Start](#starter-guide-basic-start)
@@ 54,6 55,7 @@ This documentation covers the language a
* [Default Processor](#default-processor)
* [Pseudo Instructions](#pseudo-instructions)
* [6502 Pseudo Instructions](#6502-pseudo-instructions)
+ * [65c02 Pseudo Instructions](#65c02-pseudo-instructions)
* [Z80 Pseudo Instructions](#z80-pseudo-instructions)
* [Verboseness](#verboseness)
* [Return Codes](#return-codes)
@@ 129,6 131,23 @@ Due to the large amount of source code w
[text]
python3 tools/convert_6502_keyword_case.py <my_source_directory>
+<div id="wdc65c02"></div>
+## 65C02
+
+jAsm supports all regular instructions of the Western Design Center 65C02. Instructions are written in lower case.
+
+ [65c02]
+ stz $d020
+ bra loop
+
+The bit operation instructions don't have the bit in the instruction name as some assemblers do. Instead it is a separate argument. To follow convention, there is no '#' before the bit number to indicate immediate mode, even if that would be more consistent.
+
+ [65c02]
+ bbr 0, zp, label
+ bbs 1, zp, label
+ rmb 2, zp
+ smb 3, zp
+
<div id="z80"></div>
## Z80
@@ 1216,6 1235,23 @@ These are the pseudo instructions for 65
These are equivalent to `[6502]|bcs` and `[6502]|bcc`, respectively.
+<div id="65c02-pseudo-instructions"></div>
+### 65C02 pseudo instructions
+
+These are the pseudo instructions for 65C02.
+
+ [65c02]
+ bhs addr // branch if higher or same
+ blt addr // branch if lower
+
+These are equivalent to `[65c02]|bcs` and `[65c02]|bcc`, respectively.
+
+ [65c02]
+ dea // decrement A register
+ ina // increment A register
+
+These are equivalent to the implied mode `[65c02]|dec` and `[65c02]|inc`, respectively.
+
<div id="z80-pseudo-instructions"></div>
### Z80 pseudo instructions
M jasm/docs/syntax_highlight.py +4 -1
@@ 46,6 46,7 @@ def syntax_highlight_code(code_class, te
keywords = re.compile(r'\b(address|align|basic|bss|byte|code|const|declare|define|dynamic|elif|else|enum|export|fill|for|function|if|import|incbin|include|long|macro|mapping|module|namespace|optimize|part|pop|processor|reserve|return|section|struct|subroutine|using|var|word)\b')
functions = re.compile(r'\b(abs|acos|asin|atan|atan2|ceil|clamp|cos|cosh|degrees|exp|float|floor|format|hexstring|int|lerp|log|log10|logn|max|min|modulo|offsetof|pow|print|radians|remainder|round|select|sin|sinh|sizeof|sqrt|static_assert|string|symbol|tan|tanh|unicode|uppercase|lowercase)\b')
instructions_6502 = re.compile(r'\b(adc|and|asl|bcc|bcs|beq|bit|bmi|bne|bpl|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|pla|plp|rol|ror|rti|rts|sbc|sec|sed|sei|sta|stx|sty|tax|tay|tsx|txa|txs|tya|bhs|blt)\b')
+ instructions_65c02 = re.compile(r'\b(adc|and|asl|bbr|bbs|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|rmb|rol|ror|rti|rts|sbc|sec|sed|sei|smb|sta|stp|stx|sty|stz|tax|tay|trb|tsx|txa|txs|tya|wai|bhs|blt|dea|ina)\b')
instructions_z80 = re.compile(r'\b(adc|add|and|bit|call|ccf|cp|cpd|cpdr|cpi|cpir|cpl|daa|dec|di|djnz|ei|ex|exx|halt|im|in|inc|ind|indr|ini|inir|jp|jr|ld|ldd|lddr|ldi|ldir|neg|nop|or|otdr|otir|out|outd|outi|pop|push|res|ret|reti|retn|rl|rla|rlc|rlca|rld|rr|rra|rrc|rrca|rrd|rst|sbc|scf|set|sla|sra|srl|sub|xor)\b')
operators = re.compile(r'(<<=|>>=|&&=|[|][|]=|!=|[+][+]|--|<<|>>|<=|>=|==|&&|[|][|]|[+]=|-=|[*]=|[/]=|&=|[|]=|\^=|::|!|~|[*]|[/]|[+]|-|<|>|&|\^|[|]|=|#|%)')
special = re.compile(r'({|}|\(|\)|;|\[|\])')
@@ 78,6 79,8 @@ def syntax_highlight_code(code_class, te
text = colorize(text, functions, "function")
if code_class == "[6502]":
text = colorize(text, instructions_6502, "instruction")
+ elif code_class == "[65c02]":
+ text = colorize(text, instructions_65c02, "instruction")
else:
text = colorize(text, instructions_z80, "instruction")
@@ 111,7 114,7 @@ def syntax_highlight_code(code_class, te
def syntax_highlight_text(code_class, code):
- if code_class == "[6502]" or code_class == "[z80]":
+ if code_class == "[6502]" or code_class == "[65c02]" or code_class == "[z80]":
return syntax_highlight_code(code_class, code)
elif code_class == "[text]":
return code
M jasm/exceptions/error_codes.h +1 -0
@@ 204,6 204,7 @@ enum class AssemblyErrorCodes
ExpectedPathString,
RecursiveIncludes,
CantFindIncludeFile,
+ AddressingModeRequiresBitSizeArgument,
// assembler warnings
SubroutineFallthrough = 3500,
M jasm/io/hex_source_writer.cpp +29 -13
@@ 48,7 48,7 @@ void HexSourceWriter::close()
_output_file.close();
}
-void HexSourceWriter::write_data(uint32_t address, const uint8_t *data, uint32_t size, uint32_t file_index, uint32_t start_line, uint32_t end_line)
+void HexSourceWriter::write_data(uint32_t address, const uint8_t *data, bool increasing, uint32_t size, uint32_t file_index, uint32_t start_line, uint32_t end_line)
{
// set current file
if (file_index != _current_file) {
@@ 74,9 74,11 @@ void HexSourceWriter::write_data(uint32_
// print combined lines
while(_current_line < end_line && size > 0) {
uint32_t size_to_write = std::min(size, 4U);
- write_combined(address, data, size_to_write);
+ write_combined(address, data, increasing, size_to_write);
address += size_to_write;
- data += size_to_write;
+ if (increasing) {
+ data += size_to_write;
+ }
size -= size_to_write;
++_current_line;
}
@@ 84,9 86,11 @@ void HexSourceWriter::write_data(uint32_
// write leftover data without source
while(size > 0) {
uint32_t size_to_write = std::min(size, 4U);
- write_data_only(address, data, size_to_write);
+ write_data_only(address, data, increasing, size_to_write);
address += size_to_write;
- data += size_to_write;
+ if (increasing) {
+ data += size_to_write;
+ }
size -= size_to_write;
}
// write leftover source without data
@@ 111,21 115,21 @@ void HexSourceWriter::write_source_only(
write_source_part();
}
-void HexSourceWriter::write_combined(uint32_t address, const uint8_t *data, uint32_t size)
+void HexSourceWriter::write_combined(uint32_t address, const uint8_t *data, bool increasing, uint32_t size)
{
constexpr bool include_row_number = true;
- write_data_part(address, data, size, include_row_number);
+ write_data_part(address, data, increasing, size, include_row_number);
write_source_part();
}
-void HexSourceWriter::write_data_only(uint32_t address, const uint8_t *data, uint32_t size)
+void HexSourceWriter::write_data_only(uint32_t address, const uint8_t *data, bool increasing, uint32_t size)
{
constexpr bool include_row_number = false;
- write_data_part(address, data, size, include_row_number);
+ write_data_part(address, data, increasing, size, include_row_number);
_output_file << '\n';
}
-void HexSourceWriter::write_data_part(uint32_t address, const uint8_t *data, uint32_t size, bool include_row_number)
+void HexSourceWriter::write_data_part(uint32_t address, const uint8_t *data, bool increasing, uint32_t size, bool include_row_number)
{
// generate left side
snprintf(_program_counter_buffer, sizeof(_program_counter_buffer), "%*.4x: ", _program_counter_width - 2, address);
@@ 134,13 138,25 @@ void HexSourceWriter::write_data_part(ui
snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x ", data[0]);
break;
case 2:
- snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x %02x ", data[0], data[1]);
+ if (increasing) {
+ snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x %02x ", data[0], data[1]);
+ } else {
+ snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x %02x ", data[0], data[0]);
+ }
break;
case 3:
- snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x %02x %02x ", data[0], data[1], data[2]);
+ if (increasing) {
+ snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x %02x %02x ", data[0], data[1], data[2]);
+ } else {
+ snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x %02x %02x ", data[0], data[0], data[0]);
+ }
break;
case 4:
- snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x %02x %02x %02x ", data[0], data[1], data[2], data[3]);
+ if (increasing) {
+ snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x %02x %02x %02x ", data[0], data[1], data[2], data[3]);
+ } else {
+ snprintf(_hex_buffer, sizeof(_hex_buffer), "%02x %02x %02x %02x ", data[0], data[0], data[0], data[0]);
+ }
break;
default:
break;
M jasm/io/hex_source_writer.h +5 -4
@@ 24,13 24,14 @@ public:
void close();
/// Write data as hex to the file and interleave with source data from start_line to end_line (not including).
- void write_data(uint32_t address, const uint8_t *data, uint32_t size, uint32_t file_index, uint32_t start_line, uint32_t end_line);
+ /// @param increasing True if the data pointer should be moved when reading. Otherwise it will write the same byte.
+ void write_data(uint32_t address, const uint8_t *data, bool increasing, uint32_t size, uint32_t file_index, uint32_t start_line, uint32_t end_line);
private:
void write_source_only();
- void write_combined(uint32_t address, const uint8_t *data, uint32_t size);
- void write_data_only(uint32_t address, const uint8_t *data, uint32_t size);
- void write_data_part(uint32_t address, const uint8_t *data, uint32_t size, bool include_row_number);
+ void write_combined(uint32_t address, const uint8_t *data, bool increasing, uint32_t size);
+ void write_data_only(uint32_t address, const uint8_t *data, bool increasing, uint32_t size);
+ void write_data_part(uint32_t address, const uint8_t *data, bool increasing, uint32_t size, bool include_row_number);
void write_source_part();
void change_file(uint32_t file_index);
M jasm/processor/6502/processor_6502.cpp +12 -6
@@ 490,7 490,8 @@ void Processor6502::generate_subroutine_
data.push_back(static_cast<uint8_t>(address));
data.push_back(static_cast<uint8_t>(address >> 8));
if (assembler._hex_source_writer != nullptr) {
- assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 3], 3, source_location.file_index, source_location.row, source_location.row + 1);
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 3], increase, 3, source_location.file_index, source_location.row, source_location.row + 1);
}
}
assembler._program_counter.integer_value += 3;
@@ 558,7 559,8 @@ const SyntaxToken *Processor6502::parse_
auto &data = assembler._section->generated_data(ending_instruction);
data.push_back(opcode(instruction, AddressingModeType::Implied));
if (assembler._hex_source_writer != nullptr) {
- assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 1], 1, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 1], increase, 1, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
}
}
++assembler._program_counter.integer_value;
@@ 597,7 599,8 @@ const SyntaxToken *Processor6502::parse_
data.push_back(opcode(instruction, AddressingModeType::Immediate));
data.push_back(static_cast<uint8_t>(argument_value));
if (assembler._hex_source_writer != nullptr) {
- assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], increase, 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
}
}
if (UNLIKELY(instruction_token.has_instruction_data_label)) {
@@ 643,7 646,8 @@ const SyntaxToken *Processor6502::parse_
data.push_back(opcode(instruction, mask_to_addressing_mode(addr_mode)));
data.push_back(static_cast<uint8_t>(argument_value));
if (assembler._hex_source_writer != nullptr) {
- assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], increase, 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
}
}
if (UNLIKELY(instruction_token.has_instruction_data_label)) {
@@ 669,7 673,8 @@ const SyntaxToken *Processor6502::parse_
data.push_back(static_cast<uint8_t>(argument_value));
data.push_back(static_cast<uint8_t>(argument_value >> 8));
if (assembler._hex_source_writer != nullptr) {
- assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 3], 3, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 3], increase, 3, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
}
}
if (UNLIKELY(instruction_token.has_instruction_data_label)) {
@@ 694,7 699,8 @@ const SyntaxToken *Processor6502::parse_
data.push_back(opcode(instruction, mask_to_addressing_mode(addr_mode)));
data.push_back(static_cast<uint8_t>(relative_addr));
if (assembler._hex_source_writer != nullptr) {
- assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], increase, 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
}
}
if (UNLIKELY(instruction_token.has_instruction_data_label)) {
A => jasm/processor/65c02/instructions_65c02.cpp +415 -0
@@ 0,0 1,415 @@
+#include "pch.h"
+
+#include <processor/65c02/instructions_65c02.h>
+
+namespace jasm
+{
+ namespace wdc65c02
+ {
+
+using namespace AddressingModeMask;
+
+/// All opcodes for one instruction.
+struct OpCodes
+{
+ uint8_t op_codes[static_cast<int>(AddressingModeType::NumAddressingModes)];
+};
+
+uint16_t __addressing_modes_mask[static_cast<int>(InstructionType::NumTypes)] = {
+ /* ADC */ Zp | Abs | Zpx | AbsX | ___ | AbsY | ZpI | ___ | ZpIX | ____ | ZpIY | ___ | Imm | __ | ___ | ___ ,
+ /* AND */ Zp | Abs | Zpx | AbsX | ___ | AbsY | ZpI | ___ | ZpIX | ____ | ZpIY | ___ | Imm | __ | ___ | ___ ,
+ /* ASL */ Zp | Abs | Zpx | AbsX | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* BBR */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | Bzr | ___ ,
+ /* BBS */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | Bzr | ___ ,
+ /* BCC */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* BCS */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* BEQ */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* BIT */ Zp | Abs | Zpx | AbsX | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | Imm | __ | ___ | ___ ,
+ /* BMI */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* BNE */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* BPL */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* BRA */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* BRK */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* BVC */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* BVS */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* CLC */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* CLD */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* CLI */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* CLV */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* CMP */ Zp | Abs | Zpx | AbsX | ___ | AbsY | ZpI | ___ | ZpIX | ____ | ZpIY | ___ | Imm | __ | ___ | ___ ,
+ /* CPX */ Zp | Abs | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | Imm | __ | ___ | ___ ,
+ /* CPY */ Zp | Abs | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | Imm | __ | ___ | ___ ,
+ /* DEC */ Zp | Abs | Zpx | AbsX | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* DEX */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* DEY */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* EOR */ Zp | Abs | Zpx | AbsX | ___ | AbsY | ZpI | ___ | ZpIX | ____ | ZpIY | ___ | Imm | __ | ___ | ___ ,
+ /* INC */ Zp | Abs | Zpx | AbsX | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* INX */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* INY */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* JMP */ __ | Abs | ___ | ____ | ___ | ____ | ___ | Ind | ____ | IndX | ____ | ___ | ___ | __ | ___ | ___ ,
+ /* JSR */ __ | Abs | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | ___ ,
+ /* LDA */ Zp | Abs | Zpx | AbsX | ___ | AbsY | ZpI | ___ | ZpIX | ____ | ZpIY | ___ | Imm | __ | ___ | ___ ,
+ /* LDX */ Zp | Abs | ___ | ____ | Zpy | AbsY | ___ | ___ | ____ | ____ | ____ | ___ | Imm | __ | ___ | ___ ,
+ /* LDY */ Zp | Abs | Zpx | AbsX | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | Imm | __ | ___ | ___ ,
+ /* LSR */ Zp | Abs | Zpx | AbsX | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* NOP */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* ORA */ Zp | Abs | Zpx | AbsX | ___ | AbsY | ZpI | ___ | ZpIX | ____ | ZpIY | ___ | Imm | __ | ___ | ___ ,
+ /* PHA */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* PHP */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* PHX */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* PHY */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* PLA */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* PLP */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* PLX */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* PLY */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* RMB */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | Bz | ___ | ___ ,
+ /* ROL */ Zp | Abs | Zpx | AbsX | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* ROR */ Zp | Abs | Zpx | AbsX | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* RTI */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* RTS */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* SBC */ Zp | Abs | Zpx | AbsX | ___ | AbsY | ZpI | ___ | ZpIX | ____ | ZpIY | ___ | Imm | __ | ___ | ___ ,
+ /* SEC */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* SED */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* SEI */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* SMB */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | Bz | ___ | ___ ,
+ /* STA */ Zp | Abs | Zpx | AbsX | ___ | AbsY | ZpI | ___ | ZpIX | ____ | ZpIY | ___ | ___ | __ | ___ | ___ ,
+ /* STP */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* STX */ Zp | Abs | ___ | ____ | Zpy | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | ___ ,
+ /* STY */ Zp | Abs | Zpx | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | ___ ,
+ /* STZ */ Zp | Abs | Zpx | AbsX | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | ___ ,
+ /* TAX */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* TAY */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* TRB */ Zp | Abs | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | ___ ,
+ /* TSB */ Zp | Abs | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | ___ ,
+ /* TSX */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* TXA */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* TXS */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* TYA */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* WAI */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+
+ /* BHS */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* BLT */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | ___ | ___ | __ | ___ | Rel ,
+ /* DEA */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+ /* INA */ __ | ___ | ___ | ____ | ___ | ____ | ___ | ___ | ____ | ____ | ____ | Imp | ___ | __ | ___ | ___ ,
+
+};
+
+OpCodes __opcodes[static_cast<int>(InstructionType::NumTypes)] = {
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* ADC */ {{0x65, 0x6d, 0x75, 0x7d, 0x00, 0x79, 0x72, 0x00, 0x61, 0x00, 0x71, 0x00, 0x69, 0x00, 0x00, 0x00}},
+ /* AND */ {{0x25, 0x2d, 0x35, 0x3d, 0x00, 0x39, 0x32, 0x00, 0x21, 0x00, 0x31, 0x00, 0x29, 0x00, 0x00, 0x00}},
+ /* ASL */ {{0x06, 0x0e, 0x16, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00}},
+ /* BBR */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* BBS */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00}},
+ /* BCC */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90}},
+ /* BCS */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0}},
+ /* BEQ */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* BIT */ {{0x24, 0x2c, 0x34, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00}},
+ /* BMI */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30}},
+ /* BNE */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0}},
+ /* BPL */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* BRA */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}},
+ /* BRK */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ /* BVC */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50}},
+ /* BVS */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* CLC */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00}},
+ /* CLD */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00}},
+ /* CLI */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00}},
+ /* CLV */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* CMP */ {{0xc5, 0xcd, 0xd5, 0xdd, 0x00, 0xd9, 0xd2, 0x00, 0xc1, 0x00, 0xd1, 0x00, 0xc9, 0x00, 0x00, 0x00}},
+ /* CPX */ {{0xe4, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00}},
+ /* CPY */ {{0xc4, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00}},
+ /* DEC */ {{0xc6, 0xce, 0xd6, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* DEX */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00}},
+ /* DEY */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00}},
+ /* EOR */ {{0x45, 0x4d, 0x55, 0x5d, 0x00, 0x59, 0x52, 0x00, 0x41, 0x00, 0x51, 0x00, 0x49, 0x00, 0x00, 0x00}},
+ /* INC */ {{0xe6, 0xee, 0xf6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* INX */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00}},
+ /* INY */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00}},
+ /* JMP */ {{0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ /* JSR */ {{0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* LDA */ {{0xa5, 0xad, 0xb5, 0xbd, 0x00, 0xb9, 0xb2, 0x00, 0xa1, 0x00, 0xb1, 0x00, 0xa9, 0x00, 0x00, 0x00}},
+ /* LDX */ {{0xa6, 0xae, 0x00, 0x00, 0xb6, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00}},
+ /* LDY */ {{0xa4, 0xac, 0xb4, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00}},
+ /* LSR */ {{0x46, 0x4e, 0x56, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* NOP */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0x00}},
+ /* ORA */ {{0x05, 0x0d, 0x15, 0x1d, 0x00, 0x19, 0x12, 0x00, 0x01, 0x00, 0x11, 0x00, 0x09, 0x00, 0x00, 0x00}},
+ /* PHA */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00}},
+ /* PHP */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* PHX */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x00}},
+ /* PHY */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00}},
+ /* PLA */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00}},
+ /* PLP */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* PLX */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x00}},
+ /* PLY */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x00}},
+ /* RMB */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00}},
+ /* ROL */ {{0x26, 0x2e, 0x36, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* ROR */ {{0x66, 0x6e, 0x76, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00}},
+ /* RTI */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00}},
+ /* RTS */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00}},
+ /* SBC */ {{0xe5, 0xed, 0xf5, 0xfd, 0x00, 0xf9, 0xf2, 0x00, 0xe1, 0x00, 0xf1, 0x00, 0xe9, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* SEC */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00}},
+ /* SED */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00}},
+ /* SEI */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00}},
+ /* SMB */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* STA */ {{0x85, 0x8d, 0x95, 0x9d, 0x00, 0x99, 0x92, 0x00, 0x81, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ /* STP */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x00}},
+ /* STX */ {{0x86, 0x8e, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ /* STY */ {{0x84, 0x8c, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* STZ */ {{0x64, 0x9c, 0x74, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ /* TAX */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00}},
+ /* TAY */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00}},
+ /* TRB */ {{0x14, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* TRB */ {{0x04, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ /* TSX */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00}},
+ /* TXA */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00}},
+ /* TXS */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+ /* TYA */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00}},
+ /* WAI */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+
+ /* BHS */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0}},
+ /* BLT */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90}},
+ /* DEA */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00}},
+ /* INA */ {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00}},
+ /* ZP , ABSO, ZPX, ABSX, ZPY, ABSY, ZPIN, INDI, ZPIX, INDX, ZPIY, IMPL, IMME, ZB , ZBR, RELA,*/
+
+};
+
+InstructionType __inverse_branch_instruction[static_cast<int>(InstructionType::NumTypes)] = {
+ /* ADC */ InstructionType::Brk,
+ /* AND */ InstructionType::Brk,
+ /* ASL */ InstructionType::Brk,
+ /* BBR */ InstructionType::Brk,
+ /* BBS */ InstructionType::Brk,
+ /* BCC */ InstructionType::Bcs,
+ /* BCS */ InstructionType::Bcc,
+ /* BEQ */ InstructionType::Bne,
+ /* BIT */ InstructionType::Brk,
+ /* BMI */ InstructionType::Bpl,
+ /* BNE */ InstructionType::Beq,
+ /* BPL */ InstructionType::Bmi,
+ /* BRA */ InstructionType::Nop,
+ /* BRK */ InstructionType::Brk,
+ /* BVC */ InstructionType::Bvs,
+ /* BVS */ InstructionType::Bvc,
+ /* CLC */ InstructionType::Brk,
+ /* CLD */ InstructionType::Brk,
+ /* CLI */ InstructionType::Brk,
+ /* CLV */ InstructionType::Brk,
+ /* CMP */ InstructionType::Brk,
+ /* CPX */ InstructionType::Brk,
+ /* CPY */ InstructionType::Brk,
+ /* DEC */ InstructionType::Brk,
+ /* DEX */ InstructionType::Brk,
+ /* DEY */ InstructionType::Brk,
+ /* EOR */ InstructionType::Brk,
+ /* INC */ InstructionType::Brk,
+ /* INX */ InstructionType::Brk,
+ /* INY */ InstructionType::Brk,
+ /* JMP */ InstructionType::Brk,
+ /* JSR */ InstructionType::Brk,
+ /* LDA */ InstructionType::Brk,
+ /* LDX */ InstructionType::Brk,
+ /* LDY */ InstructionType::Brk,
+ /* LSR */ InstructionType::Brk,
+ /* NOP */ InstructionType::Brk,
+ /* ORA */ InstructionType::Brk,
+ /* PHA */ InstructionType::Brk,
+ /* PHP */ InstructionType::Brk,
+ /* PHX */ InstructionType::Brk,
+ /* PHY */ InstructionType::Brk,
+ /* PLA */ InstructionType::Brk,
+ /* PLP */ InstructionType::Brk,
+ /* PLX */ InstructionType::Brk,
+ /* PLY */ InstructionType::Brk,
+ /* RMB */ InstructionType::Brk,
+ /* ROL */ InstructionType::Brk,
+ /* ROR */ InstructionType::Brk,
+ /* RTI */ InstructionType::Brk,
+ /* RTS */ InstructionType::Brk,
+ /* SBC */ InstructionType::Brk,
+ /* SEC */ InstructionType::Brk,
+ /* SED */ InstructionType::Brk,
+ /* SEI */ InstructionType::Brk,
+ /* SMB */ InstructionType::Brk,
+ /* STA */ InstructionType::Brk,
+ /* STP */ InstructionType::Brk,
+ /* STX */ InstructionType::Brk,
+ /* STY */ InstructionType::Brk,
+ /* TAX */ InstructionType::Brk,
+ /* TAY */ InstructionType::Brk,
+ /* TRB */ InstructionType::Brk,
+ /* TSB */ InstructionType::Brk,
+ /* TSX */ InstructionType::Brk,
+ /* TXA */ InstructionType::Brk,
+ /* TXS */ InstructionType::Brk,
+ /* TYA */ InstructionType::Brk,
+ /* WAI */ InstructionType::Brk,
+
+ /* BHS */ InstructionType::Blt,
+ /* BLT */ InstructionType::Bhs,
+ /* DEA */ InstructionType::Brk,
+ /* INA */ InstructionType::Brk,
+};
+
+uint16_t addressing_modes(InstructionType instruction)
+{
+ assert(instruction < InstructionType::NumTypes);
+ return __addressing_modes_mask[static_cast<int>(instruction)];
+}
+
+uint8_t opcode(InstructionType instruction, AddressingModeType addr_mode)
+{
+ assert(instruction < InstructionType::NumTypes);
+ assert(addr_mode < AddressingModeType::NumAddressingModes);
+ return __opcodes[static_cast<int>(instruction)].op_codes[static_cast<int>(addr_mode)];
+}
+
+InstructionType inverse_branch(InstructionType instruction)
+{
+ assert(instruction < InstructionType::NumTypes);
+ return __inverse_branch_instruction[static_cast<int>(instruction)];
+}
+
+bool is_ending_instruction(InstructionType type)
+{
+ return
+ type == InstructionType::Brk
+ || type == InstructionType::Bra
+ || type == InstructionType::Jmp
+ || type == InstructionType::Rti
+ || type == InstructionType::Rts
+ || type == InstructionType::Stp;
+}
+
+std::string_view to_string(AddressingModeType type)
+{
+ const static std::string_view names[] = {
+ std::string_view("zero page address"),
+ std::string_view("absolute address"),
+ std::string_view("zero page address with x offset"),
+ std::string_view("absolute address with x offset"),
+ std::string_view("zero page address with y offset"),
+ std::string_view("absolute address with y offset"),
+ std::string_view("zero page indirect"),
+ std::string_view("absolute indirect"),
+ std::string_view("indirect zero page address with x offset"),
+ std::string_view("indirect absolute address with x offset"),
+ std::string_view("indirect zero page address with y offset"),
+ std::string_view("implied"),
+ std::string_view("immediate"),
+ std::string_view("bit, zero page"),
+ std::string_view("bit, zero page, relative"),
+ std::string_view("relative address"),
+ };
+ static_assert(sizeof(names) / sizeof(names[0]) == static_cast<size_t>(AddressingModeType::NumAddressingModes), "Number of addressing modes doesn't match number of strings");
+
+ assert(type < AddressingModeType::NumAddressingModes);
+ return names[static_cast<size_t>(type)];
+}
+
+std::string_view to_string(InstructionType type)
+{
+ static const std::string_view names[] = {
+ std::string_view("adc"),
+ std::string_view("and"),
+ std::string_view("asl"),
+ std::string_view("bbr"),
+ std::string_view("bbs"),
+ std::string_view("bcc"),
+ std::string_view("bcs"),
+ std::string_view("beq"),
+ std::string_view("bit"),
+ std::string_view("bmi"),
+ std::string_view("bne"),
+ std::string_view("bpl"),
+ std::string_view("bra"),
+ std::string_view("brk"),
+ std::string_view("bvc"),
+ std::string_view("bvs"),
+ std::string_view("clc"),
+ std::string_view("cld"),
+ std::string_view("cli"),
+ std::string_view("clv"),
+ std::string_view("cmp"),
+ std::string_view("cpx"),
+ std::string_view("cpy"),
+ std::string_view("dec"),
+ std::string_view("dex"),
+ std::string_view("dey"),
+ std::string_view("eor"),
+ std::string_view("inc"),
+ std::string_view("inx"),
+ std::string_view("iny"),
+ std::string_view("jmp"),
+ std::string_view("jsr"),
+ std::string_view("lda"),
+ std::string_view("ldx"),
+ std::string_view("ldy"),
+ std::string_view("lsr"),
+ std::string_view("nop"),
+ std::string_view("ora"),
+ std::string_view("pha"),
+ std::string_view("php"),
+ std::string_view("phx"),
+ std::string_view("phy"),
+ std::string_view("pla"),
+ std::string_view("plp"),
+ std::string_view("plx"),
+ std::string_view("ply"),
+ std::string_view("rmb"),
+ std::string_view("rol"),
+ std::string_view("ror"),
+ std::string_view("rti"),
+ std::string_view("rts"),
+ std::string_view("sbc"),
+ std::string_view("sec"),
+ std::string_view("sed"),
+ std::string_view("sei"),
+ std::string_view("smb"),
+ std::string_view("sta"),
+ std::string_view("stp"),
+ std::string_view("stx"),
+ std::string_view("sty"),
+ std::string_view("stz"),
+ std::string_view("tax"),
+ std::string_view("tay"),
+ std::string_view("trb"),
+ std::string_view("tsb"),
+ std::string_view("tsx"),
+ std::string_view("txa"),
+ std::string_view("txs"),
+ std::string_view("tya"),
+ std::string_view("wai"),
+
+ std::string_view("bhs"),
+ std::string_view("blt"),
+ std::string_view("dea"),
+ std::string_view("ina"),
+ };
+ static_assert(sizeof(names) / sizeof(names[0]) == static_cast<size_t>(InstructionType::NumTypes), "Number of instructions doesn't match number of strings");
+
+ assert(type < InstructionType::NumTypes);
+ return names[static_cast<size_t>(type)];
+}
+
+ } // namespace mos6502
+} // namespace jasm
A => jasm/processor/65c02/instructions_65c02.h +193 -0
@@ 0,0 1,193 @@
+#pragma once
+
+#include <processor/instructions_common.h>
+
+namespace jasm
+{
+ namespace wdc65c02
+ {
+
+/// @addtogroup assemble
+/// @{
+
+enum class InstructionType : uint8_t
+{
+ Adc,
+ And,
+ Asl,
+ Bbr,
+ Bbs,
+ 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,
+ Rmb,
+ Rol,
+ Ror,
+ Rti,
+ Rts,
+ Sbc,
+ Sec,
+ Sed,
+ Sei,
+ Smb,
+ Sta,
+ Stp,
+ Stx,
+ Sty,
+ Stz,
+ Tax,
+ Tay,
+ Trb,
+ Tsb,
+ Tsx,
+ Txa,
+ Txs,
+ Tya,
+ Wai,
+ // end of standard instructions
+ Bhs, // branch if higher or same
+ NumStandard = Bhs,
+ Blt, // branch if less than
+ Dea, // DEC A
+ Ina, // INC A
+
+ NumTypes,
+};
+
+enum class AddressingModeType
+{
+ // these must be in zero-page-non-zero-page order
+ // because the instruction generation relies on it
+ ZeroPageAddr,
+ AbsoluteAddr,
+ ZeroPageIndexX,
+ AbsoluteIndexX,
+ ZeroPageIndexY,
+ AbsoluteIndexY,
+ ZeroPageIndirect,
+ AbsoluteIndirect,
+ ZeroPageIndirectIndexX,
+ AbsoluteIndirectIndexX,
+
+ ZeroPageIndirectIndexY,
+
+ Implied,
+ Immediate,
+ BitZp,
+ BitZpRel,
+
+ RelativeAddr,
+
+ NumAddressingModes,
+};
+
+// fake enum to be able to shorten the table in the cpp file
+namespace AddressingModeMask
+{
+ enum
+ {
+ Zp = 1 << static_cast<int>(AddressingModeType::ZeroPageAddr),
+ Abs = 1 << static_cast<int>(AddressingModeType::AbsoluteAddr),
+ Zpx = 1 << static_cast<int>(AddressingModeType::ZeroPageIndexX),
+ AbsX = 1 << static_cast<int>(AddressingModeType::AbsoluteIndexX),
+ Zpy = 1 << static_cast<int>(AddressingModeType::ZeroPageIndexY),
+ AbsY = 1 << static_cast<int>(AddressingModeType::AbsoluteIndexY),
+ ZpI = 1 << static_cast<int>(AddressingModeType::ZeroPageIndirect),
+ Ind = 1 << static_cast<int>(AddressingModeType::AbsoluteIndirect),
+ ZpIX = 1 << static_cast<int>(AddressingModeType::ZeroPageIndirectIndexX),
+ IndX = 1 << static_cast<int>(AddressingModeType::AbsoluteIndirectIndexX),
+ ZpIY = 1 << static_cast<int>(AddressingModeType::ZeroPageIndirectIndexY),
+ Imp = 1 << static_cast<int>(AddressingModeType::Implied),
+ Imm = 1 << static_cast<int>(AddressingModeType::Immediate),
+ Bz = 1 << static_cast<int>(AddressingModeType::BitZp),
+ Bzr = 1 << static_cast<int>(AddressingModeType::BitZpRel),
+ Rel = 1 << static_cast<int>(AddressingModeType::RelativeAddr),
+ __ = 0,
+ ___ = 0,
+ ____ = 0,
+ };
+}
+
+/// Select the byte mode version of a combined byte and word mode addressing mode.
+inline uint16_t select_byte_mode(uint16_t a)
+{
+ return static_cast<uint16_t>(a & 0b0101010101);
+}
+
+/// Select the word mode version of a combined byte and word mode addressing mode.
+inline uint16_t select_word_mode(uint16_t a)
+{
+ return static_cast<uint16_t>(a & 0b1010101010);
+}
+
+/// Convert a bitmask with one bit set to an addressing mode.
+inline AddressingModeType mask_to_addressing_mode(uint16_t mask)
+{
+ int result = 0;
+ result += ((mask & 0b1111111100000000) != 0) ? 8 : 0;
+ result += ((mask & 0b1111000011110000) != 0) ? 4 : 0;
+ result += ((mask & 0b1100110011001100) != 0) ? 2 : 0;
+ result += ((mask & 0b1010101010101010) != 0) ? 1 : 0;
+ return static_cast<AddressingModeType>(result);
+}
+
+/// Get the addressing mode mask with bits set for each AddressingModeTypes value.
+uint16_t addressing_modes(InstructionType instruction);
+
+/// Returns the opcode for an instruction and addressing mode.
+uint8_t opcode(InstructionType instruction, AddressingModeType addr_mode);
+
+/// Returns the instruction for the opposite branch instruction.
+/// Call it with bcc and get bcs for example.
+InstructionType inverse_branch(InstructionType instruction);
+
+/// Returns true if the instruction doesn't provide a fall-through branch.
+bool is_ending_instruction(InstructionType type);
+
+/// Convert an addressing mode to a string for printing.
+std::string_view to_string(AddressingModeType type);
+
+std::string_view to_string(InstructionType type);
+
+/// @}
+
+ } // namespace mos6502
+} // namespace jasm
A => jasm/processor/65c02/processor_65c02.cpp +958 -0
@@ 0,0 1,958 @@
+#include "pch.h"
+
+#include <algorithm>
+#include <assemble/assembler_impl/assembler_impl.h>
+#include <assemble/scope_counter.h>
+#include <exceptions/assembly_exception.h>
+#include <io/hex_source_writer.h>
+#include <processor/65c02/processor_65c02.h>
+#include <processor/65c02/processor_keywords_65c02.h>
+#include <sstream>
+#include <syntax/syntax_parser.h>
+#include <syntax/syntax_tokens.h>
+#include <tokenize/tokens.h>
+
+namespace jasm
+{
+ namespace wdc65c02
+ {
+
+namespace
+{
+ enum
+ {
+ Zp = 1 << static_cast<int>(AddressingModeType::ZeroPageAddr),
+ Abs = 1 << static_cast<int>(AddressingModeType::AbsoluteAddr),
+ Zpx = 1 << static_cast<int>(AddressingModeType::ZeroPageIndexX),
+ AbsX = 1 << static_cast<int>(AddressingModeType::AbsoluteIndexX),
+ Zpy = 1 << static_cast<int>(AddressingModeType::ZeroPageIndexY),
+ AbsY = 1 << static_cast<int>(AddressingModeType::AbsoluteIndexY),
+ ZpI = 1 << static_cast<int>(AddressingModeType::ZeroPageIndirect),
+ Ind = 1 << static_cast<int>(AddressingModeType::AbsoluteIndirect),
+ ZpIX = 1 << static_cast<int>(AddressingModeType::ZeroPageIndirectIndexX),
+ IndX = 1 << static_cast<int>(AddressingModeType::AbsoluteIndirectIndexX),
+ ZpIY = 1 << static_cast<int>(AddressingModeType::ZeroPageIndirectIndexY),
+ Imp = 1 << static_cast<int>(AddressingModeType::Implied),
+ Imm = 1 << static_cast<int>(AddressingModeType::Immediate),
+ Bz = 1 << static_cast<int>(AddressingModeType::BitZp),
+ Bzr = 1 << static_cast<int>(AddressingModeType::BitZpRel),
+ Rel = 1 << static_cast<int>(AddressingModeType::RelativeAddr),
+ };
+}
+
+struct InstructionToken : public SyntaxToken
+{
+ InstructionType instruction;
+ uint8_t padding1;
+ uint16_t addressing_modes; ///< Mask with InstructionType bits set for each possible addressing mode.
+ SourceLocation source_location; ///< Source location to instruction.
+ // 8 byte aligned
+ bool has_instruction_data_label[3]; ///< True if there is a label defined that points to the instruction data.
+ bool global_data_label[3]; ///< True if the label is global.
+ uint8_t padding2[2];
+ // 8 byte aligned
+ SourceLocation address_label_location[3]; ///< Source location to address label, if existing.
+ uint32_t padding3;
+ // 8 byte aligned
+ uint64_t data_label_symbol_hash[3]; ///< Symbol to define as the data label.
+ // 8 byte aligned
+};
+
+void Processor65c02::register_processor_keywords(std::vector<std::string> &keywords)
+{
+ add_type_tokens<ProcessorKeywordType>(keywords, TokenType::ProcessorKeyword);
+}
+
+void Processor65c02::register_processor_instructions(bool pseudo_instructions)
+{
+ // generate instruction lookup
+ uint8_t num_instructions = static_cast<uint8_t>(pseudo_instructions ? InstructionType::NumTypes : InstructionType::NumStandard);
+ for (uint8_t i = 0; i < num_instructions; ++i) {
+ const std::string_view name = to_string(static_cast<InstructionType>(i));
+ _instructions.insert(core::murmur_hash3_string_x64_64(name)) = i;
+ }
+}
+
+bool Processor65c02::allow_processor_keyword_with_prim(uint64_t &/*keyword_hash*/) const
+{
+ // no prim translation
+ return false;
+}
+
+std::string Processor65c02::token_to_string(const Token &t) const
+{
+ std::stringstream ss;
+ if (jasm::is_instruction(t)) {
+ ss << "instruction";
+ } else {
+ ss << to_string(t.type);
+ }
+
+ switch (t.type) {
+ case TokenType::Whitespace:
+ case TokenType::Char:
+ case TokenType::Integer:
+ case TokenType::Float:
+ case TokenType::String:
+ case TokenType::End:
+ case TokenType::Newline:
+ case TokenType::Processor:
+ case TokenType::NumTypes:
+ break;
+
+ case TokenType::Symbol:
+ {
+ if (t.instruction_index != invalid_instruction) {
+ ss << " " << to_string(static_cast<InstructionType>(t.instruction_index));
+ }
+ break;
+ }
+
+ case TokenType::Boolean:
+ ss << " " << to_string(t.boolean_index);
+ break;
+
+ case TokenType::Operator:
+ ss << " " << to_string(t.operator_index);
+ break;
+
+ case TokenType::Keyword:
+ ss << " " << to_string(t.keyword_index);
+ break;
+
+ case TokenType::ProcessorKeyword:
+ ss << " " << to_string(static_cast<ProcessorKeywordType>(t.processor_keyword_index));
+ break;
+
+ case TokenType::Typename:
+ ss << " " << to_string(t.typename_index);
+ break;
+ }
+ return ss.str();
+}
+
+
+const Token *Processor65c02::parse_optional_arg_label(SyntaxParser &parser, const Token *t, ArgLabel &label) const
+{
+ t = parser.skip_spaces_and_tabs(t);
+ if (parser.label_definition_follows(t)) {
+ label.enabled = true;
+ label.location = t->source_location;
+
+ t = parser.parse_symbol_definition(t, label.global, label.symbol_hash);
+ t = parser.consume_next_token(); // the colon
+ t = parser.skip_spaces_and_tabs(t);
+ }
+ return t;
+}
+
+const Token *Processor65c02::skip_optional_arg_label(SyntaxParser &parser, const Token *t, const ArgLabel &label) const
+{
+ t = parser.skip_spaces_and_tabs(t);
+ if (label.enabled) {
+ bool global = false;
+ uint64_t hash = 0;
+ t = parser.parse_symbol_definition(t, global, hash);
+ t = parser.consume_next_token(); // the colon
+ t = parser.skip_spaces_and_tabs(t);
+ }
+ return t;
+}
+
+uint16_t Processor65c02::try_parse_addressing_mode(SyntaxParser &parser, const std::vector<std::string> &source_files, const Token *t, std::array<ArgLabel, 3> &arg_labels) const
+{
+ // save read state to restore later since we are reading ahead.
+ TokenChainScope rewind_scope(parser.create_rewind_scope());
+
+ t = parse_optional_arg_label(parser, t, arg_labels[0]);
+
+ if (parser.is_operator(t, OperatorType::Hash)) {
+ // Immediate
+ return 1 << static_cast<int>(AddressingModeType::Immediate);
+ }
+
+ if (parser.is_operator(t, OperatorType::LeftParenthesis)) {
+ // (<something>
+ // possibly indirect addressing mode but could also be an expression beginning with parenthesis
+ // ZeroPageAddr
+ // AbsoluteAddr
+ // ZeroPageIndexX
+ // AbsoluteIndexX
+ // ZeroPageIndexY
+ // AbsoluteIndexY
+ // ZeroPageIndirect
+ // AbsoluteIndirect
+ // ZeroPageIndirectIndexX
+ // AbsoluteIndirectIndexX
+ // ZeroPageIndirectIndexY
+ // BitZp
+ // BitZpRel
+ // RelativeAddr
+
+ // Try to parse an expression, ignoring the first parenthesis. That makes it possible to see
+ // if there is a comma within the parenthesis. This is not optimal for performance because
+ // it does more than it needs to for this.
+ const Token *next;
+ {
+ constexpr bool end_at_unmatched_right_parenthesis = true;
+ constexpr bool end_at_newline = true;
+ next = parser.parse_expression(parser.consume_next_token(), end_at_unmatched_right_parenthesis, end_at_newline);
+ }
+ if (parser.is_operator(next, OperatorType::Comma)) {
+ // (<expression>,
+ // ZeroPageIndirectIndexX
+ // AbsoluteIndirectIndexX
+
+ // verify that "x" follows
+ next = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ if (next->type != TokenType::ProcessorKeyword || static_cast<ProcessorKeywordType>(next->processor_keyword_index) != ProcessorKeywordType::X) {
+ std::stringstream ss;
+ ss << "Expected x for indirect addressing mode, but got " << token_to_string(*next);
+ throw AssemblyException(source_files, next->source_location, AssemblyErrorCodes::InvalidIndexRegisterInAddressingMode, ss.str());
+ }
+ // (<expression>,x
+
+ // verify that right parenthesis follows
+ next = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ if (next->type != TokenType::Operator || next->operator_index != OperatorType::RightParenthesis) {
+ std::stringstream ss;
+ ss << "Expected closing parenthesis in indirect addressing mode, but got " << token_to_string(*next);
+ throw AssemblyException(source_files, next->source_location, AssemblyErrorCodes::ExpectedEndingParenthesisInIndirectAddressingMode, ss.str());
+ }
+ // (<expression>,x)
+
+ return
+ 1 << static_cast<int>(AddressingModeType::ZeroPageIndirectIndexX) |
+ 1 << static_cast<int>(AddressingModeType::AbsoluteIndirectIndexX);
+ }
+
+ if (parser.is_operator(next, OperatorType::RightParenthesis)) {
+ // (<expression>)...
+ // ZeroPageAddr
+ // AbsoluteAddr
+ // ZeroPageIndexX
+ // AbsoluteIndexX
+ // ZeroPageIndexY
+ // AbsoluteIndexY
+ // ZeroPageIndirect
+ // AbsoluteIndirect
+ // ZeroPageIndirectIndexY
+ // BitZp
+ // BitZpRel
+ // RelativeAddr
+
+ next = parser.skip_spaces_and_tabs(parser.consume_next_token());
+
+ if (next->type == TokenType::Operator && next->operator_index < OperatorType::NumOperatorFunctions) {
+ // (<expression>)<operator>
+ // ZeroPageAddr
+ // AbsoluteAddr
+ // ZeroPageIndexX
+ // AbsoluteIndexX
+ // ZeroPageIndexY
+ // AbsoluteIndexY
+ // BitZp
+ // BitZpRel
+ // RelativeAddr
+
+ // go back and parse the whole thing to get to the end of the expression and check if it ends
+ // with ,x or ,y or ,something. This is not optimal from a performance perspective. I could write
+ // specialized code to skip an expression.
+ rewind_scope.rewind();
+ {
+ constexpr bool end_at_unmatched_right_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ next = parser.parse_expression(t, end_at_unmatched_right_parenthesis, end_at_newline);
+ }
+
+ if (parser.is_operator(next, OperatorType::Comma)) {
+ // <expression>,
+ // ZeroPageIndexX
+ // AbsoluteIndexX
+ // ZeroPageIndexY
+ // AbsoluteIndexY
+ // BitZp
+ // BitZpRel
+ next = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ if (next->type == TokenType::ProcessorKeyword && static_cast<ProcessorKeywordType>(next->processor_keyword_index) == ProcessorKeywordType::X) {
+ // <expression>,x
+ // ZeroPageIndexX
+ // AbsoluteIndexX
+ return
+ 1 << static_cast<int>(AddressingModeType::ZeroPageIndexX) |
+ 1 << static_cast<int>(AddressingModeType::AbsoluteIndexX);
+ }
+ if (next->type == TokenType::ProcessorKeyword && static_cast<ProcessorKeywordType>(next->processor_keyword_index) == ProcessorKeywordType::Y) {
+ // <expression>,y
+ // ZeroPageIndexY
+ // AbsoluteIndexY
+ return
+ 1 << static_cast<int>(AddressingModeType::ZeroPageIndexY) |
+ 1 << static_cast<int>(AddressingModeType::AbsoluteIndexY);
+ }
+ // <expression>, <expression>...
+ // BitZp
+ // BitZpRel
+ next = parse_optional_arg_label(parser, next, arg_labels[1]);
+ {
+ constexpr bool end_at_unmatched_right_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ next = parser.parse_expression(next, end_at_unmatched_right_parenthesis, end_at_newline);
+ }
+ if (parser.is_operator(next, OperatorType::Comma)) {
+ // <expression>, <expression>, <expression>
+ next = parser.consume_next_token(); // comma
+ next = parse_optional_arg_label(parser, next, arg_labels[2]);
+ return 1 << static_cast<int>(AddressingModeType::BitZpRel);
+ }
+
+ // <expression>, <expression>
+ // BitZp
+ return 1 << static_cast<int>(AddressingModeType::BitZp);
+ }
+ // (<expression>)<operator><expression>
+ // ZeroPageAddr
+ // AbsoluteAddr
+ // RelativeAddr
+ return 1 << static_cast<int>(AddressingModeType::ZeroPageAddr) |
+ 1 << static_cast<int>(AddressingModeType::AbsoluteAddr) |
+ 1 << static_cast<int>(AddressingModeType::RelativeAddr);
+ }
+ if (parser.is_operator(next, OperatorType::Comma)) {
+ // (<expression>),
+ // ZeroPageIndirectIndexY
+
+ next = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ if (next->type == TokenType::ProcessorKeyword && static_cast<ProcessorKeywordType>(next->processor_keyword_index) == ProcessorKeywordType::Y) {
+ // (<expression>),y
+ // ZeroPageIndirectIndexY
+ return 1 << static_cast<int>(AddressingModeType::ZeroPageIndirectIndexY);
+ }
+ // the index register is invalid
+ std::stringstream ss;
+ ss << "Invalid index register in addressing mode. Expected y but got " << token_to_string(*next);
+ throw AssemblyException(source_files, next->source_location, AssemblyErrorCodes::InvalidIndexRegisterInAddressingMode, ss.str());
+ }
+ // (<expression>)
+ // ZeroPageIndirect
+ // AbsoluteIndirect
+ return
+ 1 << static_cast<int>(AddressingModeType::ZeroPageIndirect) |
+ 1 << static_cast<int>(AddressingModeType::AbsoluteIndirect);
+ }
+
+ // no matching parenthesis was found
+ std::stringstream ss;
+ ss << "Unmatched left parenthesis in expression";
+ throw AssemblyException(source_files, t->source_location, AssemblyErrorCodes::UnmatchedLeftParenthesis, ss.str());
+ }
+
+ if (t->type == TokenType::Newline || parser.is_operator(t, OperatorType::Semicolon)) {
+ // Implied
+ return 1 << static_cast<int>(AddressingModeType::Implied);
+ }
+
+ // <expression>...
+ // ZeroPageAddr
+ // AbsoluteAddr
+ // ZeroPageIndexX
+ // AbsoluteIndexX
+ // ZeroPageIndexY
+ // AbsoluteIndexY
+ // BitZp
+ // BitZpRel
+ // RelativeAddr
+ const Token *next;
+ {
+ constexpr bool end_at_unmatched_right_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ next = parser.parse_expression(t, end_at_unmatched_right_parenthesis, end_at_newline);
+ }
+
+ if (parser.is_operator(next, OperatorType::Comma)) {
+ // <expression>,
+ // ZeroPageIndexX
+ // AbsoluteIndexX
+ // ZeroPageIndexY
+ // AbsoluteIndexY
+ // BitZp
+ // BitZpRel
+ next = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ if (next->type == TokenType::ProcessorKeyword && static_cast<ProcessorKeywordType>(next->processor_keyword_index) == ProcessorKeywordType::X) {
+ // <expression>,x
+ // ZeroPageIndexX
+ // AbsoluteIndexX
+ return 1 << static_cast<int>(AddressingModeType::ZeroPageIndexX) |
+ 1 << static_cast<int>(AddressingModeType::AbsoluteIndexX);
+ }
+ if (next->type == TokenType::ProcessorKeyword && static_cast<ProcessorKeywordType>(next->processor_keyword_index) == ProcessorKeywordType::Y) {
+ // <expression>,y
+ // ZeroPageIndexY
+ // AbsoluteIndexY
+ return 1 << static_cast<int>(AddressingModeType::ZeroPageIndexY) |
+ 1 << static_cast<int>(AddressingModeType::AbsoluteIndexY);
+ }
+ // <expression>, <expression>...
+ // BitZp
+ // BitZpRel
+ next = parse_optional_arg_label(parser, next, arg_labels[1]);
+ {
+ constexpr bool end_at_unmatched_right_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ next = parser.parse_expression(next, end_at_unmatched_right_parenthesis, end_at_newline);
+ }
+ if (parser.is_operator(next, OperatorType::Comma)) {
+ // <expression>, <expression>, <expression>
+ next = parser.consume_next_token();
+ next = parse_optional_arg_label(parser, next, arg_labels[2]);
+ return 1 << static_cast<int>(AddressingModeType::BitZpRel);
+ }
+ // <expression>, <expression>
+ // BitZp
+ return 1 << static_cast<int>(AddressingModeType::BitZp);
+ }
+ // <expression>
+ // ZeroPageAddr
+ // AbsoluteAddr
+ // RelativeAddr
+ return 1 << static_cast<int>(AddressingModeType::ZeroPageAddr) |
+ 1 << static_cast<int>(AddressingModeType::AbsoluteAddr) |
+ 1 << static_cast<int>(AddressingModeType::RelativeAddr);
+}
+
+void Processor65c02::print_addressing_modes(std::stringstream &ss, uint16_t addressing_mode_mask)
+{
+ for (int i = 0; i < static_cast<int>(AddressingModeType::NumAddressingModes); ++i) {
+ if (((1 << i) & addressing_mode_mask) != 0)
+ ss << "\n " << to_string(static_cast<AddressingModeType>(i));
+ }
+}
+
+const Token *Processor65c02::parse_instruction(SyntaxParser &parser, const std::vector<std::string> &source_files, const Token *t, uint8_t /*InstructionType*/ instruction_index) const
+{
+ InstructionType instruction = static_cast<InstructionType>(instruction_index);
+ const Token *begin_token = t;
+
+ t = parser.consume_next_token(); // instruction token
+ t = parser.skip_spaces_and_tabs(t);
+
+ // determine possible used addressing modes and compare with existing
+ std::array<ArgLabel, 3> arg_labels;
+ uint16_t parsed_addressing_modes = try_parse_addressing_mode(parser, source_files, t, arg_labels);
+ uint16_t possible_addressing_modes = addressing_modes(instruction);
+ uint16_t selected_addressing_modes = parsed_addressing_modes & possible_addressing_modes;
+ if (selected_addressing_modes == 0) {
+ std::stringstream ss;
+ ss << "Invalid addressing mode used. Code indicates one of the following:";
+ print_addressing_modes(ss, parsed_addressing_modes);
+ ss << "\nbut possible addressing modes for " << to_string(instruction) << " are:";
+ print_addressing_modes(ss, possible_addressing_modes);
+ throw AssemblyException(source_files, t->source_location, AssemblyErrorCodes::InvalidAddressingMode, ss.str());
+ }
+
+ // store the instruction with addressing mode mask in the output
+ InstructionToken &instruction_token = parser.reserve_token_space<InstructionToken>();
+ instruction_token.type = SyntaxTokenType::Instruction;
+ instruction_token.processor = ProcessorType::Wdc65c02;
+ instruction_token.size = sizeof(InstructionToken);
+ instruction_token.instruction = instruction;
+ instruction_token.addressing_modes = selected_addressing_modes;
+ instruction_token.source_location = begin_token->source_location;
+ instruction_token.has_instruction_data_label[0] = arg_labels[0].enabled;
+ instruction_token.has_instruction_data_label[1] = arg_labels[1].enabled;
+ instruction_token.has_instruction_data_label[2] = arg_labels[2].enabled;
+ instruction_token.global_data_label[0] = arg_labels[0].global;
+ instruction_token.global_data_label[1] = arg_labels[1].global;
+ instruction_token.global_data_label[2] = arg_labels[2].global;
+ instruction_token.address_label_location[0] = arg_labels[0].location;
+ instruction_token.address_label_location[1] = arg_labels[1].location;
+ instruction_token.address_label_location[2] = arg_labels[2].location;
+ instruction_token.data_label_symbol_hash[0] = arg_labels[0].symbol_hash;
+ instruction_token.data_label_symbol_hash[1] = arg_labels[1].symbol_hash;
+ instruction_token.data_label_symbol_hash[2] = arg_labels[2].symbol_hash;
+
+ // now we should be able to parse the operand of the instruction
+ if (selected_addressing_modes == Imp) {
+ if (arg_labels[0].enabled) {
+ std::stringstream ss;
+ ss << "Implied addressing modes cannot have label to instruction data. Add a newline or a semicolon before the label to resolve this.";
+ throw AssemblyException(source_files, arg_labels[0].location, AssemblyErrorCodes::AddressingModeCannotHaveDataLabel, ss.str());
+ }
+ return t;
+ }
+
+ t = skip_optional_arg_label(parser, t, arg_labels[0]);
+
+ if (selected_addressing_modes == Imm) {
+ assert(parser.is_operator(t, OperatorType::Hash));
+ t = parser.consume_next_token(); // hash
+ constexpr bool end_at_unmatched_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ return parser.parse_and_output_expression(t, end_at_unmatched_parenthesis, end_at_newline);
+ }
+
+ if ((selected_addressing_modes & (ZpI | Ind | ZpIX | IndX | ZpIY)) != 0) {
+ // an indirect mode
+ if ((selected_addressing_modes & (ZpIX | IndX)) != 0) {
+ // skip parenthesis, parse address expression, skip comma and x
+ assert(parser.is_operator(t, OperatorType::LeftParenthesis));
+ constexpr bool end_at_unmatched_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ t = parser.parse_and_output_expression(parser.consume_next_token(), end_at_unmatched_parenthesis, end_at_newline);
+ assert(parser.is_operator(t, OperatorType::Comma));
+ t = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ assert(t->type == TokenType::ProcessorKeyword && static_cast<ProcessorKeywordType>(t->processor_keyword_index) == ProcessorKeywordType::X);
+ t = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ assert(parser.is_operator(t, OperatorType::RightParenthesis));
+ return parser.consume_next_token();
+ }
+ // parse address expression
+ constexpr bool end_at_unmatched_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ t = parser.parse_and_output_expression(t, end_at_unmatched_parenthesis, end_at_newline);
+
+ if ((selected_addressing_modes & ZpIY) != 0) {
+ // skip comma and y
+ assert(parser.is_operator(t, OperatorType::Comma));
+ t = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ assert(t->type == TokenType::ProcessorKeyword && static_cast<ProcessorKeywordType>(t->processor_keyword_index) == ProcessorKeywordType::Y);
+ t = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ }
+ return t;
+ }
+
+ // parse address expression
+ {
+ constexpr bool end_at_unmatched_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ t = parser.parse_and_output_expression(t, end_at_unmatched_parenthesis, end_at_newline);
+ }
+
+ if ((selected_addressing_modes & (Zp | Abs | Rel)) != 0) {
+ return t;
+ }
+
+ if ((selected_addressing_modes & (Zpx | AbsX)) != 0) {
+ // skip comma and x
+ assert(parser.is_operator(t, OperatorType::Comma));
+ t = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ assert(t->type == TokenType::ProcessorKeyword && static_cast<ProcessorKeywordType>(t->processor_keyword_index) == ProcessorKeywordType::X);
+ t = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ return t;
+ }
+ if ((selected_addressing_modes & (Zpy | AbsY)) != 0) {
+ // skip comma and y
+ assert(parser.is_operator(t, OperatorType::Comma));
+ t = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ assert(t->type == TokenType::ProcessorKeyword && static_cast<ProcessorKeywordType>(t->processor_keyword_index) == ProcessorKeywordType::Y);
+ t = parser.skip_spaces_and_tabs(parser.consume_next_token());
+ return t;
+ }
+
+ // at least two arguments
+ assert(parser.is_operator(t, OperatorType::Comma));
+ t = parser.consume_next_token(); // comma
+
+ t = skip_optional_arg_label(parser, t, arg_labels[1]);
+
+ if ((selected_addressing_modes & Bz) != 0) {
+ constexpr bool end_at_unmatched_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ t = parser.parse_and_output_expression(t, end_at_unmatched_parenthesis, end_at_newline);
+ return t;
+ }
+ assert((selected_addressing_modes & Bzr) != 0);
+
+ // at least three arguments
+ {
+ constexpr bool end_at_unmatched_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ t = parser.parse_and_output_expression(t, end_at_unmatched_parenthesis, end_at_newline);
+ }
+
+ assert(parser.is_operator(t, OperatorType::Comma));
+ t = parser.consume_next_token(); // comma
+
+ t = skip_optional_arg_label(parser, t, arg_labels[2]);
+
+ {
+ constexpr bool end_at_unmatched_parenthesis = false;
+ constexpr bool end_at_newline = true;
+ t = parser.parse_and_output_expression(t, end_at_unmatched_parenthesis, end_at_newline);
+ }
+ return t;
+}
+
+void Processor65c02::generate_subroutine_instruction(Assembler &assembler, bool generate, int32_t address, const SourceLocation &source_location) const
+{
+ // instructions are only allowed within code sections.
+ bool instructions_allowed = assembler.in_code_section();
+ if (UNLIKELY(!instructions_allowed)) {
+ // this is an unrecoverable error
+ std::stringstream ss;
+ ss << "Instructions must be in a code section.";
+ assembler.report_fatal_error(source_location, AssemblyErrorCodes::CodeMustBeInCodeSection, ss.str());
+ }
+
+ // recursive data generation may not be safe
+ if (assembler._data_generation_depth != 0) {
+ // this is an unrecoverable error
+ std::stringstream ss;
+ ss << "Recursive data generation isn't allowed.";
+ assembler.report_fatal_error(source_location, AssemblyErrorCodes::RecursiveDataGenerationNotAllowed, ss.str());
+ }
+
+ ScopeCounter<uint32_t> sc(assembler._data_generation_depth);
+
+ if (generate && address < 0) {
+ std::stringstream ss;
+ ss << "Addressing mode needs a positive argument. Argument value was evaluated to " << address << ".";
+ assembler.report_error(source_location, AssemblyErrorCodes::AddressingModeRequiresPositiveArgument, ss.str());
+ }
+
+ if (assembler._multi_bank_mode) {
+ // in this mode, addresses gets truncated to support memory banks
+ address &= 0xffff;
+ }
+
+ if (generate) {
+ if (address > 65535) {
+ std::stringstream ss;
+ ss << "Addressing mode needs a word size argument. Argument was evaluated to " << address << ".";
+ assembler.report_error(source_location, AssemblyErrorCodes::AddressingModeRequiresWordSizeArgument, ss.str());
+ }
+ Section::Contents ending_instruction = Section::Contents::ContinueExecutionInstruction;
+ auto &data = assembler._section->generated_data(ending_instruction);
+ data.push_back(opcode(InstructionType::Jsr, AddressingModeType::AbsoluteAddr));
+ data.push_back(static_cast<uint8_t>(address));
+ data.push_back(static_cast<uint8_t>(address >> 8));
+ if (assembler._hex_source_writer != nullptr) {
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 3], increase, 3, source_location.file_index, source_location.row, source_location.row + 1);
+ }
+ }
+ assembler._program_counter.integer_value += 3;
+}
+
+void Processor65c02::generate_instruction_data_label(Assembler &assembler, bool generate, bool export_enabled, const InstructionToken &token, uint8_t argument_index, int address, int offset, uint8_t size) const
+{
+ // exporting local variables is not allowed
+ if (generate && export_enabled && !token.global_data_label[argument_index]) {
+ std::stringstream ss;
+ ss << assembler.variable_name(token.data_label_symbol_hash[argument_index], token.global_data_label[argument_index]) << " cannot be exported since it is local.";
+ assembler.report_error(token.address_label_location[argument_index], AssemblyErrorCodes::ExportingLocalIsNotAllowed, ss.str());
+ }
+
+ if (assembler.create_label(generate, token.data_label_symbol_hash[argument_index], token.global_data_label[argument_index], StorageType::Constant, token.address_label_location[argument_index])) {
+ Value &new_label = assembler._current_pass.values.back();
+ if (size == 1) {
+ assembler.set_byte_offset(new_label, address, offset);
+ } else if (size == 2) {
+ assembler.set_word_offset(new_label, address, offset);
+ } else {
+ assert(false);
+ }
+ new_label.set_contains_address(true);
+ if (export_enabled) {
+ new_label.set_is_public(true);
+ }
+ }
+}
+
+const SyntaxToken *Processor65c02::parse_instruction(Assembler &assembler, bool generate, const SyntaxToken *t, bool export_enabled) const
+{
+ assert(t->type == SyntaxTokenType::Instruction);
+ const InstructionToken &instruction_token = *static_cast<const InstructionToken *>(t);
+
+ // instructions are only allowed within code sections.
+ bool instructions_allowed = assembler.in_code_section();
+ if (UNLIKELY(!instructions_allowed)) {
+ // this is an unrecoverable error
+ std::stringstream ss;
+ ss << "Instructions must be in a code section.";
+ assembler.report_fatal_error(instruction_token.source_location, AssemblyErrorCodes::CodeMustBeInCodeSection, ss.str());
+ }
+
+ // recursive data generation may not be safe
+ if (assembler._data_generation_depth != 0) {
+ // this is an unrecoverable error
+ std::stringstream ss;
+ ss << "Recursive data generation isn't allowed.";
+ assembler.report_fatal_error(instruction_token.source_location, AssemblyErrorCodes::RecursiveDataGenerationNotAllowed, ss.str());
+ }
+ ScopeCounter<uint32_t> sc(assembler._data_generation_depth);
+
+ InstructionType instruction = instruction_token.instruction;
+ uint16_t addr_mode = instruction_token.addressing_modes;
+ Section::Contents ending_instruction = is_ending_instruction(instruction) ? Section::Contents::EndExecutionInstruction : Section::Contents::ContinueExecutionInstruction;
+
+ t = assembler.consume_next_token(); // instruction
+
+ // in the generation pass, the program counter is guaranteed to be an integer value
+ // so there is no need to verify this
+
+ if (addr_mode == AddressingModeMask::Imp) {
+ if (generate) {
+ auto &data = assembler._section->generated_data(ending_instruction);
+ data.push_back(opcode(instruction, AddressingModeType::Implied));
+ if (assembler._hex_source_writer != nullptr) {
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 1], increase, 1, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ }
+ }
+ ++assembler._program_counter.integer_value;
+ return t;
+ }
+
+ // in all other instructions, we have to parse the expression for the first argument
+ const ExpressionToken *expr = static_cast<const ExpressionToken *>(t);
+ const Value argument = assembler.evaluate_expression(generate, t);
+ t = assembler.consume_next_token();
+
+ // The argument is guaranteed to be a valid type in the generation pass.
+ // In an assembly pass this can be Unknown.
+ int32_t argument_value = 0;
+
+ // in case of an assembly pass, unknown will be converted to 0, which is ok for all addressing modes except relative
+ if (assembler.is_integer(argument)) {
+ argument_value = assembler.dereference_integer(argument);
+ } else if (!assembler.is_unknown(argument)) {
+ if (generate) {
+ std::stringstream ss;
+ ss << "Addressing mode needs an integer value. Argument type was " << to_string(assembler.type_of_value(argument)) << ".";
+ assembler.report_error(expr->source_location, AssemblyErrorCodes::AddressingModeRequiresIntegerArgument, ss.str());
+ }
+ }
+
+ if (addr_mode == AddressingModeMask::Imm) {
+ if (generate) {
+ // handle the case where the value doesn't fit in a byte
+ if (argument_value < -128 || argument_value > 255) {
+ std::stringstream ss;
+ ss << "Addressing mode needs a byte size argument. Argument was evaluated to " << argument_value << ".";
+ assembler.report_error(expr->source_location, AssemblyErrorCodes::AddressingModeRequiresByteSizeArgument, ss.str());
+ }
+ auto &data = assembler._section->generated_data(ending_instruction);
+ data.push_back(opcode(instruction, AddressingModeType::Immediate));
+ data.push_back(static_cast<uint8_t>(argument_value));
+ if (assembler._hex_source_writer != nullptr) {
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], increase, 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ }
+ }
+ if (UNLIKELY(instruction_token.has_instruction_data_label[0])) {
+ generate_instruction_data_label(assembler, generate, export_enabled, instruction_token, 0, assembler._program_counter.integer_value + 1, 0, 1);
+ }
+
+ assembler._program_counter.integer_value += 2;
+ return t;
+ }
+
+ if (generate && argument_value < 0) {
+ std::stringstream ss;
+ ss << "Addressing mode needs a positive argument. Argument value was evaluated to " << argument_value << ".";
+ assembler.report_error(expr->source_location, AssemblyErrorCodes::AddressingModeRequiresPositiveArgument, ss.str());
+ }
+
+ if (assembler._multi_bank_mode && addr_mode != AddressingModeMask::Rel) {
+ // in this mode, addresses gets truncated to support memory banks
+ argument_value &= 0xffff;
+ }
+
+ if (addr_mode == (AddressingModeMask::Zp | AddressingModeMask::Abs)
+ || addr_mode == (AddressingModeMask::Zpx | AddressingModeMask::AbsX)
+ || addr_mode == (AddressingModeMask::Zpy | AddressingModeMask::AbsY)
+ || addr_mode == (AddressingModeMask::ZpI | AddressingModeMask::Ind)
+ || addr_mode == (AddressingModeMask::ZpIX | AddressingModeMask::IndX)
+ )
+ {
+ // mask off the zero page or absolute addressing mode regardless of modes
+ addr_mode = argument_value > 255 ? select_word_mode(addr_mode) : select_byte_mode(addr_mode);
+ }
+
+ if (addr_mode == AddressingModeMask::Zp
+ || addr_mode == AddressingModeMask::Zpx
+ || addr_mode == AddressingModeMask::Zpy
+ || addr_mode == AddressingModeMask::ZpI
+ || addr_mode == AddressingModeMask::ZpIX
+ || addr_mode == AddressingModeMask::ZpIY)
+ {
+ if (generate) {
+ if (argument_value > 255) {
+ std::stringstream ss;
+ ss << "Addressing mode needs a byte size argument. Argument was evaluated to " << argument_value << ".";
+ assembler.report_error(expr->source_location, AssemblyErrorCodes::AddressingModeRequiresByteSizeArgument, ss.str());
+ }
+ auto &data = assembler._section->generated_data(ending_instruction);
+ data.push_back(opcode(instruction, mask_to_addressing_mode(addr_mode)));
+ data.push_back(static_cast<uint8_t>(argument_value));
+ if (assembler._hex_source_writer != nullptr) {
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], increase, 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ }
+ }
+ if (UNLIKELY(instruction_token.has_instruction_data_label[0])) {
+ generate_instruction_data_label(assembler, generate, export_enabled, instruction_token, 0, assembler._program_counter.integer_value + 1, 0, 1);
+ }
+ assembler._program_counter.integer_value += 2;
+ return t;
+ }
+
+ if (addr_mode == AddressingModeMask::Abs
+ || addr_mode == AddressingModeMask::AbsX
+ || addr_mode == AddressingModeMask::AbsY
+ || addr_mode == AddressingModeMask::Ind
+ || addr_mode == AddressingModeMask::IndX
+ )
+ {
+ if (generate) {
+ if (argument_value > 65535) {
+ std::stringstream ss;
+ ss << "Addressing mode needs a word size argument. Argument was evaluated to " << argument_value << ".";
+ assembler.report_error(expr->source_location, AssemblyErrorCodes::AddressingModeRequiresWordSizeArgument, ss.str());
+ }
+ auto &data = assembler._section->generated_data(ending_instruction);
+ data.push_back(opcode(instruction, mask_to_addressing_mode(addr_mode)));
+ data.push_back(static_cast<uint8_t>(argument_value));
+ data.push_back(static_cast<uint8_t>(argument_value >> 8));
+ if (assembler._hex_source_writer != nullptr) {
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 3], increase, 3, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ }
+ }
+ if (UNLIKELY(instruction_token.has_instruction_data_label[0])) {
+ generate_instruction_data_label(assembler, generate, export_enabled, instruction_token, 0, assembler._program_counter.integer_value + 1, 0, 2);
+ }
+ assembler._program_counter.integer_value += 3;
+ return t;
+ }
+
+ if (addr_mode == AddressingModeMask::Rel) {
+ if (generate) {
+ int32_t reference_addr = assembler._program_counter.integer_value + 2; // move past the instruction
+ int32_t relative_addr = argument_value - reference_addr;
+ if (relative_addr < -128 || relative_addr > 127) {
+ std::stringstream ss;
+ ss << "Relative address out of range. Offset is " << relative_addr << " and needs to be in a [-128..127] range.";
+ assembler.report_error(expr->source_location, AssemblyErrorCodes::RelativeAddressOutOfRange, ss.str());
+ }
+ auto &data = assembler._section->generated_data(ending_instruction);
+ data.push_back(opcode(instruction, mask_to_addressing_mode(addr_mode)));
+ data.push_back(static_cast<uint8_t>(relative_addr));
+ if (assembler._hex_source_writer != nullptr) {
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], increase, 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ }
+ }
+ if (UNLIKELY(instruction_token.has_instruction_data_label[0])) {
+ generate_instruction_data_label(assembler, generate, export_enabled, instruction_token, 0, assembler._program_counter.integer_value + 1, 0, 1);
+ }
+ assembler._program_counter.integer_value += 2;
+ return t;
+ }
+
+ // Bz and Bzr left, which both use bit and zero page arguments
+ assert(t->type == SyntaxTokenType::Expression);
+ const ExpressionToken *expr2 = static_cast<const ExpressionToken *>(t);
+ const Value argument2 = assembler.evaluate_expression(generate, t);
+ t = assembler.consume_next_token();
+
+ int32_t argument2_value = 0;
+ // in case of an assembly pass, unknown will be converted to 0, which is ok for all addressing modes
+ if (assembler.is_integer(argument2)) {
+ argument2_value = assembler.dereference_integer(argument2);
+ } else {
+ if (generate) {
+ std::stringstream ss;
+ ss << "Addressing mode needs an integer value. Argument type was " << to_string(assembler.type_of_value(argument2)) << ".";
+ assembler.report_error(expr2->source_location, AssemblyErrorCodes::AddressingModeRequiresIntegerArgument, ss.str());
+ }
+ }
+
+ if (generate) {
+ if (UNLIKELY(instruction_token.has_instruction_data_label[0])) {
+ std::stringstream ss;
+ ss << "Addressing mode argument cannot have label to instruction data.";
+ assembler.report_error(expr->source_location, AssemblyErrorCodes::AddressingModeArgumentCannotHaveDataLabel, ss.str());
+ }
+
+ if (argument_value > 7) {
+ std::stringstream ss;
+ ss << "Addressing mode needs a bit size argument. Argument was evaluated to " << argument_value << ".";
+ assembler.report_error(expr->source_location, AssemblyErrorCodes::AddressingModeRequiresBitSizeArgument, ss.str());
+ }
+
+ if (argument2_value < 0) {
+ std::stringstream ss;
+ ss << "Addressing mode needs a positive argument. Argument value was evaluated to " << argument2_value << ".";
+ assembler.report_error(expr2->source_location, AssemblyErrorCodes::AddressingModeRequiresPositiveArgument, ss.str());
+ }
+
+ if (argument2_value > 255) {
+ std::stringstream ss;
+ ss << "Addressing mode needs a byte size argument. Argument was evaluated to " << argument2_value << ".";
+ assembler.report_error(expr2->source_location, AssemblyErrorCodes::AddressingModeRequiresByteSizeArgument, ss.str());
+ }
+ }
+
+ if (UNLIKELY(instruction_token.has_instruction_data_label[1])) {
+ generate_instruction_data_label(assembler, generate, export_enabled, instruction_token, 1, assembler._program_counter.integer_value + 1, 0, 1);
+ }
+
+ if (addr_mode == AddressingModeMask::Bz) {
+ if (generate) {
+ auto &data = assembler._section->generated_data(ending_instruction);
+ data.push_back(static_cast<uint8_t>(opcode(instruction, mask_to_addressing_mode(addr_mode)) | (argument_value << 4)));
+ data.push_back(static_cast<uint8_t>(argument2_value));
+ if (assembler._hex_source_writer != nullptr) {
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 2], increase, 2, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ }
+ }
+ assembler._program_counter.integer_value += 2;
+ return t;
+ }
+
+ // Just Bzr left
+ assert(t->type == SyntaxTokenType::Expression);
+ const ExpressionToken *expr3 = static_cast<const ExpressionToken *>(t);
+ const Value argument3 = assembler.evaluate_expression(generate, t);
+ t = assembler.consume_next_token();
+
+ int32_t argument3_value = 0;
+ if (assembler.is_integer(argument3)) {
+ argument3_value = assembler.dereference_integer(argument3);
+ } else {
+ if (generate) {
+ std::stringstream ss;
+ ss << "Addressing mode needs an integer value. Argument type was " << to_string(assembler.type_of_value(argument3)) << ".";
+ assembler.report_error(expr3->source_location, AssemblyErrorCodes::AddressingModeRequiresIntegerArgument, ss.str());
+ }
+ }
+
+ if (generate) {
+ int32_t reference_addr = assembler._program_counter.integer_value + 3; // move past the instruction
+ int32_t relative_addr = argument3_value - reference_addr;
+ if (relative_addr < -128 || relative_addr > 127) {
+ std::stringstream ss;
+ ss << "Relative address out of range. Offset is " << relative_addr << " and needs to be in a [-128..127] range.";
+ assembler.report_error(expr->source_location, AssemblyErrorCodes::RelativeAddressOutOfRange, ss.str());
+ }
+ auto &data = assembler._section->generated_data(ending_instruction);
+ data.push_back(static_cast<uint8_t>(opcode(instruction, mask_to_addressing_mode(addr_mode)) | (argument_value << 4)));
+ data.push_back(static_cast<uint8_t>(argument2_value));
+ data.push_back(static_cast<uint8_t>(relative_addr));
+ if (assembler._hex_source_writer != nullptr) {
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - 3], increase, 3, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ }
+ }
+ if (UNLIKELY(instruction_token.has_instruction_data_label[2])) {
+ generate_instruction_data_label(assembler, generate, export_enabled, instruction_token, 2, assembler._program_counter.integer_value + 2, 0, 1);
+ }
+ assembler._program_counter.integer_value += 3;
+ return t;
+}
+
+ }
+}
A => jasm/processor/65c02/processor_65c02.h +55 -0
@@ 0,0 1,55 @@
+#pragma once
+
+#include <processor/processor.h>
+#include <tokenize/source_location.h>
+
+namespace jasm
+{
+ namespace wdc65c02
+ {
+
+struct InstructionToken;
+
+class Processor65c02 : public Processor
+{
+public:
+ virtual void register_processor_keywords(std::vector<std::string> &keywords) override;
+ virtual void register_processor_instructions(bool pseudo_instructions) override;
+ virtual bool allow_processor_keyword_with_prim(uint64_t &keyword_hash) const override;
+
+ virtual std::string token_to_string(const Token &t) const override;
+ virtual const Token *parse_instruction(SyntaxParser &parser, const std::vector<std::string> &source_files, const Token *t, uint8_t /*InstructionType*/ instruction_index) const override;
+
+ virtual void generate_subroutine_instruction(Assembler &assembler, bool generate, int32_t address, const SourceLocation &source_location) const override;
+ virtual const SyntaxToken *parse_instruction(Assembler &assembler, bool generate, const SyntaxToken *t, bool export_enabled) const override;
+
+private:
+ struct ArgLabel
+ {
+ ArgLabel()
+ : enabled(false)
+ , global(false)
+ , symbol_hash(0)
+ {}
+
+ bool enabled;
+ bool global;
+ SourceLocation location;
+ uint64_t symbol_hash;
+ };
+
+ const Token *parse_optional_arg_label(SyntaxParser &parser, const Token *t, ArgLabel &label) const;
+ const Token *skip_optional_arg_label(SyntaxParser &parser, const Token *t, const ArgLabel &label) const;
+
+ /// Try to parse as much as needed to determine all possible addressing modes.
+ /// @return A mask with possible addressing modes.
+ uint16_t try_parse_addressing_mode(SyntaxParser &parser, const std::vector<std::string> &source_files, const Token *t, std::array<ArgLabel, 3> &arg_labels) const;
+
+ static void print_addressing_modes(std::stringstream &ss, uint16_t addressing_mode_mask);
+
+ void generate_instruction_data_label(Assembler &assembler, bool generate, bool export_enabled, const InstructionToken &token, uint8_t argument_index, int address, int offset, uint8_t size) const;
+};
+
+
+ }
+}
A => jasm/processor/65c02/processor_keywords_65c02.cpp +24 -0
@@ 0,0 1,24 @@
+#include "pch.h"
+
+#include <processor/65c02/processor_keywords_65c02.h>
+
+namespace jasm
+{
+ namespace wdc65c02
+ {
+
+std::string_view to_string(ProcessorKeywordType type)
+{
+ static const std::string_view names[] = {
+ // instruction registers
+ std::string_view("x"),
+ std::string_view("y"),
+ };
+ static_assert(sizeof(names) / sizeof(names[0]) == static_cast<size_t>(ProcessorKeywordType::NumTypes), "Number of registers/conditions doesn't match number of strings");
+
+ assert(type < ProcessorKeywordType::NumTypes);
+ return names[static_cast<size_t>(type)];
+}
+
+ } // namespace mos6502
+} // namespace jasm
A => jasm/processor/65c02/processor_keywords_65c02.h +25 -0
@@ 0,0 1,25 @@
+#pragma once
+
+namespace jasm
+{
+ namespace wdc65c02
+ {
+
+/// @addtogroup tokenize
+/// @{
+
+/// All different registers.
+enum class ProcessorKeywordType : uint8_t
+{
+ // instruction registers
+ X,
+ Y,
+ NumTypes,
+};
+
+std::string_view to_string(ProcessorKeywordType type);
+
+/// @}
+
+ } // namespace mos6502
+} // namespace jasm
M jasm/processor/instructions.h +1 -0
@@ 1,6 1,7 @@
#pragma once
#include <processor/6502/instructions_6502.h>
+#include <processor/65c02/instructions_65c02.h>
#include <processor/z80/instructions_z80.h>
namespace jasm
M jasm/processor/processor.cpp +9 -2
@@ 2,6 2,7 @@
#include <core/collections/array_helper.h>
#include <processor/6502/processor_6502.h>
+#include <processor/65c02/processor_65c02.h>
#include <processor/processor.h>
#include <processor/processor_unspecified.h>
#include <processor/z80/processor_z80.h>
@@ 19,6 20,7 @@ namespace {
std::string_view("6502"),
std::string_view("6510"),
std::string_view("8502"),
+ std::string_view("65c02"),
std::string_view("z80"),
};
}
@@ 150,6 152,8 @@ ProcessorCatalogue::ProcessorCatalogue(b
_unspecified->init(pseudo_instructions);
_mos6502 = std::make_unique<mos6502::Processor6502>();
_mos6502->init(pseudo_instructions);
+ _wdc65c02 = std::make_unique<wdc65c02::Processor65c02>();
+ _wdc65c02->init(pseudo_instructions);
_z80 = std::make_unique<z80::ProcessorZ80>();
_z80->init(pseudo_instructions);
}
@@ 160,12 164,15 @@ const Processor *ProcessorCatalogue::pro
case ProcessorType::Unspecified:
case ProcessorType::NumProcessors:
return _unspecified.get();
-
+
case ProcessorType::Mos6502:
case ProcessorType::Mos6510:
case ProcessorType::Mos8502:
return _mos6502.get();
-
+
+ case ProcessorType::Wdc65c02:
+ return _wdc65c02.get();
+
case ProcessorType::Zilog80:
return _z80.get();
}
M jasm/processor/processor.h +2 -0
@@ 22,6 22,7 @@ enum class ProcessorType : uint8_t
Mos6502,
Mos6510,
Mos8502,
+ Wdc65c02,
Zilog80,
NumProcessors
};
@@ 132,6 133,7 @@ public:
private:
std::unique_ptr<Processor> _unspecified;
std::unique_ptr<Processor> _mos6502;
+ std::unique_ptr<Processor> _wdc65c02;
std::unique_ptr<Processor> _z80;
};
M jasm/processor/z80/processor_z80.cpp +4 -3
@@ 511,9 511,9 @@ void ProcessorZ80::generate_subroutine_i
data.push_back(mutable_opcode_data[i]);
}
if (assembler._hex_source_writer != nullptr) {
- assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - opcode_data.total_size], opcode_data.total_size, source_location.file_index, source_location.row, source_location.row + 1);
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - opcode_data.total_size], increase, opcode_data.total_size, source_location.file_index, source_location.row, source_location.row + 1);
}
-
}
assembler._program_counter.integer_value += static_cast<int32_t>(opcode_data.total_size);
}
@@ 753,7 753,8 @@ const SyntaxToken *ProcessorZ80::parse_i
data.push_back(mutable_opcode_data[i]);
}
if (assembler._hex_source_writer != nullptr) {
- assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - opcode_data.total_size], opcode_data.total_size, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
+ constexpr bool increase = true;
+ assembler._hex_source_writer->write_data(static_cast<uint32_t>(assembler._program_counter.integer_value), &data[data.size() - opcode_data.total_size], increase, opcode_data.total_size, instruction_token.source_location.file_index, instruction_token.source_location.row, instruction_token.source_location.row + 1);
}
}
assembler._program_counter.integer_value += static_cast<int32_t>(opcode_data.total_size);
M jasm/tokenize/tokenizer.cpp +1 -1
@@ 579,7 579,7 @@ void Tokenizer::parse_processor(Position
ProcessorType processor;
if (!is_processor(processor_name, processor)) {
std::stringstream ss;
- ss << "Unsupported processor type \"" << processor_name << "\". Supported types are " << to_string(static_cast<ProcessorType>(1));
+ ss << "Unsupported processor type \"" << processor_name << "\". Supported types are \"" << to_string(static_cast<ProcessorType>(1)) << '\"';
for(uint32_t i = 2; i < static_cast<uint32_t>(ProcessorType::NumProcessors); ++i) {
ss << ", \"" << to_string(static_cast<ProcessorType>(i)) << '"';
}
M jasm/unit_test.py +1 -1
@@ 43,7 43,7 @@ def run_test(input_path, stdout_path, st
if exe == None:
return False
- processors = ["6502", "z80", "unspecified"]
+ processors = ["6502", "65c02", "z80", "unspecified"]
if not processor in processors:
raise Exception("Unsupported processor %s." % processor)
A => jasm/unit_tests/results/test_addressing_mode_expected_x_in_indirect_6502.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_addressing_mode_expected_x_in_indirect_6502.asm(4,10) : Error 2026 : Expected x for indirect addressing mode, but got symbol
A => jasm/unit_tests/results/test_addressing_mode_expected_x_in_indirect_65c02.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_addressing_mode_expected_x_in_indirect_65c02.asm(4,10) : Error 2026 : Expected x for indirect addressing mode, but got symbol
A => jasm/unit_tests/results/test_addressing_mode_expected_x_or_y_in_absolute_1_6502.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_addressing_mode_expected_x_or_y_in_absolute_1_6502.asm(4,13) : Error 2026 : Invalid index register in addressing mode. Expected x or y but got operator =
A => jasm/unit_tests/results/test_addressing_mode_expected_x_or_y_in_absolute_2_6502.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_addressing_mode_expected_x_or_y_in_absolute_2_6502.asm(4,9) : Error 2026 : Invalid index register in addressing mode. Expected x or y but got symbol
A => jasm/unit_tests/results/test_addressing_mode_expected_y_in_indirect_6502.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_addressing_mode_expected_y_in_indirect_6502.asm(4,11) : Error 2026 : Invalid index register in addressing mode. Expected y but got integer
R jasm/unit_tests/results/test_addressing_mode_is_illegal.stdout => +0 -7
@@ 1,7 0,0 @@
-unit_tests/test_addressing_mode_is_illegal.asm(5,5) : Error 2031 : Invalid addressing mode used. Code indicates one of the following:
- implied
-but possible addressing modes for dec are:
- zero page address
- absolute address
- zero page address with x offset
- absolute address with x offset
R jasm/unit_tests/results/test_addressing_mode_is_illegal2.stdout => +0 -12
@@ 1,12 0,0 @@
-unit_tests/test_addressing_mode_is_illegal2.asm(4,5) : Error 2031 : Invalid addressing mode used. Code indicates:
-in r
-but possible addressing modes are:
-in a, (c)
-in a, (<byte value>)
-in b, (c)
-in c, (c)
-in d, (c)
-in e, (c)
-in h, (c)
-in l, (c)
-
A => jasm/unit_tests/results/test_addressing_mode_is_illegal_6502.stdout +7 -0
@@ 0,0 1,7 @@
+unit_tests/test_addressing_mode_is_illegal_6502.asm(5,5) : Error 2031 : Invalid addressing mode used. Code indicates one of the following:
+ implied
+but possible addressing modes for dec are:
+ zero page address
+ absolute address
+ zero page address with x offset
+ absolute address with x offset
A => jasm/unit_tests/results/test_addressing_mode_is_illegal_65c02.stdout +4 -0
@@ 0,0 1,4 @@
+unit_tests/test_addressing_mode_is_illegal_65c02.asm(5,5) : Error 2031 : Invalid addressing mode used. Code indicates one of the following:
+ implied
+but possible addressing modes for bne are:
+ relative address
R jasm/unit_tests/results/test_addressing_mode_is_illegal_and_too_many_possibilities.stdout => +0 -3
@@ 1,3 0,0 @@
-unit_tests/test_addressing_mode_is_illegal_and_too_many_possibilities.asm(4,5) : Error 2031 : Invalid addressing mode used. Code indicates:
-ld r
-
A => jasm/unit_tests/results/test_addressing_mode_is_illegal_and_too_many_possibilities_z80.stdout +3 -0
@@ 0,0 1,3 @@
+unit_tests/test_addressing_mode_is_illegal_and_too_many_possibilities_z80.asm(4,5) : Error 2031 : Invalid addressing mode used. Code indicates:
+ld r
+
A => jasm/unit_tests/results/test_addressing_mode_is_illegal_z80.stdout +12 -0
@@ 0,0 1,12 @@
+unit_tests/test_addressing_mode_is_illegal_z80.asm(4,5) : Error 2031 : Invalid addressing mode used. Code indicates:
+in r
+but possible addressing modes are:
+in a, (c)
+in a, (<byte value>)
+in b, (c)
+in c, (c)
+in d, (c)
+in e, (c)
+in h, (c)
+in l, (c)
+
R jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_1.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_bit_size_argument_1.asm(4,6) : Error 3084 : Addressing mode needs a bit argument in range [0..7]. Argument was evaluated to -1.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_1_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_bit_size_argument_1_z80.asm(4,6) : Error 3084 : Addressing mode needs a bit argument in range [0..7]. Argument was evaluated to -1.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_2.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_bit_size_argument_2.asm(4,6) : Error 3084 : Addressing mode needs a bit argument in range [0..7]. Argument was evaluated to 8.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_2_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_bit_size_argument_2_z80.asm(4,6) : Error 3084 : Addressing mode needs a bit argument in range [0..7]. Argument was evaluated to 8.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_bit_size_argument_65c02.asm(4,6) : Error 3113 : Addressing mode needs a bit size argument. Argument was evaluated to 8.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_branch_offset_size_argument_1.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_branch_offset_size_argument_1.asm(6,5) : Error 3009 : Relative address out of range. Offset is -129 and needs to be in a [-128..127] range.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_branch_offset_size_argument_1_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_branch_offset_size_argument_1_z80.asm(6,5) : Error 3009 : Relative address out of range. Offset is -129 and needs to be in a [-128..127] range.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_branch_offset_size_argument_2.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_branch_offset_size_argument_2.asm(4,5) : Error 3009 : Relative address out of range. Offset is 128 and needs to be in a [-128..127] range.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_branch_offset_size_argument_2_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_branch_offset_size_argument_2_z80.asm(4,5) : Error 3009 : Relative address out of range. Offset is 128 and needs to be in a [-128..127] range.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_byte_argument.asm(4,7) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 256.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_1_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_byte_argument_1_6502.asm(4,7) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 256.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_1_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_byte_argument_1_65c02.asm(4,7) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 256.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_1_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_byte_argument_1_z80.asm(4,9) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 256.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_2.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_byte_argument_2.asm(5,7) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 3072.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_2_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_byte_argument_2_6502.asm(5,7) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 3072.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_2_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_byte_argument_2_65c02.asm(5,7) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 3072.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_2_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_byte_argument_2_z80.asm(4,9) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to -129.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_3.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_byte_argument_3.asm(4,9) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 256.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_3_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_byte_argument_3_65c02.asm(4,9) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 256.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_3_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_byte_argument_3_z80.asm(4,12) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 256.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_4.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_byte_argument_4.asm(4,9) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to -129.
-Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_5.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_byte_argument_5.asm(4,12) : Error 3007 : Addressing mode needs a byte size argument. Argument was evaluated to 256.
-Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_integer_argument.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_integer_argument.asm(4,7) : Error 3029 : Addressing mode needs an integer value. Argument type was float.
-Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_integer_argument2.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_integer_argument2.asm(4,9) : Error 3029 : Addressing mode needs an integer value. Argument type was string.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_1_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_integer_argument_1_6502.asm(4,7) : Error 3029 : Addressing mode needs an integer value. Argument type was float.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_1_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_integer_argument_1_65c02.asm(4,7) : Error 3029 : Addressing mode needs an integer value. Argument type was float.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_1_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_integer_argument_1_z80.asm(4,9) : Error 3029 : Addressing mode needs an integer value. Argument type was string.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_2_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_integer_argument_2_65c02.asm(4,9) : Error 3029 : Addressing mode needs an integer value. Argument type was string.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_3_65c02.stdout +3 -0
@@ 0,0 1,3 @@
+unit_tests/test_addressing_mode_needs_integer_argument_3_65c02.asm(4,12) : Error 3029 : Addressing mode needs an integer value. Argument type was string.
+unit_tests/test_addressing_mode_needs_integer_argument_3_65c02.asm(4,6) : Error 3009 : Relative address out of range. Offset is -32771 and needs to be in a [-128..127] range.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_4_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_integer_argument_4_65c02.asm(4,6) : Error 3029 : Addressing mode needs an integer value. Argument type was string.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_1.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_offset_size_argument_1.asm(4,11) : Error 3083 : Addressing mode needs an offset in range [-128..127]. Argument was evaluated to -129.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_1_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_offset_size_argument_1_z80.asm(4,11) : Error 3083 : Addressing mode needs an offset in range [-128..127]. Argument was evaluated to -129.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_2.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_offset_size_argument_2.asm(4,11) : Error 3083 : Addressing mode needs an offset in range [-128..127]. Argument was evaluated to 128.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_2_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_offset_size_argument_2_z80.asm(4,11) : Error 3083 : Addressing mode needs an offset in range [-128..127]. Argument was evaluated to 128.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_3.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_offset_size_argument_3.asm(4,8) : Error 3083 : Addressing mode needs an offset in range [-128..127]. Argument was evaluated to 128.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_3_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_offset_size_argument_3_z80.asm(4,8) : Error 3083 : Addressing mode needs an offset in range [-128..127]. Argument was evaluated to 128.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_positive_argument.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_positive_argument.asm(5,6) : Error 3006 : Addressing mode needs a positive argument. Argument value was evaluated to -1.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_positive_argument_1_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_positive_argument_1_6502.asm(5,6) : Error 3006 : Addressing mode needs a positive argument. Argument value was evaluated to -1.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_positive_argument_1_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_positive_argument_1_65c02.asm(5,6) : Error 3006 : Addressing mode needs a positive argument. Argument value was evaluated to -1.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_positive_argument_2_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_positive_argument_2_65c02.asm(4,9) : Error 3006 : Addressing mode needs a positive argument. Argument value was evaluated to -1.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_positive_argument_3_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_positive_argument_3_65c02.asm(4,6) : Error 3006 : Addressing mode needs a positive argument. Argument value was evaluated to -1.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_word_size_argument.asm(5,6) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to 786432.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_1_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_word_size_argument_1_6502.asm(5,6) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to 786432.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_1_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_word_size_argument_1_65c02.asm(5,6) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to 786432.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_2.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_word_size_argument_2.asm(4,6) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to 786432.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_2_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_word_size_argument_2_6502.asm(4,6) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to 786432.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_2_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_word_size_argument_2_65c02.asm(4,6) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to 786432.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_3.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_word_size_argument_3.asm(4,7) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to 65536.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_3_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_word_size_argument_3_z80.asm(4,7) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to 65536.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_4.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_word_size_argument_4.asm(4,7) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to -32769.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_4_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_word_size_argument_4_z80.asm(4,7) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to -32769.
+Assembly ended with errors.
R jasm/unit_tests/results/test_addressing_mode_needs_zero_page_size_argument.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_addressing_mode_needs_zero_page_size_argument.asm(4,6) : Error 3085 : Zero page address must be 0, 8, 16, 24, 32, 40, 48, 56. Argument was evaluated to 1.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_addressing_mode_needs_zero_page_size_argument_1_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_addressing_mode_needs_zero_page_size_argument_1_z80.asm(4,6) : Error 3085 : Zero page address must be 0, 8, 16, 24, 32, 40, 48, 56. Argument was evaluated to 1.
+Assembly ended with errors.
R jasm/unit_tests/results/test_all_instructions.bin => +0 -0
A => jasm/unit_tests/results/test_all_instructions_6502.bin +0 -0
A => jasm/unit_tests/results/test_all_instructions_65c02.bin +0 -0
R jasm/unit_tests/results/test_bank_mode_truncates_6502_address_instructions.bin => +0 -1
@@ 1,1 0,0 @@
-`
No newline at end of file
A => jasm/unit_tests/results/test_bank_mode_truncates_address_instructions_6502.bin +1 -0
@@ 0,0 1,1 @@
+`
No newline at end of file
A => jasm/unit_tests/results/test_bank_mode_truncates_address_instructions_65c02.bin +1 -0
@@ 0,0 1,1 @@
+`
No newline at end of file
A => jasm/unit_tests/results/test_bank_mode_truncates_address_instructions_z80.bin +1 -0
@@ 0,0 1,1 @@
+!*"
No newline at end of file
R jasm/unit_tests/results/test_bank_mode_truncates_z80_address_instructions.bin => +0 -1
@@ 1,1 0,0 @@
-!*"
No newline at end of file
R jasm/unit_tests/results/test_expected_x_in_indirect_addressing_mode.stdout => +0 -1
@@ 1,1 0,0 @@
-unit_tests/test_expected_x_in_indirect_addressing_mode.asm(4,10) : Error 2026 : Expected x for indirect addressing mode, but got symbol
R jasm/unit_tests/results/test_expected_x_or_y_in_absolute_addressing_mode1.stdout => +0 -1
@@ 1,1 0,0 @@
-unit_tests/test_expected_x_or_y_in_absolute_addressing_mode1.asm(4,13) : Error 2026 : Invalid index register in addressing mode. Expected x or y but got operator =
R jasm/unit_tests/results/test_expected_x_or_y_in_absolute_addressing_mode2.stdout => +0 -1
@@ 1,1 0,0 @@
-unit_tests/test_expected_x_or_y_in_absolute_addressing_mode2.asm(4,9) : Error 2026 : Invalid index register in addressing mode. Expected x or y but got symbol
R jasm/unit_tests/results/test_expected_y_in_indirect_addressing_mode.stdout => +0 -1
@@ 1,1 0,0 @@
-unit_tests/test_expected_y_in_indirect_addressing_mode.asm(4,11) : Error 2026 : Invalid index register in addressing mode. Expected y but got integer
R jasm/unit_tests/results/test_generate_data_in_instruction_1.stdout => +0 -3
@@ 1,3 0,0 @@
-unit_tests/test_generate_data_in_instruction_1.asm(7,3) : Error 3092 : Recursive data generation isn't allowed.
-unit_tests/test_generate_data_in_instruction_1.asm(10,15) : Invoked from here
-Fatal error, aborting assembly.
A => jasm/unit_tests/results/test_generate_data_in_instruction_1_6502.stdout +3 -0
@@ 0,0 1,3 @@
+unit_tests/test_generate_data_in_instruction_1_6502.asm(7,3) : Error 3092 : Recursive data generation isn't allowed.
+unit_tests/test_generate_data_in_instruction_1_6502.asm(10,15) : Invoked from here
+Fatal error, aborting assembly.
A => jasm/unit_tests/results/test_generate_data_in_instruction_1_65c02.stdout +3 -0
@@ 0,0 1,3 @@
+unit_tests/test_generate_data_in_instruction_1_65c02.asm(7,3) : Error 3092 : Recursive data generation isn't allowed.
+unit_tests/test_generate_data_in_instruction_1_65c02.asm(10,15) : Invoked from here
+Fatal error, aborting assembly.
R jasm/unit_tests/results/test_generate_data_in_instruction_2.stdout => +0 -3
@@ 1,3 0,0 @@
-unit_tests/test_generate_data_in_instruction_2.asm(7,3) : Error 3092 : Recursive data generation isn't allowed.
-unit_tests/test_generate_data_in_instruction_2.asm(10,15) : Invoked from here
-Fatal error, aborting assembly.
A => jasm/unit_tests/results/test_generate_data_in_instruction_2_z80.stdout +3 -0
@@ 0,0 1,3 @@
+unit_tests/test_generate_data_in_instruction_2_z80.asm(7,3) : Error 3092 : Recursive data generation isn't allowed.
+unit_tests/test_generate_data_in_instruction_2_z80.asm(10,15) : Invoked from here
+Fatal error, aborting assembly.
R jasm/unit_tests/results/test_instruction_data_global_label.bin => +0 -0
A => jasm/unit_tests/results/test_instruction_data_global_label_6502.bin +0 -0
A => jasm/unit_tests/results/test_instruction_data_global_label_65c02.bin +0 -0
R jasm/unit_tests/results/test_instruction_data_label_cant_have_implied_addressing_mode.stdout => +0 -1
@@ 1,1 0,0 @@
-unit_tests/test_instruction_data_label_cant_have_implied_addressing_mode.asm(5,6) : Error 2046 : Implied addressing modes cannot have label to instruction data. Add a newline or a semicolon before the label to resolve this.
A => jasm/unit_tests/results/test_instruction_data_label_cant_have_implied_addressing_mode_6502.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_instruction_data_label_cant_have_implied_addressing_mode_6502.asm(5,6) : Error 2046 : Implied addressing modes cannot have label to instruction data. Add a newline or a semicolon before the label to resolve this.
A => jasm/unit_tests/results/test_instruction_data_label_cant_have_implied_addressing_mode_65c02.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_instruction_data_label_cant_have_implied_addressing_mode_65c02.asm(5,6) : Error 2046 : Implied addressing modes cannot have label to instruction data. Add a newline or a semicolon before the label to resolve this.
R jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type1.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_instruction_data_label_for_wrong_argument_type1.asm(4,6) : Error 3099 : Addressing mode argument cannot have label to instruction data.
-Assembly ended with errors.
R jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type2.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_instruction_data_label_for_wrong_argument_type2.asm(4,9) : Error 3099 : Addressing mode argument cannot have label to instruction data.
-Assembly ended with errors.
A => jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type_1_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_instruction_data_label_for_wrong_argument_type_1_z80.asm(4,6) : Error 3099 : Addressing mode argument cannot have label to instruction data.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type_2_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_instruction_data_label_for_wrong_argument_type_2_z80.asm(4,9) : Error 3099 : Addressing mode argument cannot have label to instruction data.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type_3_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_instruction_data_label_for_wrong_argument_type_3_65c02.asm(4,11) : Error 3099 : Addressing mode argument cannot have label to instruction data.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_instruction_data_label_has_lo_hi_properties_65c02.bin +1 -0
@@ 0,0 1,1 @@
+L
No newline at end of file
R jasm/unit_tests/results/test_instruction_data_label_offsets.bin => +0 -1
@@ 1,1 0,0 @@
-ݎ݆ݦFFNNVV^^ffnnvv~~444444444ݾ554444444444480 (6wpqrstu6wpqrstu624C4S4"4"4"4s4~~:4>FFK44NNVV[44^^ff&*4!4*4!4*4!4nn.{414ݶݞ&&..>>ݖݮ
No newline at end of file
A => jasm/unit_tests/results/test_instruction_data_label_offsets_65c02.bin +0 -0
A => jasm/unit_tests/results/test_instruction_data_label_offsets_z80.bin +1 -0
@@ 0,0 1,1 @@
+ݎ݆ݦFFNNVV^^ffnnvv~~444444444ݾ554444444444480 (6wpqrstu6wpqrstu624C4S4"4"4"4s4~~:4>FFK44NNVV[44^^ff&*4!4*4!4*4!4nn.{414ݶݞ&&..>>ݖݮ
No newline at end of file
A => jasm/unit_tests/results/test_instruction_data_label_sizes_65c02.bin +0 -0
A => jasm/unit_tests/results/test_instruction_data_label_with_export_65c02.bin +1 -0
@@ 0,0 1,1 @@
+``
No newline at end of file
A => jasm/unit_tests/results/test_instruction_data_label_with_local_export_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_instruction_data_label_with_local_export_65c02.asm(11,14) : Error 3064 : .addr cannot be exported since it is local.
+Assembly ended with errors.
R jasm/unit_tests/results/test_instruction_data_local_label.bin => +0 -0
A => jasm/unit_tests/results/test_instruction_data_local_label_6502.bin +0 -0
A => jasm/unit_tests/results/test_instruction_data_local_label_65c02.bin +0 -0
R jasm/unit_tests/results/test_instruction_ends_at_newline.bin => +0 -0
R jasm/unit_tests/results/test_instruction_ends_at_newline2.stdout => +0 -1
@@ 1,1 0,0 @@
-unit_tests/test_instruction_ends_at_newline2.asm(6,7) : Error 2009 : Expected expression value but got newline
A => jasm/unit_tests/results/test_instruction_ends_at_newline_1_6502.bin +0 -0
A => jasm/unit_tests/results/test_instruction_ends_at_newline_1_65c02.bin +0 -0
A => jasm/unit_tests/results/test_instruction_ends_at_newline_2_6502.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_instruction_ends_at_newline_2_6502.asm(6,7) : Error 2009 : Expected expression value but got newline
A => jasm/unit_tests/results/test_instruction_ends_at_newline_2_65c02.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_instruction_ends_at_newline_2_65c02.asm(6,7) : Error 2009 : Expected expression value but got newline
A => jasm/unit_tests/results/test_instruction_names_can_be_used_in_local_variables_65c02.bin +0 -0
R jasm/unit_tests/results/test_instructions_must_be_in_code_sections1.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_instructions_must_be_in_code_sections1.asm(3,1) : Error 3057 : Instructions must be in a code section.
-Fatal error, aborting assembly.
R jasm/unit_tests/results/test_instructions_must_be_in_code_sections2.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_instructions_must_be_in_code_sections2.asm(4,2) : Error 3057 : Instructions must be in a code section.
-Fatal error, aborting assembly.
A => jasm/unit_tests/results/test_instructions_must_be_in_code_sections_1_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_instructions_must_be_in_code_sections_1_6502.asm(3,1) : Error 3057 : Instructions must be in a code section.
+Fatal error, aborting assembly.
A => jasm/unit_tests/results/test_instructions_must_be_in_code_sections_1_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_instructions_must_be_in_code_sections_1_65c02.asm(3,1) : Error 3057 : Instructions must be in a code section.
+Fatal error, aborting assembly.
A => jasm/unit_tests/results/test_instructions_must_be_in_code_sections_2_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_instructions_must_be_in_code_sections_2_6502.asm(4,2) : Error 3057 : Instructions must be in a code section.
+Fatal error, aborting assembly.
A => jasm/unit_tests/results/test_instructions_must_be_in_code_sections_2_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_instructions_must_be_in_code_sections_2_65c02.asm(4,2) : Error 3057 : Instructions must be in a code section.
+Fatal error, aborting assembly.
R jasm/unit_tests/results/test_keyword_cannot_be_used_for_indirect_addressing.stdout => +0 -1
@@ 1,1 0,0 @@
-unit_tests/test_keyword_cannot_be_used_for_indirect_addressing.asm(4,10) : Error 2041 : a cannot be used for indirect addessing.
A => jasm/unit_tests/results/test_keyword_cannot_be_used_for_indirect_addressing_z80.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_keyword_cannot_be_used_for_indirect_addressing_z80.asm(4,10) : Error 2041 : a cannot be used for indirect addessing.
M jasm/unit_tests/results/test_processor_with_invalid_name.stdout +1 -1
@@ 1,1 1,1 @@
-unit_tests/test_processor_with_invalid_name.asm(3,11) : Error 1013 : Unsupported processor type "test". Supported types are 6502, "6510", "8502", "z80"
+unit_tests/test_processor_with_invalid_name.asm(3,11) : Error 1013 : Unsupported processor type "test". Supported types are "6502", "6510", "8502", "65c02", "z80"
A => jasm/unit_tests/results/test_pseudo_instructions_for_branching_65c02.bin +1 -0
@@ 0,0 1,1 @@
+
No newline at end of file
A => jasm/unit_tests/results/test_pseudo_instructions_for_incrementing_65c02.bin +1 -0
@@ 0,0 1,1 @@
+:
No newline at end of file
A => jasm/unit_tests/results/test_pseudo_instructions_in_standard_mode_65c02.stdout +7 -0
@@ 0,0 1,7 @@
+unit_tests/test_pseudo_instructions_in_standard_mode_65c02.asm(5,2) : Error 3004 : Reference to undefined symbol bhs
+unit_tests/test_pseudo_instructions_in_standard_mode_65c02.asm(6,2) : Error 3004 : Reference to undefined symbol blt
+unit_tests/test_pseudo_instructions_in_standard_mode_65c02.asm(5,6) : Error 3000 : Operator * is not defined for left hand side unknown type.
+unit_tests/test_pseudo_instructions_in_standard_mode_65c02.asm(7,2) : Error 3004 : Reference to undefined symbol dea
+unit_tests/test_pseudo_instructions_in_standard_mode_65c02.asm(6,6) : Error 3000 : Operator * is not defined for left hand side unknown type.
+unit_tests/test_pseudo_instructions_in_standard_mode_65c02.asm(8,2) : Error 3004 : Reference to undefined symbol ina
+Assembly ended with errors.
A => jasm/unit_tests/results/test_pseudo_instructions_use_names_in_standard_mode_65c02.bin +1 -0
@@ 0,0 1,1 @@
+`
No newline at end of file
A => jasm/unit_tests/results/test_register_names_can_be_used_in_local_names_65c02.bin +0 -0
A => jasm/unit_tests/results/test_register_names_cant_be_used_as_global_variables_65c02.stdout +1 -0
@@ 0,0 1,1 @@
+unit_tests/test_register_names_cant_be_used_as_global_variables_65c02.asm(5,8) : Error 2007 : Expected symbol name but got processor keyword x
A => jasm/unit_tests/results/test_subroutine_call_65c02.bin +1 -0
@@ 0,0 1,1 @@
+ `
No newline at end of file
A => jasm/unit_tests/results/test_subroutine_call_must_be_in_code_section_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_call_must_be_in_code_section_65c02.asm(3,5) : Error 3057 : Instructions must be in a code section.
+Fatal error, aborting assembly.
A => jasm/unit_tests/results/test_subroutine_call_negative_argument_65c02.stdout +3 -0
@@ 0,0 1,3 @@
+unit_tests/test_subroutine_call_negative_argument_65c02.asm(3,23) : Error 3013 : Section start cannot be negative. It is evaluated to -4.
+unit_tests/test_subroutine_call_negative_argument_65c02.asm(5,6) : Error 3006 : Addressing mode needs a positive argument. Argument value was evaluated to -1.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_subroutine_call_recursive_data_generation_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_call_recursive_data_generation_65c02.asm(5,11) : Error 3092 : Recursive data generation isn't allowed.
+Fatal error, aborting assembly.
A => jasm/unit_tests/results/test_subroutine_call_too_large_argument_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_call_too_large_argument_65c02.asm(5,6) : Error 3008 : Addressing mode needs a word size argument. Argument was evaluated to 65536.
+Assembly ended with errors.
A => jasm/unit_tests/results/test_subroutine_call_with_arguments_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_call_with_arguments_65c02.asm(5,6) : Error 3108 : Subroutine calls don't support arguments.
+Assembly ended with errors.
R jasm/unit_tests/results/test_subroutine_falls_through_1.bin => +0 -0
R jasm/unit_tests/results/test_subroutine_falls_through_1.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_subroutine_falls_through_1.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
-$8000 - $8001 ($0001) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_1_6502.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_1_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_falls_through_1_6502.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
+$8000 - $8001 ($0001) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_1_65c02.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_1_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_falls_through_1_65c02.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
+$8000 - $8001 ($0001) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_1_z80.bin +1 -0
@@ 0,0 1,1 @@
+
No newline at end of file
A => jasm/unit_tests/results/test_subroutine_falls_through_1_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_falls_through_1_z80.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
+$8000 - $8001 ($0001) code: main
R jasm/unit_tests/results/test_subroutine_falls_through_2.bin => +0 -0
R jasm/unit_tests/results/test_subroutine_falls_through_2.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_subroutine_falls_through_2.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
-$8000 - $8002 ($0002) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_2_6502.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_2_6502.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_falls_through_2_6502.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
+$8000 - $8002 ($0002) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_2_65c02.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_2_65c02.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_falls_through_2_65c02.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
+$8000 - $8002 ($0002) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_2_z80.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_2_z80.stdout +2 -0
@@ 0,0 1,2 @@
+unit_tests/test_subroutine_falls_through_2_z80.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
+$8000 - $8002 ($0002) code: main
R jasm/unit_tests/results/test_subroutine_falls_through_3.bin => +0 -0
R jasm/unit_tests/results/test_subroutine_falls_through_3.stdout => +0 -1
@@ 1,1 0,0 @@
-$8000 - $8001 ($0001) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_3_6502.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_3_6502.stdout +1 -0
@@ 0,0 1,1 @@
+$8000 - $8001 ($0001) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_3_65c02.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_3_65c02.stdout +1 -0
@@ 0,0 1,1 @@
+$8000 - $8001 ($0001) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_3_z80.bin +1 -0
@@ 0,0 1,1 @@
+
No newline at end of file
A => jasm/unit_tests/results/test_subroutine_falls_through_3_z80.stdout +1 -0
@@ 0,0 1,1 @@
+$8000 - $8001 ($0001) code: main
R jasm/unit_tests/results/test_subroutine_falls_through_4.bin => +0 -0
R jasm/unit_tests/results/test_subroutine_falls_through_4.stdout => +0 -1
@@ 1,1 0,0 @@
-$8000 - $8003 ($0003) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_4_6502.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_4_6502.stdout +1 -0
@@ 0,0 1,1 @@
+$8000 - $8003 ($0003) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_4_65c02.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_4_65c02.stdout +1 -0
@@ 0,0 1,1 @@
+$8000 - $8003 ($0003) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_4_z80.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_4_z80.stdout +1 -0
@@ 0,0 1,1 @@
+$8000 - $8003 ($0003) code: main
R jasm/unit_tests/results/test_subroutine_falls_through_5.bin => +0 -1
@@ 1,1 0,0 @@
-
No newline at end of file
R jasm/unit_tests/results/test_subroutine_falls_through_5.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_subroutine_falls_through_5.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
-$8000 - $8001 ($0001) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_5_65c02.bin +0 -0
A => jasm/unit_tests/results/test_subroutine_falls_through_5_65c02.stdout +1 -0
@@ 0,0 1,1 @@
+$8000 - $8002 ($0002) code: main
A => jasm/unit_tests/results/test_subroutine_falls_through_5_z80.bin +1 -0
@@ 0,0 1,1 @@
+
No newline at end of file
A => jasm/unit_tests/results/test_subroutine_falls_through_5_z80.stdout +1 -0
@@ 0,0 1,1 @@
+$8000 - $8002 ($0002) code: main
R jasm/unit_tests/results/test_subroutine_falls_through_6.bin => +0 -0
R jasm/unit_tests/results/test_subroutine_falls_through_6.stdout => +0 -2
@@ 1,2 0,0 @@
-unit_tests/test_subroutine_falls_through_6.asm(5,13) : Warning 3500 : Code in subroutine test falls through at end of subroutine.
-$8000 - $8002 ($0002) code: main
R jasm/unit_tests/results/test_subroutine_falls_through_7.bin => +0 -1
@@ 1,1 0,0 @@
-
No newline at end of file
R jasm/unit_tests/results/test_subroutine_falls_through_7.stdout => +0 -1
@@ 1,1 0,0 @@
-$8000 - $8001 ($0001) code: main
R jasm/unit_tests/results/test_subroutine_falls_through_8.bin => +0 -0
R jasm/unit_tests/results/test_subroutine_falls_through_8.stdout => +0 -1
@@ 1,1 0,0 @@
-$8000 - $8003 ($0003) code: main
R jasm/unit_tests/results/test_subroutine_falls_through_9.bin => +0 -1
@@ 1,1 0,0 @@
-
No newline at end of file
R jasm/unit_tests/results/test_subroutine_falls_through_9.stdout => +0 -1
@@ 1,1 0,0 @@
-$8000 - $8002 ($0002) code: main
A => jasm/unit_tests/test_addressing_mode_expected_x_in_indirect_6502.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000 {
+ lda (55,q
+}
A => jasm/unit_tests/test_addressing_mode_expected_x_in_indirect_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000 {
+ lda (55,q
+}
A => jasm/unit_tests/test_addressing_mode_expected_x_or_y_in_absolute_1_6502.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000 {
+ lda (55)+1,=
+}
A => jasm/unit_tests/test_addressing_mode_expected_x_or_y_in_absolute_2_6502.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000 {
+ lda 55,p
+}
No newline at end of file
A => jasm/unit_tests/test_addressing_mode_expected_y_in_indirect_6502.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000 {
+ lda (55),1
+}
R jasm/unit_tests/test_addressing_mode_is_illegal.asm => +0 -6
@@ 1,6 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000
-{
- dec;
-}
R jasm/unit_tests/test_addressing_mode_is_illegal2.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- in r
-}
A => jasm/unit_tests/test_addressing_mode_is_illegal_6502.asm +6 -0
@@ 0,0 1,6 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000
+{
+ dec;
+}
A => jasm/unit_tests/test_addressing_mode_is_illegal_65c02.asm +6 -0
@@ 0,0 1,6 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000
+{
+ bne;
+}
R jasm/unit_tests/test_addressing_mode_is_illegal_and_too_many_possibilities.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0]
-
-section code, "main", $8000 {
- ld r
-}
A => jasm/unit_tests/test_addressing_mode_is_illegal_and_too_many_possibilities_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0]
+
+section code, "main", $8000 {
+ ld r
+}
A => jasm/unit_tests/test_addressing_mode_is_illegal_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ in r
+}
R jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_1.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- set -1,(hl)
-}
A => jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_1_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ set -1,(hl)
+}
R jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_2.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- set 8,(hl)
-}
A => jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_2_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ set 8,(hl)
+}
A => jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000 {
+ rmb 8,0
+}
R jasm/unit_tests/test_addressing_mode_needs_branch_offset_size_argument_1.asm => +0 -7
@@ 1,7 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
-.lbl:
- define byte[127] = {0, ...}
- jr .lbl
-}
A => jasm/unit_tests/test_addressing_mode_needs_branch_offset_size_argument_1_z80.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+.lbl:
+ define byte[127] = {0, ...}
+ jr .lbl
+}
R jasm/unit_tests/test_addressing_mode_needs_branch_offset_size_argument_2.asm => +0 -7
@@ 1,7 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- jr .lbl
- define byte[128] = {0, ...}
-.lbl:
-}
A => jasm/unit_tests/test_addressing_mode_needs_branch_offset_size_argument_2_z80.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ jr .lbl
+ define byte[128] = {0, ...}
+.lbl:
+}
R jasm/unit_tests/test_addressing_mode_needs_byte_argument.asm => +0 -7
@@ 1,7 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000 {
- lda #256
- sta $c000
- rts
-}
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_1_6502.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000 {
+ lda #256
+ sta $c000
+ rts
+}
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_1_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000 {
+ lda #256
+ sta $c000
+ rts
+}
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_1_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ adc a, 256
+}
R jasm/unit_tests/test_addressing_mode_needs_byte_argument_2.asm => +0 -7
@@ 1,7 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000 {
- ldx #0
- lda ($c00,x)
- rts
-}
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_2_6502.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000 {
+ ldx #0
+ lda ($c00,x)
+ rts
+}
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_2_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000 {
+ ldx #0
+ lda ($c00,x)
+ rts
+}
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_2_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ adc a, -129
+}
R jasm/unit_tests/test_addressing_mode_needs_byte_argument_3.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- adc a, 256
-}
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_3_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000 {
+ rmb 0, 256
+}
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_3_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ ld (ix+0),256
+}
R jasm/unit_tests/test_addressing_mode_needs_byte_argument_4.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- adc a, -129
-}
R jasm/unit_tests/test_addressing_mode_needs_byte_argument_5.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- ld (ix+0),256
-}
R jasm/unit_tests/test_addressing_mode_needs_integer_argument.asm => +0 -6
@@ 1,6 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $1000, $2000 {
- lda #5.5
- rts
-}
R jasm/unit_tests/test_addressing_mode_needs_integer_argument2.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- adc a, "hello"
-}
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_1_6502.asm +6 -0
@@ 0,0 1,6 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $1000, $2000 {
+ lda #5.5
+ rts
+}
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_1_65c02.asm +6 -0
@@ 0,0 1,6 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $1000, $2000 {
+ lda #5.5
+ rts
+}
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_1_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ adc a, "hello"
+}
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_2_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000 {
+ smb 0, "H"
+}
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_3_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000 {
+ bbr 0, 0, "H"
+}
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_4_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000 {
+ smb "H", 0
+}
R jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_1.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- adc a,(ix-129)
-}
A => jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_1_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ adc a,(ix-129)
+}
R jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_2.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- adc a,(ix+128)
-}
A => jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_2_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ adc a,(ix+128)
+}
R jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_3.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- ld (ix+128),0
-}
A => jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_3_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ ld (ix+128),0
+}
R jasm/unit_tests/test_addressing_mode_needs_positive_argument.asm => +0 -7
@@ 1,7 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000 {
- lda #0
- sta -1
- rts
-}
A => jasm/unit_tests/test_addressing_mode_needs_positive_argument_1_6502.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000 {
+ lda #0
+ sta -1
+ rts
+}
A => jasm/unit_tests/test_addressing_mode_needs_positive_argument_1_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000 {
+ lda #0
+ sta -1
+ rts
+}
A => jasm/unit_tests/test_addressing_mode_needs_positive_argument_2_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000 {
+ smb 0, -1
+}
A => jasm/unit_tests/test_addressing_mode_needs_positive_argument_3_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000 {
+ smb -1, 0
+}
R jasm/unit_tests/test_addressing_mode_needs_word_size_argument.asm => +0 -7
@@ 1,7 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000 {
- ldx #0
- lda $c0000,x
- rts
-}
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_1_6502.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000 {
+ ldx #0
+ lda $c0000,x
+ rts
+}
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_1_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000 {
+ ldx #0
+ lda $c0000,x
+ rts
+}
R jasm/unit_tests/test_addressing_mode_needs_word_size_argument_2.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000 {
- jmp ($c0000)
-}
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_2_6502.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000 {
+ jmp ($c0000)
+}
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_2_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000 {
+ jmp ($c0000)
+}
R jasm/unit_tests/test_addressing_mode_needs_word_size_argument_3.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- call $10000
-}
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_3_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ call $10000
+}
R jasm/unit_tests/test_addressing_mode_needs_word_size_argument_4.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- call -32769
-}
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_4_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ call -32769
+}
R jasm/unit_tests/test_addressing_mode_needs_zero_page_size_argument.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- rst 1
-}
A => jasm/unit_tests/test_addressing_mode_needs_zero_page_size_argument_1_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ rst 1
+}
R jasm/unit_tests/test_all_instructions.asm => +0 -166
@@ 1,166 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $1000
-{
- adc #0
- adc $01
- adc $01,x
- adc $01,y
- adc $ffff
- adc $ffff,x
- adc $ffff,y
- adc ($01,x)
- adc ($01),y
- and #0
- and $01
- and $01,x
- and $01,y
- and $ffff
- and $ffff,x
- and $ffff,y
- and ($01,x)
- and ($01),y
- asl
- asl $01
- asl $01,x
- asl $ffff
- asl $ffff,x
- bcc *
- bcs *
- beq *
- bit $01
- bit $ffff
- bmi *
- bne *
- bpl *
- brk
- bvc *
- bvs *
- clc
- cld
- cli
- clv
- cmp #0
- cmp $01
- cmp $01,x
- cmp $01,y
- cmp $ffff
- cmp $ffff,x
- cmp $ffff,y
- cmp ($01,x)
- cmp ($01),y
- cpx #0
- cpx $01
- cpx $ffff
- cpy #0
- cpy $01
- cpy $ffff
- dec $01
- dec $01,x
- dec $ffff
- dec $ffff,x
- dex
- dey
- eor #0
- eor $01
- eor $01,x
- eor $01,y
- eor $ffff
- eor $ffff,x
- eor $ffff,y
- eor ($01,x)
- eor ($01),y
- inc $01
- inc $01,x
- inc $ffff
- inc $ffff,x
- inx
- iny
- jmp $01
- jmp $ffff
- jmp ($ffff)
- jsr $01
- jsr $ffff
- lda #0
- lda $01
- lda $01,x
- lda $01,y
- lda $ffff
- lda $ffff,x
- lda $ffff,y
- lda ($01,x)
- lda ($01),y
- ldx #0
- ldx $01
- ldx $01,y
- ldx $ffff
- ldx $ffff,y
- ldy #0
- ldy $01
- ldy $01,x
- ldy $ffff
- ldy $ffff,x
- lsr
- lsr $01
- lsr $01,x
- lsr $ffff
- lsr $ffff,x
- nop
- ora #0
- ora $01
- ora $01,x
- ora $01,y
- ora $ffff
- ora $ffff,x
- ora $ffff,y
- ora ($01,x)
- ora ($01),y
- pha
- php
- pla
- plp
- rol
- rol $01
- rol $01,x
- rol $ffff
- rol $ffff,x
- ror
- ror $01
- ror $01,x
- ror $ffff
- ror $ffff,x
- rti
- rts
- sbc #0
- sbc $01
- sbc $01,x
- sbc $01,y
- sbc $ffff
- sbc $ffff,x
- sbc $ffff,y
- sbc ($01,x)
- sbc ($01),y
- sec
- sed
- sei
- sta $01
- sta $01,x
- sta $01,y
- sta $ffff
- sta $ffff,x
- sta $ffff,y
- sta ($01,x)
- sta ($01),y
- stx $01
- stx $01,y
- stx $ffff
- sty $01
- sty $01,x
- sty $ffff
- tax
- tay
- tsx
- txa
- txs
- tya
-}
A => jasm/unit_tests/test_all_instructions_6502.asm +166 -0
@@ 0,0 1,166 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $1000
+{
+ adc #0
+ adc $01
+ adc $01,x
+ adc $01,y
+ adc $ffff
+ adc $ffff,x
+ adc $ffff,y
+ adc ($01,x)
+ adc ($01),y
+ and #0
+ and $01
+ and $01,x
+ and $01,y
+ and $ffff
+ and $ffff,x
+ and $ffff,y
+ and ($01,x)
+ and ($01),y
+ asl
+ asl $01
+ asl $01,x
+ asl $ffff
+ asl $ffff,x
+ bcc *
+ bcs *
+ beq *
+ bit $01
+ bit $ffff
+ bmi *
+ bne *
+ bpl *
+ brk
+ bvc *
+ bvs *
+ clc
+ cld
+ cli
+ clv
+ cmp #0
+ cmp $01
+ cmp $01,x
+ cmp $01,y
+ cmp $ffff
+ cmp $ffff,x
+ cmp $ffff,y
+ cmp ($01,x)
+ cmp ($01),y
+ cpx #0
+ cpx $01
+ cpx $ffff
+ cpy #0
+ cpy $01
+ cpy $ffff
+ dec $01
+ dec $01,x
+ dec $ffff
+ dec $ffff,x
+ dex
+ dey
+ eor #0
+ eor $01
+ eor $01,x
+ eor $01,y
+ eor $ffff
+ eor $ffff,x
+ eor $ffff,y
+ eor ($01,x)
+ eor ($01),y
+ inc $01
+ inc $01,x
+ inc $ffff
+ inc $ffff,x
+ inx
+ iny
+ jmp $01
+ jmp $ffff
+ jmp ($ffff)
+ jsr $01
+ jsr $ffff
+ lda #0
+ lda $01
+ lda $01,x
+ lda $01,y
+ lda $ffff
+ lda $ffff,x
+ lda $ffff,y
+ lda ($01,x)
+ lda ($01),y
+ ldx #0
+ ldx $01
+ ldx $01,y
+ ldx $ffff
+ ldx $ffff,y
+ ldy #0
+ ldy $01
+ ldy $01,x
+ ldy $ffff
+ ldy $ffff,x
+ lsr
+ lsr $01
+ lsr $01,x
+ lsr $ffff
+ lsr $ffff,x
+ nop
+ ora #0
+ ora $01
+ ora $01,x
+ ora $01,y
+ ora $ffff
+ ora $ffff,x
+ ora $ffff,y
+ ora ($01,x)
+ ora ($01),y
+ pha
+ php
+ pla
+ plp
+ rol
+ rol $01
+ rol $01,x
+ rol $ffff
+ rol $ffff,x
+ ror
+ ror $01
+ ror $01,x
+ ror $ffff
+ ror $ffff,x
+ rti
+ rts
+ sbc #0
+ sbc $01
+ sbc $01,x
+ sbc $01,y
+ sbc $ffff
+ sbc $ffff,x
+ sbc $ffff,y
+ sbc ($01,x)
+ sbc ($01),y
+ sec
+ sed
+ sei
+ sta $01
+ sta $01,x
+ sta $01,y
+ sta $ffff
+ sta $ffff,x
+ sta $ffff,y
+ sta ($01,x)
+ sta ($01),y
+ stx $01
+ stx $01,y
+ stx $ffff
+ sty $01
+ sty $01,x
+ sty $ffff
+ tax
+ tay
+ tsx
+ txa
+ txs
+ tya
+}
A => jasm/unit_tests/test_all_instructions_65c02.asm +230 -0
@@ 0,0 1,230 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $1000
+{
+ // 6502 compatible
+ adc #0
+ adc $01
+ adc $01,x
+ adc $01,y
+ adc $ffff
+ adc $ffff,x
+ adc $ffff,y
+ adc ($01,x)
+ adc ($01),y
+ and #0
+ and $01
+ and $01,x
+ and $01,y
+ and $ffff
+ and $ffff,x
+ and $ffff,y
+ and ($01,x)
+ and ($01),y
+ asl
+ asl $01
+ asl $01,x
+ asl $ffff
+ asl $ffff,x
+ bcc *
+ bcs *
+ beq *
+ bit $01
+ bit $ffff
+ bmi *
+ bne *
+ bpl *
+ brk
+ bvc *
+ bvs *
+ clc
+ cld
+ cli
+ clv
+ cmp #0
+ cmp $01
+ cmp $01,x
+ cmp $01,y
+ cmp $ffff
+ cmp $ffff,x
+ cmp $ffff,y
+ cmp ($01,x)
+ cmp ($01),y
+ cpx #0
+ cpx $01
+ cpx $ffff
+ cpy #0
+ cpy $01
+ cpy $ffff
+ dec $01
+ dec $01,x
+ dec $ffff
+ dec $ffff,x
+ dex
+ dey
+ eor #0
+ eor $01
+ eor $01,x
+ eor $01,y
+ eor $ffff
+ eor $ffff,x
+ eor $ffff,y
+ eor ($01,x)
+ eor ($01),y
+ inc $01
+ inc $01,x
+ inc $ffff
+ inc $ffff,x
+ inx
+ iny
+ jmp $01
+ jmp $ffff
+ jmp ($ffff)
+ jsr $01
+ jsr $ffff
+ lda #0
+ lda $01
+ lda $01,x
+ lda $01,y
+ lda $ffff
+ lda $ffff,x
+ lda $ffff,y
+ lda ($01,x)
+ lda ($01),y
+ ldx #0
+ ldx $01
+ ldx $01,y
+ ldx $ffff
+ ldx $ffff,y
+ ldy #0
+ ldy $01
+ ldy $01,x
+ ldy $ffff
+ ldy $ffff,x
+ lsr
+ lsr $01
+ lsr $01,x
+ lsr $ffff
+ lsr $ffff,x
+ nop
+ ora #0
+ ora $01
+ ora $01,x
+ ora $01,y
+ ora $ffff
+ ora $ffff,x
+ ora $ffff,y
+ ora ($01,x)
+ ora ($01),y
+ pha
+ php
+ pla
+ plp
+ rol
+ rol $01
+ rol $01,x
+ rol $ffff
+ rol $ffff,x
+ ror
+ ror $01
+ ror $01,x
+ ror $ffff
+ ror $ffff,x
+ rti
+ rts
+ sbc #0
+ sbc $01
+ sbc $01,x
+ sbc $01,y
+ sbc $ffff
+ sbc $ffff,x
+ sbc $ffff,y
+ sbc ($01,x)
+ sbc ($01),y
+ sec
+ sed
+ sei
+ sta $01
+ sta $01,x
+ sta $01,y
+ sta $ffff
+ sta $ffff,x
+ sta $ffff,y
+ sta ($01,x)
+ sta ($01),y
+ stx $01
+ stx $01,y
+ stx $ffff
+ sty $01
+ sty $01,x
+ sty $ffff
+ tax
+ tay
+ tsx
+ txa
+ txs
+ tya
+
+ // 65c02 specific
+ adc ($01)
+ and ($01)
+ cmp ($01)
+ eor ($01)
+ lda ($01)
+ ora ($01)
+ sbc ($01)
+ sta ($01)
+ bit #0
+ bit $01,x
+ bit $0302,x
+ dec
+ inc
+ jmp ($0302,x)
+ bra *
+ phx
+ phy
+ plx
+ ply
+ stz $01
+ stz $01,x
+ stz $0302
+ stz $0302,x
+ trb $01
+ trb $0302
+ tsb $01
+ tsb $0302
+ bbr 0,$01,*
+ bbr 1,$01,*
+ bbr 2,$01,*
+ bbr 3,$01,*
+ bbr 4,$01,*
+ bbr 5,$01,*
+ bbr 6,$01,*
+ bbr 7,$01,*
+ bbs 0,$01,*
+ bbs 1,$01,*
+ bbs 2,$01,*
+ bbs 3,$01,*
+ bbs 4,$01,*
+ bbs 5,$01,*
+ bbs 6,$01,*
+ bbs 7,$01,*
+ rmb 0,$01
+ rmb 1,$01
+ rmb 2,$01
+ rmb 3,$01
+ rmb 4,$01
+ rmb 5,$01
+ rmb 6,$01
+ rmb 7,$01
+ smb 0,$01
+ smb 1,$01
+ smb 2,$01
+ smb 3,$01
+ smb 4,$01
+ smb 5,$01
+ smb 6,$01
+ smb 7,$01
+ stp
+ wai
+}
R jasm/unit_tests/test_bank_mode_truncates_6502_address_instructions.asm => +0 -8
@@ 1,8 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla -bm]
-
-section code, "main", $10203
-{
-.start:
- lda .start
- rts
-}
A => jasm/unit_tests/test_bank_mode_truncates_address_instructions_6502.asm +8 -0
@@ 0,0 1,8 @@
+// assembler command line arguments: 6502 [-v0 -hla -bm]
+
+section code, "main", $10203
+{
+.start:
+ lda .start
+ rts
+}
A => jasm/unit_tests/test_bank_mode_truncates_address_instructions_65c02.asm +8 -0
@@ 0,0 1,8 @@
+// assembler command line arguments: 65c02 [-v0 -hla -bm]
+
+section code, "main", $10203
+{
+.start:
+ lda .start
+ rts
+}
A => jasm/unit_tests/test_bank_mode_truncates_address_instructions_z80.asm +13 -0
@@ 0,0 1,13 @@
+// assembler command line arguments: z80 [-v0 -bm]
+
+section code, "main", $10203
+{
+.start:
+ ld hl, .start
+ ld hl, (.start)
+ ld (.start), hl
+ jp .start
+ jp z, .start
+ call .start
+ call z, .start
+}
R jasm/unit_tests/test_bank_mode_truncates_z80_address_instructions.asm => +0 -13
@@ 1,13 0,0 @@
-// assembler command line arguments: z80 [-v0 -bm]
-
-section code, "main", $10203
-{
-.start:
- ld hl, .start
- ld hl, (.start)
- ld (.start), hl
- jp .start
- jp z, .start
- call .start
- call z, .start
-}
R jasm/unit_tests/test_expected_x_in_indirect_addressing_mode.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000 {
- lda (55,q
-}
R jasm/unit_tests/test_expected_x_or_y_in_absolute_addressing_mode1.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000 {
- lda (55)+1,=
-}
R jasm/unit_tests/test_expected_x_or_y_in_absolute_addressing_mode2.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000 {
- lda 55,p
-}
No newline at end of file
R jasm/unit_tests/test_expected_y_in_indirect_addressing_mode.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000 {
- lda (55),1
-}
R jasm/unit_tests/test_generate_data_in_instruction_1.asm => +0 -11
@@ 1,11 0,0 @@
-// assembler command line arguments: 6502 [-v0]
-
-section code, "main", $8000
-{
- macro generate()
- {
- nop
- return 0
- }
- lda #generate()
-}
A => jasm/unit_tests/test_generate_data_in_instruction_1_6502.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 6502 [-v0]
+
+section code, "main", $8000
+{
+ macro generate()
+ {
+ nop
+ return 0
+ }
+ lda #generate()
+}
A => jasm/unit_tests/test_generate_data_in_instruction_1_65c02.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000
+{
+ macro generate()
+ {
+ nop
+ return 0
+ }
+ lda #generate()
+}
R jasm/unit_tests/test_generate_data_in_instruction_2.asm => +0 -11
@@ 1,11 0,0 @@
-// assembler command line arguments: z80 [-v0]
-
-section code, "main", $8000
-{
- macro generate()
- {
- nop
- return 0
- }
- ld a,generate()
-}
A => jasm/unit_tests/test_generate_data_in_instruction_2_z80.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: z80 [-v0]
+
+section code, "main", $8000
+{
+ macro generate()
+ {
+ nop
+ return 0
+ }
+ ld a,generate()
+}
R jasm/unit_tests/test_instruction_data_global_label.asm => +0 -8
@@ 1,8 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000
-{
- lda bulle:#0
- ldx bulle
- rts
-}
A => jasm/unit_tests/test_instruction_data_global_label_6502.asm +8 -0
@@ 0,0 1,8 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000
+{
+ lda bulle:#0
+ ldx bulle
+ rts
+}
A => jasm/unit_tests/test_instruction_data_global_label_65c02.asm +8 -0
@@ 0,0 1,8 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000
+{
+ lda bulle:#0
+ ldx bulle
+ rts
+}
R jasm/unit_tests/test_instruction_data_label_cant_have_implied_addressing_mode.asm => +0 -7
@@ 1,7 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000
-{
- nop bulle:
- rts
-}
A => jasm/unit_tests/test_instruction_data_label_cant_have_implied_addressing_mode_6502.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000
+{
+ nop bulle:
+ rts
+}
A => jasm/unit_tests/test_instruction_data_label_cant_have_implied_addressing_mode_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000
+{
+ nop bulle:
+ rts
+}
R jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type1.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- adc label:a, a
-}
R jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type2.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- adc a, label:a
-}
A => jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type_1_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ adc label:a, a
+}
A => jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type_2_z80.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ adc a, label:a
+}
A => jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type_3_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000 {
+ bbr .lbl:0, 0, *
+}
A => jasm/unit_tests/test_instruction_data_label_has_lo_hi_properties_65c02.asm +8 -0
@@ 0,0 1,8 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000
+{
+ lda .lbl.lo
+ lda .lbl.hi
+ jmp .lbl:*
+}
R jasm/unit_tests/test_instruction_data_label_offsets.asm => +0 -706
@@ 1,706 0,0 @@
-// assembler command line arguments: z80 [-v0]
-
-const dd = 1
-const n = 2
-const nn = $1234
-
-section code, "main", $8000 {
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- adc a, .lbl:(ix+dd) // [dd8e d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- adc a, .lbl:(iy+dd) // [fd8e d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- adc a, .lbl:n // [ce n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- add a, .lbl:(ix+dd) // [dd86 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- add a, .lbl:(iy+dd) // [fd86 d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- add a, .lbl:n // [c6 n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- and .lbl:(ix+dd) // [dda6 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- and .lbl:(iy+dd) // [fda6 d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- and .lbl:n // [e6 n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 0, .lbl:(ix+dd) // [ddcb d 46]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 0, .lbl:(iy+dd) // [fdcb d 46]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 1, .lbl:(ix+dd) // [ddcb d 4e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 1, .lbl:(iy+dd) // [fdcb d 4e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 2, .lbl:(ix+dd) // [ddcb d 56]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 2, .lbl:(iy+dd) // [fdcb d 56]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 3, .lbl:(ix+dd) // [ddcb d 5e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 3, .lbl:(iy+dd) // [fdcb d 5e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 4, .lbl:(ix+dd) // [ddcb d 66]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 4, .lbl:(iy+dd) // [fdcb d 66]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 5, .lbl:(ix+dd) // [ddcb d 6e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 5, .lbl:(iy+dd) // [fdcb d 6e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 6, .lbl:(ix+dd) // [ddcb d 76]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 6, .lbl:(iy+dd) // [fdcb d 76]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 7, .lbl:(ix+dd) // [ddcb d 7e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- bit 7, .lbl:(iy+dd) // [fdcb d 7e]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- call .lbl:nn // [cd n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- call c, .lbl:nn // [dc n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- call m, .lbl:nn // [fc n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- call nc, .lbl:nn // [d4 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- call nz, .lbl:nn // [c4 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- call p, .lbl:nn // [f4 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- call pe, .lbl:nn // [ec n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- call po, .lbl:nn // [e4 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- call z, .lbl:nn // [cc n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- cp .lbl:(ix+dd) // [ddbe d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- cp .lbl:(iy+dd) // [fdbe d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- cp .lbl:n // [fe n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- dec .lbl:(ix+dd) // [dd35 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- dec .lbl:(iy+dd) // [fd35 d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- djnz .lbl:* // [10 e]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- in a, .lbl:(n) // [db n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- inc .lbl:(ix+dd) // [dd34 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- inc .lbl:(iy+dd) // [fd34 d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jp .lbl:nn // [c3 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jp c, .lbl:nn // [da n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jp m, .lbl:nn // [fa n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jp nc, .lbl:nn // [d2 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jp nz, .lbl:nn // [c2 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jp p, .lbl:nn // [f2 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jp pe, .lbl:nn // [ea n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jp po, .lbl:nn // [e2 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jp z, .lbl:nn // [ca n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jr .lbl:* // [18 e]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jr c, .lbl:* // [38 e]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jr nc, .lbl:* // [30 e]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jr nz, .lbl:* // [20 e]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- jr z, .lbl:* // [28 e]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld (hl), .lbl:n // [36 n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(ix+dd), a // [dd77 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(ix+dd), b // [dd70 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(ix+dd), c // [dd71 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(ix+dd), d // [dd72 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(ix+dd), e // [dd73 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(ix+dd), h // [dd74 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(ix+dd), l // [dd75 d]
- }
- {
- static_assert(.lbl1 == * + 2, "wrong instruction data offset")
- static_assert(.lbl2 == * + 3, "wrong instruction data offset")
- ld .lbl1:(ix+dd), .lbl2:n // [dd36 d n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(iy+dd), a // [fd77 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(iy+dd), b // [fd70 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(iy+dd), c // [fd71 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(iy+dd), d // [fd72 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(iy+dd), e // [fd73 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(iy+dd), h // [fd74 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(iy+dd), l // [fd75 d]
- }
- {
- static_assert(.lbl1 == * + 2, "wrong instruction data offset")
- static_assert(.lbl2 == * + 3, "wrong instruction data offset")
- ld .lbl1:(iy+dd), .lbl2:n // [fd36 d n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld .lbl:(nn), a // [32 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(nn), bc // [ed43 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(nn), de // [ed53 n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld .lbl:(nn), hl // [22 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(nn), ix // [dd22 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(nn), iy // [fd22 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld .lbl:(nn), sp // [ed73 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld a, .lbl:(ix+dd) // [dd7e d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld a, .lbl:(iy+dd) // [fd7e d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld a, .lbl:(nn) // [3a n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld a, .lbl:n // [3e n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld b, .lbl:(ix+dd) // [dd46 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld b, .lbl:(iy+dd) // [fd46 d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld b, .lbl:n // [06 n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld bc, .lbl:(nn) // [ed4b n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld bc, .lbl:nn // [01 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld c, .lbl:(ix+dd) // [dd4e d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld c, .lbl:(iy+dd) // [fd4e d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld c, .lbl:n // [0e n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld d, .lbl:(ix+dd) // [dd56 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld d, .lbl:(iy+dd) // [fd56 d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld d, .lbl:n // [16 n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld de, .lbl:(nn) // [ed5b n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld de, .lbl:nn // [11 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld e, .lbl:(ix+dd) // [dd5e d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld e, .lbl:(iy+dd) // [fd5e d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld e, .lbl:n // [1e n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld h, .lbl:(ix+dd) // [dd66 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld h, .lbl:(iy+dd) // [fd66 d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld h, .lbl:n // [26 n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld hl, .lbl:(nn) // [2a n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld hl, .lbl:nn // [21 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld ix, .lbl:(nn) // [dd2a n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld ix, .lbl:nn // [dd21 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld iy, .lbl:(nn) // [fd2a n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld iy, .lbl:nn // [fd21 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld l, .lbl:(ix+dd) // [dd6e d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld l, .lbl:(iy+dd) // [fd6e d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld l, .lbl:n // [2e n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- ld sp, .lbl:(nn) // [ed7b n n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- ld sp, .lbl:nn // [31 n n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- or .lbl:(ix+dd) // [ddb6 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- or .lbl:(iy+dd) // [fdb6 d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- or .lbl:n // [f6 n]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- out .lbl:(n), a // [d3 n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 0, .lbl:(ix+dd) // [ddcb d 86]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 0, .lbl:(iy+dd) // [fdcb d 86]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 1, .lbl:(ix+dd) // [ddcb d 8e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 1, .lbl:(iy+dd) // [fdcb d 8e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 2, .lbl:(ix+dd) // [ddcb d 96]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 2, .lbl:(iy+dd) // [fdcb d 96]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 3, .lbl:(ix+dd) // [ddcb d 9e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 3, .lbl:(iy+dd) // [fdcb d 9e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 4, .lbl:(ix+dd) // [ddcb d a6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 4, .lbl:(iy+dd) // [fdcb d a6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 5, .lbl:(ix+dd) // [ddcb d ae]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 5, .lbl:(iy+dd) // [fdcb d ae]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 6, .lbl:(ix+dd) // [ddcb d b6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 6, .lbl:(iy+dd) // [fdcb d b6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 7, .lbl:(ix+dd) // [ddcb d be]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- res 7, .lbl:(iy+dd) // [fdcb d be]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- rl .lbl:(ix+dd) // [ddcb d 16]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- rl .lbl:(iy+dd) // [fdcb d 16]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- rlc .lbl:(ix+dd) // [ddcb d 06]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- rlc .lbl:(iy+dd) // [fdcb d 06]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- rr .lbl:(ix+dd) // [ddcb d 1e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- rr .lbl:(iy+dd) // [fdcb d 1e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- rrc .lbl:(ix+dd) // [ddcb d 0e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- rrc .lbl:(iy+dd) // [fdcb d 0e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- sbc a, .lbl:(ix+dd) // [dd9e d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- sbc a, .lbl:(iy+dd) // [fd9e d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- sbc a, .lbl:n // [de n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 0, .lbl:(ix+dd) // [ddcb d c6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 0, .lbl:(iy+dd) // [fdcb d c6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 1, .lbl:(ix+dd) // [ddcb d ce]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 1, .lbl:(iy+dd) // [fdcb d ce]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 2, .lbl:(ix+dd) // [ddcb d d6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 2, .lbl:(iy+dd) // [fdcb d d6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 3, .lbl:(ix+dd) // [ddcb d de]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 3, .lbl:(iy+dd) // [fdcb d de]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 4, .lbl:(ix+dd) // [ddcb d e6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 4, .lbl:(iy+dd) // [fdcb d e6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 5, .lbl:(ix+dd) // [ddcb d ee]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 5, .lbl:(iy+dd) // [fdcb d ee]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 6, .lbl:(ix+dd) // [ddcb d f6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 6, .lbl:(iy+dd) // [fdcb d f6]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 7, .lbl:(ix+dd) // [ddcb d fe]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- set 7, .lbl:(iy+dd) // [fdcb d fe]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- sla .lbl:(ix+dd) // [ddcb d 26]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- sla .lbl:(iy+dd) // [fdcb d 26]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- sra .lbl:(ix+dd) // [ddcb d 2e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- sra .lbl:(iy+dd) // [fdcb d 2e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- srl .lbl:(ix+dd) // [ddcb d 3e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- srl .lbl:(iy+dd) // [fdcb d 3e]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- sub .lbl:(ix+dd) // [dd96 d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- sub .lbl:(iy+dd) // [fd96 d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- sub .lbl:n // [d6 n]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- xor .lbl:(ix+dd) // [ddae d]
- }
- {
- static_assert(.lbl == * + 2, "wrong instruction data offset")
- xor .lbl:(iy+dd) // [fdae d]
- }
- {
- static_assert(.lbl == * + 1, "wrong instruction data offset")
- xor .lbl:n // [ee n]
- }
-}
A => jasm/unit_tests/test_instruction_data_label_offsets_65c02.asm +68 -0
@@ 0,0 1,68 @@
+// assembler command line arguments: 65c02 [-v0]
+
+const n = 2
+const nn = $1234
+
+section code, "main", $8000 {
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ lda .lbl:#0
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ lda .lbl:n
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ lda .lbl:n,x
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ldx .lbl:n,y
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ lda .lbl:nn
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ lda .lbl:nn,x
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ lda .lbl:nn,y
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ bcc .lbl:*
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ lda .lbl:(n,x)
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ lda .lbl:(n),y
+ }
+
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ lda .lbl:(n)
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jmp .lbl:(nn,x)
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ bbr 0,.lbl:n,*
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bbr 0,n,.lbl:*
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ rmb 0,.lbl:n
+ }
+}
A => jasm/unit_tests/test_instruction_data_label_offsets_z80.asm +706 -0
@@ 0,0 1,706 @@
+// assembler command line arguments: z80 [-v0]
+
+const dd = 1
+const n = 2
+const nn = $1234
+
+section code, "main", $8000 {
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ adc a, .lbl:(ix+dd) // [dd8e d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ adc a, .lbl:(iy+dd) // [fd8e d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ adc a, .lbl:n // [ce n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ add a, .lbl:(ix+dd) // [dd86 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ add a, .lbl:(iy+dd) // [fd86 d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ add a, .lbl:n // [c6 n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ and .lbl:(ix+dd) // [dda6 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ and .lbl:(iy+dd) // [fda6 d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ and .lbl:n // [e6 n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 0, .lbl:(ix+dd) // [ddcb d 46]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 0, .lbl:(iy+dd) // [fdcb d 46]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 1, .lbl:(ix+dd) // [ddcb d 4e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 1, .lbl:(iy+dd) // [fdcb d 4e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 2, .lbl:(ix+dd) // [ddcb d 56]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 2, .lbl:(iy+dd) // [fdcb d 56]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 3, .lbl:(ix+dd) // [ddcb d 5e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 3, .lbl:(iy+dd) // [fdcb d 5e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 4, .lbl:(ix+dd) // [ddcb d 66]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 4, .lbl:(iy+dd) // [fdcb d 66]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 5, .lbl:(ix+dd) // [ddcb d 6e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 5, .lbl:(iy+dd) // [fdcb d 6e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 6, .lbl:(ix+dd) // [ddcb d 76]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 6, .lbl:(iy+dd) // [fdcb d 76]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 7, .lbl:(ix+dd) // [ddcb d 7e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ bit 7, .lbl:(iy+dd) // [fdcb d 7e]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ call .lbl:nn // [cd n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ call c, .lbl:nn // [dc n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ call m, .lbl:nn // [fc n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ call nc, .lbl:nn // [d4 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ call nz, .lbl:nn // [c4 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ call p, .lbl:nn // [f4 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ call pe, .lbl:nn // [ec n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ call po, .lbl:nn // [e4 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ call z, .lbl:nn // [cc n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ cp .lbl:(ix+dd) // [ddbe d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ cp .lbl:(iy+dd) // [fdbe d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ cp .lbl:n // [fe n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ dec .lbl:(ix+dd) // [dd35 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ dec .lbl:(iy+dd) // [fd35 d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ djnz .lbl:* // [10 e]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ in a, .lbl:(n) // [db n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ inc .lbl:(ix+dd) // [dd34 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ inc .lbl:(iy+dd) // [fd34 d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jp .lbl:nn // [c3 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jp c, .lbl:nn // [da n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jp m, .lbl:nn // [fa n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jp nc, .lbl:nn // [d2 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jp nz, .lbl:nn // [c2 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jp p, .lbl:nn // [f2 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jp pe, .lbl:nn // [ea n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jp po, .lbl:nn // [e2 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jp z, .lbl:nn // [ca n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jr .lbl:* // [18 e]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jr c, .lbl:* // [38 e]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jr nc, .lbl:* // [30 e]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jr nz, .lbl:* // [20 e]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ jr z, .lbl:* // [28 e]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld (hl), .lbl:n // [36 n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(ix+dd), a // [dd77 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(ix+dd), b // [dd70 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(ix+dd), c // [dd71 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(ix+dd), d // [dd72 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(ix+dd), e // [dd73 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(ix+dd), h // [dd74 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(ix+dd), l // [dd75 d]
+ }
+ {
+ static_assert(.lbl1 == * + 2, "wrong instruction data offset")
+ static_assert(.lbl2 == * + 3, "wrong instruction data offset")
+ ld .lbl1:(ix+dd), .lbl2:n // [dd36 d n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(iy+dd), a // [fd77 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(iy+dd), b // [fd70 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(iy+dd), c // [fd71 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(iy+dd), d // [fd72 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(iy+dd), e // [fd73 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(iy+dd), h // [fd74 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(iy+dd), l // [fd75 d]
+ }
+ {
+ static_assert(.lbl1 == * + 2, "wrong instruction data offset")
+ static_assert(.lbl2 == * + 3, "wrong instruction data offset")
+ ld .lbl1:(iy+dd), .lbl2:n // [fd36 d n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld .lbl:(nn), a // [32 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(nn), bc // [ed43 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(nn), de // [ed53 n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld .lbl:(nn), hl // [22 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(nn), ix // [dd22 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(nn), iy // [fd22 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld .lbl:(nn), sp // [ed73 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld a, .lbl:(ix+dd) // [dd7e d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld a, .lbl:(iy+dd) // [fd7e d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld a, .lbl:(nn) // [3a n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld a, .lbl:n // [3e n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld b, .lbl:(ix+dd) // [dd46 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld b, .lbl:(iy+dd) // [fd46 d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld b, .lbl:n // [06 n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld bc, .lbl:(nn) // [ed4b n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld bc, .lbl:nn // [01 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld c, .lbl:(ix+dd) // [dd4e d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld c, .lbl:(iy+dd) // [fd4e d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld c, .lbl:n // [0e n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld d, .lbl:(ix+dd) // [dd56 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld d, .lbl:(iy+dd) // [fd56 d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld d, .lbl:n // [16 n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld de, .lbl:(nn) // [ed5b n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld de, .lbl:nn // [11 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld e, .lbl:(ix+dd) // [dd5e d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld e, .lbl:(iy+dd) // [fd5e d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld e, .lbl:n // [1e n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld h, .lbl:(ix+dd) // [dd66 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld h, .lbl:(iy+dd) // [fd66 d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld h, .lbl:n // [26 n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld hl, .lbl:(nn) // [2a n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld hl, .lbl:nn // [21 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld ix, .lbl:(nn) // [dd2a n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld ix, .lbl:nn // [dd21 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld iy, .lbl:(nn) // [fd2a n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld iy, .lbl:nn // [fd21 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld l, .lbl:(ix+dd) // [dd6e d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld l, .lbl:(iy+dd) // [fd6e d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld l, .lbl:n // [2e n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ ld sp, .lbl:(nn) // [ed7b n n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ ld sp, .lbl:nn // [31 n n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ or .lbl:(ix+dd) // [ddb6 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ or .lbl:(iy+dd) // [fdb6 d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ or .lbl:n // [f6 n]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ out .lbl:(n), a // [d3 n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 0, .lbl:(ix+dd) // [ddcb d 86]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 0, .lbl:(iy+dd) // [fdcb d 86]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 1, .lbl:(ix+dd) // [ddcb d 8e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 1, .lbl:(iy+dd) // [fdcb d 8e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 2, .lbl:(ix+dd) // [ddcb d 96]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 2, .lbl:(iy+dd) // [fdcb d 96]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 3, .lbl:(ix+dd) // [ddcb d 9e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 3, .lbl:(iy+dd) // [fdcb d 9e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 4, .lbl:(ix+dd) // [ddcb d a6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 4, .lbl:(iy+dd) // [fdcb d a6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 5, .lbl:(ix+dd) // [ddcb d ae]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 5, .lbl:(iy+dd) // [fdcb d ae]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 6, .lbl:(ix+dd) // [ddcb d b6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 6, .lbl:(iy+dd) // [fdcb d b6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 7, .lbl:(ix+dd) // [ddcb d be]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ res 7, .lbl:(iy+dd) // [fdcb d be]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ rl .lbl:(ix+dd) // [ddcb d 16]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ rl .lbl:(iy+dd) // [fdcb d 16]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ rlc .lbl:(ix+dd) // [ddcb d 06]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ rlc .lbl:(iy+dd) // [fdcb d 06]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ rr .lbl:(ix+dd) // [ddcb d 1e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ rr .lbl:(iy+dd) // [fdcb d 1e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ rrc .lbl:(ix+dd) // [ddcb d 0e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ rrc .lbl:(iy+dd) // [fdcb d 0e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ sbc a, .lbl:(ix+dd) // [dd9e d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ sbc a, .lbl:(iy+dd) // [fd9e d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ sbc a, .lbl:n // [de n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 0, .lbl:(ix+dd) // [ddcb d c6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 0, .lbl:(iy+dd) // [fdcb d c6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 1, .lbl:(ix+dd) // [ddcb d ce]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 1, .lbl:(iy+dd) // [fdcb d ce]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 2, .lbl:(ix+dd) // [ddcb d d6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 2, .lbl:(iy+dd) // [fdcb d d6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 3, .lbl:(ix+dd) // [ddcb d de]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 3, .lbl:(iy+dd) // [fdcb d de]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 4, .lbl:(ix+dd) // [ddcb d e6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 4, .lbl:(iy+dd) // [fdcb d e6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 5, .lbl:(ix+dd) // [ddcb d ee]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 5, .lbl:(iy+dd) // [fdcb d ee]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 6, .lbl:(ix+dd) // [ddcb d f6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 6, .lbl:(iy+dd) // [fdcb d f6]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 7, .lbl:(ix+dd) // [ddcb d fe]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ set 7, .lbl:(iy+dd) // [fdcb d fe]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ sla .lbl:(ix+dd) // [ddcb d 26]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ sla .lbl:(iy+dd) // [fdcb d 26]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ sra .lbl:(ix+dd) // [ddcb d 2e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ sra .lbl:(iy+dd) // [fdcb d 2e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ srl .lbl:(ix+dd) // [ddcb d 3e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ srl .lbl:(iy+dd) // [fdcb d 3e]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ sub .lbl:(ix+dd) // [dd96 d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ sub .lbl:(iy+dd) // [fd96 d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ sub .lbl:n // [d6 n]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ xor .lbl:(ix+dd) // [ddae d]
+ }
+ {
+ static_assert(.lbl == * + 2, "wrong instruction data offset")
+ xor .lbl:(iy+dd) // [fdae d]
+ }
+ {
+ static_assert(.lbl == * + 1, "wrong instruction data offset")
+ xor .lbl:n // [ee n]
+ }
+}
A => jasm/unit_tests/test_instruction_data_label_sizes_65c02.asm +68 -0
@@ 0,0 1,68 @@
+// assembler command line arguments: 65c02 [-v0]
+
+const n = 2
+const nn = $1234
+
+section code, "main", $8000 {
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ lda .lbl:#0
+ }
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ lda .lbl:n
+ }
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ lda .lbl:n,x
+ }
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ ldx .lbl:n,y
+ }
+ {
+ static_assert(sizeof(.lbl) == 2, "wrong instruction data size")
+ lda .lbl:nn
+ }
+ {
+ static_assert(sizeof(.lbl) == 2, "wrong instruction data size")
+ lda .lbl:nn,x
+ }
+ {
+ static_assert(sizeof(.lbl) == 2, "wrong instruction data size")
+ lda .lbl:nn,y
+ }
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ bcc .lbl:*
+ }
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ lda .lbl:(n,x)
+ }
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ lda .lbl:(n),y
+ }
+
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ lda .lbl:(n)
+ }
+ {
+ static_assert(sizeof(.lbl) == 2, "wrong instruction data size")
+ jmp .lbl:(nn,x)
+ }
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ bbr 0,.lbl:n,*
+ }
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ bbr 0,n,.lbl:*
+ }
+ {
+ static_assert(sizeof(.lbl) == 1, "wrong instruction data size")
+ rmb 0,.lbl:n
+ }
+}
A => jasm/unit_tests/test_instruction_data_label_with_export_65c02.asm +16 -0
@@ 0,0 1,16 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000
+{
+ lda testmod::addr
+ rts
+}
+
+module testmod
+{
+ section part, "main"
+ {
+ export lda addr:$ffff
+ rts
+ }
+}
A => jasm/unit_tests/test_instruction_data_label_with_local_export_65c02.asm +14 -0
@@ 0,0 1,14 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000
+{
+}
+
+module testmod
+{
+ section part, "main"
+ {
+ export lda .addr:$ffff
+ rts
+ }
+}
R jasm/unit_tests/test_instruction_data_local_label.asm => +0 -8
@@ 1,8 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section code, "main", $8000
-{
- lda .bulle: $ffff
- ldx .bulle
- rts
-}
A => jasm/unit_tests/test_instruction_data_local_label_6502.asm +8 -0
@@ 0,0 1,8 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section code, "main", $8000
+{
+ lda .bulle: $ffff
+ ldx .bulle
+ rts
+}
A => jasm/unit_tests/test_instruction_data_local_label_65c02.asm +8 -0
@@ 0,0 1,8 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section code, "main", $8000
+{
+ lda .bulle: $ffff
+ ldx .bulle
+ rts
+}
R jasm/unit_tests/test_instruction_ends_at_newline.asm => +0 -13
@@ 1,13 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-var a = 1
-
-section code, "main", $8000 {
- lda #a
- +a + sin(0) // function looks like side effect so it tricks the assembler to not trigger the error "statement must have side effect"
- lda a
- +a + sin(0)
- rol
- +a + sin(0)
- rts
-}
R jasm/unit_tests/test_instruction_ends_at_newline2.asm => +0 -9
@@ 1,9 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-var a = 1
-
-section code, "main", $8000 {
- lda #
- +a
- rts
-}
A => jasm/unit_tests/test_instruction_ends_at_newline_1_6502.asm +13 -0
@@ 0,0 1,13 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+var a = 1
+
+section code, "main", $8000 {
+ lda #a
+ +a + sin(0) // function looks like side effect so it tricks the assembler to not trigger the error "statement must have side effect"
+ lda a
+ +a + sin(0)
+ rol
+ +a + sin(0)
+ rts
+}
A => jasm/unit_tests/test_instruction_ends_at_newline_1_65c02.asm +13 -0
@@ 0,0 1,13 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+var a = 1
+
+section code, "main", $8000 {
+ lda #a
+ +a + sin(0) // function looks like side effect so it tricks the assembler to not trigger the error "statement must have side effect"
+ lda a
+ +a + sin(0)
+ rol
+ +a + sin(0)
+ rts
+}
A => jasm/unit_tests/test_instruction_ends_at_newline_2_6502.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+var a = 1
+
+section code, "main", $8000 {
+ lda #
+ +a
+ rts
+}
A => jasm/unit_tests/test_instruction_ends_at_newline_2_65c02.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+var a = 1
+
+section code, "main", $8000 {
+ lda #
+ +a
+ rts
+}
A => jasm/unit_tests/test_instruction_names_can_be_used_in_local_variables_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $1000
+{
+ const .inc = 0
+ define byte = .inc
+}
R jasm/unit_tests/test_instructions_must_be_in_code_sections1.asm => +0 -3
@@ 1,3 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-rol
R jasm/unit_tests/test_instructions_must_be_in_code_sections2.asm => +0 -5
@@ 1,5 0,0 @@
-// assembler command line arguments: 6502 [-v0 -hla]
-
-section bss, "data", $8000 {
- rol
-}
No newline at end of file
A => jasm/unit_tests/test_instructions_must_be_in_code_sections_1_6502.asm +3 -0
@@ 0,0 1,3 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+rol
A => jasm/unit_tests/test_instructions_must_be_in_code_sections_1_65c02.asm +3 -0
@@ 0,0 1,3 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+rol
A => jasm/unit_tests/test_instructions_must_be_in_code_sections_2_6502.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 6502 [-v0 -hla]
+
+section bss, "data", $8000 {
+ rol
+}
No newline at end of file
A => jasm/unit_tests/test_instructions_must_be_in_code_sections_2_65c02.asm +5 -0
@@ 0,0 1,5 @@
+// assembler command line arguments: 65c02 [-v0 -hla]
+
+section bss, "data", $8000 {
+ rol
+}
No newline at end of file
R jasm/unit_tests/test_keyword_cannot_be_used_for_indirect_addressing.asm => +0 -6
@@ 1,6 0,0 @@
-// assembler command line arguments: z80 [-v0 -hla]
-
-section code, "main", $8000 {
- adc a, (a)
- rts
-}
A => jasm/unit_tests/test_keyword_cannot_be_used_for_indirect_addressing_z80.asm +6 -0
@@ 0,0 1,6 @@
+// assembler command line arguments: z80 [-v0 -hla]
+
+section code, "main", $8000 {
+ adc a, (a)
+ rts
+}
A => jasm/unit_tests/test_pseudo_instructions_for_branching_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0 -pi]
+
+section code, "main", $8000
+{
+ bhs *
+ blt *
+}
A => jasm/unit_tests/test_pseudo_instructions_for_incrementing_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0 -pi]
+
+section code, "main", $8000
+{
+ dea
+ ina
+}
A => jasm/unit_tests/test_pseudo_instructions_in_standard_mode_65c02.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000
+{
+ bhs *
+ blt *
+ dea
+ ina
+}
A => jasm/unit_tests/test_pseudo_instructions_use_names_in_standard_mode_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000
+{
+bhs:
+ rts
+}
A => jasm/unit_tests/test_register_names_can_be_used_in_local_names_65c02.asm +10 -0
@@ 0,0 1,10 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $1000
+{
+ const .x = 0
+ const .y = 1
+
+ define byte = .x
+ define byte = .y
+}
A => jasm/unit_tests/test_register_names_cant_be_used_as_global_variables_65c02.asm +7 -0
@@ 0,0 1,7 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $1000
+{
+ const x = 0
+ define byte = x
+}
A => jasm/unit_tests/test_subroutine_call_65c02.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000, $9000
+{
+ test()
+
+ subroutine test
+ {
+ rts
+ }
+}
A => jasm/unit_tests/test_subroutine_call_must_be_in_code_section_65c02.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 65c02 [-v0]
+
+test()
+
+section code, "main", $8000, $9000
+{
+ subroutine test
+ {
+ rts
+ }
+}
A => jasm/unit_tests/test_subroutine_call_negative_argument_65c02.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", -4, $9000
+{
+ test()
+
+ subroutine test
+ {
+ rts
+ }
+}
A => jasm/unit_tests/test_subroutine_call_recursive_data_generation_65c02.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000, $9000
+{
+ lda #test()
+
+ subroutine test
+ {
+ rts
+ }
+}
A => jasm/unit_tests/test_subroutine_call_too_large_argument_65c02.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $fffd
+{
+ test()
+
+ subroutine test
+ {
+ rts
+ }
+}
A => jasm/unit_tests/test_subroutine_call_with_arguments_65c02.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 65c02 [-v0]
+
+section code, "main", $8000
+{
+ test(1)
+
+ subroutine test
+ {
+ rts
+ }
+}
R jasm/unit_tests/test_subroutine_falls_through_1.asm => +0 -10
@@ 1,10 0,0 @@
-// assembler command line arguments: 6502 [-v2 -hla]
-
-section code, "main", $8000 {
-
- subroutine test
- {
- }
-
- rts
-}
A => jasm/unit_tests/test_subroutine_falls_through_1_6502.asm +10 -0
@@ 0,0 1,10 @@
+// assembler command line arguments: 6502 [-v2 -hla]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ }
+
+ rts
+}
A => jasm/unit_tests/test_subroutine_falls_through_1_65c02.asm +10 -0
@@ 0,0 1,10 @@
+// assembler command line arguments: 65c02 [-v2 -hla]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ }
+
+ rts
+}
A => jasm/unit_tests/test_subroutine_falls_through_1_z80.asm +10 -0
@@ 0,0 1,10 @@
+// assembler command line arguments: z80 [-v2]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+
+ }
+ ret
+}
R jasm/unit_tests/test_subroutine_falls_through_2.asm => +0 -11
@@ 1,11 0,0 @@
-// assembler command line arguments: 6502 [-v2 -hla]
-
-section code, "main", $8000 {
-
- subroutine test
- {
- nop
- }
-
- rts
-}
A => jasm/unit_tests/test_subroutine_falls_through_2_6502.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 6502 [-v2 -hla]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ nop
+ }
+
+ rts
+}
A => jasm/unit_tests/test_subroutine_falls_through_2_65c02.asm +11 -0
@@ 0,0 1,11 @@
+// assembler command line arguments: 65c02 [-v2 -hla]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ nop
+ }
+
+ rts
+}
A => jasm/unit_tests/test_subroutine_falls_through_2_z80.asm +10 -0
@@ 0,0 1,10 @@
+// assembler command line arguments: z80 [-v2]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ nop
+ }
+ ret
+}
R jasm/unit_tests/test_subroutine_falls_through_3.asm => +0 -9
@@ 1,9 0,0 @@
-// assembler command line arguments: 6502 [-v2 -hla]
-
-section code, "main", $8000 {
-
- subroutine test
- {
- rts
- }
-}
A => jasm/unit_tests/test_subroutine_falls_through_3_6502.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: 6502 [-v2 -hla]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ rts
+ }
+}
A => jasm/unit_tests/test_subroutine_falls_through_3_65c02.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: 65c02 [-v2 -hla]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ rts
+ }
+}
A => jasm/unit_tests/test_subroutine_falls_through_3_z80.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: z80 [-v2]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ ret
+ }
+}
R jasm/unit_tests/test_subroutine_falls_through_4.asm => +0 -9
@@ 1,9 0,0 @@
-// assembler command line arguments: 6502 [-v2 -hla]
-
-section code, "main", $8000 {
-
- subroutine test
- {
- jmp test
- }
-}
A => jasm/unit_tests/test_subroutine_falls_through_4_6502.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: 6502 [-v2 -hla]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ jmp test
+ }
+}
A => jasm/unit_tests/test_subroutine_falls_through_4_65c02.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: 65c02 [-v2 -hla]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ jmp test
+ }
+}
A => jasm/unit_tests/test_subroutine_falls_through_4_z80.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: z80 [-v2]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ jp test
+ }
+}
R jasm/unit_tests/test_subroutine_falls_through_5.asm => +0 -10
@@ 1,10 0,0 @@
-// assembler command line arguments: z80 [-v2]
-
-section code, "main", $8000 {
-
- subroutine test
- {
-
- }
- ret
-}
A => jasm/unit_tests/test_subroutine_falls_through_5_65c02.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: 65c02 [-v2 -hla]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ bra test
+ }
+}
A => jasm/unit_tests/test_subroutine_falls_through_5_z80.asm +9 -0
@@ 0,0 1,9 @@
+// assembler command line arguments: z80 [-v2]
+
+section code, "main", $8000 {
+
+ subroutine test
+ {
+ jr test
+ }
+}
R jasm/unit_tests/test_subroutine_falls_through_6.asm => +0 -10
@@ 1,10 0,0 @@
-// assembler command line arguments: z80 [-v2]
-
-section code, "main", $8000 {
-
- subroutine test
- {
- nop
- }
- ret
-}
R jasm/unit_tests/test_subroutine_falls_through_7.asm => +0 -9
@@ 1,9 0,0 @@
-// assembler command line arguments: z80 [-v2]
-
-section code, "main", $8000 {
-
- subroutine test
- {
- ret
- }
-}
R jasm/unit_tests/test_subroutine_falls_through_8.asm => +0 -9
@@ 1,9 0,0 @@
-// assembler command line arguments: z80 [-v2]
-
-section code, "main", $8000 {
-
- subroutine test
- {
- jp test
- }
-}
R jasm/unit_tests/test_subroutine_falls_through_9.asm => +0 -9
@@ 1,9 0,0 @@
-// assembler command line arguments: z80 [-v2]
-
-section code, "main", $8000 {
-
- subroutine test
- {
- jr test
- }
-}
M jasm/version.h +1 -1
@@ 1,1 1,1 @@
-1,26
+1,27
M jasm/website/site/docs/index.html +38 -0
@@ 34,6 34,7 @@
<li><a href="#processor-support">Processor Support</a>
<ul>
<li><a href="#m6502">6502</a></li>
+<li><a href="#wdc65c02">65c02</a></li>
<li><a href="#z80">Z80</a></li>
</ul></li>
<li><a href="#starter-guide">Starter Guide</a>
@@ 75,6 76,7 @@
<li><a href="#pseudo-instructions">Pseudo Instructions</a>
<ul>
<li><a href="#6502-pseudo-instructions">6502 Pseudo Instructions</a></li>
+<li><a href="#65c02-pseudo-instructions">65c02 Pseudo Instructions</a></li>
<li><a href="#z80-pseudo-instructions">Z80 Pseudo Instructions</a></li>
</ul></li>
<li><a href="#verboseness">Verboseness</a></li>
@@ 163,6 165,24 @@
<pre><code>python3 tools/convert_6502_keyword_case.py <my_source_directory>
</code></pre>
+<div id="wdc65c02"></div>
+
+<h2>65C02</h2>
+
+<p>jAsm supports all regular instructions of the Western Design Center 65C02. Instructions are written in lower case.</p>
+
+<pre><code><span class="instruction">stz</span> <span class="literal">$d020</span>
+<span class="instruction">bra</span> loop
+</code></pre>
+
+<p>The bit operation instructions don't have the bit in the instruction name as some assemblers do. Instead it is a separate argument. To follow convention, there is no '#' before the bit number to indicate immediate mode, even if that would be more consistent.</p>
+
+<pre><code><span class="instruction">bbr</span> <span class="literal">0</span>, zp, label
+<span class="instruction">bbs</span> <span class="literal">1</span>, zp, label
+<span class="instruction">rmb</span> <span class="literal">2</span>, zp
+<span class="instruction">smb</span> <span class="literal">3</span>, zp
+</code></pre>
+
<div id="z80"></div>
<h2>Z80</h2>
@@ 1284,6 1304,24 @@ jasm --define DEFAULT_NAME=bobo input.ja
<p>These are equivalent to <code><span class="instruction">bcs</span></code> and <code><span class="instruction">bcc</span></code>, respectively.</p>
+<div id="65c02-pseudo-instructions"></div>
+
+<h3>65C02 pseudo instructions</h3>
+
+<p>These are the pseudo instructions for 65C02.</p>
+
+<pre><code><span class="instruction">bhs</span> addr <span class="comment">// branch if higher or same</span>
+<span class="instruction">blt</span> addr <span class="comment">// branch if lower</span>
+</code></pre>
+
+<p>These are equivalent to <code><span class="instruction">bcs</span></code> and <code><span class="instruction">bcc</span></code>, respectively.</p>
+
+<pre><code><span class="instruction">dea</span> <span class="comment">// decrement A register</span>
+<span class="instruction">ina</span> <span class="comment">// increment A register</span>
+</code></pre>
+
+<p>These are equivalent to the implied mode <code><span class="instruction">dec</span></code> and <code><span class="instruction">inc</span></code>, respectively.</p>
+
<div id="z80-pseudo-instructions"></div>
<h3>Z80 pseudo instructions</h3>
M jasm/website/site/index.html +10 -2
@@ 4,7 4,7 @@
<title>jAsm</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta name="description" content="This is the official home for the jAsm assembler.">
- <meta name="keywords" content="jAsm,6502,z80,assembler,asm,cross-assembler">
+ <meta name="keywords" content="jAsm,6502,65c02,z80,assembler,asm,cross-assembler">
<meta name="author" content="Jonas Hultén">
<link rel="shortcut icon" href="images/favicon.ico">
@@ 72,7 72,7 @@
<div class="section odd">
<h1>The Assembler</h1>
<p>
- This is the official home for the 6502 and Z80 assembler jAsm. jAsm was written by me, Jonas Hultén, during 7 months in 2015. It is heavily geared towards C64 development, since that's what it's intended to be used for. It currently runs on the 64-bit Linux and Windows platforms but it should be fairly easy to port it to other platforms since it has no dependencies except the standard C++ library.
+ This is the official home for the 6502, 65C02 and Z80 assembler jAsm. jAsm was written by me, Jonas Hultén, during 7 months in 2015. It is heavily geared towards C64 development, since that's what it's intended to be used for. It currently runs on the 64-bit Linux and Windows platforms but it should be fairly easy to port it to other platforms since it has no dependencies except the standard C++ library.
</p>
<h1>The Documentation</h1>
<p>
@@ 99,6 99,14 @@
<h1>Version History</h1>
<ul>
<li>
+ 1.27
+ <ul>
+ <li>Added support for Western Design Center 65C02.</li>
+ <li>Break assembling after 100 passes.</li>
+ <li>Fixed missing hex dump output from align statements.</li>
+ </ul>
+ </li>
+ <li>
1.26
<ul>
<li>Locale support was broken in v1.25. This is now reverted to the C locale in Windows.</li>