You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 line
4.4KB

  1. ; codegen.s - documented scalar instruction emitter (E04-S03).
  2. ;
  3. ; The emitter writes into cg_code, a 256-byte RAM buffer. cg_len is the byte
  4. ; count (0-254); every failure sets cg_err and returns C=1. It does not emit a
  5. ; whole function yet: parser/codegen integration is E04-S04.
  6. ;
  7. ; API:
  8. ; cg_init
  9. ; cg_put A = byte
  10. ; cg_lda_imm A = value
  11. ; cg_ldx_imm A = value
  12. ; cg_ora_imm A = value
  13. ; cg_lda_abs A/X = address
  14. ; cg_ldx_abs A/X = address
  15. ; cg_sta_abs A/X = address
  16. ; cg_stx_abs A/X = address
  17. ; cg_adc_abs A/X = address
  18. ; cg_sbc_abs A/X = address
  19. ; cg_cmp_abs A/X = address
  20. ; cg_jsr_abs A/X = address
  21. ; cg_clc, cg_sec, cg_rts
  22. ; cg_branch_fwd A = branch opcode; emits opcode + placeholder, returns
  23. ; C=0 and A = fixup index
  24. ; cg_patch_here A = fixup index; target is the current end of buffer
  25. ; cg_here returns A = current length
  26. ;
  27. ; Only forward relative branches within +0..+127 bytes are accepted. This is
  28. ; enough for the scalar shapes and gives E04-S04 the checked primitive it
  29. ; needs for a later long-branch expansion.
  30. .setcpu "6502"
  31. .include "../common/codegen.inc"
  32. .export cg_init, cg_put, cg_here, cg_branch_fwd, cg_patch_here
  33. .export cg_lda_imm, cg_ldx_imm, cg_ora_imm, cg_lda_abs, cg_ldx_abs
  34. .export cg_sta_abs, cg_stx_abs, cg_adc_abs, cg_sbc_abs, cg_cmp_abs
  35. .export cg_jsr_abs, cg_clc, cg_sec, cg_rts
  36. .export cg_code, cg_len, cg_err
  37. .segment "CODE"
  38. cg_init:
  39. lda #$00
  40. sta cg_len
  41. sta cg_err
  42. sta cg_fix_count
  43. clc
  44. rts
  45. cg_here:
  46. lda cg_len
  47. rts
  48. ; A = byte to append. C=1 on overflow.
  49. cg_put:
  50. ldy cg_len
  51. cpy #CG_MAX
  52. bcs @full
  53. sta cg_code,y
  54. inc cg_len
  55. clc
  56. rts
  57. @full: lda #CG_ERR_FULL
  58. sta cg_err
  59. sec
  60. rts
  61. ; Immediate forms.
  62. cg_lda_imm:
  63. pha
  64. lda #$A9
  65. jsr cg_put
  66. bcs @out
  67. pla
  68. jmp cg_put
  69. @out: pla
  70. sec
  71. rts
  72. cg_ldx_imm:
  73. pha
  74. lda #$A2
  75. jsr cg_put
  76. bcs @out
  77. pla
  78. jmp cg_put
  79. @out: pla
  80. sec
  81. rts
  82. cg_ora_imm:
  83. pha
  84. lda #$09
  85. jsr cg_put
  86. bcs @out
  87. pla
  88. jmp cg_put
  89. @out: pla
  90. sec
  91. rts
  92. ; Absolute-address forms. Each wrapper supplies the opcode in Y; the shared
  93. ; routine stores the address before Y is reused by cg_put.
  94. cg_lda_abs:
  95. ldy #$AD
  96. jmp cg_emit_addr
  97. cg_ldx_abs:
  98. ldy #$AE
  99. jmp cg_emit_addr
  100. cg_sta_abs:
  101. ldy #$8D
  102. jmp cg_emit_addr
  103. cg_stx_abs:
  104. ldy #$8E
  105. jmp cg_emit_addr
  106. cg_adc_abs:
  107. ldy #$6D
  108. jmp cg_emit_addr
  109. cg_sbc_abs:
  110. ldy #$ED
  111. jmp cg_emit_addr
  112. cg_cmp_abs:
  113. ldy #$CD
  114. jmp cg_emit_addr
  115. cg_jsr_abs:
  116. ldy #$20
  117. jmp cg_emit_addr
  118. cg_emit_addr:
  119. sta cg_addr
  120. stx cg_addr+1
  121. tya
  122. jsr cg_put
  123. bcs @out
  124. lda cg_addr
  125. jsr cg_put
  126. bcs @out
  127. lda cg_addr+1
  128. jmp cg_put
  129. @out: sec
  130. rts
  131. cg_clc:
  132. lda #$18
  133. jmp cg_put
  134. cg_sec:
  135. lda #$38
  136. jmp cg_put
  137. cg_rts:
  138. lda #$60
  139. jmp cg_put
  140. ; A = branch opcode; forward target must be patched later.
  141. cg_branch_fwd:
  142. sta cg_op
  143. lda cg_fix_count
  144. cmp #CG_FIX_MAX
  145. bcs @fix_full
  146. sta cg_idx
  147. lda cg_op
  148. jsr cg_put
  149. bcs @out
  150. lda cg_len
  151. sta cg_pos
  152. ldy cg_idx
  153. sta cg_fixpos,y
  154. inc cg_fix_count
  155. lda #$00
  156. jsr cg_put
  157. bcs @out
  158. lda cg_idx
  159. clc
  160. rts
  161. @fix_full:
  162. lda #CG_ERR_FIX
  163. sta cg_err
  164. sec
  165. rts
  166. @out: sec
  167. rts
  168. ; A = fixup index. Patch its placeholder so the branch targets cg_len.
  169. cg_patch_here:
  170. cmp cg_fix_count
  171. bcs @bad
  172. tax
  173. lda cg_len
  174. sec
  175. sbc cg_fixpos,x
  176. sec
  177. sbc #1
  178. cmp #128
  179. bcs @range
  180. ldy cg_fixpos,x
  181. sta cg_code,y
  182. clc
  183. rts
  184. @bad: lda #CG_ERR_FIX
  185. sta cg_err
  186. sec
  187. rts
  188. @range: lda #CG_ERR_RANGE
  189. sta cg_err
  190. sec
  191. rts
  192. .segment "BSS"
  193. cg_code: .res 256
  194. cg_len: .res 1
  195. cg_err: .res 1
  196. cg_fix_count: .res 1
  197. cg_fixpos: .res CG_FIX_MAX
  198. cg_addr: .res 2
  199. cg_op: .res 1
  200. cg_idx: .res 1
  201. cg_pos: .res 1

Powered by TurnKey Linux.