|
- ; E06-S01: interface value ABI fixture in x128.
- ;
- ; Runs under CR=$0E. It checks:
- ; - the four-byte value is little-endian: object low/high then table
- ; low/high;
- ; - null conversion writes four zero bytes and ignores the table pointer;
- ; - a non-null object with no table is IF_ERR_TABLE with a zero table half;
- ; - copying preserves all four bytes and never reads through a null pointer;
- ; - slot lookup reads table[slot*2] in declaration slot order;
- ; - the four-byte result area IF_RESULT carries all four bytes, and a failed
- ; store leaves the previous result intact;
- ; - four interface bytes pushed right-to-left arrive at FP+2..FP+5.
- ;
- ; MB_DATA flags 0..5 report the six phases.
-
- .setcpu "6502"
- .include "../../src/common/c128.inc"
- .include "../../src/common/mailbox.inc"
- .include "../../src/common/print.inc"
- .include "../../src/common/frames.inc"
- .include "../../src/common/interfaces.inc"
-
- .import pr_char, pr_cr, pr_text
- .import frame_init, frame_enter, frame_leave, frame_push_byte, frame_discard
- .import if_conv, if_copy, if_is_null, if_slot, if_ret_store, if_ret_load
- .import if_error
- .importzp if_obj, if_tab, if_dst, if_src
-
- .macro TEXT src, len
- lda #<src
- ldx #>src
- ldy #len
- jsr pr_text
- .endmacro
-
- .macro PHASE n
- lda #n
- sta MB_CODE
- lda #$00
- sta MB_CODE+1
- .endmacro
-
- .macro POINT var
- lda #<var
- sta tptr
- lda #>var
- sta tptr+1
- .endmacro
-
- .macro SETDST var
- lda #<var
- sta if_dst
- lda #>var
- sta if_dst+1
- .endmacro
-
- .macro SETSRC var
- lda #<var
- sta if_src
- lda #>var
- sta if_src+1
- .endmacro
-
- .macro EXPECT v0, v1, v2, v3
- lda #v0
- sta e0
- lda #v1
- sta e1
- lda #v2
- sta e2
- lda #v3
- sta e3
- .endmacro
-
- .macro FAIL_CS
- bcc :+
- jmp @fail
- :
- .endmacro
-
- .macro FAIL_CC
- bcs :+
- jmp @fail
- :
- .endmacro
-
- .macro FAIL_NE
- beq :+
- jmp @fail
- :
- .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 "ZEROPAGE"
- tptr: .res 2
-
- .segment "STARTUP"
- .export test_entry, test_end
- 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 MB_CODE
- sta MB_CODE+1
-
- lda MMU_CR
- sta saved_cr
- lda #CR_RAM0_KERNAL
- sta MMU_CR
- lda #PR_CLEAR
- jsr pr_char
- TEXT title, 22
- jsr pr_cr
-
- ; 1: little-endian layout of object and table pointers.
- PHASE 1
- lda #$34
- sta if_obj
- lda #$12
- sta if_obj+1
- lda #$78
- sta if_tab
- lda #$56
- sta if_tab+1
- SETDST val_a
- jsr if_conv
- FAIL_CS
- lda if_error
- FAIL_NE
- POINT val_a
- EXPECT $34, $12, $78, $56
- jsr cmp_val
- FAIL_CS
- lda #$01
- sta MB_DATA+0
-
- ; 2: canonical null and invalid conversion.
- PHASE 2
- lda #$00
- sta if_obj
- sta if_obj+1
- lda #$78
- sta if_tab
- lda #$56
- sta if_tab+1
- SETDST val_b
- jsr if_conv
- FAIL_CS
- lda if_error
- FAIL_NE
- POINT val_b
- EXPECT $00, $00, $00, $00
- jsr cmp_val
- FAIL_CS
-
- lda #<val_b
- ldx #>val_b
- jsr if_is_null
- FAIL_CC
- lda #<val_a
- ldx #>val_a
- jsr if_is_null
- FAIL_CS
-
- lda #$34
- sta if_obj
- lda #$12
- sta if_obj+1
- lda #$00
- sta if_tab
- sta if_tab+1
- SETDST val_c
- jsr if_conv
- FAIL_CC
- lda if_error
- cmp #IF_ERR_TABLE
- FAIL_NE
- POINT val_c
- EXPECT $34, $12, $00, $00
- jsr cmp_val
- FAIL_CS
-
- lda #$00
- ldx #$00
- jsr if_is_null
- FAIL_CC
- lda #$01
- sta MB_DATA+1
-
- ; 3: copying preserves every byte and rejects a null source pointer.
- PHASE 3
- SETSRC val_a
- SETDST val_d
- jsr if_copy
- FAIL_CS
- POINT val_d
- EXPECT $34, $12, $78, $56
- jsr cmp_val
- FAIL_CS
- POINT val_a
- EXPECT $34, $12, $78, $56
- jsr cmp_val
- FAIL_CS
-
- SETSRC val_b
- SETDST val_e
- jsr if_copy
- FAIL_CS
- POINT val_e
- EXPECT $00, $00, $00, $00
- jsr cmp_val
- FAIL_CS
-
- lda #$00
- sta if_src
- sta if_src+1
- SETDST val_e
- jsr if_copy
- FAIL_CC
- lda if_error
- cmp #IF_ERR_NULL
- FAIL_NE
- POINT val_e
- EXPECT $00, $00, $00, $00
- jsr cmp_val
- FAIL_CS
- lda #$01
- sta MB_DATA+2
-
- ; 4: slot order and the two refusal cases.
- PHASE 4
- lda #$34
- sta if_obj
- lda #$12
- sta if_obj+1
- lda #<slot_tab
- sta if_tab
- lda #>slot_tab
- sta if_tab+1
- SETDST val_f
- jsr if_conv
- FAIL_CS
-
- lda #<val_f
- ldx #>val_f
- ldy #0
- jsr if_slot
- FAIL_CS
- cmp #$EF
- FAIL_NE
- cpx #$BE
- FAIL_NE
-
- lda #<val_f
- ldx #>val_f
- ldy #1
- jsr if_slot
- FAIL_CS
- cmp #$FE
- FAIL_NE
- cpx #$CA
- FAIL_NE
-
- lda #<val_b
- ldx #>val_b
- ldy #0
- jsr if_slot
- FAIL_CC
- lda if_error
- cmp #IF_ERR_NULL
- FAIL_NE
-
- lda #<val_c
- ldx #>val_c
- ldy #0
- jsr if_slot
- FAIL_CC
- lda if_error
- cmp #IF_ERR_TABLE
- FAIL_NE
- lda #$01
- sta MB_DATA+3
-
- ; 5: four-byte result area.
- PHASE 5
- lda #<val_a
- ldx #>val_a
- jsr if_ret_store
- FAIL_CS
- POINT IF_RESULT
- EXPECT $34, $12, $78, $56
- jsr cmp_val
- FAIL_CS
-
- lda #<val_g
- ldx #>val_g
- jsr if_ret_load
- FAIL_CS
- POINT val_g
- EXPECT $34, $12, $78, $56
- jsr cmp_val
- FAIL_CS
-
- lda #<val_b
- ldx #>val_b
- jsr if_ret_store
- FAIL_CS
- lda #<val_h
- ldx #>val_h
- jsr if_ret_load
- FAIL_CS
- POINT val_h
- EXPECT $00, $00, $00, $00
- jsr cmp_val
- FAIL_CS
-
- lda #<val_a
- ldx #>val_a
- jsr if_ret_store
- FAIL_CS
- lda #$00
- ldx #$00
- jsr if_ret_store
- FAIL_CC
- lda if_error
- cmp #IF_ERR_NULL
- FAIL_NE
- POINT IF_RESULT
- EXPECT $34, $12, $78, $56
- jsr cmp_val
- FAIL_CS
- lda #$01
- sta MB_DATA+4
-
- ; 6: an interface argument pushed right-to-left lands object-first.
- PHASE 6
- jsr frame_init
- lda FRAME_SP
- sta saved_sp
- lda FRAME_SP+1
- sta saved_sp+1
-
- lda #$56
- jsr frame_push_byte
- FAIL_CS
- lda #$78
- jsr frame_push_byte
- FAIL_CS
- lda #$12
- jsr frame_push_byte
- FAIL_CS
- lda #$34
- jsr frame_push_byte
- FAIL_CS
-
- jsr take_iface
- FAIL_CS
- lda #IF_VALUE_SIZE
- ldx #$00
- jsr frame_discard
- lda FRAME_SP
- cmp saved_sp
- FAIL_NE
- lda FRAME_SP+1
- cmp saved_sp+1
- FAIL_NE
- lda #$01
- sta MB_DATA+5
-
- TEXT iface_ok, 12
- jsr pr_cr
- lda #MB_ST_PASS
- sta MB_STATUS
- lda #$00
- sta MB_CODE
- sta MB_CODE+1
- jmp @restore
-
- @fail:
- lda #MB_ST_FAIL
- sta MB_STATUS
- TEXT iface_fail, 14
- jsr pr_cr
- @restore:
- lda saved_cr
- sta MMU_CR
- plp
- rts
-
- ; Reads the four argument bytes at FP+2..FP+5: object $1234, table $5678.
- take_iface:
- lda #$00
- ldx #$00
- jsr frame_enter
- bcs @bad
- ldy #2
- lda (FRAME_FP),y
- cmp #$34
- bne @bad
- iny
- lda (FRAME_FP),y
- cmp #$12
- bne @bad
- iny
- lda (FRAME_FP),y
- cmp #$78
- bne @bad
- iny
- lda (FRAME_FP),y
- cmp #$56
- bne @bad
- jsr frame_leave
- clc
- rts
- @bad: sec
- rts
-
- ; C=1 when the four bytes at tptr differ from e0..e3.
- cmp_val:
- ldy #$00
- lda (tptr),y
- cmp e0
- bne @no
- iny
- lda (tptr),y
- cmp e1
- bne @no
- iny
- lda (tptr),y
- cmp e2
- bne @no
- iny
- lda (tptr),y
- cmp e3
- bne @no
- clc
- rts
- @no: sec
- rts
-
- .segment "DATA"
- slot_tab:
- .word $BEEF
- .word $CAFE
- .assert * - slot_tab = 2 * IF_SLOT_SIZE, error, "slot table size"
-
- .segment "RODATA"
- title: .byte "NOVA128 INTERFACE ABI"
- iface_ok: .byte "INTERFACE OK"
- iface_fail: .byte "INTERFACE FAIL"
-
- .segment "BSS"
- saved_cr: .res 1
- saved_sp: .res 2
- e0: .res 1
- e1: .res 1
- e2: .res 1
- e3: .res 1
- val_a: .res IF_VALUE_SIZE
- val_b: .res IF_VALUE_SIZE
- val_c: .res IF_VALUE_SIZE
- val_d: .res IF_VALUE_SIZE
- val_e: .res IF_VALUE_SIZE
- val_f: .res IF_VALUE_SIZE
- val_g: .res IF_VALUE_SIZE
- val_h: .res IF_VALUE_SIZE
- test_end:
|