Mirror of CollapseOS
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.

336 line
5.7KB

  1. ; *** CONSTS ***
  2. .equ D_DB 0x00
  3. .equ D_DW 0x01
  4. .equ D_EQU 0x02
  5. .equ D_ORG 0x03
  6. .equ D_FIL 0x04
  7. .equ D_OUT 0x05
  8. .equ D_INC 0x06
  9. .equ D_BIN 0x07
  10. .equ D_BAD 0xff
  11. ; *** Variables ***
  12. ; Result of the last .equ evaluation. Used for "@" symbol.
  13. .equ DIREC_LASTVAL DIREC_RAMSTART
  14. .equ DIREC_SCRATCHPAD DIREC_LASTVAL+2
  15. .equ DIREC_RAMEND DIREC_SCRATCHPAD+SCRATCHPAD_SIZE
  16. ; *** CODE ***
  17. ; 3 bytes per row, fill with zero
  18. dirNames:
  19. .db "DB", 0
  20. .db "DW", 0
  21. .db "EQU"
  22. .db "ORG"
  23. .db "FIL"
  24. .db "OUT"
  25. .db "INC"
  26. .db "BIN"
  27. ; This is a list of handlers corresponding to indexes in dirNames
  28. dirHandlers:
  29. .dw handleDB
  30. .dw handleDW
  31. .dw handleEQU
  32. .dw handleORG
  33. .dw handleFIL
  34. .dw handleOUT
  35. .dw handleINC
  36. .dw handleBIN
  37. handleDB:
  38. push hl
  39. .loop:
  40. call readWord
  41. jr nz, .badfmt
  42. ld hl, scratchpad
  43. call enterDoubleQuotes
  44. jr z, .stringLiteral
  45. call parseExpr
  46. jr nz, .badarg
  47. push ix \ pop hl
  48. ld a, h
  49. or a ; cp 0
  50. jr nz, .overflow ; not zero? overflow
  51. ld a, l
  52. call ioPutB
  53. jr nz, .ioError
  54. .stopStrLit:
  55. call readComma
  56. jr z, .loop
  57. cp a ; ensure Z
  58. pop hl
  59. ret
  60. .ioError:
  61. ld a, SHELL_ERR_IO_ERROR
  62. jr .error
  63. .badfmt:
  64. ld a, ERR_BAD_FMT
  65. jr .error
  66. .badarg:
  67. ld a, ERR_BAD_ARG
  68. jr .error
  69. .overflow:
  70. ld a, ERR_OVFL
  71. .error:
  72. call unsetZ
  73. pop hl
  74. ret
  75. .stringLiteral:
  76. ld a, (hl)
  77. inc hl
  78. or a ; when we encounter 0, that was what used to
  79. jr z, .stopStrLit ; be our closing quote. Stop.
  80. ; Normal character, output
  81. call ioPutB
  82. jr nz, .ioError
  83. jr .stringLiteral
  84. handleDW:
  85. push hl
  86. .loop:
  87. call readWord
  88. jr nz, .badfmt
  89. ld hl, scratchpad
  90. call parseExpr
  91. jr nz, .badarg
  92. push ix \ pop hl
  93. ld a, l
  94. call ioPutB
  95. jr nz, .ioError
  96. ld a, h
  97. call ioPutB
  98. jr nz, .ioError
  99. call readComma
  100. jr z, .loop
  101. cp a ; ensure Z
  102. pop hl
  103. ret
  104. .ioError:
  105. ld a, SHELL_ERR_IO_ERROR
  106. jr .error
  107. .badfmt:
  108. ld a, ERR_BAD_FMT
  109. jr .error
  110. .badarg:
  111. ld a, ERR_BAD_ARG
  112. .error:
  113. call unsetZ
  114. pop hl
  115. ret
  116. handleEQU:
  117. call zasmIsLocalPass ; Are we in local pass? Then ignore all .equ.
  118. jr z, .skip ; they mess up duplicate symbol detection.
  119. ; We register constants on both first and second pass for one little
  120. ; reason: .org. Normally, we'd register constants on second pass only
  121. ; so that we have values for forward label references, but we need .org
  122. ; to be effective during the first pass and .org needs to support
  123. ; expressions. So, we double-parse .equ, clearing the const registry
  124. ; before the second pass.
  125. push hl
  126. push de
  127. push bc
  128. ; Read our constant name
  129. call readWord
  130. jr nz, .badfmt
  131. ; We can't register our symbol yet: we don't have our value!
  132. ; Let's copy it over.
  133. ld de, DIREC_SCRATCHPAD
  134. ld bc, SCRATCHPAD_SIZE
  135. ldir
  136. ; Now, read the value associated to it
  137. call readWord
  138. jr nz, .badfmt
  139. ld hl, scratchpad
  140. call parseExpr
  141. jr nz, .badarg
  142. ld hl, DIREC_SCRATCHPAD
  143. push ix \ pop de
  144. ; Save value in "@" special variable
  145. ld (DIREC_LASTVAL), de
  146. call symRegisterConst ; A and Z set
  147. jr z, .end ; success
  148. ; register ended up in error. We need to figure which error. If it's
  149. ; a duplicate error, we ignore it and return success because, as per
  150. ; ".equ" policy, it's fine to define the same const twice. The first
  151. ; value has precedence.
  152. cp ERR_DUPSYM
  153. ; whatever the value of Z, it's the good one, return
  154. jr .end
  155. .badfmt:
  156. ld a, ERR_BAD_FMT
  157. jr .error
  158. .badarg:
  159. ld a, ERR_BAD_ARG
  160. .error:
  161. call unsetZ
  162. .end:
  163. pop bc
  164. pop de
  165. pop hl
  166. ret
  167. .skip:
  168. ; consume args and return
  169. call readWord
  170. jp readWord
  171. handleORG:
  172. call readWord
  173. jr nz, .badfmt
  174. call parseExpr
  175. jr nz, .badarg
  176. push ix \ pop hl
  177. ld (DIREC_LASTVAL), hl
  178. call zasmSetOrg
  179. cp a ; ensure Z
  180. ret
  181. .badfmt:
  182. ld a, ERR_BAD_FMT
  183. jr .error
  184. .badarg:
  185. ld a, ERR_BAD_ARG
  186. .error:
  187. call unsetZ
  188. ret
  189. handleFIL:
  190. call readWord
  191. jr nz, .badfmt
  192. call parseExpr
  193. jr nz, .badarg
  194. push bc ; --> lvl 1
  195. push ix \ pop bc
  196. ld a, b
  197. cp 0xd0
  198. jr nc, .overflow
  199. .loop:
  200. ld a, b
  201. or c
  202. jr z, .loopend
  203. xor a
  204. call ioPutB
  205. jr nz, .ioError
  206. dec bc
  207. jr .loop
  208. .loopend:
  209. cp a ; ensure Z
  210. pop bc ; <-- lvl 1
  211. ret
  212. .ioError:
  213. ld a, SHELL_ERR_IO_ERROR
  214. jp unsetZ
  215. .badfmt:
  216. ld a, ERR_BAD_FMT
  217. jp unsetZ
  218. .badarg:
  219. ld a, ERR_BAD_ARG
  220. jp unsetZ
  221. .overflow:
  222. pop bc ; <-- lvl 1
  223. ld a, ERR_OVFL
  224. jp unsetZ
  225. handleOUT:
  226. push hl
  227. ; Read our expression
  228. call readWord
  229. jr nz, .badfmt
  230. call zasmIsFirstPass ; No .out during first pass
  231. jr z, .end
  232. ld hl, scratchpad
  233. call parseExpr
  234. jr nz, .badarg
  235. push ix \ pop hl
  236. ld a, h
  237. out (ZASM_DEBUG_PORT), a
  238. ld a, l
  239. out (ZASM_DEBUG_PORT), a
  240. jr .end
  241. .badfmt:
  242. ld a, ERR_BAD_FMT
  243. jr .error
  244. .badarg:
  245. ld a, ERR_BAD_ARG
  246. .error:
  247. call unsetZ
  248. .end:
  249. pop hl
  250. ret
  251. handleINC:
  252. call readWord
  253. jr nz, .badfmt
  254. ; HL points to scratchpad
  255. call enterDoubleQuotes
  256. jr nz, .badfmt
  257. call ioOpenInclude
  258. jr nz, .badfn
  259. cp a ; ensure Z
  260. ret
  261. .badfmt:
  262. ld a, ERR_BAD_FMT
  263. jr .error
  264. .badfn:
  265. ld a, ERR_FILENOTFOUND
  266. .error:
  267. call unsetZ
  268. ret
  269. handleBIN:
  270. call readWord
  271. jr nz, .badfmt
  272. ; HL points to scratchpad
  273. call enterDoubleQuotes
  274. jr nz, .badfmt
  275. call ioSpitBin
  276. jr nz, .badfn
  277. cp a ; ensure Z
  278. ret
  279. .badfmt:
  280. ld a, ERR_BAD_FMT
  281. jr .error
  282. .badfn:
  283. ld a, ERR_FILENOTFOUND
  284. .error:
  285. call unsetZ
  286. ret
  287. ; Reads string in (HL) and returns the corresponding ID (D_*) in A. Sets Z if
  288. ; there's a match.
  289. getDirectiveID:
  290. ld a, (hl)
  291. cp '.'
  292. ret nz
  293. push hl
  294. push bc
  295. push de
  296. inc hl
  297. ld b, D_BIN+1 ; D_BIN is last
  298. ld c, 3
  299. ld de, dirNames
  300. call findStringInList
  301. pop de
  302. pop bc
  303. pop hl
  304. ret
  305. ; Parse directive specified in A (D_* const) with args in I/O and act in
  306. ; an appropriate manner. If the directive results in writing data at its
  307. ; current location, that data is directly written through ioPutB.
  308. ; Each directive has the same return value pattern: Z on success, not-Z on
  309. ; error, A contains the error number (ERR_*).
  310. parseDirective:
  311. push de
  312. ; double A to have a proper offset in dirHandlers
  313. add a, a
  314. ld de, dirHandlers
  315. call addDE
  316. call intoDE
  317. push de \ pop ix
  318. pop de
  319. jp (ix)