def test_case_y(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start _init: ldy #0x01 switch y case #0x01 nop case #0x02 inx case #0x03 iny endswitch .i16 ldy #0x4401 switch y case #0x4401 nop case #0x4402 inx case #0x4403 iny endswitch ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([ 0xA0, 0x01, 0xC0, 0x01, 0xD0, 0x03, 0xEA, 0x80, 0x0C, 0xC0, 0x02, 0xD0, 0x03, 0xE8, 0x80, 0x05, 0xC0, 0x03, 0xD0, 0x01, 0xC8, 0xA0, 0x01, 0x44, 0xC0, 0x01, 0x44, 0xD0, 0x03, 0xEA, 0x80, 0x0E, 0xC0, 0x02, 0x44, 0xD0, 0x03, 0xE8, 0x80, 0x06, 0xC0, 0x03, 0x44, 0xD0, 0x01, 0xC8 ])
def test_instruction(name, inst, result): program_string = ''' .segment "code", 0xC000, 04000, 0 .code .org start {} '''.format(inst) code = assemble_string(program_string) assert code['code']['code'][0][1] == result
def test_bcc_label(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start loop: clc bcc loop ; loop forever ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0x18, 0x90, 0xFD])
def test_nop(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start _init: nop .db 0x4C, 0x00, 0x00 ; JMP 0x0000 ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xEA, 0x4C, 0x00, 0x00])
def test_macro_error_endmacro(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start .endmacro ''' try: code = assemble_string(program_string) except MacroError: pass
def test_fill_comment(): program_string = ''' .segment "code", 0xC000, 0x3FE0, 0 .code .org start data: .fill 0x100, 0x55 /* : .fill 0x100, %10101010 .fillw 0x100, 0xAA55*/ ''' co = assemble_string(program_string) print(co) assert co['code']['code'][0][1] == bytes([0x55] * 0x100)
def test_lda_abs(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start loop: lda const bcc loop ; loop forever const: .dw $BEEF ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes( [0xAD, 0x05, 0x00, 0x90, 0xFB, 0xEF, 0xBE])
def test_no_compiler_directive_labels(): program_string = ''' .segment "code", 0xC000, 0x3FE0, 0 .code .org start .main: nop ''' try: co = assemble_string(program_string) except ReservedNameError: pass
def test_segment_redefinition(): program_string = ''' .segment "code", 0xC000, 0x3FE0, 0 .code .org start main: .segment "code", 0x8000, 0x8000, 0 ''' try: co = assemble_string(program_string) except SegmentRedefinitionError: pass
def test_label_reserved(): program_string = ''' .segment "code", 0xC000, 0x3FE0, 0 .code .org start a: jmp a ''' try: co = assemble_string(program_string) except ReservedNameError: pass
def test_fill(): program_string = ''' .segment "code", 0xC000, 0x3FE0, 0 .code .org start data: .fill 0x100, 0x55 : .fill 0x100, %10101010 .fillw 0x100, 0xAA55 ''' co = assemble_string(program_string) assert co['code']['code'][0][1] == bytes([0x55] * 0x100 + [0b10101010] * 0x100 + [0x55, 0xAA] * 0x100)
def test_doforever(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start _init: lda #0x01 do inc a forever ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xA9, 0x01, 0x1A, 0x80, 0xFD])
def test_equate_bad_expression(): program_string = ''' VALUE = "Foobar" .segment "code", 0xC000, 0x3FE0, 0 .code .org start main: jmp main ''' try: co = assemble_string(program_string) except EquateDefinitionError: pass
def test_label_equate_redefine(): program_string = ''' VALUE = 5 .segment "code", 0xC000, 0x3FE0, 0 .code .org start VALUE: jmp VALUE ''' try: co = assemble_string(program_string) except LabelRedefinitionError: pass
def test_macro_varargs_len(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start varargs: .macro x, ... lda #(\\L & 0xFF) .endmacro main: varargs 0x00, 0xEE, 0x0101, 0xF00D ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xA9, 0x03])
def test_no_segment(): program_string = ''' .segment "code", 0xC000, 0x3FE0, 0 nop .code .org start main: nop ''' try: co = assemble_string(program_string) except NoSegmentError: pass
def test_macro_parameters1(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start inc_two: .macro one, two inc one inc two .endmacro main: inc_two $0000, $0002 ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xEE, 0x00, 0x00, 0xEE, 0x02, 0x00])
def test_label_redefinition(): program_string = ''' .segment "code", 0xC000, 0x3FE0, 0 .code .org start main: nop .code main: inc $ff ''' try: co = assemble_string(program_string) except LabelRedefinitionError: pass
def test_macro_varargs(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start varargs: .macro ... inc \\0 inc \\1 .endmacro main: varargs 0xEE, 0x0101, 0xF00D ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xE6, 0xEE, 0xEE, 0x01, 0x01])
def test_macro_nop(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start insert_nop: .macro nop .endmacro main: insert_nop insert_nop ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xEA, 0xEA])
def test_program_counter(): program_string = ''' ; segments define blocks of code and data and also specify where in the output "memory" the blocks reside. ; name start size file_offset .segment "code", $C000, $3FE0, $0000 .segment "vectors16", $FFE0, $10, $3FE0 .segment "vectors8", $FFF0, $10, $3FF0 ; .org is used within a segment and is related to the 'start' of the specified segment (i.e., specifying or letting your code run out of the segment bounds will generate an error) .code ; TODO this comment is a workaround to my shoddy parser knowledge. .org $C000 hello_world_str: .dw 0x1234, $5678 .db "Hello, world!", 0 .global _init _init: sei ; disable interrupts lda #$00 ; clear A sta $00 ; reset our counters to 0 sta $01 sta $02 _a: inc $00 ; increment low byte of counter 1 bne _a inc $01 ; increment high byte of counter 1 bne _a inc $02 ; set our done flag _b: jmp _b .org $C080 _d: clc bcc _d .vectors16 ; TODO this comment is a workaround to my shoddy parser knowledge. .org start ; TODO want to support default .org. Maybe if no .org is specified, defaults to the start of the defined segment .vectors8 ; TODO this comment is a workaround to my shoddy parser knowledge. .org start .dw 0 .dw 0 .dw 0 .dw 0 v_ABORT: .dw 0 v_NMI: .dw 0 v_RESET: .dw _init v_IRQ: .dw 0 ''' code = assemble_string(program_string)
def test_if_error(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start _init: lda #0x01 if foo ldx #0xff endif ''' try: code = assemble_string(program_string) except InvalidParameterError: pass
def test_macro_parameters2(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start inc_two: .macro one inc <one inc >one .endmacro main: inc_two (data * 2) .org $CABC data: .db 0x0 ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xE6, 0xBC*2 & 0xFF, 0xE6, (0xCA*2+1) & 0xFF])
def test_macro_varargs_len2(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start varargs: .macro tmp, ... .if \\L != 1 lda #(\\1 & 0xFF) .endif .endmacro main: varargs 0x12, main varargs 0x00, 0xEE, 0xF00D ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xA9, 0x0D])
def test_dountil_n(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start _init: lda #0x01 do do inc a until n_clear until n_set ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes( [0xA9, 0x01, 0x1A, 0x30, 0xFD, 0x10, 0xFB])
def test_macro_cpu16(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start cpu16: .macro rep #%00110000 .a16 .i16 .endmacro main: cpu16 lda #$1234 ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xC2, 0x30, 0xA9, 0x34, 0x12])
def test_macro_or_not_lt_gt(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start varargs: .macro ... .if !((\\L > 1) || (\\L < 1)) lda #(\\0 & 0xFF) .endif .endmacro .org 0x1234 main: varargs main ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes([0xA9, 0x34])
def test_macro_error_nested(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start cpu16: .macro foo: .macro .endmacro main: cpu16 lda #$1234 ''' try: code = assemble_string(program_string) except MacroError: pass
def test_incbin(): import tempfile fname = tempfile.mktemp() hello_world = "aspdfij3-18jr1[3oimrcxvipijijqw\x0343".encode("ascii") with open(fname, "wb") as fp: fp.write(hello_world) program_string = ''' .segment "code", 0xC000, 0x3FE0, 0 .code .org start main: .incbin "{}" '''.format(fname) co = assemble_string(program_string) print(co) assert co['code']['code'][0][1] == bytes(hello_world)
def test_if_z(): program_string = ''' .segment "code", 0x0000, 0x10000, 0 .code .org start _init: lda #0x01 if z_set ldy #0x00 if z_clear ldx #0xff endif endif ''' code = assemble_string(program_string) assert code['code']['code'][0][1] == bytes( [0xA9, 0x01, 0xD0, 0x06, 0xA0, 0x00, 0xF0, 0x02, 0xA2, 0xFF])