; E04-S06: parse statements.n8, execute the code the parser emitted, and ; report the resulting locals and printed bytes. ; ; The fixture runs in the compiler mapping, loads STMTS.N8, parses it with ; emission on, and JSRs cg_code in place. The emitted body reaches its locals ; through FRAME_FP, so the fixture points FP at its own buffer. Print calls go ; through the em_pr_* cells, which the fixture fills with recorders: the test ; sees exactly which bytes the generated code asked to print, without ; depending on CHROUT or the screen mapping. ; ; Mailbox data: +0 diagnostics, +1 em_bad, +2 a, +3 b, +4 cg_len, +5 cg_err, ; +6 recorded length. FAIL code is the stage: 1 load, 2 diagnostics, 3 emitter, ; 4 cg. ; ; The frame prologue is not emitted yet, so the fixture owns FP; E04-S07's ; sizing pass will emit frame_enter with the measured local bytes. .setcpu "6502" .include "../../src/common/c128.inc" .include "../../src/common/mailbox.inc" .include "../../src/common/formats.inc" .include "../../src/common/frames.inc" .import mmu_init, mmu_bank0, mmu_shutdown .import src_load, src_dos_code, src_kernal_err .import names_init .import diag_init, diag_finish, diag_screen .import parse_file .import em_on, em_bad, em_pr_text, em_pr_byte, em_pr_cr .import em_entry .import cg_code, cg_len, cg_err ; A conditional branch to a far error path: near branch over an absolute JMP. .macro ON_ZERO target beq :+ jmp target : .endmacro .segment "LOADADDR" .word $1C01 .segment "EXEHDR" .word basic_end .word 10 .byte $9E .byte "7181" .byte $00 basic_end: .word $0000 .segment "MAILBOX" .res MB_SIZE .segment "STARTUP" .export test_entry test_entry: php sei ldx #MB_SIZE - 1 lda #$00 @clr: sta MB_BASE,x dex bpl @clr lda #MB_MAGIC0_VALUE sta MB_MAGIC0 lda #MB_MAGIC1_VALUE sta MB_MAGIC1 lda #MB_PROD_COMPILER sta MB_PRODUCER lda #MB_ST_RUNNING sta MB_STATUS jsr mmu_init jsr mmu_bank0 lda #name_src ldy #name_src_len jsr src_load cmp #$00 ON_ZERO @fail_load jsr names_init lda #name_src ldy #name_src_len jsr diag_init lda #$00 sta diag_screen lda #$01 sta em_on ; pass 2 emits statements lda #rec_text sta em_pr_text+1 lda #rec_byte sta em_pr_byte+1 lda #rec_cr sta em_pr_cr+1 lda #$00 sta rec_len jsr parse_file jsr diag_finish sta diag_count lda diag_count sta MB_DATA+0 lda em_bad sta MB_DATA+1 lda cg_len sta MB_DATA+4 lda cg_err sta MB_DATA+5 lda rec_len sta MB_DATA+6 lda diag_count ON_ZERO @fail_diag lda em_bad ON_ZERO @fail_emit lda cg_err ON_ZERO @fail_cg lda #em_fp sta FRAME_FP+1 lda #cg_code adc #$00 sta run_ptr+1 jsr run_entry lda em_fp - 2 ; a: the first local (FP-2) sta MB_DATA+2 lda em_fp - 3 ; b: the second local (FP-3) sta MB_DATA+3 lda rec_len sta MB_DATA+6 lda #MB_ST_PASS sta MB_STATUS jmp @done @fail_load: sta MB_DATA+5 ; src_load result lda src_dos_code sta MB_DATA+6 lda src_kernal_err sta MB_DATA+7 lda #1 jmp @fail @fail_diag: lda #2 jmp @fail @fail_emit: lda #3 jmp @fail @fail_cg: lda #4 @fail: sta MB_CODE lda #$00 sta MB_CODE+1 lda #MB_ST_FAIL sta MB_STATUS @done: jsr mmu_shutdown plp rts ; JSR to the address in run_ptr (self-modifying, so a normal RTS returns here). run_entry: lda run_ptr sta @call+1 lda run_ptr+1 sta @call+2 @call: jsr $FFFF rts ; ------------------------------------------------------------- recorders ; A/X = address, Y = length: record the literal bytes. rec_text: sta rec_ptr stx rec_ptr+1 sty rec_cnt ldy #$00 @loop: cpy rec_cnt beq @done lda (rec_ptr),y sty rec_y jsr rec_log ldy rec_y iny bne @loop @done: rts ; A = byte value: record $FF and the value, so a value print is distinct from ; text. rec_byte: pha lda #$FF jsr rec_log pla jmp rec_log ; A newline follows every print statement. rec_cr: lda #$0D jmp rec_log ; A = byte to append. rec_log: ldy rec_len cpy #32 bcs @full sta rec_buf,y inc rec_len @full: rts .segment "ZEROPAGE" rec_ptr: .res 2 run_ptr: .res 2 .segment "RODATA" name_src: .byte "STMTS.N8" name_src_len = * - name_src .segment "BSS" diag_count: .res 1 rec_cnt: .res 1 rec_y: .res 1 .export rec_len rec_len: .res 1 .export rec_buf rec_buf: .res 32 em_frame: .res 128 em_fp = em_frame + 64 .export em_fp