@jhlagado/azm 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (423) hide show
  1. package/README.md +103 -70
  2. package/dist/{src → legacy-root-azm/src}/formats/index.d.ts +1 -1
  3. package/dist/{src → legacy-root-azm/src}/formats/index.js +1 -1
  4. package/dist/{src → legacy-root-azm/src}/formats/types.d.ts +67 -7
  5. package/dist/{src → legacy-root-azm/src}/formats/writeHex.d.ts +0 -1
  6. package/dist/{src → legacy-root-azm/src}/formats/writeHex.js +0 -1
  7. package/dist/{src → legacy-root-azm/src}/pipeline.d.ts +3 -5
  8. package/dist/legacy-root-azm/src/z80/effects.d.ts +3 -0
  9. package/dist/legacy-root-azm/src/z80/effects.js +516 -0
  10. package/dist/legacy-root-azm/src/z80/encode.d.ts +10 -0
  11. package/dist/legacy-root-azm/src/z80/encode.js +412 -0
  12. package/dist/src/api-compile.d.ts +49 -8
  13. package/dist/src/api-compile.js +313 -3
  14. package/dist/src/api-tooling.d.ts +7 -25
  15. package/dist/src/api-tooling.js +3 -21
  16. package/dist/src/assembly/address-planning.d.ts +19 -0
  17. package/dist/src/assembly/address-planning.js +268 -0
  18. package/dist/src/assembly/assemble-program.d.ts +13 -0
  19. package/dist/src/assembly/assemble-program.js +34 -0
  20. package/dist/src/assembly/fixup-emission.d.ts +10 -0
  21. package/dist/src/assembly/fixup-emission.js +247 -0
  22. package/dist/src/assembly/placement.d.ts +26 -0
  23. package/dist/src/assembly/placement.js +79 -0
  24. package/dist/src/assembly/program-emission.d.ts +13 -0
  25. package/dist/src/assembly/program-emission.js +268 -0
  26. package/dist/src/cli/parse-args.d.ts +29 -0
  27. package/dist/src/cli/parse-args.js +372 -0
  28. package/dist/src/cli/run.d.ts +2 -0
  29. package/dist/src/cli/run.js +35 -0
  30. package/dist/src/cli/write-artifacts.d.ts +21 -0
  31. package/dist/src/cli/write-artifacts.js +175 -0
  32. package/dist/src/cli.d.ts +1 -30
  33. package/dist/src/cli.js +20 -524
  34. package/dist/src/core/compile-artifacts.d.ts +26 -0
  35. package/dist/src/core/compile-artifacts.js +17 -0
  36. package/dist/src/core/compile.d.ts +26 -0
  37. package/dist/src/core/compile.js +164 -0
  38. package/dist/src/diagnostics/format.d.ts +4 -0
  39. package/dist/src/diagnostics/format.js +9 -0
  40. package/dist/src/expansion/op-expansion.d.ts +96 -0
  41. package/dist/src/expansion/op-expansion.js +913 -0
  42. package/dist/src/index.d.ts +14 -3
  43. package/dist/src/index.js +7 -2
  44. package/dist/src/model/diagnostic.d.ts +50 -0
  45. package/dist/src/model/diagnostic.js +29 -0
  46. package/dist/src/model/expression.d.ts +51 -0
  47. package/dist/src/model/expression.js +1 -0
  48. package/dist/src/model/fixup.d.ts +18 -0
  49. package/dist/src/model/fixup.js +1 -0
  50. package/dist/src/model/source-item.d.ts +87 -0
  51. package/dist/src/model/source-item.js +1 -0
  52. package/dist/src/model/symbol.d.ts +1 -0
  53. package/dist/src/model/symbol.js +1 -0
  54. package/dist/src/node/source-host.d.ts +19 -0
  55. package/dist/src/node/source-host.js +146 -0
  56. package/dist/src/outputs/hex.d.ts +1 -0
  57. package/dist/src/outputs/hex.js +75 -0
  58. package/dist/src/outputs/index.d.ts +3 -0
  59. package/dist/src/outputs/index.js +13 -0
  60. package/dist/src/outputs/range.d.ts +3 -0
  61. package/dist/src/outputs/range.js +31 -0
  62. package/dist/src/outputs/types.d.ts +182 -0
  63. package/dist/src/outputs/types.js +1 -0
  64. package/dist/src/outputs/write-asm80.d.ts +7 -0
  65. package/dist/src/outputs/write-asm80.js +666 -0
  66. package/dist/src/outputs/write-bin.d.ts +2 -0
  67. package/dist/src/outputs/write-bin.js +27 -0
  68. package/dist/src/outputs/write-d8.d.ts +2 -0
  69. package/dist/src/outputs/write-d8.js +257 -0
  70. package/dist/src/outputs/write-hex.d.ts +2 -0
  71. package/dist/src/outputs/write-hex.js +53 -0
  72. package/dist/src/outputs/write-listing.d.ts +2 -0
  73. package/dist/src/outputs/write-listing.js +79 -0
  74. package/dist/src/register-care/accept-output.d.ts +2 -0
  75. package/dist/src/register-care/accept-output.js +35 -0
  76. package/dist/src/register-care/analyze.d.ts +26 -0
  77. package/dist/src/register-care/analyze.js +115 -0
  78. package/dist/src/register-care/annotate.d.ts +11 -0
  79. package/dist/src/register-care/annotate.js +76 -0
  80. package/dist/src/register-care/annotations.d.ts +8 -0
  81. package/dist/src/register-care/annotations.js +41 -0
  82. package/dist/src/register-care/boundaryHints.d.ts +2 -0
  83. package/dist/src/register-care/boundaryHints.js +11 -0
  84. package/dist/src/register-care/carriers.d.ts +2 -0
  85. package/dist/src/register-care/carriers.js +78 -0
  86. package/dist/src/register-care/controlFlow.d.ts +5 -0
  87. package/dist/src/register-care/controlFlow.js +38 -0
  88. package/dist/src/register-care/fix.d.ts +11 -0
  89. package/dist/src/register-care/fix.js +130 -0
  90. package/dist/src/register-care/instruction-shape.d.ts +11 -0
  91. package/dist/src/register-care/instruction-shape.js +129 -0
  92. package/dist/src/register-care/liveness.d.ts +3 -0
  93. package/dist/src/register-care/liveness.js +197 -0
  94. package/dist/src/register-care/profiles.d.ts +9 -0
  95. package/dist/src/register-care/profiles.js +47 -0
  96. package/dist/src/register-care/programModel.d.ts +3 -0
  97. package/dist/src/register-care/programModel.js +188 -0
  98. package/dist/src/register-care/report.d.ts +5 -0
  99. package/dist/src/register-care/report.js +139 -0
  100. package/dist/src/register-care/routine-summaries.d.ts +6 -0
  101. package/dist/src/register-care/routine-summaries.js +89 -0
  102. package/dist/src/register-care/smartComments.d.ts +5 -0
  103. package/dist/src/register-care/smartComments.js +243 -0
  104. package/dist/src/register-care/sourceText.d.ts +8 -0
  105. package/dist/src/register-care/sourceText.js +15 -0
  106. package/dist/src/register-care/summaries.d.ts +12 -0
  107. package/dist/src/register-care/summaries.js +121 -0
  108. package/dist/src/register-care/summary.d.ts +3 -0
  109. package/dist/src/register-care/summary.js +474 -0
  110. package/dist/src/{registerCare → register-care}/tooling.d.ts +7 -6
  111. package/dist/src/{registerCare → register-care}/tooling.js +17 -6
  112. package/dist/src/register-care/types.d.ts +170 -0
  113. package/dist/src/register-care/types.js +1 -0
  114. package/dist/src/semantics/expression-evaluation.d.ts +29 -0
  115. package/dist/src/semantics/expression-evaluation.js +409 -0
  116. package/dist/src/source/logical-lines.d.ts +7 -0
  117. package/dist/src/source/logical-lines.js +11 -0
  118. package/dist/src/source/source-file.d.ts +5 -0
  119. package/dist/src/source/source-file.js +3 -0
  120. package/dist/src/source/source-span.d.ts +5 -0
  121. package/dist/src/source/source-span.js +1 -0
  122. package/dist/src/source/strip-line-comment.d.ts +6 -0
  123. package/dist/src/source/strip-line-comment.js +53 -0
  124. package/dist/src/syntax/directive-aliases.d.ts +10 -0
  125. package/dist/src/syntax/directive-aliases.js +199 -0
  126. package/dist/src/syntax/parse-diagnostics.d.ts +12 -0
  127. package/dist/src/syntax/parse-diagnostics.js +18 -0
  128. package/dist/src/syntax/parse-expression.d.ts +3 -0
  129. package/dist/src/syntax/parse-expression.js +551 -0
  130. package/dist/src/syntax/parse-line.d.ts +12 -0
  131. package/dist/src/syntax/parse-line.js +382 -0
  132. package/dist/src/tooling/api.d.ts +42 -0
  133. package/dist/src/tooling/api.js +42 -0
  134. package/dist/src/tooling/case-style.d.ts +8 -0
  135. package/dist/src/tooling/case-style.js +163 -0
  136. package/dist/src/z80/effects.d.ts +3 -3
  137. package/dist/src/z80/effects.js +349 -302
  138. package/dist/src/z80/encode.d.ts +2 -10
  139. package/dist/src/z80/encode.js +951 -374
  140. package/dist/src/z80/instruction.d.ts +226 -0
  141. package/dist/src/z80/instruction.js +1 -0
  142. package/dist/src/z80/parse-instruction.d.ts +7 -0
  143. package/dist/src/z80/parse-instruction.js +1068 -0
  144. package/docs/reference/tooling-api.md +68 -9
  145. package/package.json +22 -3
  146. /package/dist/{src → legacy-root-azm/src}/analysis.d.ts +0 -0
  147. /package/dist/{src → legacy-root-azm/src}/analysis.js +0 -0
  148. /package/dist/{src → legacy-root-azm/src}/compile.d.ts +0 -0
  149. /package/dist/{src → legacy-root-azm/src}/compile.js +0 -0
  150. /package/dist/{src → legacy-root-azm/src}/compileShared.d.ts +0 -0
  151. /package/dist/{src → legacy-root-azm/src}/compileShared.js +0 -0
  152. /package/dist/{src → legacy-root-azm/src}/diagnosticTypes.d.ts +0 -0
  153. /package/dist/{src → legacy-root-azm/src}/diagnosticTypes.js +0 -0
  154. /package/dist/{src → legacy-root-azm/src}/formats/range.d.ts +0 -0
  155. /package/dist/{src → legacy-root-azm/src}/formats/range.js +0 -0
  156. /package/dist/{src → legacy-root-azm/src}/formats/types.js +0 -0
  157. /package/dist/{src → legacy-root-azm/src}/formats/writeAsm80.d.ts +0 -0
  158. /package/dist/{src → legacy-root-azm/src}/formats/writeAsm80.js +0 -0
  159. /package/dist/{src → legacy-root-azm/src}/formats/writeBin.d.ts +0 -0
  160. /package/dist/{src → legacy-root-azm/src}/formats/writeBin.js +0 -0
  161. /package/dist/{src → legacy-root-azm/src}/formats/writeD8m.d.ts +0 -0
  162. /package/dist/{src → legacy-root-azm/src}/formats/writeD8m.js +0 -0
  163. /package/dist/{src → legacy-root-azm/src}/formats/writeListing.d.ts +0 -0
  164. /package/dist/{src → legacy-root-azm/src}/formats/writeListing.js +0 -0
  165. /package/dist/{src → legacy-root-azm/src}/frontend/asm80/asmLine.d.ts +0 -0
  166. /package/dist/{src → legacy-root-azm/src}/frontend/asm80/asmLine.js +0 -0
  167. /package/dist/{src → legacy-root-azm/src}/frontend/asm80/parseAsmRawValues.d.ts +0 -0
  168. /package/dist/{src → legacy-root-azm/src}/frontend/asm80/parseAsmRawValues.js +0 -0
  169. /package/dist/{src → legacy-root-azm/src}/frontend/asm80/quoteScan.d.ts +0 -0
  170. /package/dist/{src → legacy-root-azm/src}/frontend/asm80/quoteScan.js +0 -0
  171. /package/dist/{src → legacy-root-azm/src}/frontend/ast.d.ts +0 -0
  172. /package/dist/{src → legacy-root-azm/src}/frontend/ast.js +0 -0
  173. /package/dist/{src → legacy-root-azm/src}/frontend/directiveAliases.d.ts +0 -0
  174. /package/dist/{src → legacy-root-azm/src}/frontend/directiveAliases.js +0 -0
  175. /package/dist/{src → legacy-root-azm/src}/frontend/grammarData.d.ts +0 -0
  176. /package/dist/{src → legacy-root-azm/src}/frontend/grammarData.js +0 -0
  177. /package/dist/{src → legacy-root-azm/src}/frontend/immExprUtils.d.ts +0 -0
  178. /package/dist/{src → legacy-root-azm/src}/frontend/immExprUtils.js +0 -0
  179. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmFlatDirectiveLine.d.ts +0 -0
  180. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmFlatDirectiveLine.js +0 -0
  181. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmInstruction.d.ts +0 -0
  182. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmInstruction.js +0 -0
  183. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmStatements.d.ts +0 -0
  184. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmStatements.js +0 -0
  185. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmStream.d.ts +0 -0
  186. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmStream.js +0 -0
  187. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmTopLevel.d.ts +0 -0
  188. /package/dist/{src → legacy-root-azm/src}/frontend/parseAsmTopLevel.js +0 -0
  189. /package/dist/{src → legacy-root-azm/src}/frontend/parseDiagnostics.d.ts +0 -0
  190. /package/dist/{src → legacy-root-azm/src}/frontend/parseDiagnostics.js +0 -0
  191. /package/dist/{src → legacy-root-azm/src}/frontend/parseEnum.d.ts +0 -0
  192. /package/dist/{src → legacy-root-azm/src}/frontend/parseEnum.js +0 -0
  193. /package/dist/{src → legacy-root-azm/src}/frontend/parseImm.d.ts +0 -0
  194. /package/dist/{src → legacy-root-azm/src}/frontend/parseImm.js +0 -0
  195. /package/dist/{src → legacy-root-azm/src}/frontend/parseLogicalLines.d.ts +0 -0
  196. /package/dist/{src → legacy-root-azm/src}/frontend/parseLogicalLines.js +0 -0
  197. /package/dist/{src → legacy-root-azm/src}/frontend/parseOp.d.ts +0 -0
  198. /package/dist/{src → legacy-root-azm/src}/frontend/parseOp.js +0 -0
  199. /package/dist/{src → legacy-root-azm/src}/frontend/parseOpHeader.d.ts +0 -0
  200. /package/dist/{src → legacy-root-azm/src}/frontend/parseOpHeader.js +0 -0
  201. /package/dist/{src → legacy-root-azm/src}/frontend/parseOperands.d.ts +0 -0
  202. /package/dist/{src → legacy-root-azm/src}/frontend/parseOperands.js +0 -0
  203. /package/dist/{src → legacy-root-azm/src}/frontend/parseParams.d.ts +0 -0
  204. /package/dist/{src → legacy-root-azm/src}/frontend/parseParams.js +0 -0
  205. /package/dist/{src → legacy-root-azm/src}/frontend/parseParserRecovery.d.ts +0 -0
  206. /package/dist/{src → legacy-root-azm/src}/frontend/parseParserRecovery.js +0 -0
  207. /package/dist/{src → legacy-root-azm/src}/frontend/parseParserShared.d.ts +0 -0
  208. /package/dist/{src → legacy-root-azm/src}/frontend/parseParserShared.js +0 -0
  209. /package/dist/{src → legacy-root-azm/src}/frontend/parseRawDataDirectiveStart.d.ts +0 -0
  210. /package/dist/{src → legacy-root-azm/src}/frontend/parseRawDataDirectiveStart.js +0 -0
  211. /package/dist/{src → legacy-root-azm/src}/frontend/parseRawDataDirectives.d.ts +0 -0
  212. /package/dist/{src → legacy-root-azm/src}/frontend/parseRawDataDirectives.js +0 -0
  213. /package/dist/{src → legacy-root-azm/src}/frontend/parseRecordFieldDecl.d.ts +0 -0
  214. /package/dist/{src → legacy-root-azm/src}/frontend/parseRecordFieldDecl.js +0 -0
  215. /package/dist/{src → legacy-root-azm/src}/frontend/parseSourceItemDispatch.d.ts +0 -0
  216. /package/dist/{src → legacy-root-azm/src}/frontend/parseSourceItemDispatch.js +0 -0
  217. /package/dist/{src → legacy-root-azm/src}/frontend/parseSourceItemTable.d.ts +0 -0
  218. /package/dist/{src → legacy-root-azm/src}/frontend/parseSourceItemTable.js +0 -0
  219. /package/dist/{src → legacy-root-azm/src}/frontend/parseTopLevelCommon.d.ts +0 -0
  220. /package/dist/{src → legacy-root-azm/src}/frontend/parseTopLevelCommon.js +0 -0
  221. /package/dist/{src → legacy-root-azm/src}/frontend/parseTypes.d.ts +0 -0
  222. /package/dist/{src → legacy-root-azm/src}/frontend/parseTypes.js +0 -0
  223. /package/dist/{src → legacy-root-azm/src}/frontend/parser.d.ts +0 -0
  224. /package/dist/{src → legacy-root-azm/src}/frontend/parser.js +0 -0
  225. /package/dist/{src → legacy-root-azm/src}/frontend/source.d.ts +0 -0
  226. /package/dist/{src → legacy-root-azm/src}/frontend/source.js +0 -0
  227. /package/dist/{src → legacy-root-azm/src}/frontend/sourceExtensions.d.ts +0 -0
  228. /package/dist/{src → legacy-root-azm/src}/frontend/sourceExtensions.js +0 -0
  229. /package/dist/{src → legacy-root-azm/src}/lintCaseStyle.d.ts +0 -0
  230. /package/dist/{src → legacy-root-azm/src}/lintCaseStyle.js +0 -0
  231. /package/dist/{src → legacy-root-azm/src}/lowering/asmDirectiveLowering.d.ts +0 -0
  232. /package/dist/{src → legacy-root-azm/src}/lowering/asmDirectiveLowering.js +0 -0
  233. /package/dist/{src → legacy-root-azm/src}/lowering/asmDirectiveTraversal.d.ts +0 -0
  234. /package/dist/{src → legacy-root-azm/src}/lowering/asmDirectiveTraversal.js +0 -0
  235. /package/dist/{src → legacy-root-azm/src}/lowering/asmEquResolution.d.ts +0 -0
  236. /package/dist/{src → legacy-root-azm/src}/lowering/asmEquResolution.js +0 -0
  237. /package/dist/{src → legacy-root-azm/src}/lowering/asmInstructionLdHelpers.d.ts +0 -0
  238. /package/dist/{src → legacy-root-azm/src}/lowering/asmInstructionLdHelpers.js +0 -0
  239. /package/dist/{src → legacy-root-azm/src}/lowering/asmInstructionLowering.d.ts +0 -0
  240. /package/dist/{src → legacy-root-azm/src}/lowering/asmInstructionLowering.js +0 -0
  241. /package/dist/{src → legacy-root-azm/src}/lowering/asmInstructionStream.d.ts +0 -0
  242. /package/dist/{src → legacy-root-azm/src}/lowering/asmInstructionStream.js +0 -0
  243. /package/dist/{src → legacy-root-azm/src}/lowering/asmLoweringBranchCall.d.ts +0 -0
  244. /package/dist/{src → legacy-root-azm/src}/lowering/asmLoweringBranchCall.js +0 -0
  245. /package/dist/{src → legacy-root-azm/src}/lowering/asmLoweringHost.d.ts +0 -0
  246. /package/dist/{src → legacy-root-azm/src}/lowering/asmLoweringHost.js +0 -0
  247. /package/dist/{src → legacy-root-azm/src}/lowering/asmLoweringLd.d.ts +0 -0
  248. /package/dist/{src → legacy-root-azm/src}/lowering/asmLoweringLd.js +0 -0
  249. /package/dist/{src → legacy-root-azm/src}/lowering/asmRangeLowering.d.ts +0 -0
  250. /package/dist/{src → legacy-root-azm/src}/lowering/asmRangeLowering.js +0 -0
  251. /package/dist/{src → legacy-root-azm/src}/lowering/asmRawDataLowering.d.ts +0 -0
  252. /package/dist/{src → legacy-root-azm/src}/lowering/asmRawDataLowering.js +0 -0
  253. /package/dist/{src → legacy-root-azm/src}/lowering/asmSourceEmitter.d.ts +0 -0
  254. /package/dist/{src → legacy-root-azm/src}/lowering/asmSourceEmitter.js +0 -0
  255. /package/dist/{src → legacy-root-azm/src}/lowering/asmSourceInstructionLowering.d.ts +0 -0
  256. /package/dist/{src → legacy-root-azm/src}/lowering/asmSourceInstructionLowering.js +0 -0
  257. /package/dist/{src → legacy-root-azm/src}/lowering/asmUtils.d.ts +0 -0
  258. /package/dist/{src → legacy-root-azm/src}/lowering/asmUtils.js +0 -0
  259. /package/dist/{src → legacy-root-azm/src}/lowering/assemblerFlowSetup.d.ts +0 -0
  260. /package/dist/{src → legacy-root-azm/src}/lowering/assemblerFlowSetup.js +0 -0
  261. /package/dist/{src → legacy-root-azm/src}/lowering/assemblerLoweringContext.d.ts +0 -0
  262. /package/dist/{src → legacy-root-azm/src}/lowering/assemblerLoweringContext.js +0 -0
  263. /package/dist/{src → legacy-root-azm/src}/lowering/assemblerLoweringContextSplit.d.ts +0 -0
  264. /package/dist/{src → legacy-root-azm/src}/lowering/assemblerLoweringContextSplit.js +0 -0
  265. /package/dist/{src → legacy-root-azm/src}/lowering/assemblerLoweringPhases.d.ts +0 -0
  266. /package/dist/{src → legacy-root-azm/src}/lowering/assemblerLoweringPhases.js +0 -0
  267. /package/dist/{src → legacy-root-azm/src}/lowering/bytePlacement.d.ts +0 -0
  268. /package/dist/{src → legacy-root-azm/src}/lowering/bytePlacement.js +0 -0
  269. /package/dist/{src → legacy-root-azm/src}/lowering/capabilities.d.ts +0 -0
  270. /package/dist/{src → legacy-root-azm/src}/lowering/capabilities.js +0 -0
  271. /package/dist/{src → legacy-root-azm/src}/lowering/eaResolution.d.ts +0 -0
  272. /package/dist/{src → legacy-root-azm/src}/lowering/eaResolution.js +0 -0
  273. /package/dist/{src → legacy-root-azm/src}/lowering/emissionCore.d.ts +0 -0
  274. /package/dist/{src → legacy-root-azm/src}/lowering/emissionCore.js +0 -0
  275. /package/dist/{src → legacy-root-azm/src}/lowering/emit.d.ts +0 -0
  276. /package/dist/{src → legacy-root-azm/src}/lowering/emit.js +0 -0
  277. /package/dist/{src → legacy-root-azm/src}/lowering/emitContextBuilder.d.ts +0 -0
  278. /package/dist/{src → legacy-root-azm/src}/lowering/emitContextBuilder.js +0 -0
  279. /package/dist/{src → legacy-root-azm/src}/lowering/emitFinalization.d.ts +0 -0
  280. /package/dist/{src → legacy-root-azm/src}/lowering/emitFinalization.js +0 -0
  281. /package/dist/{src → legacy-root-azm/src}/lowering/emitFinalizationSetup.d.ts +0 -0
  282. /package/dist/{src → legacy-root-azm/src}/lowering/emitFinalizationSetup.js +0 -0
  283. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1BuildProgramLoweringContext.d.ts +0 -0
  284. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1BuildProgramLoweringContext.js +0 -0
  285. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1Helpers.d.ts +0 -0
  286. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1Helpers.js +0 -0
  287. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1Types.d.ts +0 -0
  288. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1Types.js +0 -0
  289. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1WirePipeline.d.ts +0 -0
  290. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1WirePipeline.js +0 -0
  291. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1Workspace.d.ts +0 -0
  292. /package/dist/{src → legacy-root-azm/src}/lowering/emitPhase1Workspace.js +0 -0
  293. /package/dist/{src → legacy-root-azm/src}/lowering/emitPipeline.d.ts +0 -0
  294. /package/dist/{src → legacy-root-azm/src}/lowering/emitPipeline.js +0 -0
  295. /package/dist/{src → legacy-root-azm/src}/lowering/emitProgramContext.d.ts +0 -0
  296. /package/dist/{src → legacy-root-azm/src}/lowering/emitProgramContext.js +0 -0
  297. /package/dist/{src → legacy-root-azm/src}/lowering/emitState.d.ts +0 -0
  298. /package/dist/{src → legacy-root-azm/src}/lowering/emitState.js +0 -0
  299. /package/dist/{src → legacy-root-azm/src}/lowering/fixupBaseResolution.d.ts +0 -0
  300. /package/dist/{src → legacy-root-azm/src}/lowering/fixupBaseResolution.js +0 -0
  301. /package/dist/{src → legacy-root-azm/src}/lowering/fixupEmission.d.ts +0 -0
  302. /package/dist/{src → legacy-root-azm/src}/lowering/fixupEmission.js +0 -0
  303. /package/dist/{src → legacy-root-azm/src}/lowering/immMath.d.ts +0 -0
  304. /package/dist/{src → legacy-root-azm/src}/lowering/immMath.js +0 -0
  305. /package/dist/{src → legacy-root-azm/src}/lowering/inputAssets.d.ts +0 -0
  306. /package/dist/{src → legacy-root-azm/src}/lowering/inputAssets.js +0 -0
  307. /package/dist/{src → legacy-root-azm/src}/lowering/ldEncoding.d.ts +0 -0
  308. /package/dist/{src → legacy-root-azm/src}/lowering/ldEncoding.js +0 -0
  309. /package/dist/{src → legacy-root-azm/src}/lowering/ldEncodingRegMemHelpers.d.ts +0 -0
  310. /package/dist/{src → legacy-root-azm/src}/lowering/ldEncodingRegMemHelpers.js +0 -0
  311. /package/dist/{src → legacy-root-azm/src}/lowering/ldFormSelection.d.ts +0 -0
  312. /package/dist/{src → legacy-root-azm/src}/lowering/ldFormSelection.js +0 -0
  313. /package/dist/{src → legacy-root-azm/src}/lowering/ldLowering.d.ts +0 -0
  314. /package/dist/{src → legacy-root-azm/src}/lowering/ldLowering.js +0 -0
  315. /package/dist/{src → legacy-root-azm/src}/lowering/loweredAsmByteEmission.d.ts +0 -0
  316. /package/dist/{src → legacy-root-azm/src}/lowering/loweredAsmByteEmission.js +0 -0
  317. /package/dist/{src → legacy-root-azm/src}/lowering/loweredAsmPlacement.d.ts +0 -0
  318. /package/dist/{src → legacy-root-azm/src}/lowering/loweredAsmPlacement.js +0 -0
  319. /package/dist/{src → legacy-root-azm/src}/lowering/loweredAsmStreamRecording.d.ts +0 -0
  320. /package/dist/{src → legacy-root-azm/src}/lowering/loweredAsmStreamRecording.js +0 -0
  321. /package/dist/{src → legacy-root-azm/src}/lowering/loweredAsmTypes.d.ts +0 -0
  322. /package/dist/{src → legacy-root-azm/src}/lowering/loweredAsmTypes.js +0 -0
  323. /package/dist/{src → legacy-root-azm/src}/lowering/loweredFormat.d.ts +0 -0
  324. /package/dist/{src → legacy-root-azm/src}/lowering/loweredFormat.js +0 -0
  325. /package/dist/{src → legacy-root-azm/src}/lowering/loweredItemSize.d.ts +0 -0
  326. /package/dist/{src → legacy-root-azm/src}/lowering/loweredItemSize.js +0 -0
  327. /package/dist/{src → legacy-root-azm/src}/lowering/loweringDiagnostics.d.ts +0 -0
  328. /package/dist/{src → legacy-root-azm/src}/lowering/loweringDiagnostics.js +0 -0
  329. /package/dist/{src → legacy-root-azm/src}/lowering/loweringTypes.d.ts +0 -0
  330. /package/dist/{src → legacy-root-azm/src}/lowering/loweringTypes.js +0 -0
  331. /package/dist/{src → legacy-root-azm/src}/lowering/opCandidateRegistry.d.ts +0 -0
  332. /package/dist/{src → legacy-root-azm/src}/lowering/opCandidateRegistry.js +0 -0
  333. /package/dist/{src → legacy-root-azm/src}/lowering/opExpansionExecution.d.ts +0 -0
  334. /package/dist/{src → legacy-root-azm/src}/lowering/opExpansionExecution.js +0 -0
  335. /package/dist/{src → legacy-root-azm/src}/lowering/opExpansionOrchestration.d.ts +0 -0
  336. /package/dist/{src → legacy-root-azm/src}/lowering/opExpansionOrchestration.js +0 -0
  337. /package/dist/{src → legacy-root-azm/src}/lowering/opExpansionStream.d.ts +0 -0
  338. /package/dist/{src → legacy-root-azm/src}/lowering/opExpansionStream.js +0 -0
  339. /package/dist/{src → legacy-root-azm/src}/lowering/opMatching.d.ts +0 -0
  340. /package/dist/{src → legacy-root-azm/src}/lowering/opMatching.js +0 -0
  341. /package/dist/{src → legacy-root-azm/src}/lowering/opSubstitution.d.ts +0 -0
  342. /package/dist/{src → legacy-root-azm/src}/lowering/opSubstitution.js +0 -0
  343. /package/dist/{src → legacy-root-azm/src}/lowering/prescanTypes.d.ts +0 -0
  344. /package/dist/{src → legacy-root-azm/src}/lowering/prescanTypes.js +0 -0
  345. /package/dist/{src → legacy-root-azm/src}/lowering/programLowering.d.ts +0 -0
  346. /package/dist/{src → legacy-root-azm/src}/lowering/programLowering.js +0 -0
  347. /package/dist/{src → legacy-root-azm/src}/lowering/programLoweringDeclarations.d.ts +0 -0
  348. /package/dist/{src → legacy-root-azm/src}/lowering/programLoweringDeclarations.js +0 -0
  349. /package/dist/{src → legacy-root-azm/src}/lowering/programLoweringFinalize.d.ts +0 -0
  350. /package/dist/{src → legacy-root-azm/src}/lowering/programLoweringFinalize.js +0 -0
  351. /package/dist/{src → legacy-root-azm/src}/lowering/programLoweringTraversal.d.ts +0 -0
  352. /package/dist/{src → legacy-root-azm/src}/lowering/programLoweringTraversal.js +0 -0
  353. /package/dist/{src → legacy-root-azm/src}/lowering/programPrescan.d.ts +0 -0
  354. /package/dist/{src → legacy-root-azm/src}/lowering/programPrescan.js +0 -0
  355. /package/dist/{src → legacy-root-azm/src}/lowering/traceFormat.d.ts +0 -0
  356. /package/dist/{src → legacy-root-azm/src}/lowering/traceFormat.js +0 -0
  357. /package/dist/{src → legacy-root-azm/src}/packageInfo.d.ts +0 -0
  358. /package/dist/{src → legacy-root-azm/src}/packageInfo.js +0 -0
  359. /package/dist/{src → legacy-root-azm/src}/pathCompare.d.ts +0 -0
  360. /package/dist/{src → legacy-root-azm/src}/pathCompare.js +0 -0
  361. /package/dist/{src → legacy-root-azm/src}/pipeline.js +0 -0
  362. /package/dist/{src → legacy-root-azm/src}/registerCare/analyze.d.ts +0 -0
  363. /package/dist/{src → legacy-root-azm/src}/registerCare/analyze.js +0 -0
  364. /package/dist/{src → legacy-root-azm/src}/registerCare/annotate.d.ts +0 -0
  365. /package/dist/{src → legacy-root-azm/src}/registerCare/annotate.js +0 -0
  366. /package/dist/{src → legacy-root-azm/src}/registerCare/boundaryHints.d.ts +0 -0
  367. /package/dist/{src → legacy-root-azm/src}/registerCare/boundaryHints.js +0 -0
  368. /package/dist/{src → legacy-root-azm/src}/registerCare/carriers.d.ts +0 -0
  369. /package/dist/{src → legacy-root-azm/src}/registerCare/carriers.js +0 -0
  370. /package/dist/{src → legacy-root-azm/src}/registerCare/controlFlow.d.ts +0 -0
  371. /package/dist/{src → legacy-root-azm/src}/registerCare/controlFlow.js +0 -0
  372. /package/dist/{src → legacy-root-azm/src}/registerCare/fix.d.ts +0 -0
  373. /package/dist/{src → legacy-root-azm/src}/registerCare/fix.js +0 -0
  374. /package/dist/{src → legacy-root-azm/src}/registerCare/liveness.d.ts +0 -0
  375. /package/dist/{src → legacy-root-azm/src}/registerCare/liveness.js +0 -0
  376. /package/dist/{src → legacy-root-azm/src}/registerCare/profiles.d.ts +0 -0
  377. /package/dist/{src → legacy-root-azm/src}/registerCare/profiles.js +0 -0
  378. /package/dist/{src → legacy-root-azm/src}/registerCare/programModel.d.ts +0 -0
  379. /package/dist/{src → legacy-root-azm/src}/registerCare/programModel.js +0 -0
  380. /package/dist/{src → legacy-root-azm/src}/registerCare/report.d.ts +0 -0
  381. /package/dist/{src → legacy-root-azm/src}/registerCare/report.js +0 -0
  382. /package/dist/{src → legacy-root-azm/src}/registerCare/smartComments.d.ts +0 -0
  383. /package/dist/{src → legacy-root-azm/src}/registerCare/smartComments.js +0 -0
  384. /package/dist/{src → legacy-root-azm/src}/registerCare/sourceText.d.ts +0 -0
  385. /package/dist/{src → legacy-root-azm/src}/registerCare/sourceText.js +0 -0
  386. /package/dist/{src → legacy-root-azm/src}/registerCare/summary.d.ts +0 -0
  387. /package/dist/{src → legacy-root-azm/src}/registerCare/summary.js +0 -0
  388. /package/dist/{src → legacy-root-azm/src}/registerCare/types.d.ts +0 -0
  389. /package/dist/{src → legacy-root-azm/src}/registerCare/types.js +0 -0
  390. /package/dist/{src → legacy-root-azm/src}/semantics/declVisitor.d.ts +0 -0
  391. /package/dist/{src → legacy-root-azm/src}/semantics/declVisitor.js +0 -0
  392. /package/dist/{src → legacy-root-azm/src}/semantics/env.d.ts +0 -0
  393. /package/dist/{src → legacy-root-azm/src}/semantics/env.js +0 -0
  394. /package/dist/{src → legacy-root-azm/src}/semantics/layout.d.ts +0 -0
  395. /package/dist/{src → legacy-root-azm/src}/semantics/layout.js +0 -0
  396. /package/dist/{src → legacy-root-azm/src}/semantics/layoutCastFold.d.ts +0 -0
  397. /package/dist/{src → legacy-root-azm/src}/semantics/layoutCastFold.js +0 -0
  398. /package/dist/{src → legacy-root-azm/src}/semantics/semanticsDiagnostics.d.ts +0 -0
  399. /package/dist/{src → legacy-root-azm/src}/semantics/semanticsDiagnostics.js +0 -0
  400. /package/dist/{src → legacy-root-azm/src}/semantics/typeQueries.d.ts +0 -0
  401. /package/dist/{src → legacy-root-azm/src}/semantics/typeQueries.js +0 -0
  402. /package/dist/{src → legacy-root-azm/src}/sourceIncludeExpansion.d.ts +0 -0
  403. /package/dist/{src → legacy-root-azm/src}/sourceIncludeExpansion.js +0 -0
  404. /package/dist/{src → legacy-root-azm/src}/sourceIncludePaths.d.ts +0 -0
  405. /package/dist/{src → legacy-root-azm/src}/sourceIncludePaths.js +0 -0
  406. /package/dist/{src → legacy-root-azm/src}/sourceLoader.d.ts +0 -0
  407. /package/dist/{src → legacy-root-azm/src}/sourceLoader.js +0 -0
  408. /package/dist/{src → legacy-root-azm/src}/z80/encodeAlu.d.ts +0 -0
  409. /package/dist/{src → legacy-root-azm/src}/z80/encodeAlu.js +0 -0
  410. /package/dist/{src → legacy-root-azm/src}/z80/encodeBitOps.d.ts +0 -0
  411. /package/dist/{src → legacy-root-azm/src}/z80/encodeBitOps.js +0 -0
  412. /package/dist/{src → legacy-root-azm/src}/z80/encodeContext.d.ts +0 -0
  413. /package/dist/{src → legacy-root-azm/src}/z80/encodeContext.js +0 -0
  414. /package/dist/{src → legacy-root-azm/src}/z80/encodeControl.d.ts +0 -0
  415. /package/dist/{src → legacy-root-azm/src}/z80/encodeControl.js +0 -0
  416. /package/dist/{src → legacy-root-azm/src}/z80/encodeCoreOps.d.ts +0 -0
  417. /package/dist/{src → legacy-root-azm/src}/z80/encodeCoreOps.js +0 -0
  418. /package/dist/{src → legacy-root-azm/src}/z80/encodeIo.d.ts +0 -0
  419. /package/dist/{src → legacy-root-azm/src}/z80/encodeIo.js +0 -0
  420. /package/dist/{src → legacy-root-azm/src}/z80/encodeLd.d.ts +0 -0
  421. /package/dist/{src → legacy-root-azm/src}/z80/encodeLd.js +0 -0
  422. /package/dist/{src → legacy-root-azm/src}/z80/encoderRegistry.d.ts +0 -0
  423. /package/dist/{src → legacy-root-azm/src}/z80/encoderRegistry.js +0 -0
@@ -1,412 +1,989 @@
1
- import { flattenEaDottedName } from '../lowering/asmUtils.js';
2
- import { diagEncodeAt } from '../lowering/loweringDiagnostics.js';
3
- import { evalImmExpr } from '../semantics/env.js';
4
- import { getEncoderRegistryEntry } from './encoderRegistry.js';
5
- import { encodeAluInstruction } from './encodeAlu.js';
6
- import { encodeBitOpsInstruction } from './encodeBitOps.js';
7
- import { encodeControlInstruction } from './encodeControl.js';
8
- import { encodeCoreOpsInstruction } from './encodeCoreOps.js';
9
- import { encodeIoInstruction } from './encodeIo.js';
10
- import { encodeLdInstruction } from './encodeLd.js';
11
- /** Pass-through to {@link diagEncodeAt} for encoder submodules that take an instruction node. */
12
- function diag(diagnostics, node, message) {
13
- diagEncodeAt(diagnostics, node.span, message);
14
- }
15
- function immValue(op, env) {
16
- if (op.kind === 'Imm')
17
- return evalImmExpr(op.expr, env);
18
- if (op.kind !== 'Ea')
19
- return undefined;
20
- const dotted = flattenEaDottedName(op.expr);
21
- if (!dotted || !env.enums.has(dotted))
22
- return undefined;
23
- return evalImmExpr({ kind: 'ImmName', span: op.span, name: dotted }, env);
1
+ export function encodeZ80Instruction(instruction) {
2
+ switch (instruction.mnemonic) {
3
+ case 'nop':
4
+ return { size: 1, fragments: [{ kind: 'bytes', bytes: [0x00] }] };
5
+ case 'ret':
6
+ return { size: 1, fragments: [{ kind: 'bytes', bytes: [0xc9] }] };
7
+ case 'ret-cc':
8
+ return {
9
+ size: 1,
10
+ fragments: [{ kind: 'bytes', bytes: [retConditionOpcode(instruction.condition)] }],
11
+ };
12
+ case 'di':
13
+ case 'ei':
14
+ case 'scf':
15
+ case 'ccf':
16
+ case 'cpl':
17
+ case 'daa':
18
+ case 'exx':
19
+ case 'halt':
20
+ case 'rlca':
21
+ case 'rrca':
22
+ case 'rla':
23
+ case 'rra':
24
+ case 'neg':
25
+ case 'rrd':
26
+ case 'rld':
27
+ case 'ldi':
28
+ case 'ldir':
29
+ case 'ldd':
30
+ case 'lddr':
31
+ case 'cpi':
32
+ case 'cpir':
33
+ case 'cpd':
34
+ case 'cpdr':
35
+ case 'ini':
36
+ case 'inir':
37
+ case 'ind':
38
+ case 'indr':
39
+ case 'outi':
40
+ case 'otir':
41
+ case 'outd':
42
+ case 'otdr':
43
+ case 'reti':
44
+ case 'retn':
45
+ return encodeCore(instruction.mnemonic);
46
+ case 'ex':
47
+ return encodeExchange(instruction.form);
48
+ case 'im':
49
+ return {
50
+ size: 2,
51
+ fragments: [{ kind: 'bytes', bytes: [0xed, imOpcode(instruction.mode)] }],
52
+ };
53
+ case 'rst':
54
+ return {
55
+ size: 1,
56
+ fragments: [{ kind: 'bytes', bytes: [rstOpcode(instruction.vector)] }],
57
+ };
58
+ case 'inc':
59
+ case 'dec':
60
+ return encodeIncDec(instruction.mnemonic, instruction.operand);
61
+ case 'push':
62
+ case 'pop':
63
+ return encodeStack(instruction.mnemonic, instruction.register);
64
+ case 'ld-a-imm':
65
+ return {
66
+ size: 2,
67
+ fragments: [
68
+ { kind: 'bytes', bytes: [0x3e] },
69
+ { kind: 'imm8', expression: instruction.expression },
70
+ ],
71
+ };
72
+ case 'ld':
73
+ return encodeLd(instruction.target, instruction.source);
74
+ case 'in':
75
+ return encodeIn(instruction.target, instruction.port);
76
+ case 'out':
77
+ return encodeOut(instruction.port, instruction.source);
78
+ case 'bit':
79
+ case 'res':
80
+ case 'set':
81
+ return encodeBitLike(instruction.mnemonic, instruction.bit, instruction.operand, instruction.destination);
82
+ case 'rlc':
83
+ case 'rrc':
84
+ case 'rl':
85
+ case 'rr':
86
+ case 'sla':
87
+ case 'sra':
88
+ case 'sll':
89
+ case 'sls':
90
+ case 'srl':
91
+ return encodeRotateShift(instruction.mnemonic, instruction.operand, instruction.destination);
92
+ case 'add':
93
+ case 'adc':
94
+ if ('target' in instruction) {
95
+ return encode16BitAlu(instruction.mnemonic, instruction.target.register, instruction.source.register);
96
+ }
97
+ return encodeAlu(instruction.mnemonic, instruction.source);
98
+ case 'sub':
99
+ case 'sbc':
100
+ if ('target' in instruction) {
101
+ return encode16BitAlu(instruction.mnemonic, instruction.target.register, instruction.source.register);
102
+ }
103
+ return encodeAlu(instruction.mnemonic, instruction.source);
104
+ case 'and':
105
+ case 'or':
106
+ case 'xor':
107
+ case 'cp':
108
+ return encodeAlu(instruction.mnemonic, instruction.source);
109
+ case 'jp':
110
+ return absoluteTarget(0xc3, instruction.expression);
111
+ case 'jp-cc':
112
+ return absoluteTarget(jpConditionOpcode(instruction.condition), instruction.expression);
113
+ case 'jp-indirect':
114
+ return jumpIndirect(instruction.register);
115
+ case 'call':
116
+ return absoluteTarget(0xcd, instruction.expression);
117
+ case 'call-cc':
118
+ return absoluteTarget(callConditionOpcode(instruction.condition), instruction.expression);
119
+ case 'jr':
120
+ return relativeTarget(0x18, 'jr', instruction.expression);
121
+ case 'jr-cc':
122
+ return relativeTarget(jrConditionOpcode(instruction.condition), `jr ${instruction.condition}`, instruction.expression);
123
+ case 'djnz':
124
+ return relativeTarget(0x10, 'djnz', instruction.expression);
125
+ }
24
126
  }
25
- function portImmValue(op, env) {
26
- if (op.kind !== 'PortImm8')
27
- return undefined;
28
- return evalImmExpr(op.expr, env);
127
+ function encodeExchange(form) {
128
+ switch (form) {
129
+ case 'af-af':
130
+ return { size: 1, fragments: [{ kind: 'bytes', bytes: [0x08] }] };
131
+ case 'de-hl':
132
+ return { size: 1, fragments: [{ kind: 'bytes', bytes: [0xeb] }] };
133
+ case 'sp-hl':
134
+ return { size: 1, fragments: [{ kind: 'bytes', bytes: [0xe3] }] };
135
+ case 'sp-ix':
136
+ return { size: 2, fragments: [{ kind: 'bytes', bytes: [0xdd, 0xe3] }] };
137
+ case 'sp-iy':
138
+ return { size: 2, fragments: [{ kind: 'bytes', bytes: [0xfd, 0xe3] }] };
139
+ }
29
140
  }
30
- function fitsImm8(value) {
31
- return value >= -0x80 && value <= 0xff;
141
+ function encodeCore(mnemonic) {
142
+ const opcode = coreOpcode(mnemonic);
143
+ return {
144
+ size: opcode.length,
145
+ fragments: [{ kind: 'bytes', bytes: opcode }],
146
+ };
32
147
  }
33
- function fitsImm16(value) {
34
- return value >= -0x8000 && value <= 0xffff;
148
+ function coreOpcode(mnemonic) {
149
+ switch (mnemonic) {
150
+ case 'di':
151
+ return [0xf3];
152
+ case 'ei':
153
+ return [0xfb];
154
+ case 'scf':
155
+ return [0x37];
156
+ case 'ccf':
157
+ return [0x3f];
158
+ case 'cpl':
159
+ return [0x2f];
160
+ case 'daa':
161
+ return [0x27];
162
+ case 'exx':
163
+ return [0xd9];
164
+ case 'halt':
165
+ return [0x76];
166
+ case 'rlca':
167
+ return [0x07];
168
+ case 'rrca':
169
+ return [0x0f];
170
+ case 'rla':
171
+ return [0x17];
172
+ case 'rra':
173
+ return [0x1f];
174
+ case 'neg':
175
+ return [0xed, 0x44];
176
+ case 'rrd':
177
+ return [0xed, 0x67];
178
+ case 'rld':
179
+ return [0xed, 0x6f];
180
+ case 'ldi':
181
+ return [0xed, 0xa0];
182
+ case 'ldir':
183
+ return [0xed, 0xb0];
184
+ case 'ldd':
185
+ return [0xed, 0xa8];
186
+ case 'lddr':
187
+ return [0xed, 0xb8];
188
+ case 'cpi':
189
+ return [0xed, 0xa1];
190
+ case 'cpir':
191
+ return [0xed, 0xb1];
192
+ case 'cpd':
193
+ return [0xed, 0xa9];
194
+ case 'cpdr':
195
+ return [0xed, 0xb9];
196
+ case 'ini':
197
+ return [0xed, 0xa2];
198
+ case 'inir':
199
+ return [0xed, 0xb2];
200
+ case 'ind':
201
+ return [0xed, 0xaa];
202
+ case 'indr':
203
+ return [0xed, 0xba];
204
+ case 'outi':
205
+ return [0xed, 0xa3];
206
+ case 'otir':
207
+ return [0xed, 0xb3];
208
+ case 'outd':
209
+ return [0xed, 0xab];
210
+ case 'otdr':
211
+ return [0xed, 0xbb];
212
+ case 'reti':
213
+ return [0xed, 0x4d];
214
+ case 'retn':
215
+ return [0xed, 0x45];
216
+ }
35
217
  }
36
- function regName(op) {
37
- return op.kind === 'Reg' ? op.name.toUpperCase() : undefined;
218
+ function encodeIn(target, port) {
219
+ if (port.kind === 'c') {
220
+ const opcode = target ? 0x40 + register8Code(target.register) * 8 : 0x70;
221
+ return { size: 2, fragments: [{ kind: 'bytes', bytes: [0xed, opcode] }] };
222
+ }
223
+ return {
224
+ size: 2,
225
+ fragments: [
226
+ { kind: 'bytes', bytes: [0xdb] },
227
+ {
228
+ kind: 'port8',
229
+ expression: port.expression,
230
+ message: 'in a,(n) expects an imm8 port number',
231
+ },
232
+ ],
233
+ };
38
234
  }
39
- function registerTokenName(op) {
40
- const name = op.kind === 'Reg'
41
- ? op.name.toUpperCase()
42
- : op.kind === 'Imm' && op.expr.kind === 'ImmName'
43
- ? op.expr.name.toUpperCase()
44
- : undefined;
45
- if (!name)
46
- return undefined;
47
- switch (name) {
48
- case 'A':
49
- case 'B':
50
- case 'C':
51
- case 'D':
52
- case 'E':
53
- case 'H':
54
- case 'L':
55
- case 'BC':
56
- case 'DE':
57
- case 'HL':
58
- case 'SP':
59
- case 'AF':
60
- case 'IX':
61
- case 'IY':
62
- case 'IXH':
63
- case 'IXL':
64
- case 'IYH':
65
- case 'IYL':
66
- return name;
67
- default:
68
- return undefined;
235
+ function encodeOut(port, source) {
236
+ if (port.kind === 'c') {
237
+ const opcode = source.kind === 'zero' ? 0x71 : 0x41 + register8Code(source.register) * 8;
238
+ return { size: 2, fragments: [{ kind: 'bytes', bytes: [0xed, opcode] }] };
69
239
  }
240
+ return {
241
+ size: 2,
242
+ fragments: [
243
+ { kind: 'bytes', bytes: [0xd3] },
244
+ {
245
+ kind: 'port8',
246
+ expression: port.expression,
247
+ message: 'out (n),a expects an imm8 port number',
248
+ },
249
+ ],
250
+ };
70
251
  }
71
- function reg8Code(name) {
72
- switch (name.toUpperCase()) {
73
- case 'B':
74
- return 0;
75
- case 'C':
76
- return 1;
77
- case 'D':
78
- return 2;
79
- case 'E':
80
- return 3;
81
- case 'H':
82
- return 4;
83
- case 'L':
84
- return 5;
85
- case 'A':
86
- return 7;
87
- default:
88
- return undefined;
89
- }
90
- }
91
- function isPlainHLReg8(name) {
92
- return name === 'H' || name === 'L';
93
- }
94
- function indexedReg8(op) {
95
- const n = regName(op);
96
- switch (n) {
97
- case 'IXH':
98
- return { prefix: 0xdd, code: 4, display: 'IXH' };
99
- case 'IXL':
100
- return { prefix: 0xdd, code: 5, display: 'IXL' };
101
- case 'IYH':
102
- return { prefix: 0xfd, code: 4, display: 'IYH' };
103
- case 'IYL':
104
- return { prefix: 0xfd, code: 5, display: 'IYL' };
252
+ function imOpcode(mode) {
253
+ switch (mode) {
254
+ case 0:
255
+ return 0x46;
256
+ case 1:
257
+ return 0x56;
258
+ case 2:
259
+ return 0x5e;
260
+ }
261
+ }
262
+ function rstOpcode(vector) {
263
+ switch (vector) {
264
+ case 0:
265
+ return 0xc7;
266
+ case 8:
267
+ return 0xcf;
268
+ case 16:
269
+ return 0xd7;
270
+ case 24:
271
+ return 0xdf;
272
+ case 32:
273
+ return 0xe7;
274
+ case 40:
275
+ return 0xef;
276
+ case 48:
277
+ return 0xf7;
278
+ case 56:
279
+ return 0xff;
105
280
  default:
106
- return undefined;
281
+ throw new Error(`invalid RST vector: ${vector}`);
107
282
  }
108
283
  }
109
- function isMemHL(op) {
110
- return op.kind === 'Mem' && op.expr.kind === 'EaName' && op.expr.name.toUpperCase() === 'HL';
284
+ function encodeIncDec(mnemonic, operand) {
285
+ if (operand.kind === 'reg8') {
286
+ return {
287
+ size: 1,
288
+ fragments: [
289
+ {
290
+ kind: 'bytes',
291
+ bytes: [incDecBase(mnemonic).reg8 + register8Code(operand.register) * 8],
292
+ },
293
+ ],
294
+ };
295
+ }
296
+ if (operand.kind === 'reg16') {
297
+ const bytes = incDecRegister16Opcode(mnemonic, operand.register);
298
+ return { size: bytes.length, fragments: [{ kind: 'bytes', bytes }] };
299
+ }
300
+ if (operand.kind === 'reg-half-index') {
301
+ const bytes = incDecHalfIndexOpcode(mnemonic, operand.register);
302
+ return { size: bytes.length, fragments: [{ kind: 'bytes', bytes }] };
303
+ }
304
+ if (operand.kind === 'indexed') {
305
+ return {
306
+ size: 3,
307
+ fragments: [
308
+ { kind: 'bytes', bytes: [indexPrefix(operand.register), incDecBase(mnemonic).memHl] },
309
+ { kind: 'disp8', expression: operand.displacement },
310
+ ],
311
+ };
312
+ }
313
+ return {
314
+ size: 1,
315
+ fragments: [{ kind: 'bytes', bytes: [incDecBase(mnemonic).memHl] }],
316
+ };
111
317
  }
112
- function isMemRegName(op, reg) {
113
- return op.kind === 'Mem' && op.expr.kind === 'EaName' && op.expr.name.toUpperCase() === reg;
318
+ function incDecBase(mnemonic) {
319
+ return mnemonic === 'inc' ? { reg8: 0x04, memHl: 0x34 } : { reg8: 0x05, memHl: 0x35 };
114
320
  }
115
- function isReg16TransferName(name) {
116
- return (name === 'BC' ||
117
- name === 'DE' ||
118
- name === 'HL' ||
119
- name === 'SP' ||
120
- name === 'AF' ||
121
- name === 'IX' ||
122
- name === 'IY');
321
+ function incDecRegister16Opcode(mnemonic, register) {
322
+ const base = mnemonic === 'inc' ? 0x03 : 0x0b;
323
+ switch (register) {
324
+ case 'bc':
325
+ return [base];
326
+ case 'de':
327
+ return [base + 0x10];
328
+ case 'hl':
329
+ return [base + 0x20];
330
+ case 'sp':
331
+ return [base + 0x30];
332
+ case 'ix':
333
+ return [0xdd, base + 0x20];
334
+ case 'iy':
335
+ return [0xfd, base + 0x20];
336
+ }
123
337
  }
124
- function memIndexed(op, env, _diagnostics) {
125
- if (op.kind !== 'Mem')
126
- return undefined;
127
- const ea = op.expr;
128
- const encodeBaseDisp = (baseExpr, dispExpr, negate = false) => {
129
- if (baseExpr.kind !== 'EaName')
130
- return undefined;
131
- const base = baseExpr.name.toUpperCase();
132
- if (base !== 'IX' && base !== 'IY')
133
- return undefined;
134
- const rawDisp = evalImmExpr(dispExpr, env);
135
- if (rawDisp === undefined)
136
- return undefined;
137
- const prefix = base === 'IX' ? 0xdd : 0xfd;
138
- return { prefix, disp: negate ? -rawDisp : rawDisp };
338
+ function incDecHalfIndexOpcode(mnemonic, register) {
339
+ const lowOpcode = mnemonic === 'inc' ? 0x2c : 0x2d;
340
+ const highOpcode = mnemonic === 'inc' ? 0x24 : 0x25;
341
+ switch (register) {
342
+ case 'ixh':
343
+ return [0xdd, highOpcode];
344
+ case 'ixl':
345
+ return [0xdd, lowOpcode];
346
+ case 'iyh':
347
+ return [0xfd, highOpcode];
348
+ case 'iyl':
349
+ return [0xfd, lowOpcode];
350
+ }
351
+ }
352
+ function encodeStack(mnemonic, register) {
353
+ const bytes = stackOpcode(mnemonic, register);
354
+ return { size: bytes.length, fragments: [{ kind: 'bytes', bytes }] };
355
+ }
356
+ function encodeBitLike(mnemonic, bit, operand, destination) {
357
+ const operandCode = destination ? register8Code(destination.register) : cbOperandCode(operand);
358
+ const opcode = bitLikeOpcodeBase(mnemonic) + bit * 8 + operandCode;
359
+ return operand.kind === 'indexed'
360
+ ? indexedCbInstruction(operand, opcode, mnemonic)
361
+ : cbInstruction(opcode);
362
+ }
363
+ function encodeRotateShift(mnemonic, operand, destination) {
364
+ const operandCode = destination ? register8Code(destination.register) : cbOperandCode(operand);
365
+ const opcode = rotateShiftOpcodeBase(mnemonic) + operandCode;
366
+ return operand.kind === 'indexed'
367
+ ? indexedCbInstruction(operand, opcode, mnemonic)
368
+ : cbInstruction(opcode);
369
+ }
370
+ function cbInstruction(opcode) {
371
+ return {
372
+ size: 2,
373
+ fragments: [{ kind: 'bytes', bytes: [0xcb, opcode] }],
374
+ };
375
+ }
376
+ function indexedCbInstruction(operand, opcode, mnemonic) {
377
+ return {
378
+ size: 4,
379
+ fragments: [
380
+ { kind: 'bytes', bytes: [indexPrefix(operand.register), 0xcb] },
381
+ {
382
+ kind: 'disp8',
383
+ expression: operand.displacement,
384
+ message: `${mnemonic} (ix/iy+disp) expects disp8`,
385
+ },
386
+ { kind: 'bytes', bytes: [opcode] },
387
+ ],
139
388
  };
140
- if (ea.kind === 'EaIndex' && ea.index.kind === 'IndexImm') {
141
- return encodeBaseDisp(ea.base, ea.index.value);
389
+ }
390
+ function bitLikeOpcodeBase(mnemonic) {
391
+ switch (mnemonic) {
392
+ case 'bit':
393
+ return 0x40;
394
+ case 'res':
395
+ return 0x80;
396
+ case 'set':
397
+ return 0xc0;
142
398
  }
143
- if (ea.kind === 'EaName') {
144
- const base = ea.name.toUpperCase();
145
- if (base === 'IX')
146
- return { prefix: 0xdd, disp: 0 };
147
- if (base === 'IY')
148
- return { prefix: 0xfd, disp: 0 };
399
+ }
400
+ function rotateShiftOpcodeBase(mnemonic) {
401
+ switch (mnemonic) {
402
+ case 'rlc':
403
+ return 0x00;
404
+ case 'rrc':
405
+ return 0x08;
406
+ case 'rl':
407
+ return 0x10;
408
+ case 'rr':
409
+ return 0x18;
410
+ case 'sla':
411
+ return 0x20;
412
+ case 'sra':
413
+ return 0x28;
414
+ case 'sll':
415
+ case 'sls':
416
+ return 0x30;
417
+ case 'srl':
418
+ return 0x38;
149
419
  }
150
- if (ea.kind === 'EaAdd') {
151
- return encodeBaseDisp(ea.base, ea.offset);
420
+ }
421
+ function cbOperandCode(operand) {
422
+ return operand.kind === 'reg8' ? register8Code(operand.register) : 0x06;
423
+ }
424
+ function stackOpcode(mnemonic, register) {
425
+ const base = mnemonic === 'push' ? 0xc5 : 0xc1;
426
+ switch (register) {
427
+ case 'bc':
428
+ return [base];
429
+ case 'de':
430
+ return [base + 0x10];
431
+ case 'hl':
432
+ return [base + 0x20];
433
+ case 'af':
434
+ return [base + 0x30];
435
+ case 'ix':
436
+ return [0xdd, base + 0x20];
437
+ case 'iy':
438
+ return [0xfd, base + 0x20];
152
439
  }
153
- if (ea.kind === 'EaSub') {
154
- return encodeBaseDisp(ea.base, ea.offset, true);
440
+ }
441
+ function encode16BitAlu(mnemonic, target, source) {
442
+ if ((target === 'ix' || target === 'iy') && mnemonic !== 'add') {
443
+ throw new Error(`unsupported indexed ${mnemonic.toUpperCase()} target: ${target}`);
155
444
  }
156
- return undefined;
445
+ const opcode = target === 'ix' || target === 'iy'
446
+ ? indexedAddOpcode(target, source)
447
+ : hlAluOpcode(mnemonic, source);
448
+ return {
449
+ size: opcode.length,
450
+ fragments: [{ kind: 'bytes', bytes: opcode }],
451
+ };
157
452
  }
158
- function memAbs16(op, env) {
159
- if (op.kind !== 'Mem')
160
- return undefined;
161
- const evalEaAbs16 = (ea) => {
162
- switch (ea.kind) {
163
- case 'EaName':
164
- return evalImmExpr({
165
- kind: 'ImmName',
166
- span: ea.span,
167
- name: ea.name,
168
- }, env);
169
- case 'EaImm':
170
- return evalImmExpr(ea.expr, env);
171
- case 'EaAdd': {
172
- const base = evalEaAbs16(ea.base);
173
- const delta = evalImmExpr(ea.offset, env);
174
- if (base === undefined || delta === undefined)
175
- return undefined;
176
- return base + delta;
453
+ function indexedAddOpcode(target, source) {
454
+ const prefix = indexPrefix(target);
455
+ switch (source) {
456
+ case 'bc':
457
+ return [prefix, 0x09];
458
+ case 'de':
459
+ return [prefix, 0x19];
460
+ case 'sp':
461
+ return [prefix, 0x39];
462
+ case 'ix':
463
+ if (target === 'ix') {
464
+ return [prefix, 0x29];
177
465
  }
178
- case 'EaSub': {
179
- const base = evalEaAbs16(ea.base);
180
- const delta = evalImmExpr(ea.offset, env);
181
- if (base === undefined || delta === undefined)
182
- return undefined;
183
- return base - delta;
466
+ break;
467
+ case 'iy':
468
+ if (target === 'iy') {
469
+ return [prefix, 0x29];
184
470
  }
185
- default:
186
- return undefined;
187
- }
188
- };
189
- return evalEaAbs16(op.expr);
471
+ break;
472
+ }
473
+ throw new Error(`unsupported indexed ADD source: ${source}`);
190
474
  }
191
- function conditionName(op) {
192
- if (op.kind === 'Reg')
193
- return op.name.toUpperCase();
194
- if (op.kind === 'Imm' && op.expr.kind === 'ImmName')
195
- return op.expr.name.toUpperCase();
196
- return undefined;
475
+ function hlAluOpcode(mnemonic, source) {
476
+ const registerCode = register16Code(source);
477
+ switch (mnemonic) {
478
+ case 'add':
479
+ return [0x09 + registerCode * 0x10];
480
+ case 'adc':
481
+ return [0xed, 0x4a + registerCode * 0x10];
482
+ case 'sbc':
483
+ return [0xed, 0x42 + registerCode * 0x10];
484
+ }
197
485
  }
198
- function symbolicImmBaseName(op, env) {
199
- if (op.kind !== 'Imm')
200
- return undefined;
201
- const expr = op.expr;
202
- if (expr.kind === 'ImmName')
203
- return expr.name.toUpperCase();
204
- if (expr.kind !== 'ImmBinary')
486
+ function encodeAlu(mnemonic, source) {
487
+ const opcodes = aluOpcodes(mnemonic);
488
+ if (source.kind === 'reg8') {
489
+ return {
490
+ size: 1,
491
+ fragments: [
492
+ { kind: 'bytes', bytes: [opcodes.registerBase + register8Code(source.register)] },
493
+ ],
494
+ };
495
+ }
496
+ if (source.kind === 'reg-half-index') {
497
+ return {
498
+ size: 2,
499
+ fragments: [
500
+ {
501
+ kind: 'bytes',
502
+ bytes: [
503
+ halfIndexPrefix(source, source),
504
+ opcodes.registerBase + halfIndexRegisterCode(source.register),
505
+ ],
506
+ },
507
+ ],
508
+ };
509
+ }
510
+ if (source.kind === 'reg-indirect' && source.register === 'hl') {
511
+ return { size: 1, fragments: [{ kind: 'bytes', bytes: [opcodes.memHl] }] };
512
+ }
513
+ if (source.kind === 'indexed') {
514
+ return {
515
+ size: 3,
516
+ fragments: [
517
+ { kind: 'bytes', bytes: [indexPrefix(source.register), opcodes.memHl] },
518
+ { kind: 'disp8', expression: source.displacement },
519
+ ],
520
+ };
521
+ }
522
+ if (source.kind === 'imm') {
523
+ return {
524
+ size: 2,
525
+ fragments: [
526
+ { kind: 'bytes', bytes: [opcodes.immediate] },
527
+ { kind: 'imm8', expression: source.expression },
528
+ ],
529
+ };
530
+ }
531
+ return { size: 0, fragments: [] };
532
+ }
533
+ function aluOpcodes(mnemonic) {
534
+ switch (mnemonic) {
535
+ case 'add':
536
+ return { registerBase: 0x80, immediate: 0xc6, memHl: 0x86 };
537
+ case 'adc':
538
+ return { registerBase: 0x88, immediate: 0xce, memHl: 0x8e };
539
+ case 'sub':
540
+ return { registerBase: 0x90, immediate: 0xd6, memHl: 0x96 };
541
+ case 'sbc':
542
+ return { registerBase: 0x98, immediate: 0xde, memHl: 0x9e };
543
+ case 'and':
544
+ return { registerBase: 0xa0, immediate: 0xe6, memHl: 0xa6 };
545
+ case 'or':
546
+ return { registerBase: 0xb0, immediate: 0xf6, memHl: 0xb6 };
547
+ case 'xor':
548
+ return { registerBase: 0xa8, immediate: 0xee, memHl: 0xae };
549
+ case 'cp':
550
+ return { registerBase: 0xb8, immediate: 0xfe, memHl: 0xbe };
551
+ }
552
+ }
553
+ const LD_UNSUPPORTED_FORM_MESSAGE = 'ld expects a supported register/memory/immediate transfer form';
554
+ function encodeLd(target, source) {
555
+ const legacyReg16Pair = encodeLegacyReg16ByteTransferLd(target, source);
556
+ if (legacyReg16Pair) {
557
+ return legacyReg16Pair;
558
+ }
559
+ const specialRegisterLd = encodeSpecialRegisterLd(target, source);
560
+ if (specialRegisterLd) {
561
+ return specialRegisterLd;
562
+ }
563
+ if (target.kind === 'reg8' && source.kind === 'imm') {
564
+ return {
565
+ size: 2,
566
+ fragments: [
567
+ { kind: 'bytes', bytes: [0x06 + register8Code(target.register) * 8] },
568
+ {
569
+ kind: 'imm8',
570
+ expression: source.expression,
571
+ failureMessage: LD_UNSUPPORTED_FORM_MESSAGE,
572
+ },
573
+ ],
574
+ };
575
+ }
576
+ if (target.kind === 'reg8' && source.kind === 'reg8') {
577
+ return {
578
+ size: 1,
579
+ fragments: [
580
+ {
581
+ kind: 'bytes',
582
+ bytes: [0x40 + register8Code(target.register) * 8 + register8Code(source.register)],
583
+ },
584
+ ],
585
+ };
586
+ }
587
+ if (target.kind === 'reg8' && target.register === 'a' && source.kind === 'mem-abs') {
588
+ return absoluteLd(0x3a, source.expression);
589
+ }
590
+ if (target.kind === 'mem-abs' && source.kind === 'reg8' && source.register === 'a') {
591
+ return absoluteLd(0x32, target.expression);
592
+ }
593
+ if ((target.kind === 'reg8' || target.kind === 'reg-half-index') &&
594
+ (source.kind === 'reg8' || source.kind === 'reg-half-index') &&
595
+ isEncodableHalfIndexLd(target, source)) {
596
+ const prefix = halfIndexPrefix(target, source);
597
+ return {
598
+ size: 2,
599
+ fragments: [
600
+ {
601
+ kind: 'bytes',
602
+ bytes: [prefix, 0x40 + byteRegisterCode(target) * 8 + byteRegisterCode(source)],
603
+ },
604
+ ],
605
+ };
606
+ }
607
+ if (target.kind === 'reg16' && source.kind === 'imm') {
608
+ return {
609
+ size: 3,
610
+ fragments: [
611
+ { kind: 'bytes', bytes: [0x01 + register16Code(target.register) * 0x10] },
612
+ { kind: 'abs16', expression: source.expression },
613
+ ],
614
+ };
615
+ }
616
+ if (target.kind === 'reg-index16' && source.kind === 'imm') {
617
+ return {
618
+ size: 4,
619
+ fragments: [
620
+ { kind: 'bytes', bytes: [indexPrefix(target.register), 0x21] },
621
+ { kind: 'abs16', expression: source.expression },
622
+ ],
623
+ };
624
+ }
625
+ if (target.kind === 'reg16' &&
626
+ target.register === 'sp' &&
627
+ ((source.kind === 'reg16' && source.register === 'hl') || source.kind === 'reg-index16')) {
628
+ return {
629
+ size: source.kind === 'reg-index16' ? 2 : 1,
630
+ fragments: [{ kind: 'bytes', bytes: loadSpOpcode(source.register) }],
631
+ };
632
+ }
633
+ if (target.kind === 'reg16' && source.kind === 'mem-abs') {
634
+ return absoluteRegister16Load(target.register, source.expression);
635
+ }
636
+ if (target.kind === 'reg-index16' && source.kind === 'mem-abs') {
637
+ return prefixedAbsoluteLd(indexPrefix(target.register), 0x2a, source.expression);
638
+ }
639
+ if (target.kind === 'mem-abs' && source.kind === 'reg16') {
640
+ return absoluteRegister16Store(source.register, target.expression);
641
+ }
642
+ if (target.kind === 'mem-abs' && source.kind === 'reg-index16') {
643
+ return prefixedAbsoluteLd(indexPrefix(source.register), 0x22, target.expression);
644
+ }
645
+ if (target.kind === 'reg8' && target.register === 'a' && source.kind === 'reg-indirect') {
646
+ return {
647
+ size: 1,
648
+ fragments: [{ kind: 'bytes', bytes: [loadAFromIndirectOpcode(source.register)] }],
649
+ };
650
+ }
651
+ if (target.kind === 'reg-indirect' && source.kind === 'reg8' && source.register === 'a') {
652
+ return {
653
+ size: 1,
654
+ fragments: [{ kind: 'bytes', bytes: [storeAToIndirectOpcode(target.register)] }],
655
+ };
656
+ }
657
+ if (target.kind === 'reg-indirect' && target.register === 'hl' && source.kind === 'reg8') {
658
+ return {
659
+ size: 1,
660
+ fragments: [{ kind: 'bytes', bytes: [0x70 + register8Code(source.register)] }],
661
+ };
662
+ }
663
+ if (target.kind === 'reg-indirect' && target.register === 'hl' && source.kind === 'imm') {
664
+ return {
665
+ size: 2,
666
+ fragments: [
667
+ { kind: 'bytes', bytes: [0x36] },
668
+ {
669
+ kind: 'imm8',
670
+ expression: source.expression,
671
+ failureMessage: LD_UNSUPPORTED_FORM_MESSAGE,
672
+ },
673
+ ],
674
+ };
675
+ }
676
+ if (target.kind === 'reg8' && source.kind === 'reg-indirect' && source.register === 'hl') {
677
+ return {
678
+ size: 1,
679
+ fragments: [{ kind: 'bytes', bytes: [0x46 + register8Code(target.register) * 8] }],
680
+ };
681
+ }
682
+ if (target.kind === 'reg8' && source.kind === 'indexed') {
683
+ return {
684
+ size: 3,
685
+ fragments: [
686
+ {
687
+ kind: 'bytes',
688
+ bytes: [indexPrefix(source.register), 0x46 + register8Code(target.register) * 8],
689
+ },
690
+ {
691
+ kind: 'disp8',
692
+ expression: source.displacement,
693
+ message: 'ld (ix/iy+disp) expects disp8',
694
+ },
695
+ ],
696
+ };
697
+ }
698
+ if (target.kind === 'indexed' && source.kind === 'reg8') {
699
+ return {
700
+ size: 3,
701
+ fragments: [
702
+ {
703
+ kind: 'bytes',
704
+ bytes: [indexPrefix(target.register), 0x70 + register8Code(source.register)],
705
+ },
706
+ {
707
+ kind: 'disp8',
708
+ expression: target.displacement,
709
+ message: 'ld (ix/iy+disp) expects disp8',
710
+ },
711
+ ],
712
+ };
713
+ }
714
+ if (target.kind === 'indexed' && source.kind === 'imm') {
715
+ return {
716
+ size: 4,
717
+ fragments: [
718
+ { kind: 'bytes', bytes: [indexPrefix(target.register), 0x36] },
719
+ {
720
+ kind: 'disp8',
721
+ expression: target.displacement,
722
+ message: 'ld (ix/iy+disp), n expects disp8',
723
+ },
724
+ {
725
+ kind: 'imm8',
726
+ expression: source.expression,
727
+ failureMessage: LD_UNSUPPORTED_FORM_MESSAGE,
728
+ },
729
+ ],
730
+ };
731
+ }
732
+ return {
733
+ size: 0,
734
+ fragments: [],
735
+ };
736
+ }
737
+ function encodeLegacyReg16ByteTransferLd(target, source) {
738
+ if (target.kind !== 'reg16' || source.kind !== 'reg16') {
205
739
  return undefined;
206
- if (expr.op !== '+' && expr.op !== '-')
740
+ }
741
+ const transfers = legacyReg16ByteTransferOpcodes(target.register, source.register);
742
+ if (!transfers) {
207
743
  return undefined;
208
- const leftName = expr.left.kind === 'ImmName' ? expr.left.name.toUpperCase() : undefined;
209
- const rightName = expr.right.kind === 'ImmName' ? expr.right.name.toUpperCase() : undefined;
210
- if (leftName) {
211
- const right = evalImmExpr(expr.right, env);
212
- if (right !== undefined)
213
- return leftName;
214
- }
215
- if (expr.op === '+' && rightName) {
216
- const left = evalImmExpr(expr.left, env);
217
- if (left !== undefined)
218
- return rightName;
744
+ }
745
+ return {
746
+ size: transfers.length,
747
+ fragments: [{ kind: 'bytes', bytes: transfers }],
748
+ };
749
+ }
750
+ function legacyReg16ByteTransferOpcodes(target, source) {
751
+ if (target === 'hl' && source === 'de') {
752
+ return [0x62, 0x6b];
753
+ }
754
+ if (target === 'bc' && source === 'de') {
755
+ return [0x42, 0x4b];
219
756
  }
220
757
  return undefined;
221
758
  }
222
- function jpConditionOpcode(name) {
223
- switch (name) {
224
- case 'NZ':
225
- return 0xc2;
226
- case 'Z':
227
- return 0xca;
228
- case 'NC':
229
- return 0xd2;
230
- case 'C':
231
- return 0xda;
232
- case 'PO':
233
- return 0xe2;
234
- case 'PE':
235
- return 0xea;
236
- case 'P':
237
- return 0xf2;
238
- case 'M':
239
- return 0xfa;
240
- default:
241
- return undefined;
759
+ function encodeSpecialRegisterLd(target, source) {
760
+ if (target.kind === 'special8' && source.kind === 'reg8' && source.register === 'a') {
761
+ return {
762
+ size: 2,
763
+ fragments: [{ kind: 'bytes', bytes: [0xed, target.register === 'i' ? 0x47 : 0x4f] }],
764
+ };
765
+ }
766
+ if (target.kind === 'reg8' && target.register === 'a' && source.kind === 'special8') {
767
+ return {
768
+ size: 2,
769
+ fragments: [{ kind: 'bytes', bytes: [0xed, source.register === 'i' ? 0x57 : 0x5f] }],
770
+ };
242
771
  }
772
+ return undefined;
243
773
  }
244
- function jrConditionOpcode(name) {
245
- switch (name) {
246
- case 'NZ':
247
- return 0x20;
248
- case 'Z':
249
- return 0x28;
250
- case 'NC':
251
- return 0x30;
252
- case 'C':
253
- return 0x38;
254
- default:
255
- return undefined;
256
- }
257
- }
258
- function callConditionOpcode(name) {
259
- switch (name) {
260
- case 'NZ':
261
- return 0xc4;
262
- case 'Z':
263
- return 0xcc;
264
- case 'NC':
265
- return 0xd4;
266
- case 'C':
267
- return 0xdc;
268
- case 'PO':
269
- return 0xe4;
270
- case 'PE':
271
- return 0xec;
272
- case 'P':
273
- return 0xf4;
274
- case 'M':
275
- return 0xfc;
276
- default:
277
- return undefined;
774
+ function absoluteLd(opcode, expression) {
775
+ return {
776
+ size: 3,
777
+ fragments: [
778
+ { kind: 'bytes', bytes: [opcode] },
779
+ { kind: 'abs16', expression },
780
+ ],
781
+ };
782
+ }
783
+ function prefixedAbsoluteLd(prefix, opcode, expression) {
784
+ return {
785
+ size: 4,
786
+ fragments: [
787
+ { kind: 'bytes', bytes: [prefix, opcode] },
788
+ { kind: 'abs16', expression },
789
+ ],
790
+ };
791
+ }
792
+ function absoluteRegister16Load(register, expression) {
793
+ switch (register) {
794
+ case 'hl':
795
+ return absoluteLd(0x2a, expression);
796
+ case 'bc':
797
+ return prefixedAbsoluteLd(0xed, 0x4b, expression);
798
+ case 'de':
799
+ return prefixedAbsoluteLd(0xed, 0x5b, expression);
800
+ case 'sp':
801
+ return prefixedAbsoluteLd(0xed, 0x7b, expression);
278
802
  }
279
803
  }
280
- function retConditionOpcode(name) {
281
- switch (name) {
282
- case 'NZ':
283
- return 0xc0;
284
- case 'Z':
285
- return 0xc8;
286
- case 'NC':
287
- return 0xd0;
288
- case 'C':
289
- return 0xd8;
290
- case 'PO':
291
- return 0xe0;
292
- case 'PE':
293
- return 0xe8;
294
- case 'P':
295
- return 0xf0;
296
- case 'M':
297
- return 0xf8;
804
+ function absoluteRegister16Store(register, expression) {
805
+ switch (register) {
806
+ case 'hl':
807
+ return absoluteLd(0x22, expression);
808
+ case 'bc':
809
+ return prefixedAbsoluteLd(0xed, 0x43, expression);
810
+ case 'de':
811
+ return prefixedAbsoluteLd(0xed, 0x53, expression);
812
+ case 'sp':
813
+ return prefixedAbsoluteLd(0xed, 0x73, expression);
814
+ }
815
+ }
816
+ function indexPrefix(register) {
817
+ return register === 'ix' ? 0xdd : 0xfd;
818
+ }
819
+ function loadSpOpcode(register) {
820
+ switch (register) {
821
+ case 'hl':
822
+ return [0xf9];
823
+ case 'ix':
824
+ return [0xdd, 0xf9];
825
+ case 'iy':
826
+ return [0xfd, 0xf9];
298
827
  default:
299
- return undefined;
300
- }
301
- }
302
- function encodeFamilyInstruction(family, node, env, diagnostics) {
303
- switch (family) {
304
- case 'control':
305
- return encodeControlInstruction(node, env, diagnostics, {
306
- diag,
307
- immValue,
308
- registerTokenName,
309
- conditionName,
310
- symbolicImmBaseName,
311
- fitsImm16,
312
- isMemRegName,
313
- retConditionOpcode,
314
- callConditionOpcode,
315
- jpConditionOpcode,
316
- jrConditionOpcode,
317
- });
318
- case 'alu':
319
- return encodeAluInstruction(node, env, diagnostics, {
320
- diag,
321
- regName,
322
- immValue,
323
- indexedReg8,
324
- reg8Code,
325
- fitsImm8,
326
- isMemHL,
327
- memIndexed: (op, env) => memIndexed(op, env, diagnostics),
328
- });
329
- case 'io':
330
- return encodeIoInstruction(node, env, diagnostics, {
331
- diag,
332
- regName,
333
- immValue,
334
- portImmValue,
335
- indexedReg8,
336
- reg8Code,
337
- fitsImm8,
338
- });
339
- case 'ld':
340
- return encodeLdInstruction(node, env, diagnostics, {
341
- diag,
342
- regName,
343
- immValue,
344
- indexedReg8,
345
- reg8Code,
346
- fitsImm8,
347
- fitsImm16,
348
- memAbs16,
349
- memIndexed: (op, env) => memIndexed(op, env, diagnostics),
350
- isMemHL,
351
- isMemRegName,
352
- isReg16TransferName,
353
- isPlainHLReg8,
354
- });
355
- case 'core':
356
- return encodeCoreOpsInstruction(node, env, diagnostics, {
357
- diag,
358
- regName,
359
- indexedReg8,
360
- reg8Code,
361
- isMemHL,
362
- memIndexed: (op, env) => memIndexed(op, env, diagnostics),
363
- });
364
- case 'bit':
365
- return encodeBitOpsInstruction(node, env, diagnostics, {
366
- diag,
367
- regName,
368
- immValue,
369
- indexedReg8,
370
- reg8Code,
371
- isMemHL,
372
- memIndexed: (op, env) => memIndexed(op, env, diagnostics),
373
- });
374
- }
375
- }
376
- /**
377
- * Encode a single `asm` instruction node into Z80 machine-code bytes.
378
- *
379
- * - Immediate operands may be `imm` expressions (const/enum names and operators), evaluated via the env.
380
- * - Unsupported forms append an error diagnostic and return `undefined`.
381
- */
382
- export function encodeInstruction(node, env, diagnostics) {
383
- const diagnosticsBefore = diagnostics.length;
384
- const head = node.head.toLowerCase();
385
- const entry = getEncoderRegistryEntry(head);
386
- if (!entry) {
387
- diagEncodeAt(diagnostics, node.span, `Unsupported instruction: ${node.head}`);
388
- return undefined;
828
+ throw new Error(`unsupported LD SP source register: ${register}`);
389
829
  }
390
- if (entry.kind === 'zero') {
391
- if (node.operands.length === 0)
392
- return entry.bytes;
393
- diagEncodeAt(diagnostics, node.span, `${head} expects no operands`);
394
- return undefined;
830
+ }
831
+ function halfIndexPrefix(target, source) {
832
+ const register = target.kind === 'reg-half-index'
833
+ ? target.register
834
+ : source.kind === 'reg-half-index'
835
+ ? source.register
836
+ : undefined;
837
+ if (!register) {
838
+ throw new Error('expected half-index register');
395
839
  }
396
- const encoded = encodeFamilyInstruction(entry.family, node, env, diagnostics);
397
- if (encoded)
398
- return encoded;
399
- if (entry.fallback === 'none')
400
- return undefined;
401
- if (diagnostics.length > diagnosticsBefore)
402
- return undefined;
403
- const arityMessage = entry.arityDiagnostic(head, node.operands.length);
404
- if (entry.fallback === 'arity-short-circuit' && arityMessage === undefined)
405
- return undefined;
406
- if (arityMessage !== undefined) {
407
- diagEncodeAt(diagnostics, node.span, arityMessage);
840
+ return register.startsWith('ix') ? 0xdd : 0xfd;
841
+ }
842
+ function isEncodableHalfIndexLd(target, source) {
843
+ if (target.kind !== 'reg-half-index' && source.kind !== 'reg-half-index') {
844
+ return false;
845
+ }
846
+ return (isSameHalfIndexFamily(target, source) &&
847
+ isHalfIndexCompatibleByteOperand(target) &&
848
+ isHalfIndexCompatibleByteOperand(source));
849
+ }
850
+ function isSameHalfIndexFamily(target, source) {
851
+ const targetFamily = halfIndexFamily(target);
852
+ const sourceFamily = halfIndexFamily(source);
853
+ return !targetFamily || !sourceFamily || targetFamily === sourceFamily;
854
+ }
855
+ function halfIndexFamily(operand) {
856
+ if (operand.kind !== 'reg-half-index') {
408
857
  return undefined;
409
858
  }
410
- diagEncodeAt(diagnostics, node.span, `${head} has unsupported operand form`);
411
- return undefined;
859
+ return operand.register.startsWith('ix') ? 'ix' : 'iy';
860
+ }
861
+ function isHalfIndexCompatibleByteOperand(operand) {
862
+ return (operand.kind === 'reg-half-index' ||
863
+ (operand.kind === 'reg8' && operand.register !== 'h' && operand.register !== 'l'));
864
+ }
865
+ function byteRegisterCode(operand) {
866
+ return operand.kind === 'reg8'
867
+ ? register8Code(operand.register)
868
+ : halfIndexRegisterCode(operand.register);
869
+ }
870
+ function halfIndexRegisterCode(register) {
871
+ switch (register) {
872
+ case 'ixh':
873
+ case 'iyh':
874
+ return 4;
875
+ case 'ixl':
876
+ case 'iyl':
877
+ return 5;
878
+ }
879
+ }
880
+ function register8Code(register) {
881
+ switch (register) {
882
+ case 'b':
883
+ return 0;
884
+ case 'c':
885
+ return 1;
886
+ case 'd':
887
+ return 2;
888
+ case 'e':
889
+ return 3;
890
+ case 'h':
891
+ return 4;
892
+ case 'l':
893
+ return 5;
894
+ case 'a':
895
+ return 7;
896
+ }
897
+ }
898
+ function register16Code(register) {
899
+ switch (register) {
900
+ case 'bc':
901
+ return 0;
902
+ case 'de':
903
+ return 1;
904
+ case 'hl':
905
+ return 2;
906
+ case 'sp':
907
+ return 3;
908
+ }
909
+ }
910
+ function loadAFromIndirectOpcode(register) {
911
+ switch (register) {
912
+ case 'bc':
913
+ return 0x0a;
914
+ case 'de':
915
+ return 0x1a;
916
+ case 'hl':
917
+ return 0x7e;
918
+ }
919
+ }
920
+ function storeAToIndirectOpcode(register) {
921
+ switch (register) {
922
+ case 'bc':
923
+ return 0x02;
924
+ case 'de':
925
+ return 0x12;
926
+ case 'hl':
927
+ return 0x77;
928
+ }
929
+ }
930
+ function absoluteTarget(opcode, expression) {
931
+ return {
932
+ size: 3,
933
+ fragments: [
934
+ { kind: 'bytes', bytes: [opcode] },
935
+ { kind: 'abs16', expression },
936
+ ],
937
+ };
938
+ }
939
+ function jumpIndirect(register) {
940
+ switch (register) {
941
+ case 'hl':
942
+ return { size: 1, fragments: [{ kind: 'bytes', bytes: [0xe9] }] };
943
+ case 'ix':
944
+ return { size: 2, fragments: [{ kind: 'bytes', bytes: [0xdd, 0xe9] }] };
945
+ case 'iy':
946
+ return { size: 2, fragments: [{ kind: 'bytes', bytes: [0xfd, 0xe9] }] };
947
+ }
948
+ }
949
+ function relativeTarget(opcode, mnemonic, expression) {
950
+ return {
951
+ size: 2,
952
+ fragments: [
953
+ { kind: 'bytes', bytes: [opcode] },
954
+ { kind: 'rel8', expression, mnemonic },
955
+ ],
956
+ };
957
+ }
958
+ function conditionCode(condition) {
959
+ switch (condition) {
960
+ case 'nz':
961
+ return 0;
962
+ case 'z':
963
+ return 1;
964
+ case 'nc':
965
+ return 2;
966
+ case 'c':
967
+ return 3;
968
+ case 'po':
969
+ return 4;
970
+ case 'pe':
971
+ return 5;
972
+ case 'p':
973
+ return 6;
974
+ case 'm':
975
+ return 7;
976
+ }
977
+ }
978
+ function retConditionOpcode(condition) {
979
+ return 0xc0 + conditionCode(condition) * 8;
980
+ }
981
+ function jpConditionOpcode(condition) {
982
+ return 0xc2 + conditionCode(condition) * 8;
983
+ }
984
+ function callConditionOpcode(condition) {
985
+ return 0xc4 + conditionCode(condition) * 8;
986
+ }
987
+ function jrConditionOpcode(condition) {
988
+ return 0x20 + conditionCode(condition) * 8;
412
989
  }