|
- ; E04-S07: compile COUNTER.N8, assign final code addresses, and write two
- ; deterministic PRGs. The generated code runs from the PRG in a second x128
- ; session; the fixture-owned wrapper places FRAME_FP and reports the program's
- ; `total` local through the mailbox.
-
- .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_base
- .import em_on, em_bad
- .import cg_code, cg_len, cg_err
- .import fl_err
- .import sz_plan_code, sz_code_base
- .import out_begin, out_section, out_end_section, out_byte, out_bytes
- .import out_finish, out_abort, out_load, out_entry, out_start, out_err
- .import gen_stub
-
- FRAME_BASE = $BF80 ; software frame area under CR=$0E
- WRAPPER_LEN = 66
- CODE_ADDR = PRG_ENTRY_ADDR + WRAPPER_LEN
-
- .macro ON_CARRY target
- bcc :+
- jmp target
- :
- .endmacro
-
- .macro ON_NONZERO 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
- ldx #>name_src
- ldy #name_src_len
- jsr src_load
- cmp #$00
- ON_NONZERO fail_load ; src_load returns A=0 on success
-
- jsr names_init
- lda #<name_src
- ldx #>name_src
- ldy #name_src_len
- jsr diag_init
- lda #$00
- sta diag_screen
- lda #$01
- sta em_on
- lda #<PRG_LOAD_ADDR
- sta out_load
- lda #>PRG_LOAD_ADDR
- sta out_load+1
- lda #<PRG_ENTRY_ADDR
- sta out_entry
- lda #>PRG_ENTRY_ADDR
- sta out_entry+1
- lda #WRAPPER_LEN
- jsr sz_plan_code ; final code base for absolute fixups
-
- lda sz_code_base
- ldx sz_code_base+1
- jsr parse_file_base
- 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+2
- lda cg_err
- sta MB_DATA+3
- lda fl_err
- sta MB_DATA+4
- lda sz_code_base
- sta MB_DATA+6
- lda sz_code_base+1
- sta MB_DATA+7
-
- lda diag_count
- ON_NONZERO fail_diag
- lda em_bad
- ON_NONZERO fail_emit
- lda cg_err
- ON_NONZERO fail_emit
- lda fl_err
- ON_NONZERO fail_emit
-
- lda #<name_counter
- sta out_name_ptr
- lda #>name_counter
- sta out_name_ptr+1
- lda #name_counter_len
- sta out_name_len
- jsr emit_output
- bcs fail_out
-
- lda #<name_countb
- sta out_name_ptr
- lda #>name_countb
- sta out_name_ptr+1
- lda #name_countb_len
- sta out_name_len
- jsr emit_output
- bcs fail_out
-
- lda #MB_ST_PASS
- sta MB_STATUS
- jmp done
-
- fail_diag:
- lda #2
- jmp fail_common
- fail_emit:
- lda #3
- jmp fail_common
- fail_out:
- lda emit_err
- sta MB_DATA+5
- lda #4
- jmp fail_common
- fail_load:
- sta MB_DATA+5
- lda src_dos_code
- sta MB_DATA+6
- lda src_kernal_err
- sta MB_DATA+7
- lda #1
- fail_common:
- sta MB_CODE
- lda #$00
- sta MB_CODE+1
- lda #MB_ST_FAIL
- sta MB_STATUS
- done: jsr mmu_shutdown
- plp
- rts
-
- ; Write one output pair with the same generated bytes. A/X = base name,
- ; out_name_len = length. C=1 on any output failure.
- emit_output:
- lda out_name_ptr
- ldx out_name_ptr+1
- ldy out_name_len
- jsr out_begin
- ON_CARRY out_fail
-
- lda #<PRG_LOAD_ADDR
- sta out_start
- lda #>PRG_LOAD_ADDR
- sta out_start+1
- lda #<sec_stub
- ldx #>sec_stub
- ldy #4
- jsr out_section
- ON_CARRY out_fail
- lda #<gen_stub
- ldx #>gen_stub
- ldy #PRG_STUB_SIZE
- jsr out_bytes
- ON_CARRY out_fail
- jsr out_end_section
- ON_CARRY out_fail
-
- lda #<PRG_ENTRY_ADDR
- sta out_start
- lda #>PRG_ENTRY_ADDR
- sta out_start+1
- lda #<sec_start
- ldx #>sec_start
- ldy #5
- jsr out_section
- ON_CARRY out_fail
- lda #<wrapper
- ldx #>wrapper
- ldy #WRAPPER_LEN
- jsr out_bytes
- ON_CARRY out_fail
- jsr out_end_section
- ON_CARRY out_fail
-
- lda sz_code_base
- sta out_start
- lda sz_code_base+1
- sta out_start+1
- lda #<sec_code
- ldx #>sec_code
- ldy #4
- jsr out_section
- ON_CARRY out_fail
- lda #<cg_code
- ldx #>cg_code
- ldy cg_len
- jsr out_bytes
- ON_CARRY out_fail
- jsr out_end_section
- ON_CARRY out_fail
- jsr out_finish
- ON_CARRY out_fail
- clc
- rts
- out_fail: lda out_err
- sta emit_err
- jsr out_abort
- sec
- rts
-
- ; The PRG's fixed entry, at $1C0D. It clears the mailbox, installs a frame
- ; base, calls the generated program body at CODE_ADDR, and reports `total`
- ; (the second local, FP-2) as MB_DATA.
- wrapper:
- lda $FF00 ; save CR, select RAM through $BFFF
- pha
- lda #$0E
- sta $FF00
- 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_PROGRAM
- sta MB_PRODUCER
- lda #MB_ST_RUNNING
- sta MB_STATUS
- lda #<FRAME_BASE
- sta FRAME_FP
- lda #>FRAME_BASE
- sta FRAME_FP+1
- jsr CODE_ADDR
- lda FRAME_BASE - 3
- sta MB_DATA
- pla
- sta $FF00 ; restore the BASIC entry mapping
- lda #MB_ST_PASS
- sta MB_STATUS
- rts
- .assert * - wrapper = WRAPPER_LEN, error, "counter wrapper length changed"
- .assert CODE_ADDR < $4000, error, "generated code must stay below BASIC ROM"
-
- .segment "ZEROPAGE"
- out_name_ptr: .res 2
-
- .segment "RODATA"
- name_src: .byte "COUNTER.N8"
- name_src_len = * - name_src
- name_counter: .byte "COUNTER"
- name_counter_len = * - name_counter
- name_countb: .byte "COUNTB"
- name_countb_len = * - name_countb
- sec_stub: .byte "STUB"
- sec_start: .byte "START"
- sec_code: .byte "CODE"
-
- .segment "BSS"
- diag_count: .res 1
- out_name_len: .res 1
- emit_err: .res 1
|