您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

600 行
13KB

  1. ; E05-S04: fields, self, and concrete calls in x128.
  2. ;
  3. ; members.s emits method-body fragments; this fixture generates several and
  4. ; executes them against two objects of the same class layout (descriptor word
  5. ; at +0, byte field at +2, word field at +3..4):
  6. ;
  7. ; 1. a field writer storing the immediates in gen_count/gen_lo/gen_hi,
  8. ; run on both objects, then read back through emitted byte and word
  9. ; loaders, which proves offsets and independent state;
  10. ; 2. a caller that loads a receiver reference with mb_point, pushes arguments
  11. ; on the frame stack, and calls a real method with self in A/X, which
  12. ; proves the direct-JSR call ABI and argument discard;
  13. ; 3. the same caller shape with a word result, stored by the call site.
  14. ;
  15. ; Mailbox data:
  16. ; +0 field store/load offsets verified (1)
  17. ; +1 the two objects kept independent state (1)
  18. ; +2 concrete call ABI and argument discard verified (1)
  19. ; +3 word result preserved across the call path (1)
  20. ; +4 word result low byte ($78)
  21. ; +5 word result high byte ($56)
  22. ; Failure bits: 1 emitter, 2 store/offset, 4 independence, 8 call ABI,
  23. ; 16 result.
  24. .setcpu "6502"
  25. .include "../../src/common/c128.inc"
  26. .include "../../src/common/mailbox.inc"
  27. .include "../../src/common/print.inc"
  28. .include "../../src/common/codegen.inc"
  29. .include "../../src/common/flow.inc"
  30. .include "../../src/common/frames.inc"
  31. .include "../../src/common/members.inc"
  32. .import cg_init, cg_err, cg_code, cg_rts
  33. .import cg_lda_imm, cg_ldx_imm, cg_jsr_abs, cg_sta_abs, cg_stx_abs
  34. .import fl_err, fl_enter, fl_leave, fl_discard
  35. .import mb_init, mb_point, mb_self_load, mb_self_store
  36. .import mb_ld_field, mb_st_field, mb_call, mb_call_word
  37. .import mb_err
  38. .import frame_init, frame_enter, frame_leave, frame_discard, frame_push_byte, frame_push_word
  39. .import pr_char, pr_text, pr_cr
  40. COUNT_OFF = 2 ; byte field
  41. TOTAL_OFF = 3 ; word field
  42. OBJ_SIZE = 5
  43. .macro TEXT src, len
  44. lda #<src
  45. ldx #>src
  46. ldy #len
  47. jsr pr_text
  48. .endmacro
  49. ; Branch to a global label even when it is out of relative range.
  50. .macro ON_CARRY target
  51. bcc :+
  52. jmp target
  53. :
  54. .endmacro
  55. .macro ON_NE target
  56. beq :+
  57. jmp target
  58. :
  59. .endmacro
  60. .segment "LOADADDR"
  61. .word $1C01
  62. .segment "EXEHDR"
  63. .word basic_end
  64. .word 10
  65. .byte $9E
  66. .byte "7181"
  67. .byte $00
  68. basic_end:
  69. .word $0000
  70. .segment "MAILBOX"
  71. .res MB_SIZE
  72. .segment "ZEROPAGE"
  73. set_ptr: .res 2 ; receiver for the hand-written methods
  74. .segment "STARTUP"
  75. .export test_entry, test_end
  76. test_entry:
  77. php
  78. sei
  79. ldx #MB_SIZE - 1
  80. lda #$00
  81. @clr: sta MB_BASE,x
  82. dex
  83. bpl @clr
  84. lda #MB_MAGIC0_VALUE
  85. sta MB_MAGIC0
  86. lda #MB_MAGIC1_VALUE
  87. sta MB_MAGIC1
  88. lda #MB_PROD_PROGRAM
  89. sta MB_PRODUCER
  90. lda #MB_ST_RUNNING
  91. sta MB_STATUS
  92. lda #$00
  93. sta MB_CODE
  94. sta MB_CODE+1
  95. lda MMU_CR
  96. sta saved_cr
  97. lda #CR_RAM0_KERNAL
  98. sta MMU_CR
  99. lda #PR_CLEAR
  100. jsr pr_char
  101. jsr clear_state
  102. jsr frame_init
  103. jsr mb_init
  104. ; Runtime addresses the emitted prologue and call helpers need.
  105. lda #<frame_enter
  106. sta fl_enter
  107. lda #>frame_enter
  108. sta fl_enter+1
  109. lda #<frame_leave
  110. sta fl_leave
  111. lda #>frame_leave
  112. sta fl_leave+1
  113. lda #<frame_discard
  114. sta fl_discard
  115. lda #>frame_discard
  116. sta fl_discard+1
  117. ; ---------------------------------------- 1. field store on both objects
  118. lda #3
  119. sta gen_count
  120. lda #$34
  121. sta gen_lo
  122. lda #$12
  123. sta gen_hi
  124. jsr cg_init
  125. jsr gen_store
  126. ON_CARRY emitter_error
  127. jsr run_a
  128. lda obj_a+COUNT_OFF
  129. cmp #3
  130. ON_NE store_fail
  131. lda obj_a+TOTAL_OFF
  132. cmp #$34
  133. ON_NE store_fail
  134. lda obj_a+TOTAL_OFF+1
  135. cmp #$12
  136. ON_NE store_fail
  137. lda #7
  138. sta gen_count
  139. lda #$78
  140. sta gen_lo
  141. lda #$56
  142. sta gen_hi
  143. jsr cg_init
  144. jsr gen_store
  145. ON_CARRY emitter_error
  146. jsr run_b
  147. lda obj_b+COUNT_OFF
  148. cmp #7
  149. ON_NE store_fail
  150. lda obj_b+TOTAL_OFF
  151. cmp #$78
  152. ON_NE store_fail
  153. lda obj_b+TOTAL_OFF+1
  154. cmp #$56
  155. ON_NE store_fail
  156. ; A must be untouched by writing B.
  157. lda obj_a+COUNT_OFF
  158. cmp #3
  159. ON_NE indep_fail
  160. lda obj_a+TOTAL_OFF
  161. cmp #$34
  162. ON_NE indep_fail
  163. lda obj_a+TOTAL_OFF+1
  164. cmp #$12
  165. ON_NE indep_fail
  166. ; ------------------------------------- field loads through the emitter
  167. jsr cg_init
  168. jsr gen_read_count
  169. ON_CARRY emitter_error
  170. jsr run_a
  171. sta v_count_a
  172. jsr run_b
  173. sta v_count_b
  174. lda v_count_a
  175. cmp #3
  176. ON_NE store_fail
  177. lda v_count_b
  178. cmp #7
  179. ON_NE indep_fail
  180. jsr cg_init
  181. jsr gen_read_total
  182. ON_CARRY emitter_error
  183. jsr run_a
  184. sta v_lo_a
  185. stx v_hi_a
  186. jsr run_b
  187. sta v_lo_b
  188. stx v_hi_b
  189. lda v_lo_a
  190. cmp #$34
  191. ON_NE store_fail
  192. lda v_hi_a
  193. cmp #$12
  194. ON_NE store_fail
  195. lda v_lo_b
  196. cmp #$78
  197. ON_NE indep_fail
  198. lda v_hi_b
  199. cmp #$56
  200. ON_NE indep_fail
  201. lda #$01
  202. sta MB_DATA+0
  203. sta MB_DATA+1
  204. ; ------------------------------- 2. concrete call with arguments
  205. lda FRAME_SP
  206. sta sp_before
  207. lda FRAME_SP+1
  208. sta sp_before+1
  209. lda #<ref_a
  210. sta call_ref
  211. lda #>ref_a
  212. sta call_ref+1
  213. lda #9
  214. sta call_count
  215. lda #$CD
  216. sta call_lo
  217. lda #$AB
  218. sta call_hi
  219. jsr cg_init
  220. jsr gen_call_set
  221. ON_CARRY emitter_error
  222. lda #$00
  223. jsr run_plain
  224. lda obj_a+COUNT_OFF
  225. cmp #9
  226. ON_NE call_fail
  227. lda obj_a+TOTAL_OFF
  228. cmp #$CD
  229. ON_NE call_fail
  230. lda obj_a+TOTAL_OFF+1
  231. cmp #$AB
  232. ON_NE call_fail
  233. lda FRAME_SP
  234. cmp sp_before
  235. ON_NE call_fail
  236. lda FRAME_SP+1
  237. cmp sp_before+1
  238. ON_NE call_fail
  239. lda obj_b+COUNT_OFF ; B was not the receiver
  240. cmp #7
  241. ON_NE call_fail
  242. lda #$01
  243. sta MB_DATA+2
  244. ; ------------------------------------- 3. word result at the call site
  245. lda #<ref_b
  246. sta call_ref
  247. lda #>ref_b
  248. sta call_ref+1
  249. jsr cg_init
  250. jsr gen_call_total
  251. ON_CARRY emitter_error
  252. lda #$00
  253. jsr run_plain
  254. lda res_lo
  255. sta MB_DATA+4
  256. lda res_hi
  257. sta MB_DATA+5
  258. lda res_lo
  259. cmp #$78
  260. ON_NE result_fail
  261. lda res_hi
  262. cmp #$56
  263. ON_NE result_fail
  264. lda #$01
  265. sta MB_DATA+3
  266. jmp report
  267. emitter_error:
  268. lda #$01
  269. jmp fail
  270. store_fail:
  271. lda #$02
  272. jmp fail
  273. indep_fail:
  274. lda #$04
  275. jmp fail
  276. call_fail:
  277. lda #$08
  278. jmp fail
  279. result_fail:
  280. lda #$10
  281. jmp fail
  282. fail:
  283. ora fail_mask
  284. sta fail_mask
  285. report:
  286. lda saved_cr
  287. sta MMU_CR
  288. lda fail_mask
  289. sta MB_CODE
  290. lda #$00
  291. sta MB_CODE+1
  292. ldx fail_mask
  293. bne @fail
  294. lda #MB_ST_PASS
  295. sta MB_STATUS
  296. TEXT msg_ok, 9
  297. jmp @end
  298. @fail:
  299. lda #MB_ST_FAIL
  300. sta MB_STATUS
  301. TEXT msg_fail, 11
  302. @end: jsr pr_cr
  303. plp
  304. rts
  305. ; ------------------------------------------------------------- state
  306. clear_state:
  307. lda #$00
  308. sta fail_mask
  309. sta res_lo
  310. sta res_hi
  311. sta v_count_a
  312. sta v_count_b
  313. ldx #OBJ_SIZE - 1
  314. @a: sta obj_a,x
  315. dex
  316. bpl @a
  317. ldx #OBJ_SIZE - 1
  318. @b: sta obj_b,x
  319. dex
  320. bpl @b
  321. sta obj_a+0 ; descriptor words stay zero here: these
  322. sta obj_b+0 ; fixtures exercise fields, not classes
  323. lda #<obj_a
  324. sta ref_a
  325. lda #>obj_a
  326. sta ref_a+1
  327. lda #<obj_b
  328. sta ref_b
  329. lda #>obj_b
  330. sta ref_b+1
  331. rts
  332. ; --------------------------------------------------------- generators
  333. ; store self.count = gen_count; self.total = gen_hi:gen_lo
  334. gen_store:
  335. jsr mb_self_store
  336. ON_CARRY gen_out
  337. lda gen_count
  338. jsr cg_lda_imm
  339. ON_CARRY gen_out
  340. lda #COUNT_OFF
  341. ldx #MB_BYTE
  342. jsr mb_st_field
  343. ON_CARRY gen_out
  344. lda gen_lo
  345. jsr cg_lda_imm
  346. ON_CARRY gen_out
  347. lda gen_hi
  348. jsr cg_ldx_imm
  349. ON_CARRY gen_out
  350. lda #TOTAL_OFF
  351. ldx #MB_WORD
  352. jsr mb_st_field
  353. ON_CARRY gen_out
  354. jmp cg_rts
  355. gen_out:
  356. sec
  357. rts
  358. ; return self.count
  359. gen_read_count:
  360. jsr mb_self_store
  361. ON_CARRY gen_out
  362. lda #COUNT_OFF
  363. ldx #MB_BYTE
  364. jsr mb_ld_field
  365. ON_CARRY gen_out
  366. jmp cg_rts
  367. ; return self.total
  368. gen_read_total:
  369. jsr mb_self_store
  370. ON_CARRY gen_out
  371. lda #TOTAL_OFF
  372. ldx #MB_WORD
  373. jsr mb_ld_field
  374. ON_CARRY gen_out
  375. jmp cg_rts
  376. ; receiver = *call_ref; push(word call_hi:call_lo); push(byte call_count);
  377. ; call setter(3 bytes). Demonstrates the caller ABI from generated code.
  378. gen_call_set:
  379. lda call_ref
  380. ldx call_ref+1
  381. jsr mb_point
  382. ON_CARRY gen_out
  383. lda call_lo
  384. jsr cg_lda_imm
  385. ON_CARRY gen_out
  386. lda call_hi
  387. jsr cg_ldx_imm
  388. ON_CARRY gen_out
  389. lda #<frame_push_word
  390. ldx #>frame_push_word
  391. jsr cg_jsr_abs
  392. ON_CARRY gen_out
  393. lda call_count
  394. jsr cg_lda_imm
  395. ON_CARRY gen_out
  396. lda #<frame_push_byte
  397. ldx #>frame_push_byte
  398. jsr cg_jsr_abs
  399. ON_CARRY gen_out
  400. lda #<setter
  401. ldx #>setter
  402. ldy #3
  403. jsr mb_call
  404. ON_CARRY gen_out
  405. jmp cg_rts
  406. ; receiver = *call_ref; result = total(). The call site stores A/X, so the
  407. ; word result has to survive the call epilogue.
  408. gen_call_total:
  409. lda call_ref
  410. ldx call_ref+1
  411. jsr mb_point
  412. ON_CARRY gen_out
  413. lda #<total_of
  414. ldx #>total_of
  415. ldy #0
  416. jsr mb_call_word
  417. ON_CARRY gen_out
  418. lda #<res_lo
  419. ldx #>res_lo
  420. jsr cg_sta_abs
  421. ON_CARRY gen_out
  422. lda #<res_hi
  423. ldx #>res_hi
  424. jsr cg_stx_abs
  425. ON_CARRY gen_out
  426. jmp cg_rts
  427. ; ------------------------------------------------------------ methods
  428. ; set(count as byte, total as word): self in A/X.
  429. setter:
  430. sta cur_self
  431. stx cur_self+1
  432. lda #$00
  433. ldx #$00
  434. jsr frame_enter
  435. bcs @fault
  436. lda cur_self
  437. sta set_ptr
  438. lda cur_self+1
  439. sta set_ptr+1
  440. ldy #2
  441. lda (FRAME_FP),y
  442. ldy #COUNT_OFF
  443. sta (set_ptr),y
  444. ldy #3
  445. lda (FRAME_FP),y
  446. ldy #TOTAL_OFF
  447. sta (set_ptr),y
  448. ldy #4
  449. lda (FRAME_FP),y
  450. ldy #TOTAL_OFF+1
  451. sta (set_ptr),y
  452. jsr frame_leave
  453. clc
  454. rts
  455. @fault: sec
  456. rts
  457. ; total() as word: A = low, X = high.
  458. total_of:
  459. sta cur_self
  460. stx cur_self+1
  461. lda #$00
  462. ldx #$00
  463. jsr frame_enter
  464. bcs @fault
  465. lda cur_self
  466. sta set_ptr
  467. lda cur_self+1
  468. sta set_ptr+1
  469. ldy #TOTAL_OFF
  470. lda (set_ptr),y
  471. pha
  472. ldy #TOTAL_OFF+1
  473. lda (set_ptr),y
  474. tax
  475. pla
  476. pha
  477. txa
  478. pha
  479. jsr frame_leave
  480. pla
  481. tax
  482. pla
  483. clc
  484. rts
  485. @fault: sec
  486. rts
  487. ; ------------------------------------------------------------- runners
  488. ; A = code offset; A/X = self for the snippet.
  489. run_self:
  490. clc
  491. adc #<cg_code
  492. sta @target+1
  493. lda #>cg_code
  494. adc #$00
  495. sta @target+2
  496. lda run_ptr
  497. ldx run_ptr+1
  498. @target:
  499. jsr $FFFF
  500. rts
  501. ; A = code offset; no receiver.
  502. run_plain:
  503. clc
  504. adc #<cg_code
  505. sta @target+1
  506. lda #>cg_code
  507. adc #$00
  508. sta @target+2
  509. @target:
  510. jsr $FFFF
  511. rts
  512. run_a:
  513. lda #<obj_a
  514. sta run_ptr
  515. lda #>obj_a
  516. sta run_ptr+1
  517. lda #$00
  518. jmp run_self
  519. run_b:
  520. lda #<obj_b
  521. sta run_ptr
  522. lda #>obj_b
  523. sta run_ptr+1
  524. lda #$00
  525. jmp run_self
  526. .segment "RODATA"
  527. msg_ok: .byte "MEMBER OK"
  528. msg_fail: .byte "MEMBER FAIL"
  529. .segment "BSS"
  530. saved_cr: .res 1
  531. fail_mask: .res 1
  532. gen_count: .res 1
  533. gen_lo: .res 1
  534. gen_hi: .res 1
  535. call_ref: .res 2
  536. call_count: .res 1
  537. call_lo: .res 1
  538. call_hi: .res 1
  539. run_ptr: .res 2
  540. sp_before: .res 2
  541. res_lo: .res 1
  542. res_hi: .res 1
  543. v_count_a: .res 1
  544. v_count_b: .res 1
  545. v_lo_a: .res 1
  546. v_hi_a: .res 1
  547. v_lo_b: .res 1
  548. v_hi_b: .res 1
  549. obj_a: .res OBJ_SIZE
  550. obj_b: .res OBJ_SIZE
  551. ref_a: .res 2
  552. ref_b: .res 2
  553. cur_self: .res 2
  554. test_end:

Powered by TurnKey Linux.