|
- ; E04-S02: software-frame ABI test in x128.
- ;
- ; The fixture runs with CR=$0E and IRQs masked so the frame stack at
- ; $B800-$BFFF is RAM. It restores the entry CR before returning to BASIC.
- ; Checks:
- ; +0/+1 recursive two-byte result (sum 1..50 = 1275 = $04FB)
- ; +2 one-byte return (5+7 = 12)
- ; +3 overflow error (FRAME_ERR_STACK)
- ; +4/+5 SP after the overflow unwinds ($C000)
- ; +6 frame_error after overflow (FRAME_ERR_STACK)
- ; +7 FP low after unwinding (0)
- ; Failure bits: 1 recursion, 2 one-byte return, 4 overflow, 8 stack state.
-
- .setcpu "6502"
- .include "../../src/common/c128.inc"
- .include "../../src/common/mailbox.inc"
- .include "../../src/common/frames.inc"
-
- .import frame_init, frame_enter, frame_leave, frame_discard
- .import frame_push_byte, frame_push_word, frame_error
-
- .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_PROGRAM
- sta MB_PRODUCER
- lda #MB_ST_RUNNING
- sta MB_STATUS
- lda #$00
- sta fail_mask
- sta sum_lo
- sta sum_hi
- sta byte_sum
- sta ov_error
- sta MB_CODE
- sta MB_CODE+1
-
- jsr frame_init
- lda MMU_CR
- sta saved_cr
- lda #CR_RAM0_KERNAL
- sta MMU_CR
-
- ; ------------------------------------------------ successful recursion
- jsr frame_init
- lda #<50
- ldx #>50
- jsr frame_push_word
- bcs @rec_push_fail
- jsr recurse
- bcs @rec_call_fail
- sta sum_lo
- stx sum_hi
- lda #2
- ldx #0
- jsr frame_discard
- lda sum_lo
- cmp #$FB
- bne @rec_bad
- lda sum_hi
- cmp #$04
- bne @rec_bad
- lda FRAME_SP
- cmp #<FRAME_STACK_TOP
- bne @rec_bad
- lda FRAME_SP+1
- cmp #>FRAME_STACK_TOP
- bne @rec_bad
- jmp @byte_return
- @rec_push_fail:
- lda #$01
- jsr fail
- jmp @byte_return
- @rec_call_fail:
- lda #2
- ldx #0
- jsr frame_discard
- lda #$01
- jsr fail
- jmp @byte_return
- @rec_bad:
- lda #$01
- jsr fail
-
- ; --------------------------------------------------- one-byte return
- @byte_return:
- jsr frame_init
- lda #7
- jsr frame_push_byte
- bcs @byte_fail
- lda #5
- jsr frame_push_byte
- bcs @byte_fail
- jsr sum_bytes
- bcs @byte_fail
- sta byte_sum
- lda #2
- ldx #0
- jsr frame_discard
- lda byte_sum
- cmp #12
- beq @overflow
- @byte_fail:
- lda #$02
- jsr fail
-
- ; ------------------------------------------------------ stack overflow
- @overflow:
- jsr frame_init
- lda #<1000
- ldx #>1000
- jsr frame_push_word
- bcs @ov_push_fail
- jsr recurse
- bcc @ov_no_fault
- lda #2
- ldx #0
- jsr frame_discard
- lda frame_error
- sta ov_error
- cmp #FRAME_ERR_STACK
- beq @ov_check_sp
- lda #$04
- jsr fail
- jmp @ov_check_sp
- @ov_push_fail:
- lda #$04
- jsr fail
- jmp @finish
- @ov_no_fault:
- lda #2
- ldx #0
- jsr frame_discard
- lda #$04
- jsr fail
- @ov_check_sp:
- lda FRAME_SP
- cmp #<FRAME_STACK_TOP
- bne @ov_bad
- lda FRAME_SP+1
- cmp #>FRAME_STACK_TOP
- bne @ov_bad
- lda FRAME_FP
- ora FRAME_FP+1
- beq @finish
- @ov_bad:
- lda #$08
- jsr fail
-
- ; ---------------------------------------------- hardware-stack guard
- tsx
- stx saved_hw_sp
- ldx #$20
- txs
- lda #0
- ldx #0
- jsr frame_enter
- ldx saved_hw_sp
- txs
- bcc @hw_bad
- lda frame_error
- cmp #FRAME_ERR_STACK
- beq @finish
- @hw_bad:
- lda #$10
- jsr fail
-
- ; ---------------------------------------------------------- report
- @finish:
- lda sum_lo
- sta MB_DATA+0
- lda sum_hi
- sta MB_DATA+1
- lda byte_sum
- sta MB_DATA+2
- lda ov_error
- sta MB_DATA+3
- lda FRAME_SP
- sta MB_DATA+4
- lda FRAME_SP+1
- sta MB_DATA+5
- lda frame_error
- sta MB_DATA+6
- lda FRAME_FP
- sta MB_DATA+7
-
- lda saved_cr
- sta MMU_CR
- lda fail_mask
- sta MB_CODE
- lda #$00
- sta MB_CODE+1
- lda #MB_ST_FAIL
- ldx fail_mask
- bne @status
- lda #MB_ST_PASS
- @status:
- sta MB_STATUS
-
- ldy #$00
- @print: lda message,y
- beq @end
- sty print_y
- jsr CHROUT
- ldy print_y
- iny
- bne @print
- @end: plp
- rts
-
- .segment "CODE"
- fail:
- ora fail_mask
- sta fail_mask
- rts
-
- ; recurse(depth) -> depth + recurse(depth-1), zero at depth 0.
- ; Arguments: depth word at FP+2. Locals: depth word, result word.
- recurse:
- lda #24
- ldx #0
- jsr frame_enter
- bcc @entered
- jmp @entry_err
- @entered:
-
- ; local +0/+1 = depth, local +2/+3 = sentinel/result
- ldy #2
- lda (FRAME_FP),y
- ldy #0
- sta (FRAME_SP),y
- ldy #3
- lda (FRAME_FP),y
- ldy #1
- sta (FRAME_SP),y
- ldy #2
- lda #$A5
- sta (FRAME_SP),y
- iny
- lda #$5A
- sta (FRAME_SP),y
-
- ldy #0
- lda (FRAME_SP),y
- sta depth
- iny
- lda (FRAME_SP),y
- sta depth+1
- lda depth
- ora depth+1
- beq @zero
-
- lda depth
- sec
- sbc #1
- sta calc
- lda depth+1
- sbc #0
- sta calc+1
- lda calc
- ldx calc+1
- jsr frame_push_word
- bcs @push_err
-
- jsr recurse
- bcs @nested_err
- sta result
- stx result+1
- lda #2
- ldx #0
- jsr frame_discard
-
- ldy #2
- lda (FRAME_SP),y
- cmp #$A5
- bne @corrupt
- iny
- lda (FRAME_SP),y
- cmp #$5A
- bne @corrupt
-
- ldy #0
- lda (FRAME_SP),y
- clc
- adc result
- sta result
- ldy #1
- lda (FRAME_SP),y
- adc result+1
- sta result+1
- ldy #2
- lda result
- sta (FRAME_SP),y
- ldy #3
- lda result+1
- sta (FRAME_SP),y
- lda result
- ldx result+1
- jmp @leave
-
- @zero: lda #0
- ldx #0
- @leave:
- sta ret_lo
- stx ret_hi
- jsr frame_leave
- lda ret_lo
- ldx ret_hi
- clc
- rts
- @entry_err:
- lda #FRAME_ERR_STACK
- sec
- rts
- @push_err:
- jsr frame_leave
- lda #FRAME_ERR_STACK
- sec
- rts
- @nested_err:
- lda #2
- ldx #0
- jsr frame_discard
- jsr frame_leave
- lda #FRAME_ERR_STACK
- sec
- rts
- @corrupt:
- lda #2
- ldx #0
- jsr frame_discard
- jsr frame_leave
- lda #FRAME_ERR_STATE
- sec
- rts
-
- ; sum_bytes(a,b) -> A = a+b. Two byte arguments at FP+2 and FP+3.
- sum_bytes:
- lda #0
- ldx #0
- jsr frame_enter
- bcs @out
- ldy #2
- lda (FRAME_FP),y
- iny
- clc
- adc (FRAME_FP),y
- sta sum_result
- jsr frame_leave
- lda sum_result
- clc
- rts
- @out: sec
- rts
-
- .segment "RODATA"
- message: .byte "NOVA128 FRAME TEST DONE", $0D, $00
-
- .segment "BSS"
- fail_mask: .res 1
- print_y: .res 1
- saved_cr: .res 1
- saved_hw_sp: .res 1
- sum_lo: .res 1
- sum_hi: .res 1
- byte_sum: .res 1
- ov_error: .res 1
- depth: .res 2
- calc: .res 2
- result: .res 2
- ret_lo: .res 1
- ret_hi: .res 1
- sum_result: .res 1
|