25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

654 lines
13KB

  1. ; E06-S02: indirect-call trampoline fixture in x128.
  2. ;
  3. ; Runs under CR=$0E. It checks:
  4. ; - three targets chosen at runtime from value records dispatch correctly,
  5. ; with A/X results and self = the object pointer;
  6. ; - nested dispatch returns through three levels;
  7. ; - recursive dispatch through 8 levels returns the right count;
  8. ; - SP, software frame, frame arguments, IRQ vectors, and the I/D flags are
  9. ; unchanged across a dispatch;
  10. ; - null, table-less, and zero-entry targets fault without executing
  11. ; anything, and a later dispatch still works;
  12. ; - a full hardware stack is refused with IF_ERR_STACK and recovers after SP
  13. ; is restored;
  14. ; - 12-level recursion stays above FRAME_HW_MIN and restores the frame.
  15. ;
  16. ; MB_DATA flags 0..6 report the seven phases.
  17. .setcpu "6502"
  18. .include "../../src/common/c128.inc"
  19. .include "../../src/common/mailbox.inc"
  20. .include "../../src/common/print.inc"
  21. .include "../../src/common/frames.inc"
  22. .include "../../src/common/interfaces.inc"
  23. .import pr_char, pr_cr, pr_text
  24. .import frame_init, frame_enter, frame_leave, frame_push_byte, frame_discard
  25. .import if_call
  26. .import if_error
  27. .macro TEXT src, len
  28. lda #<src
  29. ldx #>src
  30. ldy #len
  31. jsr pr_text
  32. .endmacro
  33. .macro PHASE n
  34. lda #n
  35. sta MB_CODE
  36. lda #$00
  37. sta MB_CODE+1
  38. .endmacro
  39. .macro FAIL_CS
  40. bcc :+
  41. jmp @fail
  42. :
  43. .endmacro
  44. .macro FAIL_CC
  45. bcs :+
  46. jmp @fail
  47. :
  48. .endmacro
  49. .macro FAIL_NE
  50. beq :+
  51. jmp @fail
  52. :
  53. .endmacro
  54. .segment "LOADADDR"
  55. .word $1C01
  56. .segment "EXEHDR"
  57. .word basic_end
  58. .word 10
  59. .byte $9E
  60. .byte "7181"
  61. .byte $00
  62. basic_end:
  63. .word $0000
  64. .segment "MAILBOX"
  65. .res MB_SIZE
  66. .segment "ZEROPAGE"
  67. vp: .res 2
  68. pv: .res 2
  69. .segment "STARTUP"
  70. .export test_entry, test_end
  71. test_entry:
  72. php
  73. sei
  74. ldx #MB_SIZE - 1
  75. lda #$00
  76. @clr: sta MB_BASE,x
  77. dex
  78. bpl @clr
  79. lda #MB_MAGIC0_VALUE
  80. sta MB_MAGIC0
  81. lda #MB_MAGIC1_VALUE
  82. sta MB_MAGIC1
  83. lda #MB_PROD_PROGRAM
  84. sta MB_PRODUCER
  85. lda #MB_ST_RUNNING
  86. sta MB_STATUS
  87. lda #$00
  88. sta MB_CODE
  89. sta MB_CODE+1
  90. lda MMU_CR
  91. sta saved_cr
  92. lda #CR_RAM0_KERNAL
  93. sta MMU_CR
  94. lda #PR_CLEAR
  95. jsr pr_char
  96. TEXT title, 21
  97. jsr pr_cr
  98. ; 1: three targets selected at runtime, self and A/X checked.
  99. PHASE 1
  100. lda #$00
  101. sta idx
  102. sta impl_calls
  103. sta impl_self_bad
  104. tsx
  105. stx sp_before
  106. @pick: lda idx
  107. asl a
  108. asl a
  109. clc
  110. adc #<vals
  111. sta vp
  112. lda #>vals
  113. adc #$00
  114. sta vp+1
  115. lda vp
  116. ldx vp+1
  117. ldy #$00
  118. jsr if_call
  119. sta result_a
  120. stx result_x
  121. lda if_error
  122. FAIL_NE
  123. tsx
  124. txa
  125. cmp sp_before
  126. FAIL_NE
  127. lda idx
  128. tay
  129. lda result_a
  130. cmp exp_ids,y
  131. FAIL_NE
  132. lda exp_ids,y
  133. clc
  134. adc #$01
  135. cmp result_x
  136. FAIL_NE
  137. inc idx
  138. lda idx
  139. cmp #$03
  140. bne @pick
  141. lda impl_calls
  142. cmp #$03
  143. FAIL_NE
  144. lda impl_self_bad
  145. FAIL_NE
  146. lda #$01
  147. sta MB_DATA+0
  148. ; 2: three-level nested dispatch.
  149. PHASE 2
  150. lda #<val_one
  151. ldx #>val_one
  152. ldy #$00
  153. jsr if_call
  154. sta result_a
  155. stx result_x
  156. lda if_error
  157. FAIL_NE
  158. lda result_a
  159. cmp #$33
  160. FAIL_NE
  161. lda result_x
  162. cmp #$31
  163. FAIL_NE
  164. lda #$01
  165. sta MB_DATA+1
  166. ; 3: recursive dispatch through 8 levels.
  167. PHASE 3
  168. jsr frame_init
  169. lda #$FF
  170. sta rec_min_sp
  171. lda #$00
  172. sta rec_entries
  173. lda #$08
  174. jsr frame_push_byte
  175. FAIL_CS
  176. lda #<val_rec
  177. ldx #>val_rec
  178. ldy #$00
  179. jsr if_call
  180. sta result_a
  181. lda if_error
  182. FAIL_NE
  183. lda #$01
  184. ldx #$00
  185. jsr frame_discard
  186. lda result_a
  187. cmp #$08
  188. FAIL_NE
  189. lda rec_entries
  190. cmp #$09
  191. FAIL_NE
  192. lda FRAME_SP
  193. cmp #<FRAME_STACK_TOP
  194. FAIL_NE
  195. lda FRAME_SP+1
  196. cmp #>FRAME_STACK_TOP
  197. FAIL_NE
  198. lda #$01
  199. sta MB_DATA+2
  200. ; 4: SP, frame, arguments, vectors, and I/D survive a dispatch.
  201. PHASE 4
  202. php
  203. pla
  204. sta p_before
  205. lda $0314
  206. sta v_before
  207. lda $0315
  208. sta v_before+1
  209. lda #$AB
  210. jsr frame_push_byte
  211. FAIL_CS
  212. lda #$CD
  213. jsr frame_push_byte
  214. FAIL_CS
  215. tsx
  216. stx sp_before
  217. lda FRAME_SP
  218. sta fsp_before
  219. lda FRAME_SP+1
  220. sta fsp_before+1
  221. lda #<val_a
  222. ldx #>val_a
  223. ldy #$00
  224. jsr if_call
  225. sta result_a
  226. stx result_x
  227. lda if_error
  228. FAIL_NE
  229. lda result_a
  230. cmp #$A0
  231. FAIL_NE
  232. lda result_x
  233. cmp #$A1
  234. FAIL_NE
  235. tsx
  236. txa
  237. cmp sp_before
  238. FAIL_NE
  239. lda FRAME_SP
  240. cmp fsp_before
  241. FAIL_NE
  242. lda FRAME_SP+1
  243. cmp fsp_before+1
  244. FAIL_NE
  245. lda FRAME_SP
  246. sta pv
  247. lda FRAME_SP+1
  248. sta pv+1
  249. ldy #$00
  250. lda (pv),y
  251. cmp #$CD
  252. FAIL_NE
  253. iny
  254. lda (pv),y
  255. cmp #$AB
  256. FAIL_NE
  257. lda $0314
  258. cmp v_before
  259. FAIL_NE
  260. lda $0315
  261. cmp v_before+1
  262. FAIL_NE
  263. php
  264. pla
  265. and #$0C
  266. sta p_after
  267. lda p_before
  268. and #$0C
  269. cmp p_after
  270. FAIL_NE
  271. lda #$02
  272. ldx #$00
  273. jsr frame_discard
  274. lda FRAME_SP
  275. cmp #<FRAME_STACK_TOP
  276. FAIL_NE
  277. lda FRAME_SP+1
  278. cmp #>FRAME_STACK_TOP
  279. FAIL_NE
  280. lda #$01
  281. sta MB_DATA+3
  282. ; 5: faults never execute a target, and dispatch recovers.
  283. PHASE 5
  284. lda impl_calls
  285. sta calls_before
  286. tsx
  287. stx sp_before
  288. lda #<val_null
  289. ldx #>val_null
  290. ldy #$00
  291. jsr if_call
  292. FAIL_CC
  293. sta result_a
  294. stx result_x
  295. lda if_error
  296. cmp #IF_ERR_NULL
  297. FAIL_NE
  298. lda result_a
  299. FAIL_NE
  300. lda result_x
  301. FAIL_NE
  302. tsx
  303. txa
  304. cmp sp_before
  305. FAIL_NE
  306. lda #<val_notable
  307. ldx #>val_notable
  308. ldy #$00
  309. jsr if_call
  310. FAIL_CC
  311. sta result_a
  312. stx result_x
  313. lda if_error
  314. cmp #IF_ERR_TABLE
  315. FAIL_NE
  316. lda result_a
  317. FAIL_NE
  318. lda result_x
  319. FAIL_NE
  320. tsx
  321. txa
  322. cmp sp_before
  323. FAIL_NE
  324. lda #<val_zero
  325. ldx #>val_zero
  326. ldy #$00
  327. jsr if_call
  328. FAIL_CC
  329. sta result_a
  330. stx result_x
  331. lda if_error
  332. cmp #IF_ERR_ENTRY
  333. FAIL_NE
  334. lda result_a
  335. FAIL_NE
  336. lda result_x
  337. FAIL_NE
  338. lda impl_calls
  339. cmp calls_before
  340. FAIL_NE
  341. lda #<val_a
  342. ldx #>val_a
  343. ldy #$00
  344. jsr if_call
  345. sta result_a
  346. lda if_error
  347. FAIL_NE
  348. lda result_a
  349. cmp #$A0
  350. FAIL_NE
  351. lda #$01
  352. sta MB_DATA+4
  353. ; 6: a full hardware stack is refused, then SP is restored.
  354. PHASE 6
  355. tsx
  356. stx sp_saved
  357. @fill: lda #$00
  358. pha
  359. tsx
  360. cpx #(FRAME_HW_MIN - 1)
  361. bne @fill
  362. lda #<val_a
  363. ldx #>val_a
  364. ldy #$00
  365. jsr if_call
  366. FAIL_CC
  367. sta result_a
  368. stx result_x
  369. lda if_error
  370. cmp #IF_ERR_STACK
  371. FAIL_NE
  372. lda result_a
  373. FAIL_NE
  374. lda result_x
  375. FAIL_NE
  376. ldx sp_saved
  377. txs
  378. tsx
  379. cpx sp_saved
  380. FAIL_NE
  381. lda #<val_a
  382. ldx #>val_a
  383. ldy #$00
  384. jsr if_call
  385. sta result_a
  386. lda if_error
  387. FAIL_NE
  388. lda result_a
  389. cmp #$A0
  390. FAIL_NE
  391. lda #$01
  392. sta MB_DATA+5
  393. ; 7: 12-level recursion stays above the stack floor.
  394. PHASE 7
  395. lda #$FF
  396. sta rec_min_sp
  397. lda #$00
  398. sta rec_entries
  399. lda #$0C
  400. jsr frame_push_byte
  401. FAIL_CS
  402. lda #<val_rec
  403. ldx #>val_rec
  404. ldy #$00
  405. jsr if_call
  406. sta result_a
  407. lda if_error
  408. FAIL_NE
  409. lda #$01
  410. ldx #$00
  411. jsr frame_discard
  412. lda result_a
  413. cmp #$0C
  414. FAIL_NE
  415. lda rec_entries
  416. cmp #$0D
  417. FAIL_NE
  418. lda rec_min_sp
  419. cmp #FRAME_HW_MIN
  420. FAIL_CC
  421. lda FRAME_SP
  422. cmp #<FRAME_STACK_TOP
  423. FAIL_NE
  424. lda FRAME_SP+1
  425. cmp #>FRAME_STACK_TOP
  426. FAIL_NE
  427. lda #$01
  428. sta MB_DATA+6
  429. TEXT dispatch_ok, 11
  430. jsr pr_cr
  431. lda #MB_ST_PASS
  432. sta MB_STATUS
  433. lda #$00
  434. sta MB_CODE
  435. sta MB_CODE+1
  436. jmp @restore
  437. @fail:
  438. lda #MB_ST_FAIL
  439. sta MB_STATUS
  440. TEXT dispatch_fail, 13
  441. jsr pr_cr
  442. @restore:
  443. lda saved_cr
  444. sta MMU_CR
  445. plp
  446. rts
  447. ; Three runtime-selected targets. Each checks that A/X is its object pointer,
  448. ; then returns an id pair ($?0/$?1).
  449. impl_a:
  450. cmp #$11
  451. bne @bad
  452. cpx #$11
  453. beq @ok
  454. @bad: inc impl_self_bad
  455. @ok: inc impl_calls
  456. lda #$A0
  457. ldx #$A1
  458. rts
  459. impl_b:
  460. cmp #$22
  461. bne @bad
  462. cpx #$22
  463. beq @ok
  464. @bad: inc impl_self_bad
  465. @ok: inc impl_calls
  466. lda #$B0
  467. ldx #$B1
  468. rts
  469. impl_c:
  470. cmp #$33
  471. bne @bad
  472. cpx #$33
  473. beq @ok
  474. @bad: inc impl_self_bad
  475. @ok: inc impl_calls
  476. lda #$C0
  477. ldx #$C1
  478. rts
  479. ; Nested chain: one -> two -> three, each level adding its own offset.
  480. impl_three:
  481. inc impl_calls
  482. lda #$30
  483. ldx #$31
  484. rts
  485. impl_two:
  486. inc impl_calls
  487. lda #<val_three
  488. ldx #>val_three
  489. ldy #$00
  490. jsr if_call
  491. sta child
  492. lda if_error
  493. bne @err
  494. lda child
  495. clc
  496. adc #$02
  497. rts
  498. @err: lda #$00
  499. ldx #$00
  500. sec
  501. rts
  502. impl_one:
  503. inc impl_calls
  504. lda #<val_two
  505. ldx #>val_two
  506. ldy #$00
  507. jsr if_call
  508. sta child
  509. lda if_error
  510. bne @err
  511. lda child
  512. clc
  513. adc #$01
  514. rts
  515. @err: lda #$00
  516. ldx #$00
  517. sec
  518. rts
  519. ; Recursive target: A/X = self, depth arrives at FP+2. Returns depth in A, X=0.
  520. impl_rec:
  521. lda #$00
  522. ldx #$00
  523. jsr frame_enter
  524. bcc @in
  525. sec
  526. rts
  527. @in: inc rec_entries
  528. tsx
  529. cpx rec_min_sp
  530. bcs :+
  531. stx rec_min_sp
  532. : ldy #$02
  533. lda (FRAME_FP),y
  534. beq @zero
  535. sec
  536. sbc #$01
  537. jsr frame_push_byte
  538. bcs @bad_stack
  539. lda #<val_rec
  540. ldx #>val_rec
  541. ldy #$00
  542. jsr if_call
  543. sta child
  544. lda if_error
  545. bne @bad_nested
  546. lda #$01
  547. ldx #$00
  548. jsr frame_discard
  549. lda child
  550. clc
  551. adc #$01
  552. sta child
  553. jsr frame_leave
  554. lda child
  555. ldx #$00
  556. clc
  557. rts
  558. @zero: jsr frame_leave
  559. lda #$00
  560. ldx #$00
  561. clc
  562. rts
  563. @bad_stack:
  564. jsr frame_leave
  565. sec
  566. rts
  567. @bad_nested:
  568. lda #$01
  569. ldx #$00
  570. jsr frame_discard
  571. jsr frame_leave
  572. sec
  573. rts
  574. .segment "DATA"
  575. vals: .word $1111, tab_a
  576. .word $2222, tab_b
  577. .word $3333, tab_c
  578. .assert * - vals = 12, error, "three value records"
  579. exp_ids: .byte $A0, $B0, $C0
  580. tab_a: .word impl_a
  581. tab_b: .word impl_b
  582. tab_c: .word impl_c
  583. val_a: .word $1111, tab_a
  584. val_one: .word $4444, tab_one
  585. tab_one: .word impl_one
  586. val_two: .word $5555, tab_two
  587. tab_two: .word impl_two
  588. val_three: .word $6666, tab_three
  589. tab_three: .word impl_three
  590. val_rec: .word $7777, tab_rec
  591. tab_rec: .word impl_rec
  592. val_null: .word $0000, $0000
  593. val_notable: .word $1111, $0000
  594. tab_zero: .word $0000
  595. .assert * - tab_zero = IF_SLOT_SIZE, error, "one slot per table"
  596. val_zero: .word $2222, tab_zero
  597. .segment "RODATA"
  598. title: .byte "NOVA128 DISPATCH TEST"
  599. dispatch_ok: .byte "DISPATCH OK"
  600. dispatch_fail: .byte "DISPATCH FAIL"
  601. .segment "BSS"
  602. saved_cr: .res 1
  603. idx: .res 1
  604. impl_calls: .res 1
  605. impl_self_bad: .res 1
  606. result_a: .res 1
  607. result_x: .res 1
  608. sp_before: .res 1
  609. sp_saved: .res 1
  610. p_before: .res 1
  611. p_after: .res 1
  612. fsp_before: .res 2
  613. v_before: .res 2
  614. calls_before: .res 1
  615. child: .res 1
  616. rec_min_sp: .res 1
  617. rec_entries: .res 1
  618. test_end:

Powered by TurnKey Linux.