Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

188 строки
4.5KB

  1. ; frames.s - generated-program software frames (E04-S02).
  2. ;
  3. ; All routines run with CR=$0E and IRQs masked. FRAME_SP/FRAME_FP live at
  4. ; $FB-$FE; the frame stack occupies $B800-$BFFF and grows downward from
  5. ; $C000. See src/common/frames.inc for the layout and calling convention.
  6. ;
  7. ; frame_enter is transactional on failure: if the stack bound would be
  8. ; crossed, SP and FP are restored to their entry values and C=1 with
  9. ; frame_error=FRAME_ERR_STACK. No partial frame remains.
  10. .setcpu "6502"
  11. .include "../common/frames.inc"
  12. .export frame_init, frame_enter, frame_leave, frame_discard
  13. .export frame_push_byte, frame_push_word, frame_error
  14. .segment "CODE"
  15. ; Empty software stack: SP=$C000, FP=0, no error.
  16. frame_init:
  17. lda #<FRAME_STACK_TOP
  18. sta FRAME_SP
  19. lda #>FRAME_STACK_TOP
  20. sta FRAME_SP+1
  21. lda #$00
  22. sta FRAME_FP
  23. sta FRAME_FP+1
  24. sta frame_error
  25. clc
  26. rts
  27. ; A/X = byte count (low/high). C=0 and SP updated on success; C=1 with
  28. ; FRAME_ERR_STACK and SP unchanged when the new SP would fall below the base.
  29. frame_reserve:
  30. sta frame_size
  31. stx frame_size+1
  32. lda FRAME_SP
  33. sec
  34. sbc frame_size
  35. sta frame_new_sp
  36. lda FRAME_SP+1
  37. sbc frame_size+1
  38. sta frame_new_sp+1
  39. lda frame_new_sp+1
  40. cmp #>FRAME_STACK_BASE
  41. bcc @fail
  42. bne @ok
  43. lda frame_new_sp
  44. cmp #<FRAME_STACK_BASE
  45. bcc @fail
  46. @ok: lda frame_new_sp
  47. sta FRAME_SP
  48. lda frame_new_sp+1
  49. sta FRAME_SP+1
  50. clc
  51. rts
  52. @fail: lda #FRAME_ERR_STACK
  53. sta frame_error
  54. sec
  55. rts
  56. ; Push one argument byte (A). C=1 on stack overflow.
  57. frame_push_byte:
  58. sta frame_byte
  59. lda #1
  60. ldx #0
  61. jsr frame_reserve
  62. bcs @out
  63. ldy #0
  64. lda frame_byte
  65. sta (FRAME_SP),y
  66. clc
  67. @out: rts
  68. ; Push one argument word: A=low, X=high. C=1 on stack overflow.
  69. frame_push_word:
  70. sta frame_word
  71. stx frame_word+1
  72. lda #2
  73. ldx #0
  74. jsr frame_reserve
  75. bcs @out
  76. ldy #1
  77. lda frame_word+1
  78. sta (FRAME_SP),y
  79. dey
  80. lda frame_word
  81. sta (FRAME_SP),y
  82. clc
  83. @out: rts
  84. ; Enter a callee frame. Arguments are already on the stack above FP+2.
  85. ; A/X = local byte count (low/high)
  86. ; C=0: old FP pushed, FP set, locals reserved
  87. ; C=1: no frame was created; SP/FP are unchanged
  88. frame_enter:
  89. sta frame_locals
  90. stx frame_locals+1
  91. tsx
  92. cpx #FRAME_HW_MIN
  93. bcs @hw_ok
  94. lda #FRAME_ERR_STACK
  95. sta frame_error
  96. sec
  97. rts
  98. @hw_ok: lda FRAME_SP
  99. sta frame_saved_sp
  100. lda FRAME_SP+1
  101. sta frame_saved_sp+1
  102. lda FRAME_FP
  103. sta frame_saved_fp
  104. lda FRAME_FP+1
  105. sta frame_saved_fp+1
  106. lda FRAME_FP
  107. ldx FRAME_FP+1
  108. jsr frame_push_word
  109. bcs @out ; old-FP push overflow: nothing changed
  110. lda FRAME_SP
  111. sta FRAME_FP
  112. lda FRAME_SP+1
  113. sta FRAME_FP+1
  114. lda frame_locals
  115. ldx frame_locals+1
  116. jsr frame_reserve
  117. bcc @ok
  118. lda frame_saved_sp ; locals overflow: undo the old FP push
  119. sta FRAME_SP
  120. lda frame_saved_sp+1
  121. sta FRAME_SP+1
  122. lda frame_saved_fp
  123. sta FRAME_FP
  124. lda frame_saved_fp+1
  125. sta FRAME_FP+1
  126. sec
  127. @out: rts
  128. @ok: clc
  129. rts
  130. ; Leave the current frame. SP=FP, pop the previous FP, and leave SP pointing
  131. ; at arg0. The caller still owns the argument bytes.
  132. frame_leave:
  133. lda FRAME_FP
  134. sta FRAME_SP
  135. lda FRAME_FP+1
  136. sta FRAME_SP+1
  137. ldy #0
  138. lda (FRAME_SP),y
  139. sta FRAME_FP
  140. iny
  141. lda (FRAME_SP),y
  142. sta FRAME_FP+1
  143. lda FRAME_SP
  144. clc
  145. adc #2
  146. sta FRAME_SP
  147. bcc @done
  148. inc FRAME_SP+1
  149. @done: rts
  150. ; Pop argument bytes after a return. A/X = byte count (low/high). A and X
  151. ; are preserved so the caller can still store the callee's result.
  152. frame_discard:
  153. sta frame_discard_n
  154. stx frame_discard_n+1
  155. clc
  156. lda FRAME_SP
  157. adc frame_discard_n
  158. sta FRAME_SP
  159. lda FRAME_SP+1
  160. adc frame_discard_n+1
  161. sta FRAME_SP+1
  162. lda frame_discard_n
  163. ldx frame_discard_n+1
  164. rts
  165. .segment "BSS"
  166. frame_size: .res 2
  167. frame_new_sp: .res 2
  168. frame_byte: .res 1
  169. frame_word: .res 2
  170. frame_locals: .res 2
  171. frame_saved_sp: .res 2
  172. frame_saved_fp: .res 2
  173. frame_discard_n: .res 2
  174. frame_error: .res 1

Powered by TurnKey Linux.