@jhlagado/azm 0.1.0

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 (301) hide show
  1. package/LICENSE +649 -0
  2. package/README.md +142 -0
  3. package/dist/src/analysis.d.ts +11 -0
  4. package/dist/src/analysis.js +41 -0
  5. package/dist/src/api-compile.d.ts +8 -0
  6. package/dist/src/api-compile.js +3 -0
  7. package/dist/src/api-tooling.d.ts +25 -0
  8. package/dist/src/api-tooling.js +21 -0
  9. package/dist/src/cli.d.ts +30 -0
  10. package/dist/src/cli.js +523 -0
  11. package/dist/src/compile.d.ts +10 -0
  12. package/dist/src/compile.js +175 -0
  13. package/dist/src/compileShared.d.ts +3 -0
  14. package/dist/src/compileShared.js +7 -0
  15. package/dist/src/diagnosticTypes.d.ts +77 -0
  16. package/dist/src/diagnosticTypes.js +53 -0
  17. package/dist/src/formats/index.d.ts +7 -0
  18. package/dist/src/formats/index.js +17 -0
  19. package/dist/src/formats/range.d.ts +17 -0
  20. package/dist/src/formats/range.js +45 -0
  21. package/dist/src/formats/types.d.ts +208 -0
  22. package/dist/src/formats/types.js +1 -0
  23. package/dist/src/formats/writeAsm80.d.ts +6 -0
  24. package/dist/src/formats/writeAsm80.js +86 -0
  25. package/dist/src/formats/writeBin.d.ts +7 -0
  26. package/dist/src/formats/writeBin.js +23 -0
  27. package/dist/src/formats/writeD8m.d.ts +9 -0
  28. package/dist/src/formats/writeD8m.js +239 -0
  29. package/dist/src/formats/writeHex.d.ts +9 -0
  30. package/dist/src/formats/writeHex.js +39 -0
  31. package/dist/src/formats/writeListing.d.ts +8 -0
  32. package/dist/src/formats/writeListing.js +83 -0
  33. package/dist/src/frontend/asm80/asmLine.d.ts +39 -0
  34. package/dist/src/frontend/asm80/asmLine.js +89 -0
  35. package/dist/src/frontend/asm80/parseAsmRawValues.d.ts +4 -0
  36. package/dist/src/frontend/asm80/parseAsmRawValues.js +94 -0
  37. package/dist/src/frontend/asm80/quoteScan.d.ts +10 -0
  38. package/dist/src/frontend/asm80/quoteScan.js +25 -0
  39. package/dist/src/frontend/ast.d.ts +376 -0
  40. package/dist/src/frontend/ast.js +1 -0
  41. package/dist/src/frontend/directiveAliases.d.ts +14 -0
  42. package/dist/src/frontend/directiveAliases.js +189 -0
  43. package/dist/src/frontend/grammarData.d.ts +14 -0
  44. package/dist/src/frontend/grammarData.js +65 -0
  45. package/dist/src/frontend/immExprUtils.d.ts +2 -0
  46. package/dist/src/frontend/immExprUtils.js +12 -0
  47. package/dist/src/frontend/parseAsmFlatDirectiveLine.d.ts +17 -0
  48. package/dist/src/frontend/parseAsmFlatDirectiveLine.js +187 -0
  49. package/dist/src/frontend/parseAsmInstruction.d.ts +3 -0
  50. package/dist/src/frontend/parseAsmInstruction.js +73 -0
  51. package/dist/src/frontend/parseAsmStatements.d.ts +6 -0
  52. package/dist/src/frontend/parseAsmStatements.js +16 -0
  53. package/dist/src/frontend/parseAsmStream.d.ts +10 -0
  54. package/dist/src/frontend/parseAsmStream.js +33 -0
  55. package/dist/src/frontend/parseAsmTopLevel.d.ts +18 -0
  56. package/dist/src/frontend/parseAsmTopLevel.js +34 -0
  57. package/dist/src/frontend/parseDiagnostics.d.ts +9 -0
  58. package/dist/src/frontend/parseDiagnostics.js +16 -0
  59. package/dist/src/frontend/parseEnum.d.ts +12 -0
  60. package/dist/src/frontend/parseEnum.js +70 -0
  61. package/dist/src/frontend/parseImm.d.ts +10 -0
  62. package/dist/src/frontend/parseImm.js +397 -0
  63. package/dist/src/frontend/parseLogicalLines.d.ts +11 -0
  64. package/dist/src/frontend/parseLogicalLines.js +94 -0
  65. package/dist/src/frontend/parseOp.d.ts +25 -0
  66. package/dist/src/frontend/parseOp.js +120 -0
  67. package/dist/src/frontend/parseOpHeader.d.ts +20 -0
  68. package/dist/src/frontend/parseOpHeader.js +32 -0
  69. package/dist/src/frontend/parseOperands.d.ts +4 -0
  70. package/dist/src/frontend/parseOperands.js +290 -0
  71. package/dist/src/frontend/parseParams.d.ts +6 -0
  72. package/dist/src/frontend/parseParams.js +62 -0
  73. package/dist/src/frontend/parseParserRecovery.d.ts +12 -0
  74. package/dist/src/frontend/parseParserRecovery.js +17 -0
  75. package/dist/src/frontend/parseParserShared.d.ts +2 -0
  76. package/dist/src/frontend/parseParserShared.js +8 -0
  77. package/dist/src/frontend/parseRawDataDirectiveStart.d.ts +1 -0
  78. package/dist/src/frontend/parseRawDataDirectiveStart.js +3 -0
  79. package/dist/src/frontend/parseRawDataDirectives.d.ts +7 -0
  80. package/dist/src/frontend/parseRawDataDirectives.js +142 -0
  81. package/dist/src/frontend/parseRecordFieldDecl.d.ts +34 -0
  82. package/dist/src/frontend/parseRecordFieldDecl.js +177 -0
  83. package/dist/src/frontend/parseSourceItemDispatch.d.ts +46 -0
  84. package/dist/src/frontend/parseSourceItemDispatch.js +53 -0
  85. package/dist/src/frontend/parseSourceItemTable.d.ts +16 -0
  86. package/dist/src/frontend/parseSourceItemTable.js +68 -0
  87. package/dist/src/frontend/parseTopLevelCommon.d.ts +11 -0
  88. package/dist/src/frontend/parseTopLevelCommon.js +50 -0
  89. package/dist/src/frontend/parseTypes.d.ts +24 -0
  90. package/dist/src/frontend/parseTypes.js +77 -0
  91. package/dist/src/frontend/parser.d.ts +11 -0
  92. package/dist/src/frontend/parser.js +88 -0
  93. package/dist/src/frontend/source.d.ts +28 -0
  94. package/dist/src/frontend/source.js +58 -0
  95. package/dist/src/frontend/sourceExtensions.d.ts +2 -0
  96. package/dist/src/frontend/sourceExtensions.js +6 -0
  97. package/dist/src/index.d.ts +3 -0
  98. package/dist/src/index.js +2 -0
  99. package/dist/src/lintCaseStyle.d.ts +4 -0
  100. package/dist/src/lintCaseStyle.js +129 -0
  101. package/dist/src/lowering/asmDirectiveLowering.d.ts +4 -0
  102. package/dist/src/lowering/asmDirectiveLowering.js +229 -0
  103. package/dist/src/lowering/asmDirectiveTraversal.d.ts +47 -0
  104. package/dist/src/lowering/asmDirectiveTraversal.js +52 -0
  105. package/dist/src/lowering/asmEquResolution.d.ts +8 -0
  106. package/dist/src/lowering/asmEquResolution.js +69 -0
  107. package/dist/src/lowering/asmInstructionLdHelpers.d.ts +15 -0
  108. package/dist/src/lowering/asmInstructionLdHelpers.js +102 -0
  109. package/dist/src/lowering/asmInstructionLowering.d.ts +5 -0
  110. package/dist/src/lowering/asmInstructionLowering.js +54 -0
  111. package/dist/src/lowering/asmInstructionStream.d.ts +46 -0
  112. package/dist/src/lowering/asmInstructionStream.js +51 -0
  113. package/dist/src/lowering/asmLoweringBranchCall.d.ts +43 -0
  114. package/dist/src/lowering/asmLoweringBranchCall.js +254 -0
  115. package/dist/src/lowering/asmLoweringHost.d.ts +23 -0
  116. package/dist/src/lowering/asmLoweringHost.js +1 -0
  117. package/dist/src/lowering/asmLoweringLd.d.ts +28 -0
  118. package/dist/src/lowering/asmLoweringLd.js +144 -0
  119. package/dist/src/lowering/asmRangeLowering.d.ts +17 -0
  120. package/dist/src/lowering/asmRangeLowering.js +39 -0
  121. package/dist/src/lowering/asmRawDataLowering.d.ts +16 -0
  122. package/dist/src/lowering/asmRawDataLowering.js +209 -0
  123. package/dist/src/lowering/asmSourceEmitter.d.ts +4 -0
  124. package/dist/src/lowering/asmSourceEmitter.js +9 -0
  125. package/dist/src/lowering/asmSourceInstructionLowering.d.ts +4 -0
  126. package/dist/src/lowering/asmSourceInstructionLowering.js +14 -0
  127. package/dist/src/lowering/asmUtils.d.ts +13 -0
  128. package/dist/src/lowering/asmUtils.js +105 -0
  129. package/dist/src/lowering/assemblerFlowSetup.d.ts +54 -0
  130. package/dist/src/lowering/assemblerFlowSetup.js +128 -0
  131. package/dist/src/lowering/assemblerLoweringContext.d.ts +151 -0
  132. package/dist/src/lowering/assemblerLoweringContext.js +16 -0
  133. package/dist/src/lowering/assemblerLoweringContextSplit.d.ts +7 -0
  134. package/dist/src/lowering/assemblerLoweringContextSplit.js +75 -0
  135. package/dist/src/lowering/assemblerLoweringPhases.d.ts +66 -0
  136. package/dist/src/lowering/assemblerLoweringPhases.js +166 -0
  137. package/dist/src/lowering/bytePlacement.d.ts +7 -0
  138. package/dist/src/lowering/bytePlacement.js +37 -0
  139. package/dist/src/lowering/capabilities.d.ts +67 -0
  140. package/dist/src/lowering/capabilities.js +1 -0
  141. package/dist/src/lowering/eaResolution.d.ts +58 -0
  142. package/dist/src/lowering/eaResolution.js +159 -0
  143. package/dist/src/lowering/emissionCore.d.ts +17 -0
  144. package/dist/src/lowering/emissionCore.js +21 -0
  145. package/dist/src/lowering/emit.d.ts +17 -0
  146. package/dist/src/lowering/emit.js +46 -0
  147. package/dist/src/lowering/emitContextBuilder.d.ts +63 -0
  148. package/dist/src/lowering/emitContextBuilder.js +41 -0
  149. package/dist/src/lowering/emitFinalization.d.ts +61 -0
  150. package/dist/src/lowering/emitFinalization.js +66 -0
  151. package/dist/src/lowering/emitFinalizationSetup.d.ts +19 -0
  152. package/dist/src/lowering/emitFinalizationSetup.js +26 -0
  153. package/dist/src/lowering/emitPhase1BuildProgramLoweringContext.d.ts +7 -0
  154. package/dist/src/lowering/emitPhase1BuildProgramLoweringContext.js +119 -0
  155. package/dist/src/lowering/emitPhase1Helpers.d.ts +4 -0
  156. package/dist/src/lowering/emitPhase1Helpers.js +12 -0
  157. package/dist/src/lowering/emitPhase1Types.d.ts +21 -0
  158. package/dist/src/lowering/emitPhase1Types.js +1 -0
  159. package/dist/src/lowering/emitPhase1WirePipeline.d.ts +70 -0
  160. package/dist/src/lowering/emitPhase1WirePipeline.js +203 -0
  161. package/dist/src/lowering/emitPhase1Workspace.d.ts +82 -0
  162. package/dist/src/lowering/emitPhase1Workspace.js +55 -0
  163. package/dist/src/lowering/emitPipeline.d.ts +121 -0
  164. package/dist/src/lowering/emitPipeline.js +57 -0
  165. package/dist/src/lowering/emitProgramContext.d.ts +39 -0
  166. package/dist/src/lowering/emitProgramContext.js +29 -0
  167. package/dist/src/lowering/emitState.d.ts +90 -0
  168. package/dist/src/lowering/emitState.js +124 -0
  169. package/dist/src/lowering/fixupBaseResolution.d.ts +7 -0
  170. package/dist/src/lowering/fixupBaseResolution.js +23 -0
  171. package/dist/src/lowering/fixupEmission.d.ts +64 -0
  172. package/dist/src/lowering/fixupEmission.js +199 -0
  173. package/dist/src/lowering/immMath.d.ts +2 -0
  174. package/dist/src/lowering/immMath.js +34 -0
  175. package/dist/src/lowering/inputAssets.d.ts +7 -0
  176. package/dist/src/lowering/inputAssets.js +106 -0
  177. package/dist/src/lowering/ldEncoding.d.ts +15 -0
  178. package/dist/src/lowering/ldEncoding.js +12 -0
  179. package/dist/src/lowering/ldEncodingRegMemHelpers.d.ts +5 -0
  180. package/dist/src/lowering/ldEncodingRegMemHelpers.js +124 -0
  181. package/dist/src/lowering/ldFormSelection.d.ts +26 -0
  182. package/dist/src/lowering/ldFormSelection.js +92 -0
  183. package/dist/src/lowering/ldLowering.d.ts +7 -0
  184. package/dist/src/lowering/ldLowering.js +13 -0
  185. package/dist/src/lowering/loweredAsmByteEmission.d.ts +23 -0
  186. package/dist/src/lowering/loweredAsmByteEmission.js +185 -0
  187. package/dist/src/lowering/loweredAsmPlacement.d.ts +13 -0
  188. package/dist/src/lowering/loweredAsmPlacement.js +86 -0
  189. package/dist/src/lowering/loweredAsmStreamRecording.d.ts +27 -0
  190. package/dist/src/lowering/loweredAsmStreamRecording.js +215 -0
  191. package/dist/src/lowering/loweredAsmTypes.d.ts +202 -0
  192. package/dist/src/lowering/loweredAsmTypes.js +1 -0
  193. package/dist/src/lowering/loweredFormat.d.ts +3 -0
  194. package/dist/src/lowering/loweredFormat.js +26 -0
  195. package/dist/src/lowering/loweredItemSize.d.ts +4 -0
  196. package/dist/src/lowering/loweredItemSize.js +17 -0
  197. package/dist/src/lowering/loweringDiagnostics.d.ts +9 -0
  198. package/dist/src/lowering/loweringDiagnostics.js +55 -0
  199. package/dist/src/lowering/loweringTypes.d.ts +27 -0
  200. package/dist/src/lowering/loweringTypes.js +1 -0
  201. package/dist/src/lowering/opCandidateRegistry.d.ts +9 -0
  202. package/dist/src/lowering/opCandidateRegistry.js +9 -0
  203. package/dist/src/lowering/opExpansionExecution.d.ts +15 -0
  204. package/dist/src/lowering/opExpansionExecution.js +45 -0
  205. package/dist/src/lowering/opExpansionOrchestration.d.ts +15 -0
  206. package/dist/src/lowering/opExpansionOrchestration.js +88 -0
  207. package/dist/src/lowering/opExpansionStream.d.ts +12 -0
  208. package/dist/src/lowering/opExpansionStream.js +176 -0
  209. package/dist/src/lowering/opMatching.d.ts +52 -0
  210. package/dist/src/lowering/opMatching.js +355 -0
  211. package/dist/src/lowering/opSubstitution.d.ts +13 -0
  212. package/dist/src/lowering/opSubstitution.js +175 -0
  213. package/dist/src/lowering/prescanTypes.d.ts +7 -0
  214. package/dist/src/lowering/prescanTypes.js +1 -0
  215. package/dist/src/lowering/programLowering.d.ts +144 -0
  216. package/dist/src/lowering/programLowering.js +2 -0
  217. package/dist/src/lowering/programLoweringDeclarations.d.ts +5 -0
  218. package/dist/src/lowering/programLoweringDeclarations.js +5 -0
  219. package/dist/src/lowering/programLoweringFinalize.d.ts +18 -0
  220. package/dist/src/lowering/programLoweringFinalize.js +115 -0
  221. package/dist/src/lowering/programLoweringTraversal.d.ts +2 -0
  222. package/dist/src/lowering/programLoweringTraversal.js +93 -0
  223. package/dist/src/lowering/programPrescan.d.ts +3 -0
  224. package/dist/src/lowering/programPrescan.js +37 -0
  225. package/dist/src/lowering/traceFormat.d.ts +13 -0
  226. package/dist/src/lowering/traceFormat.js +211 -0
  227. package/dist/src/pathCompare.d.ts +3 -0
  228. package/dist/src/pathCompare.js +26 -0
  229. package/dist/src/pipeline.d.ts +78 -0
  230. package/dist/src/pipeline.js +1 -0
  231. package/dist/src/registerCare/analyze.d.ts +24 -0
  232. package/dist/src/registerCare/analyze.js +327 -0
  233. package/dist/src/registerCare/annotate.d.ts +11 -0
  234. package/dist/src/registerCare/annotate.js +76 -0
  235. package/dist/src/registerCare/boundaryHints.d.ts +2 -0
  236. package/dist/src/registerCare/boundaryHints.js +10 -0
  237. package/dist/src/registerCare/carriers.d.ts +4 -0
  238. package/dist/src/registerCare/carriers.js +78 -0
  239. package/dist/src/registerCare/controlFlow.d.ts +5 -0
  240. package/dist/src/registerCare/controlFlow.js +35 -0
  241. package/dist/src/registerCare/fix.d.ts +11 -0
  242. package/dist/src/registerCare/fix.js +119 -0
  243. package/dist/src/registerCare/liveness.d.ts +7 -0
  244. package/dist/src/registerCare/liveness.js +227 -0
  245. package/dist/src/registerCare/profiles.d.ts +11 -0
  246. package/dist/src/registerCare/profiles.js +45 -0
  247. package/dist/src/registerCare/programModel.d.ts +3 -0
  248. package/dist/src/registerCare/programModel.js +181 -0
  249. package/dist/src/registerCare/report.d.ts +5 -0
  250. package/dist/src/registerCare/report.js +139 -0
  251. package/dist/src/registerCare/smartComments.d.ts +5 -0
  252. package/dist/src/registerCare/smartComments.js +247 -0
  253. package/dist/src/registerCare/sourceText.d.ts +8 -0
  254. package/dist/src/registerCare/sourceText.js +15 -0
  255. package/dist/src/registerCare/summary.d.ts +3 -0
  256. package/dist/src/registerCare/summary.js +492 -0
  257. package/dist/src/registerCare/tooling.d.ts +42 -0
  258. package/dist/src/registerCare/tooling.js +50 -0
  259. package/dist/src/registerCare/types.d.ts +154 -0
  260. package/dist/src/registerCare/types.js +1 -0
  261. package/dist/src/semantics/declVisitor.d.ts +5 -0
  262. package/dist/src/semantics/declVisitor.js +11 -0
  263. package/dist/src/semantics/env.d.ts +28 -0
  264. package/dist/src/semantics/env.js +432 -0
  265. package/dist/src/semantics/layout.d.ts +21 -0
  266. package/dist/src/semantics/layout.js +226 -0
  267. package/dist/src/semantics/layoutCastFold.d.ts +22 -0
  268. package/dist/src/semantics/layoutCastFold.js +118 -0
  269. package/dist/src/semantics/semanticsDiagnostics.d.ts +2 -0
  270. package/dist/src/semantics/semanticsDiagnostics.js +4 -0
  271. package/dist/src/semantics/typeQueries.d.ts +31 -0
  272. package/dist/src/semantics/typeQueries.js +124 -0
  273. package/dist/src/sourceIncludeExpansion.d.ts +17 -0
  274. package/dist/src/sourceIncludeExpansion.js +124 -0
  275. package/dist/src/sourceIncludePaths.d.ts +1 -0
  276. package/dist/src/sourceIncludePaths.js +12 -0
  277. package/dist/src/sourceLoader.d.ts +15 -0
  278. package/dist/src/sourceLoader.js +118 -0
  279. package/dist/src/z80/effects.d.ts +3 -0
  280. package/dist/src/z80/effects.js +516 -0
  281. package/dist/src/z80/encode.d.ts +10 -0
  282. package/dist/src/z80/encode.js +412 -0
  283. package/dist/src/z80/encodeAlu.d.ts +7 -0
  284. package/dist/src/z80/encodeAlu.js +219 -0
  285. package/dist/src/z80/encodeBitOps.d.ts +7 -0
  286. package/dist/src/z80/encodeBitOps.js +123 -0
  287. package/dist/src/z80/encodeContext.d.ts +29 -0
  288. package/dist/src/z80/encodeContext.js +1 -0
  289. package/dist/src/z80/encodeControl.d.ts +26 -0
  290. package/dist/src/z80/encodeControl.js +180 -0
  291. package/dist/src/z80/encodeCoreOps.d.ts +7 -0
  292. package/dist/src/z80/encodeCoreOps.js +131 -0
  293. package/dist/src/z80/encodeIo.d.ts +9 -0
  294. package/dist/src/z80/encodeIo.js +128 -0
  295. package/dist/src/z80/encodeLd.d.ts +13 -0
  296. package/dist/src/z80/encodeLd.js +273 -0
  297. package/dist/src/z80/encoderRegistry.d.ts +13 -0
  298. package/dist/src/z80/encoderRegistry.js +169 -0
  299. package/docs/reference/cli.md +134 -0
  300. package/docs/reference/tooling-api.md +248 -0
  301. package/package.json +98 -0
@@ -0,0 +1,102 @@
1
+ import { isConstantLayoutCastEa } from '../semantics/layoutCastFold.js';
2
+ export function createAsmInstructionLdHelpers(ctx) {
3
+ const isUnresolvedLayoutLdOperand = (op) => {
4
+ if (op.kind === 'Ea') {
5
+ if (isConstantLayoutCastEa(op.expr))
6
+ return false;
7
+ return true;
8
+ }
9
+ return false;
10
+ };
11
+ const resolveRawLabelName = (name) => ctx.resolveRawAliasTargetName(name) ?? name;
12
+ const emitAbs16LdFixup = (dst, src, span) => {
13
+ const dstName = dst.kind === 'Reg' ? dst.name.toUpperCase() : undefined;
14
+ const srcName = src.kind === 'Reg' ? src.name.toUpperCase() : undefined;
15
+ const memExpr = dst.kind === 'Mem' ? dst.expr : src.kind === 'Mem' ? src.expr : undefined;
16
+ if (!memExpr || memExpr.kind !== 'EaName')
17
+ return false;
18
+ // Register-indirect `(hl)`, `(bc)`, `(de)`, `(ix)`, `(iy)` use `EaName`; these are not
19
+ // the absolute-address `ld r/(nn)` forms handled below (see `isRegisterLikeMemEa`).
20
+ // Labels that spell HL/BC/DE/IX/IY cannot use `(name)` for absolute memory here; `(hl)` is always HL indirect.
21
+ if (ctx.reg16.has(memExpr.name.toUpperCase()))
22
+ return false;
23
+ const baseLower = resolveRawLabelName(memExpr.name).toLowerCase();
24
+ if (dst.kind === 'Reg' && src.kind === 'Mem') {
25
+ if (dstName === 'A') {
26
+ ctx.emitAbs16Fixup(0x3a, baseLower, 0, span);
27
+ return true;
28
+ }
29
+ if (dstName === 'HL') {
30
+ ctx.emitAbs16Fixup(0x2a, baseLower, 0, span);
31
+ return true;
32
+ }
33
+ if (dstName === 'BC') {
34
+ ctx.emitAbs16FixupPrefixed(0xed, 0x4b, baseLower, 0, span);
35
+ return true;
36
+ }
37
+ if (dstName === 'DE') {
38
+ ctx.emitAbs16FixupPrefixed(0xed, 0x5b, baseLower, 0, span);
39
+ return true;
40
+ }
41
+ if (dstName === 'SP') {
42
+ ctx.emitAbs16FixupPrefixed(0xed, 0x7b, baseLower, 0, span);
43
+ return true;
44
+ }
45
+ if (dstName === 'IX') {
46
+ ctx.emitAbs16FixupPrefixed(0xdd, 0x2a, baseLower, 0, span);
47
+ return true;
48
+ }
49
+ if (dstName === 'IY') {
50
+ ctx.emitAbs16FixupPrefixed(0xfd, 0x2a, baseLower, 0, span);
51
+ return true;
52
+ }
53
+ }
54
+ if (dst.kind === 'Mem' && src.kind === 'Reg') {
55
+ if (srcName === 'A') {
56
+ ctx.emitAbs16Fixup(0x32, baseLower, 0, span);
57
+ return true;
58
+ }
59
+ if (srcName === 'HL') {
60
+ ctx.emitAbs16Fixup(0x22, baseLower, 0, span);
61
+ return true;
62
+ }
63
+ if (srcName === 'BC') {
64
+ ctx.emitAbs16FixupPrefixed(0xed, 0x43, baseLower, 0, span);
65
+ return true;
66
+ }
67
+ if (srcName === 'DE') {
68
+ ctx.emitAbs16FixupPrefixed(0xed, 0x53, baseLower, 0, span);
69
+ return true;
70
+ }
71
+ if (srcName === 'SP') {
72
+ ctx.emitAbs16FixupPrefixed(0xed, 0x73, baseLower, 0, span);
73
+ return true;
74
+ }
75
+ if (srcName === 'IX') {
76
+ ctx.emitAbs16FixupPrefixed(0xdd, 0x22, baseLower, 0, span);
77
+ return true;
78
+ }
79
+ if (srcName === 'IY') {
80
+ ctx.emitAbs16FixupPrefixed(0xfd, 0x22, baseLower, 0, span);
81
+ return true;
82
+ }
83
+ }
84
+ return false;
85
+ };
86
+ const isRegisterLikeMemEa = (ea) => {
87
+ if (ea.kind === 'EaName') {
88
+ return ctx.reg16.has(ea.name.toUpperCase());
89
+ }
90
+ if ((ea.kind === 'EaAdd' || ea.kind === 'EaSub') && ea.base.kind === 'EaName') {
91
+ const base = ea.base.name.toUpperCase();
92
+ return base === 'IX' || base === 'IY';
93
+ }
94
+ return false;
95
+ };
96
+ return {
97
+ isUnresolvedLayoutLdOperand,
98
+ resolveRawLabelName,
99
+ emitAbs16LdFixup,
100
+ isRegisterLikeMemEa,
101
+ };
102
+ }
@@ -0,0 +1,5 @@
1
+ import type { AsmInstructionNode } from '../frontend/ast.js';
2
+ import type { AsmLoweringHost } from './asmLoweringHost.js';
3
+ export declare function createAsmInstructionLoweringHelpers(host: AsmLoweringHost): {
4
+ lowerAsmInstructionDispatcher: (asmItem: AsmInstructionNode) => void;
5
+ };
@@ -0,0 +1,54 @@
1
+ import { createAsmInstructionLdHelpers } from './asmInstructionLdHelpers.js';
2
+ import { tryLowerBranchCallInstruction } from './asmLoweringBranchCall.js';
3
+ import { tryLowerLdInstruction } from './asmLoweringLd.js';
4
+ export function createAsmInstructionLoweringHelpers(host) {
5
+ const { isUnresolvedLayoutLdOperand, resolveRawLabelName, emitAbs16LdFixup, isRegisterLikeMemEa, } = createAsmInstructionLdHelpers(host);
6
+ const lowerAsmInstructionDispatcher = (asmItem) => {
7
+ const branchResult = tryLowerBranchCallInstruction(asmItem, host);
8
+ if (branchResult !== undefined) {
9
+ if (!branchResult)
10
+ return;
11
+ return;
12
+ }
13
+ const ldResult = tryLowerLdInstruction(asmItem, {
14
+ diagnostics: host.diagnostics,
15
+ diagAt: host.diagAt,
16
+ emitAbs16Fixup: host.emitAbs16Fixup,
17
+ emitAbs16FixupPrefixed: host.emitAbs16FixupPrefixed,
18
+ evalImmExpr: host.evalImmExpr,
19
+ symbolicTargetFromExpr: host.symbolicTargetFromExpr,
20
+ resolveEa: host.resolveEa,
21
+ lowerLdWithEa: host.lowerLdWithEa,
22
+ emitAbs16LdFixup,
23
+ isUnresolvedLayoutLdOperand,
24
+ resolveRawLabelName,
25
+ isRegisterLikeMemEa,
26
+ syncToFlow: host.syncToFlow,
27
+ });
28
+ if (ldResult !== undefined) {
29
+ if (!ldResult)
30
+ return;
31
+ return;
32
+ }
33
+ const head = asmItem.head.toLowerCase();
34
+ if (head !== 'ld' && host.lowerLdWithEa(asmItem)) {
35
+ host.syncToFlow();
36
+ return;
37
+ }
38
+ if (host.emitVirtualReg16Transfer(asmItem)) {
39
+ host.syncToFlow();
40
+ return;
41
+ }
42
+ if (!host.emitInstr(asmItem.head, asmItem.operands, asmItem.span))
43
+ return;
44
+ if ((head === 'jp' || head === 'jr') && asmItem.operands.length === 1) {
45
+ host.flowRef.current.reachable = false;
46
+ }
47
+ else if ((head === 'ret' || head === 'retn' || head === 'reti') &&
48
+ asmItem.operands.length === 0) {
49
+ host.flowRef.current.reachable = false;
50
+ }
51
+ host.syncToFlow();
52
+ };
53
+ return { lowerAsmInstructionDispatcher };
54
+ }
@@ -0,0 +1,46 @@
1
+ import { DiagnosticIds } from '../diagnosticTypes.js';
2
+ import type { Diagnostic } from '../diagnosticTypes.js';
3
+ import type { AsmInstructionNode, AsmOperandNode, EaExprNode, ImmExprNode, OpDeclNode, SourceSpan } from '../frontend/ast.js';
4
+ import type { CompileEnv } from '../semantics/env.js';
5
+ import type { SourceSegmentTag } from './loweringTypes.js';
6
+ import type { OpOverloadSelection } from './opMatching.js';
7
+ import type { FlowState, OpExpansionFrame } from './assemblerFlowSetup.js';
8
+ type AsmInstructionStreamAddressingContext = {
9
+ flattenEaDottedName: (ea: EaExprNode) => string | undefined;
10
+ };
11
+ type AsmInstructionStreamContext = {
12
+ diagnostics: Diagnostic[];
13
+ asmItemSpanSourceTag: (span: SourceSpan) => SourceSegmentTag;
14
+ getCurrentCodeSegmentTag: () => SourceSegmentTag | undefined;
15
+ setCurrentCodeSegmentTag: (tag: SourceSegmentTag | undefined) => void;
16
+ appendInvalidOpExpansionDiagnostic: (asmItem: AsmInstructionNode, diagnosticsStart: number, stack: OpExpansionFrame[]) => void;
17
+ addressing: Readonly<AsmInstructionStreamAddressingContext>;
18
+ diagAt: (diagnostics: Diagnostic[], span: SourceSpan, message: string) => void;
19
+ diagAtWithSeverityAndId: (diagnostics: Diagnostic[], span: SourceSpan, id: (typeof DiagnosticIds)[keyof typeof DiagnosticIds], severity: 'error' | 'warning', message: string) => void;
20
+ env: CompileEnv;
21
+ emitInstr: (head: string, operands: AsmOperandNode[], span: SourceSpan) => boolean;
22
+ emitAbs16Fixup: (opcode: number, baseLower: string, addend: number, span: SourceSpan, asmText?: string) => void;
23
+ syncToFlow: () => void;
24
+ resolveOpCandidates: (name: string, file: string) => OpDeclNode[] | undefined;
25
+ opExpansionStack: OpExpansionFrame[];
26
+ diagAtWithId: (diagnostics: Diagnostic[], span: SourceSpan, id: (typeof DiagnosticIds)[keyof typeof DiagnosticIds], message: string) => void;
27
+ formatAsmOperandForOpDiag: (operand: AsmOperandNode) => string;
28
+ selectOpOverload: (overloads: OpDeclNode[], operands: AsmOperandNode[]) => OpOverloadSelection;
29
+ cloneImmExpr: (expr: ImmExprNode) => ImmExprNode;
30
+ cloneEaExpr: (expr: EaExprNode) => EaExprNode;
31
+ cloneOperand: (operand: AsmOperandNode) => AsmOperandNode;
32
+ normalizeFixedToken: (operand: AsmOperandNode) => string | undefined;
33
+ inverseConditionName: (name: string) => string | undefined;
34
+ newHiddenLabel: (prefix: string) => string;
35
+ lowerAsmInstructionDispatcher: (asmItem: AsmInstructionNode) => void;
36
+ defineCodeLabel: (name: string, span: SourceSpan, scope: 'global' | 'local') => void;
37
+ flowRef: {
38
+ readonly current: FlowState;
39
+ };
40
+ syncFromFlow: () => void;
41
+ };
42
+ export declare function createAsmInstructionStreamHelpers(ctx: AsmInstructionStreamContext): {
43
+ emitAsmInstruction: (asmItem: AsmInstructionNode) => void;
44
+ lowerAsmRange: (asmItems: readonly import("../frontend/ast.js").AsmItemNode[], startIndex: number, stopKinds: Set<string>) => number;
45
+ };
46
+ export {};
@@ -0,0 +1,51 @@
1
+ import { createAsmRangeLoweringHelpers } from './asmRangeLowering.js';
2
+ import { createOpExpansionOrchestrationHelpers } from './opExpansionOrchestration.js';
3
+ export function createAsmInstructionStreamHelpers(ctx) {
4
+ const emitAsmInstruction = (asmItem) => {
5
+ const prevTag = ctx.getCurrentCodeSegmentTag();
6
+ const diagnosticsStart = ctx.diagnostics.length;
7
+ ctx.setCurrentCodeSegmentTag(ctx.asmItemSpanSourceTag(asmItem.span));
8
+ try {
9
+ const { tryHandleOpExpansion } = createOpExpansionOrchestrationHelpers({
10
+ resolveOpCandidates: ctx.resolveOpCandidates,
11
+ diagnostics: ctx.diagnostics,
12
+ env: ctx.env,
13
+ opExpansionStack: ctx.opExpansionStack,
14
+ diagAt: ctx.diagAt,
15
+ diagAtWithId: ctx.diagAtWithId,
16
+ diagAtWithSeverityAndId: ctx.diagAtWithSeverityAndId,
17
+ formatAsmOperandForOpDiag: ctx.formatAsmOperandForOpDiag,
18
+ selectOpOverload: ctx.selectOpOverload,
19
+ cloneImmExpr: ctx.cloneImmExpr,
20
+ cloneEaExpr: ctx.cloneEaExpr,
21
+ cloneOperand: ctx.cloneOperand,
22
+ flattenEaDottedName: ctx.addressing.flattenEaDottedName,
23
+ normalizeFixedToken: ctx.normalizeFixedToken,
24
+ inverseConditionName: ctx.inverseConditionName,
25
+ newHiddenLabel: ctx.newHiddenLabel,
26
+ lowerAsmRange,
27
+ syncToFlow: ctx.syncToFlow,
28
+ });
29
+ if (tryHandleOpExpansion(asmItem))
30
+ return;
31
+ ctx.lowerAsmInstructionDispatcher(asmItem);
32
+ }
33
+ finally {
34
+ ctx.appendInvalidOpExpansionDiagnostic(asmItem, diagnosticsStart, ctx.opExpansionStack);
35
+ ctx.setCurrentCodeSegmentTag(prevTag);
36
+ }
37
+ };
38
+ const { lowerAsmRange } = createAsmRangeLoweringHelpers({
39
+ sourceTagForSpan: ctx.asmItemSpanSourceTag,
40
+ getCurrentCodeSegmentTag: ctx.getCurrentCodeSegmentTag,
41
+ setCurrentCodeSegmentTag: ctx.setCurrentCodeSegmentTag,
42
+ defineCodeLabel: ctx.defineCodeLabel,
43
+ emitAsmInstruction,
44
+ flowRef: ctx.flowRef,
45
+ syncFromFlow: ctx.syncFromFlow,
46
+ });
47
+ return {
48
+ emitAsmInstruction,
49
+ lowerAsmRange,
50
+ };
51
+ }
@@ -0,0 +1,43 @@
1
+ import { DiagnosticIds, type Diagnostic } from '../diagnosticTypes.js';
2
+ import type { AsmInstructionNode, AsmOperandNode } from '../frontend/ast.js';
3
+ type DiagAt = (diagnostics: Diagnostic[], span: AsmInstructionNode['span'], message: string) => void;
4
+ type DiagAtWithId = (diagnostics: Diagnostic[], span: AsmInstructionNode['span'], id: (typeof DiagnosticIds)[keyof typeof DiagnosticIds], message: string) => void;
5
+ export type BranchCallLoweringContext = {
6
+ diagnostics: Diagnostic[];
7
+ diagAt: DiagAt;
8
+ diagAtWithId: DiagAtWithId;
9
+ emitInstr: (head: string, operands: AsmOperandNode[], span: AsmInstructionNode['span']) => boolean;
10
+ emitRawCodeBytes: (bytes: Uint8Array, file: string, asmText: string) => void;
11
+ emitAbs16Fixup: (opcode: number, baseLower: string, addend: number, span: AsmInstructionNode['span']) => void;
12
+ emitRel8Fixup: (opcode: number, baseLower: string, addend: number, span: AsmInstructionNode['span'], mnemonic: string, asmText?: string) => void;
13
+ conditionOpcodeFromName: (nameRaw: string) => number | undefined;
14
+ callConditionOpcodeFromName: (nameRaw: string) => number | undefined;
15
+ jrConditionOpcodeFromName: (nameRaw: string) => number | undefined;
16
+ conditionOpcode: (op: AsmOperandNode) => number | undefined;
17
+ symbolicTargetFromExpr: (expr: Extract<AsmOperandNode, {
18
+ kind: 'Imm';
19
+ }>['expr']) => {
20
+ baseLower: string;
21
+ addend: number;
22
+ } | undefined;
23
+ evalImmExpr: (expr: Extract<AsmOperandNode, {
24
+ kind: 'Imm';
25
+ }>['expr']) => number | undefined;
26
+ currentAddress: () => number;
27
+ evalCurrentTarget?: (expr: Extract<AsmOperandNode, {
28
+ kind: 'Imm';
29
+ }>['expr']) => number | undefined;
30
+ diagIfRetStackImbalanced: (span: AsmInstructionNode['span'], mnemonic?: string) => void;
31
+ diagIfCallStackUnverifiable: (options: {
32
+ span: AsmInstructionNode['span'];
33
+ mnemonic?: string;
34
+ }) => void;
35
+ syncToFlow: () => void;
36
+ flowRef: {
37
+ current: {
38
+ reachable: boolean;
39
+ };
40
+ };
41
+ };
42
+ export declare function tryLowerBranchCallInstruction(asmItem: AsmInstructionNode, ctx: BranchCallLoweringContext): boolean | undefined;
43
+ export {};
@@ -0,0 +1,254 @@
1
+ import { DiagnosticIds } from '../diagnosticTypes.js';
2
+ function diagEncode(ctx, asmItem, message) {
3
+ ctx.diagAtWithId(ctx.diagnostics, asmItem.span, DiagnosticIds.EncodeError, message);
4
+ }
5
+ const emitRel8FromOperand = (ctx, asmItem, operand, opcode, mnemonic) => {
6
+ if (operand.kind !== 'Imm') {
7
+ if (mnemonic === 'djnz' || mnemonic.startsWith('jr')) {
8
+ diagEncode(ctx, asmItem, `${mnemonic} expects disp8`);
9
+ }
10
+ else {
11
+ diagEncode(ctx, asmItem, `${mnemonic} expects an immediate target.`);
12
+ }
13
+ return false;
14
+ }
15
+ const symbolicTarget = ctx.symbolicTargetFromExpr(operand.expr);
16
+ if (symbolicTarget) {
17
+ ctx.emitRel8Fixup(opcode, symbolicTarget.baseLower, symbolicTarget.addend, asmItem.span, mnemonic);
18
+ return true;
19
+ }
20
+ const currentTarget = ctx.evalCurrentTarget?.(operand.expr);
21
+ if (currentTarget !== undefined) {
22
+ const currentRelativeValue = currentTarget - (ctx.currentAddress() + 2);
23
+ if (currentRelativeValue < -128 || currentRelativeValue > 127) {
24
+ diagEncode(ctx, asmItem, `${mnemonic} relative branch displacement out of range (-128..127): ${currentRelativeValue}.`);
25
+ return false;
26
+ }
27
+ ctx.emitRawCodeBytes(Uint8Array.of(opcode, currentRelativeValue & 0xff), asmItem.span.file, `${mnemonic} ${currentRelativeValue}`);
28
+ return true;
29
+ }
30
+ const value = ctx.evalImmExpr(operand.expr);
31
+ if (value === undefined) {
32
+ diagEncode(ctx, asmItem, `Failed to evaluate ${mnemonic} target.`);
33
+ return false;
34
+ }
35
+ if (value < -128 || value > 127) {
36
+ diagEncode(ctx, asmItem, `${mnemonic} relative branch displacement out of range (-128..127): ${value}.`);
37
+ return false;
38
+ }
39
+ ctx.emitRawCodeBytes(Uint8Array.of(opcode, value & 0xff), asmItem.span.file, `${mnemonic} ${value}`);
40
+ return true;
41
+ };
42
+ function conditionNameFromOperand(op) {
43
+ if (op.kind === 'Imm' && op.expr.kind === 'ImmName')
44
+ return op.expr.name;
45
+ if (op.kind === 'Reg')
46
+ return op.name;
47
+ return undefined;
48
+ }
49
+ function rejectInvalidRel8Target(ctx, asmItem, target, messages) {
50
+ if (target.kind === 'Mem') {
51
+ diagEncode(ctx, asmItem, messages.indirect);
52
+ return true;
53
+ }
54
+ if (target.kind === 'Reg') {
55
+ diagEncode(ctx, asmItem, messages.register);
56
+ return true;
57
+ }
58
+ if (target.kind !== 'Imm') {
59
+ diagEncode(ctx, asmItem, messages.other);
60
+ return true;
61
+ }
62
+ return false;
63
+ }
64
+ function emitAbs16CurrentTargetFromOperand(ctx, asmItem, target, opcode) {
65
+ if (target.kind !== 'Imm')
66
+ return false;
67
+ const value = ctx.evalCurrentTarget?.(target.expr);
68
+ if (value === undefined)
69
+ return false;
70
+ if (value < 0 || value > 0xffff) {
71
+ diagEncode(ctx, asmItem, `16-bit branch target out of range: ${value}.`);
72
+ return true;
73
+ }
74
+ ctx.emitRawCodeBytes(Uint8Array.of(opcode, value & 0xff, (value >> 8) & 0xff), asmItem.span.file, `${asmItem.head.toLowerCase()} ${value}`);
75
+ ctx.syncToFlow();
76
+ return true;
77
+ }
78
+ function emitAbs16FixupFromOperand(ctx, asmItem, operand, opcode) {
79
+ if (operand.kind !== 'Imm')
80
+ return false;
81
+ const symbolicTarget = ctx.symbolicTargetFromExpr(operand.expr);
82
+ if (!symbolicTarget)
83
+ return false;
84
+ ctx.emitAbs16Fixup(opcode, symbolicTarget.baseLower, symbolicTarget.addend, asmItem.span);
85
+ ctx.syncToFlow();
86
+ return true;
87
+ }
88
+ export function tryLowerBranchCallInstruction(asmItem, ctx) {
89
+ const head = asmItem.head.toLowerCase();
90
+ if (head === 'call') {
91
+ ctx.diagIfCallStackUnverifiable({ span: asmItem.span });
92
+ }
93
+ if (head === 'jr') {
94
+ if (asmItem.operands.length === 1) {
95
+ if (asmItem.operands[0].kind === 'Mem') {
96
+ diagEncode(ctx, asmItem, `jr does not support indirect targets; expects disp8`);
97
+ return true;
98
+ }
99
+ const single = asmItem.operands[0];
100
+ const ccSingle = conditionNameFromOperand(single);
101
+ if (ccSingle && ctx.jrConditionOpcodeFromName(ccSingle) !== undefined) {
102
+ diagEncode(ctx, asmItem, `jr cc, disp expects two operands (cc, disp8)`);
103
+ return true;
104
+ }
105
+ if (single.kind === 'Imm') {
106
+ const symbolicTarget = ctx.symbolicTargetFromExpr(single.expr);
107
+ if (symbolicTarget &&
108
+ ctx.jrConditionOpcodeFromName(symbolicTarget.baseLower) !== undefined) {
109
+ diagEncode(ctx, asmItem, `jr cc, disp expects two operands (cc, disp8)`);
110
+ return true;
111
+ }
112
+ }
113
+ if (single.kind === 'Reg') {
114
+ diagEncode(ctx, asmItem, `jr does not support register targets; expects disp8`);
115
+ return true;
116
+ }
117
+ if (!emitRel8FromOperand(ctx, asmItem, single, 0x18, 'jr'))
118
+ return false;
119
+ ctx.flowRef.current.reachable = false;
120
+ ctx.syncToFlow();
121
+ return true;
122
+ }
123
+ if (asmItem.operands.length === 2) {
124
+ const ccOp = asmItem.operands[0];
125
+ const ccName = conditionNameFromOperand(ccOp);
126
+ const opcode = ccName ? ctx.jrConditionOpcodeFromName(ccName) : undefined;
127
+ if (opcode === undefined) {
128
+ diagEncode(ctx, asmItem, `jr cc expects valid condition code NZ/Z/NC/C`);
129
+ return true;
130
+ }
131
+ const target = asmItem.operands[1];
132
+ if (rejectInvalidRel8Target(ctx, asmItem, target, {
133
+ indirect: 'jr cc, disp does not support indirect targets',
134
+ register: 'jr cc, disp does not support register targets; expects disp8',
135
+ other: 'jr cc, disp expects disp8',
136
+ })) {
137
+ return true;
138
+ }
139
+ if (!emitRel8FromOperand(ctx, asmItem, target, opcode, `jr ${ccName.toLowerCase()}`))
140
+ return false;
141
+ ctx.syncToFlow();
142
+ return true;
143
+ }
144
+ }
145
+ if (head === 'djnz') {
146
+ if (asmItem.operands.length !== 1) {
147
+ diagEncode(ctx, asmItem, `djnz expects one operand (disp8)`);
148
+ return true;
149
+ }
150
+ const target = asmItem.operands[0];
151
+ if (rejectInvalidRel8Target(ctx, asmItem, target, {
152
+ indirect: 'djnz does not support indirect targets; expects disp8',
153
+ register: 'djnz does not support register targets; expects disp8',
154
+ other: 'djnz expects disp8',
155
+ })) {
156
+ return true;
157
+ }
158
+ if (!emitRel8FromOperand(ctx, asmItem, target, 0x10, 'djnz'))
159
+ return false;
160
+ ctx.syncToFlow();
161
+ return true;
162
+ }
163
+ if (head === 'rst' && asmItem.operands.length === 1) {
164
+ ctx.diagIfCallStackUnverifiable({ span: asmItem.span, mnemonic: 'rst' });
165
+ }
166
+ if (head === 'ret') {
167
+ if (asmItem.operands.length === 0) {
168
+ ctx.diagIfRetStackImbalanced(asmItem.span);
169
+ ctx.emitInstr('ret', [], asmItem.span);
170
+ ctx.flowRef.current.reachable = false;
171
+ ctx.syncToFlow();
172
+ return true;
173
+ }
174
+ if (asmItem.operands.length === 1) {
175
+ const op = ctx.conditionOpcode(asmItem.operands[0]);
176
+ if (op === undefined) {
177
+ diagEncode(ctx, asmItem, `ret cc expects a valid condition code`);
178
+ return true;
179
+ }
180
+ ctx.diagIfRetStackImbalanced(asmItem.span);
181
+ ctx.emitInstr('ret', [asmItem.operands[0]], asmItem.span);
182
+ ctx.syncToFlow();
183
+ return true;
184
+ }
185
+ }
186
+ if ((head === 'retn' || head === 'reti') && asmItem.operands.length === 0) {
187
+ ctx.diagIfRetStackImbalanced(asmItem.span, head);
188
+ ctx.emitInstr(head, [], asmItem.span);
189
+ ctx.flowRef.current.reachable = false;
190
+ ctx.syncToFlow();
191
+ return true;
192
+ }
193
+ if (head === 'jp' && asmItem.operands.length === 1) {
194
+ const target = asmItem.operands[0];
195
+ if (target.kind === 'Imm') {
196
+ const symbolicTarget = ctx.symbolicTargetFromExpr(target.expr);
197
+ if (symbolicTarget && ctx.conditionOpcodeFromName(symbolicTarget.baseLower) !== undefined) {
198
+ diagEncode(ctx, asmItem, `jp cc, nn expects two operands (cc, nn)`);
199
+ return true;
200
+ }
201
+ if (symbolicTarget) {
202
+ ctx.emitAbs16Fixup(0xc3, symbolicTarget.baseLower, symbolicTarget.addend, asmItem.span);
203
+ ctx.flowRef.current.reachable = false;
204
+ ctx.syncToFlow();
205
+ return true;
206
+ }
207
+ if (emitAbs16CurrentTargetFromOperand(ctx, asmItem, target, 0xc3)) {
208
+ ctx.flowRef.current.reachable = false;
209
+ return true;
210
+ }
211
+ }
212
+ }
213
+ if (head === 'jp' && asmItem.operands.length === 2) {
214
+ const ccOp = asmItem.operands[0];
215
+ const ccName = conditionNameFromOperand(ccOp);
216
+ const opcode = ccName ? ctx.conditionOpcodeFromName(ccName) : undefined;
217
+ const target = asmItem.operands[1];
218
+ if (opcode !== undefined &&
219
+ (emitAbs16CurrentTargetFromOperand(ctx, asmItem, target, opcode) ||
220
+ emitAbs16FixupFromOperand(ctx, asmItem, target, opcode))) {
221
+ return true;
222
+ }
223
+ }
224
+ if (head === 'call' && asmItem.operands.length === 1) {
225
+ const target = asmItem.operands[0];
226
+ if (target.kind === 'Imm') {
227
+ const symbolicTarget = ctx.symbolicTargetFromExpr(target.expr);
228
+ if (symbolicTarget &&
229
+ ctx.callConditionOpcodeFromName(symbolicTarget.baseLower) !== undefined) {
230
+ diagEncode(ctx, asmItem, `call cc, nn expects two operands (cc, nn)`);
231
+ return true;
232
+ }
233
+ if (symbolicTarget) {
234
+ ctx.emitAbs16Fixup(0xcd, symbolicTarget.baseLower, symbolicTarget.addend, asmItem.span);
235
+ ctx.syncToFlow();
236
+ return true;
237
+ }
238
+ if (emitAbs16CurrentTargetFromOperand(ctx, asmItem, target, 0xcd))
239
+ return true;
240
+ }
241
+ }
242
+ if (head === 'call' && asmItem.operands.length === 2) {
243
+ const ccOp = asmItem.operands[0];
244
+ const ccName = conditionNameFromOperand(ccOp);
245
+ const opcode = ccName ? ctx.callConditionOpcodeFromName(ccName) : undefined;
246
+ const target = asmItem.operands[1];
247
+ if (opcode !== undefined &&
248
+ (emitAbs16CurrentTargetFromOperand(ctx, asmItem, target, opcode) ||
249
+ emitAbs16FixupFromOperand(ctx, asmItem, target, opcode))) {
250
+ return true;
251
+ }
252
+ }
253
+ return undefined;
254
+ }
@@ -0,0 +1,23 @@
1
+ import type { AsmInstructionNode } from '../frontend/ast.js';
2
+ import type { BranchCallLoweringContext } from './asmLoweringBranchCall.js';
3
+ import type { LdHelperContext } from './asmInstructionLdHelpers.js';
4
+ import type { LdLoweringContext } from './asmLoweringLd.js';
5
+ /**
6
+ * Fields required by {@link createAsmInstructionLdHelpers} beyond what
7
+ * {@link BranchCallLoweringContext} already provides (`emitInstr`, `emitAbs16Fixup`).
8
+ */
9
+ type AsmLoweringLdHelperSlice = Omit<LdHelperContext, 'emitInstr' | 'emitAbs16Fixup'>;
10
+ type AsmLoweringLdSlice = Pick<LdLoweringContext, 'resolveEa' | 'symbolicTargetFromExpr'>;
11
+ /**
12
+ * Dispatcher path shared by the non-`ld` `lowerLdWithEa` fallback.
13
+ */
14
+ type AsmLoweringDispatcherSlice = {
15
+ lowerLdWithEa: (asmItem: AsmInstructionNode) => boolean;
16
+ };
17
+ /**
18
+ * Narrow surface for {@link createAsmInstructionLoweringHelpers}: branch/call, LD helpers,
19
+ * and raw-instruction fallback. Composed from helper-family contracts plus LD-helper
20
+ * and dispatcher-only fields.
21
+ */
22
+ export type AsmLoweringHost = BranchCallLoweringContext & AsmLoweringLdHelperSlice & AsmLoweringLdSlice & AsmLoweringDispatcherSlice;
23
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import type { Diagnostic } from '../diagnosticTypes.js';
2
+ import type { AsmInstructionNode, AsmOperandNode, EaExprNode, SourceSpan } from '../frontend/ast.js';
3
+ import type { EaResolution } from './eaResolution.js';
4
+ type DiagAt = (diagnostics: Diagnostic[], span: AsmInstructionNode['span'], message: string) => void;
5
+ export type LdLoweringContext = {
6
+ diagnostics: Diagnostic[];
7
+ diagAt: DiagAt;
8
+ emitAbs16Fixup: (opcode: number, baseLower: string, addend: number, span: AsmInstructionNode['span']) => void;
9
+ emitAbs16FixupPrefixed: (prefix: number, opcode2: number, baseLower: string, addend: number, span: AsmInstructionNode['span']) => void;
10
+ evalImmExpr: (expr: Extract<AsmOperandNode, {
11
+ kind: 'Imm';
12
+ }>['expr']) => number | undefined;
13
+ symbolicTargetFromExpr: (expr: Extract<AsmOperandNode, {
14
+ kind: 'Imm';
15
+ }>['expr']) => {
16
+ baseLower: string;
17
+ addend: number;
18
+ } | undefined;
19
+ resolveEa: (ea: EaExprNode, span: SourceSpan) => EaResolution | undefined;
20
+ lowerLdWithEa: (asmItem: AsmInstructionNode) => boolean;
21
+ emitAbs16LdFixup: (dst: AsmOperandNode, src: AsmOperandNode, span: AsmInstructionNode['span']) => boolean;
22
+ isUnresolvedLayoutLdOperand: (op: AsmOperandNode) => boolean;
23
+ resolveRawLabelName: (name: string) => string;
24
+ isRegisterLikeMemEa: (ea: EaExprNode) => boolean;
25
+ syncToFlow: () => void;
26
+ };
27
+ export declare function tryLowerLdInstruction(asmItem: AsmInstructionNode, ctx: LdLoweringContext): boolean | undefined;
28
+ export {};