322 files changed, 3998 insertions(+), 1362 deletions(-)

M jasm/CMakeLists.txt
M jasm/assemble/assembler_impl/assembler_impl.cpp
M jasm/assemble/assembler_impl/assembler_impl.h
M jasm/assemble/assembler_impl/syntax_impl.cpp
M jasm/docs/jasm.md
M jasm/docs/syntax_highlight.py
M jasm/exceptions/error_codes.h
M jasm/io/hex_source_writer.cpp
M jasm/io/hex_source_writer.h
M jasm/processor/6502/processor_6502.cpp
A => jasm/processor/65c02/instructions_65c02.cpp
A => jasm/processor/65c02/instructions_65c02.h
A => jasm/processor/65c02/processor_65c02.cpp
A => jasm/processor/65c02/processor_65c02.h
A => jasm/processor/65c02/processor_keywords_65c02.cpp
A => jasm/processor/65c02/processor_keywords_65c02.h
M jasm/processor/instructions.h
M jasm/processor/processor.cpp
M jasm/processor/processor.h
M jasm/processor/z80/processor_z80.cpp
M jasm/tokenize/tokenizer.cpp
M jasm/unit_test.py
A => jasm/unit_tests/results/test_addressing_mode_expected_x_in_indirect_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_expected_x_in_indirect_65c02.stdout
A => jasm/unit_tests/results/test_addressing_mode_expected_x_or_y_in_absolute_1_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_expected_x_or_y_in_absolute_2_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_expected_y_in_indirect_6502.stdout
R jasm/unit_tests/results/test_addressing_mode_is_illegal.stdout => 
R jasm/unit_tests/results/test_addressing_mode_is_illegal2.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_is_illegal_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_is_illegal_65c02.stdout
R jasm/unit_tests/results/test_addressing_mode_is_illegal_and_too_many_possibilities.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_is_illegal_and_too_many_possibilities_z80.stdout
A => jasm/unit_tests/results/test_addressing_mode_is_illegal_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_1.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_1_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_2.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_2_z80.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_bit_size_argument_65c02.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_branch_offset_size_argument_1.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_branch_offset_size_argument_1_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_branch_offset_size_argument_2.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_branch_offset_size_argument_2_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_1_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_1_65c02.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_1_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_2.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_2_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_2_65c02.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_2_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_3.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_3_65c02.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_3_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_4.stdout => 
R jasm/unit_tests/results/test_addressing_mode_needs_byte_argument_5.stdout => 
R jasm/unit_tests/results/test_addressing_mode_needs_integer_argument.stdout => 
R jasm/unit_tests/results/test_addressing_mode_needs_integer_argument2.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_1_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_1_65c02.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_1_z80.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_2_65c02.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_3_65c02.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_integer_argument_4_65c02.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_1.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_1_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_2.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_2_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_3.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_offset_size_argument_3_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_positive_argument.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_positive_argument_1_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_positive_argument_1_65c02.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_positive_argument_2_65c02.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_positive_argument_3_65c02.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_1_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_1_65c02.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_2.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_2_6502.stdout
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_2_65c02.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_3.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_3_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_4.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_word_size_argument_4_z80.stdout
R jasm/unit_tests/results/test_addressing_mode_needs_zero_page_size_argument.stdout => 
A => jasm/unit_tests/results/test_addressing_mode_needs_zero_page_size_argument_1_z80.stdout
R jasm/unit_tests/results/test_bank_mode_truncates_6502_address_instructions.bin => 
A => jasm/unit_tests/results/test_bank_mode_truncates_address_instructions_6502.bin
A => jasm/unit_tests/results/test_bank_mode_truncates_address_instructions_65c02.bin
A => jasm/unit_tests/results/test_bank_mode_truncates_address_instructions_z80.bin
R jasm/unit_tests/results/test_bank_mode_truncates_z80_address_instructions.bin => 
R jasm/unit_tests/results/test_expected_x_in_indirect_addressing_mode.stdout => 
R jasm/unit_tests/results/test_expected_x_or_y_in_absolute_addressing_mode1.stdout => 
R jasm/unit_tests/results/test_expected_x_or_y_in_absolute_addressing_mode2.stdout => 
R jasm/unit_tests/results/test_expected_y_in_indirect_addressing_mode.stdout => 
R jasm/unit_tests/results/test_generate_data_in_instruction_1.stdout => 
A => jasm/unit_tests/results/test_generate_data_in_instruction_1_6502.stdout
A => jasm/unit_tests/results/test_generate_data_in_instruction_1_65c02.stdout
R jasm/unit_tests/results/test_generate_data_in_instruction_2.stdout => 
A => jasm/unit_tests/results/test_generate_data_in_instruction_2_z80.stdout
R jasm/unit_tests/results/test_instruction_data_label_cant_have_implied_addressing_mode.stdout => 
A => jasm/unit_tests/results/test_instruction_data_label_cant_have_implied_addressing_mode_6502.stdout
A => jasm/unit_tests/results/test_instruction_data_label_cant_have_implied_addressing_mode_65c02.stdout
R jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type1.stdout => 
R jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type2.stdout => 
A => jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type_1_z80.stdout
A => jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type_2_z80.stdout
A => jasm/unit_tests/results/test_instruction_data_label_for_wrong_argument_type_3_65c02.stdout
A => jasm/unit_tests/results/test_instruction_data_label_has_lo_hi_properties_65c02.bin
R jasm/unit_tests/results/test_instruction_data_label_offsets.bin => 
A => jasm/unit_tests/results/test_instruction_data_label_offsets_z80.bin
A => jasm/unit_tests/results/test_instruction_data_label_with_export_65c02.bin
A => jasm/unit_tests/results/test_instruction_data_label_with_local_export_65c02.stdout
R jasm/unit_tests/results/test_instruction_ends_at_newline2.stdout => 
A => jasm/unit_tests/results/test_instruction_ends_at_newline_2_6502.stdout
A => jasm/unit_tests/results/test_instruction_ends_at_newline_2_65c02.stdout
R jasm/unit_tests/results/test_instructions_must_be_in_code_sections1.stdout => 
R jasm/unit_tests/results/test_instructions_must_be_in_code_sections2.stdout => 
A => jasm/unit_tests/results/test_instructions_must_be_in_code_sections_1_6502.stdout
A => jasm/unit_tests/results/test_instructions_must_be_in_code_sections_1_65c02.stdout
A => jasm/unit_tests/results/test_instructions_must_be_in_code_sections_2_6502.stdout
A => jasm/unit_tests/results/test_instructions_must_be_in_code_sections_2_65c02.stdout
R jasm/unit_tests/results/test_keyword_cannot_be_used_for_indirect_addressing.stdout => 
A => jasm/unit_tests/results/test_keyword_cannot_be_used_for_indirect_addressing_z80.stdout
M jasm/unit_tests/results/test_processor_with_invalid_name.stdout
A => jasm/unit_tests/results/test_pseudo_instructions_for_branching_65c02.bin
A => jasm/unit_tests/results/test_pseudo_instructions_for_incrementing_65c02.bin
A => jasm/unit_tests/results/test_pseudo_instructions_in_standard_mode_65c02.stdout
A => jasm/unit_tests/results/test_pseudo_instructions_use_names_in_standard_mode_65c02.bin
A => jasm/unit_tests/results/test_register_names_cant_be_used_as_global_variables_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_call_65c02.bin
A => jasm/unit_tests/results/test_subroutine_call_must_be_in_code_section_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_call_negative_argument_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_call_recursive_data_generation_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_call_too_large_argument_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_call_with_arguments_65c02.stdout
R jasm/unit_tests/results/test_subroutine_falls_through_1.stdout => 
A => jasm/unit_tests/results/test_subroutine_falls_through_1_6502.stdout
A => jasm/unit_tests/results/test_subroutine_falls_through_1_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_falls_through_1_z80.bin
A => jasm/unit_tests/results/test_subroutine_falls_through_1_z80.stdout
R jasm/unit_tests/results/test_subroutine_falls_through_2.stdout => 
A => jasm/unit_tests/results/test_subroutine_falls_through_2_6502.stdout
A => jasm/unit_tests/results/test_subroutine_falls_through_2_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_falls_through_2_z80.stdout
R jasm/unit_tests/results/test_subroutine_falls_through_3.stdout => 
A => jasm/unit_tests/results/test_subroutine_falls_through_3_6502.stdout
A => jasm/unit_tests/results/test_subroutine_falls_through_3_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_falls_through_3_z80.bin
A => jasm/unit_tests/results/test_subroutine_falls_through_3_z80.stdout
R jasm/unit_tests/results/test_subroutine_falls_through_4.stdout => 
A => jasm/unit_tests/results/test_subroutine_falls_through_4_6502.stdout
A => jasm/unit_tests/results/test_subroutine_falls_through_4_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_falls_through_4_z80.stdout
R jasm/unit_tests/results/test_subroutine_falls_through_5.bin => 
R jasm/unit_tests/results/test_subroutine_falls_through_5.stdout => 
A => jasm/unit_tests/results/test_subroutine_falls_through_5_65c02.stdout
A => jasm/unit_tests/results/test_subroutine_falls_through_5_z80.bin
A => jasm/unit_tests/results/test_subroutine_falls_through_5_z80.stdout
R jasm/unit_tests/results/test_subroutine_falls_through_6.stdout => 
R jasm/unit_tests/results/test_subroutine_falls_through_7.bin => 
R jasm/unit_tests/results/test_subroutine_falls_through_7.stdout => 
R jasm/unit_tests/results/test_subroutine_falls_through_8.stdout => 
R jasm/unit_tests/results/test_subroutine_falls_through_9.bin => 
R jasm/unit_tests/results/test_subroutine_falls_through_9.stdout => 
A => jasm/unit_tests/test_addressing_mode_expected_x_in_indirect_6502.asm
A => jasm/unit_tests/test_addressing_mode_expected_x_in_indirect_65c02.asm
A => jasm/unit_tests/test_addressing_mode_expected_x_or_y_in_absolute_1_6502.asm
A => jasm/unit_tests/test_addressing_mode_expected_x_or_y_in_absolute_2_6502.asm
A => jasm/unit_tests/test_addressing_mode_expected_y_in_indirect_6502.asm
R jasm/unit_tests/test_addressing_mode_is_illegal.asm => 
R jasm/unit_tests/test_addressing_mode_is_illegal2.asm => 
A => jasm/unit_tests/test_addressing_mode_is_illegal_6502.asm
A => jasm/unit_tests/test_addressing_mode_is_illegal_65c02.asm
R jasm/unit_tests/test_addressing_mode_is_illegal_and_too_many_possibilities.asm => 
A => jasm/unit_tests/test_addressing_mode_is_illegal_and_too_many_possibilities_z80.asm
A => jasm/unit_tests/test_addressing_mode_is_illegal_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_1.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_1_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_2.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_2_z80.asm
A => jasm/unit_tests/test_addressing_mode_needs_bit_size_argument_65c02.asm
R jasm/unit_tests/test_addressing_mode_needs_branch_offset_size_argument_1.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_branch_offset_size_argument_1_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_branch_offset_size_argument_2.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_branch_offset_size_argument_2_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_byte_argument.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_1_6502.asm
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_1_65c02.asm
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_1_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_byte_argument_2.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_2_6502.asm
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_2_65c02.asm
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_2_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_byte_argument_3.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_3_65c02.asm
A => jasm/unit_tests/test_addressing_mode_needs_byte_argument_3_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_byte_argument_4.asm => 
R jasm/unit_tests/test_addressing_mode_needs_byte_argument_5.asm => 
R jasm/unit_tests/test_addressing_mode_needs_integer_argument.asm => 
R jasm/unit_tests/test_addressing_mode_needs_integer_argument2.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_1_6502.asm
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_1_65c02.asm
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_1_z80.asm
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_2_65c02.asm
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_3_65c02.asm
A => jasm/unit_tests/test_addressing_mode_needs_integer_argument_4_65c02.asm
R jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_1.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_1_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_2.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_2_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_3.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_offset_size_argument_3_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_positive_argument.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_positive_argument_1_6502.asm
A => jasm/unit_tests/test_addressing_mode_needs_positive_argument_1_65c02.asm
A => jasm/unit_tests/test_addressing_mode_needs_positive_argument_2_65c02.asm
A => jasm/unit_tests/test_addressing_mode_needs_positive_argument_3_65c02.asm
R jasm/unit_tests/test_addressing_mode_needs_word_size_argument.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_1_6502.asm
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_1_65c02.asm
R jasm/unit_tests/test_addressing_mode_needs_word_size_argument_2.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_2_6502.asm
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_2_65c02.asm
R jasm/unit_tests/test_addressing_mode_needs_word_size_argument_3.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_3_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_word_size_argument_4.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_word_size_argument_4_z80.asm
R jasm/unit_tests/test_addressing_mode_needs_zero_page_size_argument.asm => 
A => jasm/unit_tests/test_addressing_mode_needs_zero_page_size_argument_1_z80.asm
R jasm/unit_tests/test_all_instructions.asm => 
A => jasm/unit_tests/test_all_instructions_6502.asm
A => jasm/unit_tests/test_all_instructions_65c02.asm
R jasm/unit_tests/test_bank_mode_truncates_6502_address_instructions.asm => 
A => jasm/unit_tests/test_bank_mode_truncates_address_instructions_6502.asm
A => jasm/unit_tests/test_bank_mode_truncates_address_instructions_65c02.asm
A => jasm/unit_tests/test_bank_mode_truncates_address_instructions_z80.asm
R jasm/unit_tests/test_bank_mode_truncates_z80_address_instructions.asm => 
R jasm/unit_tests/test_expected_x_in_indirect_addressing_mode.asm => 
R jasm/unit_tests/test_expected_x_or_y_in_absolute_addressing_mode1.asm => 
R jasm/unit_tests/test_expected_x_or_y_in_absolute_addressing_mode2.asm => 
R jasm/unit_tests/test_expected_y_in_indirect_addressing_mode.asm => 
R jasm/unit_tests/test_generate_data_in_instruction_1.asm => 
A => jasm/unit_tests/test_generate_data_in_instruction_1_6502.asm
A => jasm/unit_tests/test_generate_data_in_instruction_1_65c02.asm
R jasm/unit_tests/test_generate_data_in_instruction_2.asm => 
A => jasm/unit_tests/test_generate_data_in_instruction_2_z80.asm
R jasm/unit_tests/test_instruction_data_global_label.asm => 
A => jasm/unit_tests/test_instruction_data_global_label_6502.asm
A => jasm/unit_tests/test_instruction_data_global_label_65c02.asm
R jasm/unit_tests/test_instruction_data_label_cant_have_implied_addressing_mode.asm => 
A => jasm/unit_tests/test_instruction_data_label_cant_have_implied_addressing_mode_6502.asm
A => jasm/unit_tests/test_instruction_data_label_cant_have_implied_addressing_mode_65c02.asm
R jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type1.asm => 
R jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type2.asm => 
A => jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type_1_z80.asm
A => jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type_2_z80.asm
A => jasm/unit_tests/test_instruction_data_label_for_wrong_argument_type_3_65c02.asm
A => jasm/unit_tests/test_instruction_data_label_has_lo_hi_properties_65c02.asm
R jasm/unit_tests/test_instruction_data_label_offsets.asm => 
A => jasm/unit_tests/test_instruction_data_label_offsets_65c02.asm
A => jasm/unit_tests/test_instruction_data_label_offsets_z80.asm
A => jasm/unit_tests/test_instruction_data_label_sizes_65c02.asm
A => jasm/unit_tests/test_instruction_data_label_with_export_65c02.asm
A => jasm/unit_tests/test_instruction_data_label_with_local_export_65c02.asm
R jasm/unit_tests/test_instruction_data_local_label.asm => 
A => jasm/unit_tests/test_instruction_data_local_label_6502.asm
A => jasm/unit_tests/test_instruction_data_local_label_65c02.asm
R jasm/unit_tests/test_instruction_ends_at_newline.asm => 
R jasm/unit_tests/test_instruction_ends_at_newline2.asm => 
A => jasm/unit_tests/test_instruction_ends_at_newline_1_6502.asm
A => jasm/unit_tests/test_instruction_ends_at_newline_1_65c02.asm
A => jasm/unit_tests/test_instruction_ends_at_newline_2_6502.asm
A => jasm/unit_tests/test_instruction_ends_at_newline_2_65c02.asm
A => jasm/unit_tests/test_instruction_names_can_be_used_in_local_variables_65c02.asm
R jasm/unit_tests/test_instructions_must_be_in_code_sections1.asm => 
R jasm/unit_tests/test_instructions_must_be_in_code_sections2.asm => 
A => jasm/unit_tests/test_instructions_must_be_in_code_sections_1_6502.asm
A => jasm/unit_tests/test_instructions_must_be_in_code_sections_1_65c02.asm
A => jasm/unit_tests/test_instructions_must_be_in_code_sections_2_6502.asm
A => jasm/unit_tests/test_instructions_must_be_in_code_sections_2_65c02.asm
R jasm/unit_tests/test_keyword_cannot_be_used_for_indirect_addressing.asm => 
A => jasm/unit_tests/test_keyword_cannot_be_used_for_indirect_addressing_z80.asm
A => jasm/unit_tests/test_pseudo_instructions_for_branching_65c02.asm
A => jasm/unit_tests/test_pseudo_instructions_for_incrementing_65c02.asm
A => jasm/unit_tests/test_pseudo_instructions_in_standard_mode_65c02.asm
A => jasm/unit_tests/test_pseudo_instructions_use_names_in_standard_mode_65c02.asm
A => jasm/unit_tests/test_register_names_can_be_used_in_local_names_65c02.asm
A => jasm/unit_tests/test_register_names_cant_be_used_as_global_variables_65c02.asm
A => jasm/unit_tests/test_subroutine_call_65c02.asm
A => jasm/unit_tests/test_subroutine_call_must_be_in_code_section_65c02.asm
A => jasm/unit_tests/test_subroutine_call_negative_argument_65c02.asm
A => jasm/unit_tests/test_subroutine_call_recursive_data_generation_65c02.asm
A => jasm/unit_tests/test_subroutine_call_too_large_argument_65c02.asm
A => jasm/unit_tests/test_subroutine_call_with_arguments_65c02.asm
R jasm/unit_tests/test_subroutine_falls_through_1.asm => 
A => jasm/unit_tests/test_subroutine_falls_through_1_6502.asm
A => jasm/unit_tests/test_subroutine_falls_through_1_65c02.asm
A => jasm/unit_tests/test_subroutine_falls_through_1_z80.asm
R jasm/unit_tests/test_subroutine_falls_through_2.asm => 
A => jasm/unit_tests/test_subroutine_falls_through_2_6502.asm
A => jasm/unit_tests/test_subroutine_falls_through_2_65c02.asm
A => jasm/unit_tests/test_subroutine_falls_through_2_z80.asm
R jasm/unit_tests/test_subroutine_falls_through_3.asm => 
A => jasm/unit_tests/test_subroutine_falls_through_3_6502.asm
A => jasm/unit_tests/test_subroutine_falls_through_3_65c02.asm
A => jasm/unit_tests/test_subroutine_falls_through_3_z80.asm
R jasm/unit_tests/test_subroutine_falls_through_4.asm => 
A => jasm/unit_tests/test_subroutine_falls_through_4_6502.asm
A => jasm/unit_tests/test_subroutine_falls_through_4_65c02.asm
A => jasm/unit_tests/test_subroutine_falls_through_4_z80.asm
R jasm/unit_tests/test_subroutine_falls_through_5.asm => 
A => jasm/unit_tests/test_subroutine_falls_through_5_65c02.asm
A => jasm/unit_tests/test_subroutine_falls_through_5_z80.asm
R jasm/unit_tests/test_subroutine_falls_through_6.asm => 
R jasm/unit_tests/test_subroutine_falls_through_7.asm => 
R jasm/unit_tests/test_subroutine_falls_through_8.asm => 
R jasm/unit_tests/test_subroutine_falls_through_9.asm => 
M jasm/version.h
M jasm/website/site/docs/index.html
M jasm/website/site/index.html
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'(<<=|>>=|&amp;&amp;=|[|][|]=|!=|[+][+]|--|<<|>>|<=|>=|==|&amp;&amp;|[|][|]|[+]=|-=|[*]=|[/]=|&amp;=|[|]=|\^=|::|!|~|[*]|[/]|[+]|-|&lt;|&gt;|&amp;|\^|[|]|=|#|%)')
 	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_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_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_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_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_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_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

          
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_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.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.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.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.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.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.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.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.stdout =>  +0 -1
@@ 1,1 0,0 @@ 
-$8000 - $8001 ($0001) code: main

          
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.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.stdout =>  +0 -1
@@ 1,1 0,0 @@ 
-$8000 - $8003 ($0003) code: main

          
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.stdout +1 -0
@@ 0,0 1,1 @@ 
+$8000 - $8003 ($0003) code: main

          
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.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.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.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