@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.
- package/LICENSE +649 -0
- package/README.md +142 -0
- package/dist/src/analysis.d.ts +11 -0
- package/dist/src/analysis.js +41 -0
- package/dist/src/api-compile.d.ts +8 -0
- package/dist/src/api-compile.js +3 -0
- package/dist/src/api-tooling.d.ts +25 -0
- package/dist/src/api-tooling.js +21 -0
- package/dist/src/cli.d.ts +30 -0
- package/dist/src/cli.js +523 -0
- package/dist/src/compile.d.ts +10 -0
- package/dist/src/compile.js +175 -0
- package/dist/src/compileShared.d.ts +3 -0
- package/dist/src/compileShared.js +7 -0
- package/dist/src/diagnosticTypes.d.ts +77 -0
- package/dist/src/diagnosticTypes.js +53 -0
- package/dist/src/formats/index.d.ts +7 -0
- package/dist/src/formats/index.js +17 -0
- package/dist/src/formats/range.d.ts +17 -0
- package/dist/src/formats/range.js +45 -0
- package/dist/src/formats/types.d.ts +208 -0
- package/dist/src/formats/types.js +1 -0
- package/dist/src/formats/writeAsm80.d.ts +6 -0
- package/dist/src/formats/writeAsm80.js +86 -0
- package/dist/src/formats/writeBin.d.ts +7 -0
- package/dist/src/formats/writeBin.js +23 -0
- package/dist/src/formats/writeD8m.d.ts +9 -0
- package/dist/src/formats/writeD8m.js +239 -0
- package/dist/src/formats/writeHex.d.ts +9 -0
- package/dist/src/formats/writeHex.js +39 -0
- package/dist/src/formats/writeListing.d.ts +8 -0
- package/dist/src/formats/writeListing.js +83 -0
- package/dist/src/frontend/asm80/asmLine.d.ts +39 -0
- package/dist/src/frontend/asm80/asmLine.js +89 -0
- package/dist/src/frontend/asm80/parseAsmRawValues.d.ts +4 -0
- package/dist/src/frontend/asm80/parseAsmRawValues.js +94 -0
- package/dist/src/frontend/asm80/quoteScan.d.ts +10 -0
- package/dist/src/frontend/asm80/quoteScan.js +25 -0
- package/dist/src/frontend/ast.d.ts +376 -0
- package/dist/src/frontend/ast.js +1 -0
- package/dist/src/frontend/directiveAliases.d.ts +14 -0
- package/dist/src/frontend/directiveAliases.js +189 -0
- package/dist/src/frontend/grammarData.d.ts +14 -0
- package/dist/src/frontend/grammarData.js +65 -0
- package/dist/src/frontend/immExprUtils.d.ts +2 -0
- package/dist/src/frontend/immExprUtils.js +12 -0
- package/dist/src/frontend/parseAsmFlatDirectiveLine.d.ts +17 -0
- package/dist/src/frontend/parseAsmFlatDirectiveLine.js +187 -0
- package/dist/src/frontend/parseAsmInstruction.d.ts +3 -0
- package/dist/src/frontend/parseAsmInstruction.js +73 -0
- package/dist/src/frontend/parseAsmStatements.d.ts +6 -0
- package/dist/src/frontend/parseAsmStatements.js +16 -0
- package/dist/src/frontend/parseAsmStream.d.ts +10 -0
- package/dist/src/frontend/parseAsmStream.js +33 -0
- package/dist/src/frontend/parseAsmTopLevel.d.ts +18 -0
- package/dist/src/frontend/parseAsmTopLevel.js +34 -0
- package/dist/src/frontend/parseDiagnostics.d.ts +9 -0
- package/dist/src/frontend/parseDiagnostics.js +16 -0
- package/dist/src/frontend/parseEnum.d.ts +12 -0
- package/dist/src/frontend/parseEnum.js +70 -0
- package/dist/src/frontend/parseImm.d.ts +10 -0
- package/dist/src/frontend/parseImm.js +397 -0
- package/dist/src/frontend/parseLogicalLines.d.ts +11 -0
- package/dist/src/frontend/parseLogicalLines.js +94 -0
- package/dist/src/frontend/parseOp.d.ts +25 -0
- package/dist/src/frontend/parseOp.js +120 -0
- package/dist/src/frontend/parseOpHeader.d.ts +20 -0
- package/dist/src/frontend/parseOpHeader.js +32 -0
- package/dist/src/frontend/parseOperands.d.ts +4 -0
- package/dist/src/frontend/parseOperands.js +290 -0
- package/dist/src/frontend/parseParams.d.ts +6 -0
- package/dist/src/frontend/parseParams.js +62 -0
- package/dist/src/frontend/parseParserRecovery.d.ts +12 -0
- package/dist/src/frontend/parseParserRecovery.js +17 -0
- package/dist/src/frontend/parseParserShared.d.ts +2 -0
- package/dist/src/frontend/parseParserShared.js +8 -0
- package/dist/src/frontend/parseRawDataDirectiveStart.d.ts +1 -0
- package/dist/src/frontend/parseRawDataDirectiveStart.js +3 -0
- package/dist/src/frontend/parseRawDataDirectives.d.ts +7 -0
- package/dist/src/frontend/parseRawDataDirectives.js +142 -0
- package/dist/src/frontend/parseRecordFieldDecl.d.ts +34 -0
- package/dist/src/frontend/parseRecordFieldDecl.js +177 -0
- package/dist/src/frontend/parseSourceItemDispatch.d.ts +46 -0
- package/dist/src/frontend/parseSourceItemDispatch.js +53 -0
- package/dist/src/frontend/parseSourceItemTable.d.ts +16 -0
- package/dist/src/frontend/parseSourceItemTable.js +68 -0
- package/dist/src/frontend/parseTopLevelCommon.d.ts +11 -0
- package/dist/src/frontend/parseTopLevelCommon.js +50 -0
- package/dist/src/frontend/parseTypes.d.ts +24 -0
- package/dist/src/frontend/parseTypes.js +77 -0
- package/dist/src/frontend/parser.d.ts +11 -0
- package/dist/src/frontend/parser.js +88 -0
- package/dist/src/frontend/source.d.ts +28 -0
- package/dist/src/frontend/source.js +58 -0
- package/dist/src/frontend/sourceExtensions.d.ts +2 -0
- package/dist/src/frontend/sourceExtensions.js +6 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +2 -0
- package/dist/src/lintCaseStyle.d.ts +4 -0
- package/dist/src/lintCaseStyle.js +129 -0
- package/dist/src/lowering/asmDirectiveLowering.d.ts +4 -0
- package/dist/src/lowering/asmDirectiveLowering.js +229 -0
- package/dist/src/lowering/asmDirectiveTraversal.d.ts +47 -0
- package/dist/src/lowering/asmDirectiveTraversal.js +52 -0
- package/dist/src/lowering/asmEquResolution.d.ts +8 -0
- package/dist/src/lowering/asmEquResolution.js +69 -0
- package/dist/src/lowering/asmInstructionLdHelpers.d.ts +15 -0
- package/dist/src/lowering/asmInstructionLdHelpers.js +102 -0
- package/dist/src/lowering/asmInstructionLowering.d.ts +5 -0
- package/dist/src/lowering/asmInstructionLowering.js +54 -0
- package/dist/src/lowering/asmInstructionStream.d.ts +46 -0
- package/dist/src/lowering/asmInstructionStream.js +51 -0
- package/dist/src/lowering/asmLoweringBranchCall.d.ts +43 -0
- package/dist/src/lowering/asmLoweringBranchCall.js +254 -0
- package/dist/src/lowering/asmLoweringHost.d.ts +23 -0
- package/dist/src/lowering/asmLoweringHost.js +1 -0
- package/dist/src/lowering/asmLoweringLd.d.ts +28 -0
- package/dist/src/lowering/asmLoweringLd.js +144 -0
- package/dist/src/lowering/asmRangeLowering.d.ts +17 -0
- package/dist/src/lowering/asmRangeLowering.js +39 -0
- package/dist/src/lowering/asmRawDataLowering.d.ts +16 -0
- package/dist/src/lowering/asmRawDataLowering.js +209 -0
- package/dist/src/lowering/asmSourceEmitter.d.ts +4 -0
- package/dist/src/lowering/asmSourceEmitter.js +9 -0
- package/dist/src/lowering/asmSourceInstructionLowering.d.ts +4 -0
- package/dist/src/lowering/asmSourceInstructionLowering.js +14 -0
- package/dist/src/lowering/asmUtils.d.ts +13 -0
- package/dist/src/lowering/asmUtils.js +105 -0
- package/dist/src/lowering/assemblerFlowSetup.d.ts +54 -0
- package/dist/src/lowering/assemblerFlowSetup.js +128 -0
- package/dist/src/lowering/assemblerLoweringContext.d.ts +151 -0
- package/dist/src/lowering/assemblerLoweringContext.js +16 -0
- package/dist/src/lowering/assemblerLoweringContextSplit.d.ts +7 -0
- package/dist/src/lowering/assemblerLoweringContextSplit.js +75 -0
- package/dist/src/lowering/assemblerLoweringPhases.d.ts +66 -0
- package/dist/src/lowering/assemblerLoweringPhases.js +166 -0
- package/dist/src/lowering/bytePlacement.d.ts +7 -0
- package/dist/src/lowering/bytePlacement.js +37 -0
- package/dist/src/lowering/capabilities.d.ts +67 -0
- package/dist/src/lowering/capabilities.js +1 -0
- package/dist/src/lowering/eaResolution.d.ts +58 -0
- package/dist/src/lowering/eaResolution.js +159 -0
- package/dist/src/lowering/emissionCore.d.ts +17 -0
- package/dist/src/lowering/emissionCore.js +21 -0
- package/dist/src/lowering/emit.d.ts +17 -0
- package/dist/src/lowering/emit.js +46 -0
- package/dist/src/lowering/emitContextBuilder.d.ts +63 -0
- package/dist/src/lowering/emitContextBuilder.js +41 -0
- package/dist/src/lowering/emitFinalization.d.ts +61 -0
- package/dist/src/lowering/emitFinalization.js +66 -0
- package/dist/src/lowering/emitFinalizationSetup.d.ts +19 -0
- package/dist/src/lowering/emitFinalizationSetup.js +26 -0
- package/dist/src/lowering/emitPhase1BuildProgramLoweringContext.d.ts +7 -0
- package/dist/src/lowering/emitPhase1BuildProgramLoweringContext.js +119 -0
- package/dist/src/lowering/emitPhase1Helpers.d.ts +4 -0
- package/dist/src/lowering/emitPhase1Helpers.js +12 -0
- package/dist/src/lowering/emitPhase1Types.d.ts +21 -0
- package/dist/src/lowering/emitPhase1Types.js +1 -0
- package/dist/src/lowering/emitPhase1WirePipeline.d.ts +70 -0
- package/dist/src/lowering/emitPhase1WirePipeline.js +203 -0
- package/dist/src/lowering/emitPhase1Workspace.d.ts +82 -0
- package/dist/src/lowering/emitPhase1Workspace.js +55 -0
- package/dist/src/lowering/emitPipeline.d.ts +121 -0
- package/dist/src/lowering/emitPipeline.js +57 -0
- package/dist/src/lowering/emitProgramContext.d.ts +39 -0
- package/dist/src/lowering/emitProgramContext.js +29 -0
- package/dist/src/lowering/emitState.d.ts +90 -0
- package/dist/src/lowering/emitState.js +124 -0
- package/dist/src/lowering/fixupBaseResolution.d.ts +7 -0
- package/dist/src/lowering/fixupBaseResolution.js +23 -0
- package/dist/src/lowering/fixupEmission.d.ts +64 -0
- package/dist/src/lowering/fixupEmission.js +199 -0
- package/dist/src/lowering/immMath.d.ts +2 -0
- package/dist/src/lowering/immMath.js +34 -0
- package/dist/src/lowering/inputAssets.d.ts +7 -0
- package/dist/src/lowering/inputAssets.js +106 -0
- package/dist/src/lowering/ldEncoding.d.ts +15 -0
- package/dist/src/lowering/ldEncoding.js +12 -0
- package/dist/src/lowering/ldEncodingRegMemHelpers.d.ts +5 -0
- package/dist/src/lowering/ldEncodingRegMemHelpers.js +124 -0
- package/dist/src/lowering/ldFormSelection.d.ts +26 -0
- package/dist/src/lowering/ldFormSelection.js +92 -0
- package/dist/src/lowering/ldLowering.d.ts +7 -0
- package/dist/src/lowering/ldLowering.js +13 -0
- package/dist/src/lowering/loweredAsmByteEmission.d.ts +23 -0
- package/dist/src/lowering/loweredAsmByteEmission.js +185 -0
- package/dist/src/lowering/loweredAsmPlacement.d.ts +13 -0
- package/dist/src/lowering/loweredAsmPlacement.js +86 -0
- package/dist/src/lowering/loweredAsmStreamRecording.d.ts +27 -0
- package/dist/src/lowering/loweredAsmStreamRecording.js +215 -0
- package/dist/src/lowering/loweredAsmTypes.d.ts +202 -0
- package/dist/src/lowering/loweredAsmTypes.js +1 -0
- package/dist/src/lowering/loweredFormat.d.ts +3 -0
- package/dist/src/lowering/loweredFormat.js +26 -0
- package/dist/src/lowering/loweredItemSize.d.ts +4 -0
- package/dist/src/lowering/loweredItemSize.js +17 -0
- package/dist/src/lowering/loweringDiagnostics.d.ts +9 -0
- package/dist/src/lowering/loweringDiagnostics.js +55 -0
- package/dist/src/lowering/loweringTypes.d.ts +27 -0
- package/dist/src/lowering/loweringTypes.js +1 -0
- package/dist/src/lowering/opCandidateRegistry.d.ts +9 -0
- package/dist/src/lowering/opCandidateRegistry.js +9 -0
- package/dist/src/lowering/opExpansionExecution.d.ts +15 -0
- package/dist/src/lowering/opExpansionExecution.js +45 -0
- package/dist/src/lowering/opExpansionOrchestration.d.ts +15 -0
- package/dist/src/lowering/opExpansionOrchestration.js +88 -0
- package/dist/src/lowering/opExpansionStream.d.ts +12 -0
- package/dist/src/lowering/opExpansionStream.js +176 -0
- package/dist/src/lowering/opMatching.d.ts +52 -0
- package/dist/src/lowering/opMatching.js +355 -0
- package/dist/src/lowering/opSubstitution.d.ts +13 -0
- package/dist/src/lowering/opSubstitution.js +175 -0
- package/dist/src/lowering/prescanTypes.d.ts +7 -0
- package/dist/src/lowering/prescanTypes.js +1 -0
- package/dist/src/lowering/programLowering.d.ts +144 -0
- package/dist/src/lowering/programLowering.js +2 -0
- package/dist/src/lowering/programLoweringDeclarations.d.ts +5 -0
- package/dist/src/lowering/programLoweringDeclarations.js +5 -0
- package/dist/src/lowering/programLoweringFinalize.d.ts +18 -0
- package/dist/src/lowering/programLoweringFinalize.js +115 -0
- package/dist/src/lowering/programLoweringTraversal.d.ts +2 -0
- package/dist/src/lowering/programLoweringTraversal.js +93 -0
- package/dist/src/lowering/programPrescan.d.ts +3 -0
- package/dist/src/lowering/programPrescan.js +37 -0
- package/dist/src/lowering/traceFormat.d.ts +13 -0
- package/dist/src/lowering/traceFormat.js +211 -0
- package/dist/src/pathCompare.d.ts +3 -0
- package/dist/src/pathCompare.js +26 -0
- package/dist/src/pipeline.d.ts +78 -0
- package/dist/src/pipeline.js +1 -0
- package/dist/src/registerCare/analyze.d.ts +24 -0
- package/dist/src/registerCare/analyze.js +327 -0
- package/dist/src/registerCare/annotate.d.ts +11 -0
- package/dist/src/registerCare/annotate.js +76 -0
- package/dist/src/registerCare/boundaryHints.d.ts +2 -0
- package/dist/src/registerCare/boundaryHints.js +10 -0
- package/dist/src/registerCare/carriers.d.ts +4 -0
- package/dist/src/registerCare/carriers.js +78 -0
- package/dist/src/registerCare/controlFlow.d.ts +5 -0
- package/dist/src/registerCare/controlFlow.js +35 -0
- package/dist/src/registerCare/fix.d.ts +11 -0
- package/dist/src/registerCare/fix.js +119 -0
- package/dist/src/registerCare/liveness.d.ts +7 -0
- package/dist/src/registerCare/liveness.js +227 -0
- package/dist/src/registerCare/profiles.d.ts +11 -0
- package/dist/src/registerCare/profiles.js +45 -0
- package/dist/src/registerCare/programModel.d.ts +3 -0
- package/dist/src/registerCare/programModel.js +181 -0
- package/dist/src/registerCare/report.d.ts +5 -0
- package/dist/src/registerCare/report.js +139 -0
- package/dist/src/registerCare/smartComments.d.ts +5 -0
- package/dist/src/registerCare/smartComments.js +247 -0
- package/dist/src/registerCare/sourceText.d.ts +8 -0
- package/dist/src/registerCare/sourceText.js +15 -0
- package/dist/src/registerCare/summary.d.ts +3 -0
- package/dist/src/registerCare/summary.js +492 -0
- package/dist/src/registerCare/tooling.d.ts +42 -0
- package/dist/src/registerCare/tooling.js +50 -0
- package/dist/src/registerCare/types.d.ts +154 -0
- package/dist/src/registerCare/types.js +1 -0
- package/dist/src/semantics/declVisitor.d.ts +5 -0
- package/dist/src/semantics/declVisitor.js +11 -0
- package/dist/src/semantics/env.d.ts +28 -0
- package/dist/src/semantics/env.js +432 -0
- package/dist/src/semantics/layout.d.ts +21 -0
- package/dist/src/semantics/layout.js +226 -0
- package/dist/src/semantics/layoutCastFold.d.ts +22 -0
- package/dist/src/semantics/layoutCastFold.js +118 -0
- package/dist/src/semantics/semanticsDiagnostics.d.ts +2 -0
- package/dist/src/semantics/semanticsDiagnostics.js +4 -0
- package/dist/src/semantics/typeQueries.d.ts +31 -0
- package/dist/src/semantics/typeQueries.js +124 -0
- package/dist/src/sourceIncludeExpansion.d.ts +17 -0
- package/dist/src/sourceIncludeExpansion.js +124 -0
- package/dist/src/sourceIncludePaths.d.ts +1 -0
- package/dist/src/sourceIncludePaths.js +12 -0
- package/dist/src/sourceLoader.d.ts +15 -0
- package/dist/src/sourceLoader.js +118 -0
- package/dist/src/z80/effects.d.ts +3 -0
- package/dist/src/z80/effects.js +516 -0
- package/dist/src/z80/encode.d.ts +10 -0
- package/dist/src/z80/encode.js +412 -0
- package/dist/src/z80/encodeAlu.d.ts +7 -0
- package/dist/src/z80/encodeAlu.js +219 -0
- package/dist/src/z80/encodeBitOps.d.ts +7 -0
- package/dist/src/z80/encodeBitOps.js +123 -0
- package/dist/src/z80/encodeContext.d.ts +29 -0
- package/dist/src/z80/encodeContext.js +1 -0
- package/dist/src/z80/encodeControl.d.ts +26 -0
- package/dist/src/z80/encodeControl.js +180 -0
- package/dist/src/z80/encodeCoreOps.d.ts +7 -0
- package/dist/src/z80/encodeCoreOps.js +131 -0
- package/dist/src/z80/encodeIo.d.ts +9 -0
- package/dist/src/z80/encodeIo.js +128 -0
- package/dist/src/z80/encodeLd.d.ts +13 -0
- package/dist/src/z80/encodeLd.js +273 -0
- package/dist/src/z80/encoderRegistry.d.ts +13 -0
- package/dist/src/z80/encoderRegistry.js +169 -0
- package/docs/reference/cli.md +134 -0
- package/docs/reference/tooling-api.md +248 -0
- package/package.json +98 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { formatAbs16FixupAsm, formatAbs16FixupEdAsm, formatAbs16FixupPrefixedAsm, } from './traceFormat.js';
|
|
2
|
+
export function createFixupEmissionHelpers(ctx) {
|
|
3
|
+
const recordLoweredInstr = (bytes, asmText, span) => {
|
|
4
|
+
ctx.recordLoweredInstr?.(bytes, asmText, span);
|
|
5
|
+
};
|
|
6
|
+
const emitAbs16Bytes = (bytes, patchOffsetFromStart, baseLower, addend, span, asmText) => {
|
|
7
|
+
const start = ctx.getCodeOffset();
|
|
8
|
+
for (let index = 0; index < bytes.length; index++) {
|
|
9
|
+
ctx.setCodeByte(start + index, bytes[index]);
|
|
10
|
+
}
|
|
11
|
+
ctx.setCodeOffset(start + bytes.length);
|
|
12
|
+
ctx.recordCodeSourceRange(start, start + bytes.length);
|
|
13
|
+
ctx.pushFixup({ offset: start + patchOffsetFromStart, baseLower, addend, file: span.file });
|
|
14
|
+
ctx.traceInstruction(start, bytes, asmText);
|
|
15
|
+
recordLoweredInstr(bytes, asmText, span);
|
|
16
|
+
};
|
|
17
|
+
const emitAbs16Fixup = (opcode, baseLower, addend, span, asmText) => {
|
|
18
|
+
const bytes = Uint8Array.of(opcode, 0x00, 0x00);
|
|
19
|
+
const text = asmText ?? formatAbs16FixupAsm(opcode, baseLower, addend);
|
|
20
|
+
emitAbs16Bytes(bytes, 1, baseLower, addend, span, text);
|
|
21
|
+
};
|
|
22
|
+
const emitAbs16FixupEd = (opcode2, baseLower, addend, span, asmText) => {
|
|
23
|
+
const bytes = Uint8Array.of(0xed, opcode2, 0x00, 0x00);
|
|
24
|
+
const text = asmText ?? formatAbs16FixupEdAsm(opcode2, baseLower, addend);
|
|
25
|
+
emitAbs16Bytes(bytes, 2, baseLower, addend, span, text);
|
|
26
|
+
};
|
|
27
|
+
const emitAbs16FixupPrefixed = (prefix, opcode2, baseLower, addend, span, asmText) => {
|
|
28
|
+
const bytes = Uint8Array.of(prefix, opcode2, 0x00, 0x00);
|
|
29
|
+
const text = asmText ?? formatAbs16FixupPrefixedAsm(prefix, opcode2, baseLower, addend);
|
|
30
|
+
emitAbs16Bytes(bytes, 2, baseLower, addend, span, text);
|
|
31
|
+
};
|
|
32
|
+
const emitRel8Fixup = (opcode, baseLower, addend, span, mnemonic, asmText) => {
|
|
33
|
+
const start = ctx.getCodeOffset();
|
|
34
|
+
ctx.setCodeByte(start, opcode);
|
|
35
|
+
ctx.setCodeByte(start + 1, 0x00);
|
|
36
|
+
ctx.setCodeOffset(start + 2);
|
|
37
|
+
ctx.recordCodeSourceRange(start, start + 2);
|
|
38
|
+
ctx.pushRel8Fixup({
|
|
39
|
+
offset: start + 1,
|
|
40
|
+
origin: start + 2,
|
|
41
|
+
baseLower,
|
|
42
|
+
addend,
|
|
43
|
+
file: span.file,
|
|
44
|
+
mnemonic,
|
|
45
|
+
});
|
|
46
|
+
const bytes = Uint8Array.of(opcode, 0x00);
|
|
47
|
+
const text = asmText ?? `${mnemonic} ${baseLower}`;
|
|
48
|
+
ctx.traceInstruction(start, bytes, text);
|
|
49
|
+
recordLoweredInstr(bytes, text, span);
|
|
50
|
+
};
|
|
51
|
+
const conditionOpcodeFromName = (nameRaw) => {
|
|
52
|
+
const asName = nameRaw.toUpperCase();
|
|
53
|
+
switch (asName) {
|
|
54
|
+
case 'NZ':
|
|
55
|
+
return 0xc2;
|
|
56
|
+
case 'Z':
|
|
57
|
+
return 0xca;
|
|
58
|
+
case 'NC':
|
|
59
|
+
return 0xd2;
|
|
60
|
+
case 'C':
|
|
61
|
+
return 0xda;
|
|
62
|
+
case 'PO':
|
|
63
|
+
return 0xe2;
|
|
64
|
+
case 'PE':
|
|
65
|
+
return 0xea;
|
|
66
|
+
case 'P':
|
|
67
|
+
return 0xf2;
|
|
68
|
+
case 'M':
|
|
69
|
+
return 0xfa;
|
|
70
|
+
default:
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const conditionNameFromOpcode = (opcode) => {
|
|
75
|
+
switch (opcode) {
|
|
76
|
+
case 0xc2:
|
|
77
|
+
return 'NZ';
|
|
78
|
+
case 0xca:
|
|
79
|
+
return 'Z';
|
|
80
|
+
case 0xd2:
|
|
81
|
+
return 'NC';
|
|
82
|
+
case 0xda:
|
|
83
|
+
return 'C';
|
|
84
|
+
case 0xe2:
|
|
85
|
+
return 'PO';
|
|
86
|
+
case 0xea:
|
|
87
|
+
return 'PE';
|
|
88
|
+
case 0xf2:
|
|
89
|
+
return 'P';
|
|
90
|
+
case 0xfa:
|
|
91
|
+
return 'M';
|
|
92
|
+
default:
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const callConditionOpcodeFromName = (nameRaw) => {
|
|
97
|
+
switch (nameRaw.toUpperCase()) {
|
|
98
|
+
case 'NZ':
|
|
99
|
+
return 0xc4;
|
|
100
|
+
case 'Z':
|
|
101
|
+
return 0xcc;
|
|
102
|
+
case 'NC':
|
|
103
|
+
return 0xd4;
|
|
104
|
+
case 'C':
|
|
105
|
+
return 0xdc;
|
|
106
|
+
case 'PO':
|
|
107
|
+
return 0xe4;
|
|
108
|
+
case 'PE':
|
|
109
|
+
return 0xec;
|
|
110
|
+
case 'P':
|
|
111
|
+
return 0xf4;
|
|
112
|
+
case 'M':
|
|
113
|
+
return 0xfc;
|
|
114
|
+
default:
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const symbolicTargetFromExpr = (expr) => {
|
|
119
|
+
if (expr.kind === 'ImmName')
|
|
120
|
+
return { baseLower: expr.name.toLowerCase(), addend: 0 };
|
|
121
|
+
if (expr.kind !== 'ImmBinary')
|
|
122
|
+
return undefined;
|
|
123
|
+
if (expr.op !== '+' && expr.op !== '-')
|
|
124
|
+
return undefined;
|
|
125
|
+
const leftName = expr.left.kind === 'ImmName' ? expr.left.name.toLowerCase() : undefined;
|
|
126
|
+
const rightName = expr.right.kind === 'ImmName' ? expr.right.name.toLowerCase() : undefined;
|
|
127
|
+
if (leftName) {
|
|
128
|
+
const right = ctx.evalImmExpr(expr.right);
|
|
129
|
+
if (right === undefined)
|
|
130
|
+
return undefined;
|
|
131
|
+
return { baseLower: leftName, addend: expr.op === '+' ? right : -right };
|
|
132
|
+
}
|
|
133
|
+
if (expr.op === '+' && rightName) {
|
|
134
|
+
const left = ctx.evalImmExpr(expr.left);
|
|
135
|
+
if (left === undefined)
|
|
136
|
+
return undefined;
|
|
137
|
+
return { baseLower: rightName, addend: left };
|
|
138
|
+
}
|
|
139
|
+
return undefined;
|
|
140
|
+
};
|
|
141
|
+
const jrConditionOpcodeFromName = (nameRaw) => {
|
|
142
|
+
switch (nameRaw.toUpperCase()) {
|
|
143
|
+
case 'NZ':
|
|
144
|
+
return 0x20;
|
|
145
|
+
case 'Z':
|
|
146
|
+
return 0x28;
|
|
147
|
+
case 'NC':
|
|
148
|
+
return 0x30;
|
|
149
|
+
case 'C':
|
|
150
|
+
return 0x38;
|
|
151
|
+
default:
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const conditionOpcode = (op) => {
|
|
156
|
+
const asName = op.kind === 'Imm' && op.expr.kind === 'ImmName'
|
|
157
|
+
? op.expr.name
|
|
158
|
+
: op.kind === 'Reg'
|
|
159
|
+
? op.name
|
|
160
|
+
: undefined;
|
|
161
|
+
return asName ? conditionOpcodeFromName(asName) : undefined;
|
|
162
|
+
};
|
|
163
|
+
const inverseConditionName = (nameRaw) => {
|
|
164
|
+
const name = nameRaw.toUpperCase();
|
|
165
|
+
switch (name) {
|
|
166
|
+
case 'NZ':
|
|
167
|
+
return 'Z';
|
|
168
|
+
case 'Z':
|
|
169
|
+
return 'NZ';
|
|
170
|
+
case 'NC':
|
|
171
|
+
return 'C';
|
|
172
|
+
case 'C':
|
|
173
|
+
return 'NC';
|
|
174
|
+
case 'PO':
|
|
175
|
+
return 'PE';
|
|
176
|
+
case 'PE':
|
|
177
|
+
return 'PO';
|
|
178
|
+
case 'P':
|
|
179
|
+
return 'M';
|
|
180
|
+
case 'M':
|
|
181
|
+
return 'P';
|
|
182
|
+
default:
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
callConditionOpcodeFromName,
|
|
188
|
+
conditionNameFromOpcode,
|
|
189
|
+
conditionOpcode,
|
|
190
|
+
conditionOpcodeFromName,
|
|
191
|
+
emitAbs16Fixup,
|
|
192
|
+
emitAbs16FixupEd,
|
|
193
|
+
emitAbs16FixupPrefixed,
|
|
194
|
+
emitRel8Fixup,
|
|
195
|
+
inverseConditionName,
|
|
196
|
+
jrConditionOpcodeFromName,
|
|
197
|
+
symbolicTargetFromExpr,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function evalUnaryImmOp(op, value) {
|
|
2
|
+
switch (op) {
|
|
3
|
+
case '+':
|
|
4
|
+
return +value;
|
|
5
|
+
case '-':
|
|
6
|
+
return -value;
|
|
7
|
+
case '~':
|
|
8
|
+
return ~value;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function evalBinaryImmOp(op, left, right) {
|
|
12
|
+
switch (op) {
|
|
13
|
+
case '*':
|
|
14
|
+
return left * right;
|
|
15
|
+
case '/':
|
|
16
|
+
return right === 0 ? undefined : Math.trunc(left / right);
|
|
17
|
+
case '%':
|
|
18
|
+
return right === 0 ? undefined : left % right;
|
|
19
|
+
case '+':
|
|
20
|
+
return left + right;
|
|
21
|
+
case '-':
|
|
22
|
+
return left - right;
|
|
23
|
+
case '&':
|
|
24
|
+
return left & right;
|
|
25
|
+
case '^':
|
|
26
|
+
return left ^ right;
|
|
27
|
+
case '|':
|
|
28
|
+
return left | right;
|
|
29
|
+
case '<<':
|
|
30
|
+
return left << right;
|
|
31
|
+
case '>>':
|
|
32
|
+
return left >> right;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type InputDiag = (file: string, message: string) => void;
|
|
2
|
+
export declare function loadBinInput(fromFile: string, fromPath: string, includeDirs: readonly string[], report: InputDiag): Buffer | undefined;
|
|
3
|
+
export declare function parseIntelHex(ownerFile: string, hexText: string, report: InputDiag): {
|
|
4
|
+
bytes: Map<number, number>;
|
|
5
|
+
minAddress: number;
|
|
6
|
+
} | undefined;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
function resolveInputPath(fromFile, fromPath, includeDirs, report) {
|
|
4
|
+
const candidates = [];
|
|
5
|
+
candidates.push(resolve(dirname(fromFile), fromPath));
|
|
6
|
+
for (const inc of includeDirs)
|
|
7
|
+
candidates.push(resolve(inc, fromPath));
|
|
8
|
+
const seen = new Set();
|
|
9
|
+
for (const candidate of candidates) {
|
|
10
|
+
if (seen.has(candidate))
|
|
11
|
+
continue;
|
|
12
|
+
seen.add(candidate);
|
|
13
|
+
if (existsSync(candidate))
|
|
14
|
+
return candidate;
|
|
15
|
+
}
|
|
16
|
+
report(fromFile, `Failed to resolve input path "${fromPath}".`);
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
export function loadBinInput(fromFile, fromPath, includeDirs, report) {
|
|
20
|
+
const path = resolveInputPath(fromFile, fromPath, includeDirs, report);
|
|
21
|
+
if (!path)
|
|
22
|
+
return undefined;
|
|
23
|
+
try {
|
|
24
|
+
return readFileSync(path);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
report(fromFile, `Failed to read bin file "${path}": ${String(err)}`);
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function parseIntelHex(ownerFile, hexText, report) {
|
|
32
|
+
const out = new Map();
|
|
33
|
+
let minAddress = Number.POSITIVE_INFINITY;
|
|
34
|
+
const lines = hexText.split(/\r?\n/);
|
|
35
|
+
let sawData = false;
|
|
36
|
+
let sawEof = false;
|
|
37
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
38
|
+
const raw = lines[lineIndex].trim();
|
|
39
|
+
if (raw.length === 0)
|
|
40
|
+
continue;
|
|
41
|
+
if (!raw.startsWith(':')) {
|
|
42
|
+
report(ownerFile, `Invalid Intel HEX record at line ${lineIndex + 1}.`);
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const body = raw.slice(1);
|
|
46
|
+
if (body.length < 10 || body.length % 2 !== 0) {
|
|
47
|
+
report(ownerFile, `Malformed Intel HEX record at line ${lineIndex + 1}.`);
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const bytesLine = [];
|
|
51
|
+
for (let i = 0; i < body.length; i += 2) {
|
|
52
|
+
const pair = body.slice(i, i + 2);
|
|
53
|
+
const value = Number.parseInt(pair, 16);
|
|
54
|
+
if (Number.isNaN(value)) {
|
|
55
|
+
report(ownerFile, `Invalid HEX byte "${pair}" at line ${lineIndex + 1}.`);
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
bytesLine.push(value & 0xff);
|
|
59
|
+
}
|
|
60
|
+
const len = bytesLine[0];
|
|
61
|
+
const addr = ((bytesLine[1] << 8) | bytesLine[2]) & 0xffff;
|
|
62
|
+
const type = bytesLine[3];
|
|
63
|
+
const data = bytesLine.slice(4, bytesLine.length - 1);
|
|
64
|
+
if (len !== data.length) {
|
|
65
|
+
report(ownerFile, `Intel HEX length mismatch at line ${lineIndex + 1}.`);
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const sum = bytesLine.reduce((acc, byte) => (acc + byte) & 0xff, 0);
|
|
69
|
+
if (sum !== 0) {
|
|
70
|
+
report(ownerFile, `Intel HEX checksum mismatch at line ${lineIndex + 1}.`);
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
if (sawEof) {
|
|
74
|
+
report(ownerFile, `Intel HEX data found after EOF record.`);
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
if (type === 0x00) {
|
|
78
|
+
for (let i = 0; i < data.length; i++) {
|
|
79
|
+
const address = addr + i;
|
|
80
|
+
if (address < 0 || address > 0xffff) {
|
|
81
|
+
report(ownerFile, `Intel HEX address out of range at line ${lineIndex + 1}.`);
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
if (out.has(address)) {
|
|
85
|
+
report(ownerFile, `Intel HEX overlaps itself at address ${address}.`);
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
out.set(address, data[i]);
|
|
89
|
+
minAddress = Math.min(minAddress, address);
|
|
90
|
+
}
|
|
91
|
+
sawData = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (type === 0x01) {
|
|
95
|
+
sawEof = true;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
report(ownerFile, `Unsupported Intel HEX record type ${type.toString(16).padStart(2, '0')} at line ${lineIndex + 1}.`);
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
if (!sawData) {
|
|
102
|
+
report(ownerFile, `Intel HEX file has no data records.`);
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
return { bytes: out, minAddress };
|
|
106
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Diagnostic } from '../diagnosticTypes.js';
|
|
2
|
+
import type { SourceSpan } from '../frontend/ast.js';
|
|
3
|
+
import type { LdForm } from './ldFormSelection.js';
|
|
4
|
+
export type LdEncodingContext = {
|
|
5
|
+
diagAt: (diagnostics: Diagnostic[], span: SourceSpan, message: string) => void;
|
|
6
|
+
diagnostics: Diagnostic[];
|
|
7
|
+
emitAbs16Fixup: (opcode: number, target: string, addend: number, span: SourceSpan, asmText?: string) => void;
|
|
8
|
+
emitAbs16FixupEd: (opcode: number, target: string, addend: number, span: SourceSpan, asmText?: string) => void;
|
|
9
|
+
emitAbs16FixupPrefixed: (prefix: number, opcode: number, target: string, addend: number, span: SourceSpan, asmText?: string) => void;
|
|
10
|
+
reg8Code: ReadonlyMap<string, number>;
|
|
11
|
+
setSpTrackingInvalid: () => void;
|
|
12
|
+
};
|
|
13
|
+
export declare function createLdEncodingHelpers(ctx: LdEncodingContext): {
|
|
14
|
+
emitLdForm: (form: LdForm) => boolean;
|
|
15
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createLdEncodingRegMemHelpers } from './ldEncodingRegMemHelpers.js';
|
|
2
|
+
export function createLdEncodingHelpers(ctx) {
|
|
3
|
+
const { emitLdRegMemForm } = createLdEncodingRegMemHelpers(ctx);
|
|
4
|
+
const emitLdForm = (form) => {
|
|
5
|
+
const regMemHandled = emitLdRegMemForm(form);
|
|
6
|
+
if (regMemHandled !== null) {
|
|
7
|
+
return regMemHandled;
|
|
8
|
+
}
|
|
9
|
+
return false;
|
|
10
|
+
};
|
|
11
|
+
return { emitLdForm };
|
|
12
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
export function createLdEncodingRegMemHelpers(ctx) {
|
|
2
|
+
const { emitAbs16Fixup, emitAbs16FixupEd, emitAbs16FixupPrefixed, reg8Code, setSpTrackingInvalid, } = ctx;
|
|
3
|
+
const emitRegFromMem = (form) => {
|
|
4
|
+
const { dst, src, inst, srcResolved } = form;
|
|
5
|
+
if (dst.kind !== 'Reg' || src.kind !== 'Mem')
|
|
6
|
+
return false;
|
|
7
|
+
if (form.srcHasRegisterLikeEaBase)
|
|
8
|
+
return false;
|
|
9
|
+
if (form.srcIsIxIyDispMem && reg8Code.has(dst.name.toUpperCase()))
|
|
10
|
+
return false;
|
|
11
|
+
if (form.srcIsEaNameHL)
|
|
12
|
+
return false;
|
|
13
|
+
if (dst.name.toUpperCase() === 'A' && form.srcIsEaNameBCorDE)
|
|
14
|
+
return false;
|
|
15
|
+
if (dst.name.toUpperCase() === 'A' && srcResolved?.kind === 'abs') {
|
|
16
|
+
emitAbs16Fixup(0x3a, srcResolved.baseLower, srcResolved.addend, inst.span);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
const regUp = dst.name.toUpperCase();
|
|
20
|
+
if (reg8Code.has(regUp)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const r16 = dst.name.toUpperCase();
|
|
24
|
+
if (r16 === 'HL') {
|
|
25
|
+
if (srcResolved?.kind === 'abs') {
|
|
26
|
+
emitAbs16Fixup(0x2a, srcResolved.baseLower, srcResolved.addend, inst.span);
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
if (r16 === 'DE') {
|
|
32
|
+
if (srcResolved?.kind === 'abs') {
|
|
33
|
+
emitAbs16FixupEd(0x5b, srcResolved.baseLower, srcResolved.addend, inst.span);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if (r16 === 'BC') {
|
|
39
|
+
if (srcResolved?.kind === 'abs') {
|
|
40
|
+
emitAbs16FixupEd(0x4b, srcResolved.baseLower, srcResolved.addend, inst.span);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
if (r16 === 'SP' && srcResolved?.kind === 'abs') {
|
|
46
|
+
emitAbs16FixupEd(0x7b, srcResolved.baseLower, srcResolved.addend, inst.span);
|
|
47
|
+
setSpTrackingInvalid();
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
if (r16 === 'IX' || r16 === 'IY') {
|
|
51
|
+
if (srcResolved?.kind === 'abs') {
|
|
52
|
+
emitAbs16FixupPrefixed(r16 === 'IX' ? 0xdd : 0xfd, 0x2a, srcResolved.baseLower, srcResolved.addend, inst.span);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
};
|
|
59
|
+
const emitMemFromReg = (form) => {
|
|
60
|
+
const { dst, src, inst, dstResolved } = form;
|
|
61
|
+
if (dst.kind !== 'Mem' || src.kind !== 'Reg')
|
|
62
|
+
return false;
|
|
63
|
+
if (form.dstHasRegisterLikeEaBase)
|
|
64
|
+
return false;
|
|
65
|
+
if (form.dstIsIxIyDispMem && reg8Code.has(src.name.toUpperCase()))
|
|
66
|
+
return false;
|
|
67
|
+
if (form.dstIsEaNameHL)
|
|
68
|
+
return false;
|
|
69
|
+
if (src.name.toUpperCase() === 'A' && form.dstIsEaNameBCorDE)
|
|
70
|
+
return false;
|
|
71
|
+
if (src.name.toUpperCase() === 'A' && dstResolved?.kind === 'abs') {
|
|
72
|
+
emitAbs16Fixup(0x32, dstResolved.baseLower, dstResolved.addend, inst.span);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
const regUp = src.name.toUpperCase();
|
|
76
|
+
if (reg8Code.has(regUp)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
const r16 = src.name.toUpperCase();
|
|
80
|
+
if (r16 === 'HL') {
|
|
81
|
+
if (dstResolved?.kind === 'abs') {
|
|
82
|
+
emitAbs16Fixup(0x22, dstResolved.baseLower, dstResolved.addend, inst.span);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
if (r16 === 'DE') {
|
|
88
|
+
if (dstResolved?.kind === 'abs') {
|
|
89
|
+
emitAbs16FixupEd(0x53, dstResolved.baseLower, dstResolved.addend, inst.span);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
if (r16 === 'BC') {
|
|
95
|
+
if (dstResolved?.kind === 'abs') {
|
|
96
|
+
emitAbs16FixupEd(0x43, dstResolved.baseLower, dstResolved.addend, inst.span);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (r16 === 'SP' && dstResolved?.kind === 'abs') {
|
|
102
|
+
emitAbs16FixupEd(0x73, dstResolved.baseLower, dstResolved.addend, inst.span);
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
if (r16 === 'IX' || r16 === 'IY') {
|
|
106
|
+
if (dstResolved?.kind === 'abs') {
|
|
107
|
+
emitAbs16FixupPrefixed(r16 === 'IX' ? 0xdd : 0xfd, 0x22, dstResolved.baseLower, dstResolved.addend, inst.span);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
};
|
|
114
|
+
const emitLdRegMemForm = (form) => {
|
|
115
|
+
if (form.dst.kind === 'Reg' && form.src.kind === 'Mem') {
|
|
116
|
+
return emitRegFromMem(form);
|
|
117
|
+
}
|
|
118
|
+
if (form.dst.kind === 'Mem' && form.src.kind === 'Reg') {
|
|
119
|
+
return emitMemFromReg(form);
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
};
|
|
123
|
+
return { emitLdRegMemForm };
|
|
124
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AsmInstructionNode, AsmOperandNode, EaExprNode } from '../frontend/ast.js';
|
|
2
|
+
import type { SourceSpan } from '../frontend/ast.js';
|
|
3
|
+
import type { CompileEnv } from '../semantics/env.js';
|
|
4
|
+
import type { EaResolution } from './eaResolution.js';
|
|
5
|
+
export type LdForm = {
|
|
6
|
+
inst: AsmInstructionNode;
|
|
7
|
+
dst: AsmOperandNode;
|
|
8
|
+
src: AsmOperandNode;
|
|
9
|
+
dstResolved: EaResolution | undefined;
|
|
10
|
+
srcResolved: EaResolution | undefined;
|
|
11
|
+
srcHasRegisterLikeEaBase: boolean;
|
|
12
|
+
dstHasRegisterLikeEaBase: boolean;
|
|
13
|
+
srcIsIxIyDispMem: boolean;
|
|
14
|
+
dstIsIxIyDispMem: boolean;
|
|
15
|
+
srcIsEaNameHL: boolean;
|
|
16
|
+
dstIsEaNameHL: boolean;
|
|
17
|
+
srcIsEaNameBCorDE: boolean;
|
|
18
|
+
dstIsEaNameBCorDE: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type LdFormSelectionContext = {
|
|
21
|
+
env: CompileEnv;
|
|
22
|
+
resolveEa: (ea: EaExprNode, span: SourceSpan) => EaResolution | undefined;
|
|
23
|
+
};
|
|
24
|
+
export declare function createLdFormSelectionHelpers(ctx: LdFormSelectionContext): {
|
|
25
|
+
analyzeLdInstruction: (inst: AsmInstructionNode) => LdForm | null;
|
|
26
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export function createLdFormSelectionHelpers(ctx) {
|
|
2
|
+
const { env, resolveEa } = ctx;
|
|
3
|
+
const coerceValueOperand = (op) => {
|
|
4
|
+
if (op.kind === 'Reg') {
|
|
5
|
+
const lower = op.name.toLowerCase();
|
|
6
|
+
if (env.equates.has(lower)) {
|
|
7
|
+
return {
|
|
8
|
+
kind: 'Mem',
|
|
9
|
+
span: op.span,
|
|
10
|
+
expr: { kind: 'EaName', span: op.span, name: op.name },
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return op;
|
|
15
|
+
};
|
|
16
|
+
const isRegisterToken = (name) => {
|
|
17
|
+
const token = name.toUpperCase();
|
|
18
|
+
return (token === 'A' ||
|
|
19
|
+
token === 'B' ||
|
|
20
|
+
token === 'C' ||
|
|
21
|
+
token === 'D' ||
|
|
22
|
+
token === 'E' ||
|
|
23
|
+
token === 'H' ||
|
|
24
|
+
token === 'L' ||
|
|
25
|
+
token === 'AF' ||
|
|
26
|
+
token === 'BC' ||
|
|
27
|
+
token === 'DE' ||
|
|
28
|
+
token === 'HL' ||
|
|
29
|
+
token === 'SP' ||
|
|
30
|
+
token === 'IX' ||
|
|
31
|
+
token === 'IY' ||
|
|
32
|
+
token === 'IXH' ||
|
|
33
|
+
token === 'IXL' ||
|
|
34
|
+
token === 'IYH' ||
|
|
35
|
+
token === 'IYL');
|
|
36
|
+
};
|
|
37
|
+
const isBoundEaName = (name) => {
|
|
38
|
+
const lower = name.toLowerCase();
|
|
39
|
+
return env.equates.has(lower);
|
|
40
|
+
};
|
|
41
|
+
const hasRegisterLikeEaBase = (ea) => {
|
|
42
|
+
switch (ea.kind) {
|
|
43
|
+
case 'EaName':
|
|
44
|
+
return isRegisterToken(ea.name) && !isBoundEaName(ea.name);
|
|
45
|
+
case 'EaImm':
|
|
46
|
+
return false;
|
|
47
|
+
case 'EaLayoutCast':
|
|
48
|
+
return false;
|
|
49
|
+
case 'EaField':
|
|
50
|
+
return hasRegisterLikeEaBase(ea.base);
|
|
51
|
+
case 'EaIndex':
|
|
52
|
+
return hasRegisterLikeEaBase(ea.base);
|
|
53
|
+
case 'EaAdd':
|
|
54
|
+
case 'EaSub':
|
|
55
|
+
return hasRegisterLikeEaBase(ea.base);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const isEaNameHL = (ea) => ea.kind === 'EaName' && ea.name.toUpperCase() === 'HL';
|
|
59
|
+
const isEaNameBCorDE = (ea) => ea.kind === 'EaName' && (ea.name.toUpperCase() === 'BC' || ea.name.toUpperCase() === 'DE');
|
|
60
|
+
const isIxIyBaseEa = (ea) => ea.kind === 'EaName' && (ea.name.toUpperCase() === 'IX' || ea.name.toUpperCase() === 'IY');
|
|
61
|
+
const isIxIyDispMem = (op) => op.kind === 'Mem' &&
|
|
62
|
+
(isIxIyBaseEa(op.expr) ||
|
|
63
|
+
(op.expr.kind === 'EaIndex' &&
|
|
64
|
+
isIxIyBaseEa(op.expr.base) &&
|
|
65
|
+
op.expr.index.kind === 'IndexImm') ||
|
|
66
|
+
((op.expr.kind === 'EaAdd' || op.expr.kind === 'EaSub') && isIxIyBaseEa(op.expr.base)));
|
|
67
|
+
const analyzeLdInstruction = (inst) => {
|
|
68
|
+
const head = inst.head.toLowerCase();
|
|
69
|
+
if (head !== 'ld' || inst.operands.length !== 2)
|
|
70
|
+
return null;
|
|
71
|
+
const dst = coerceValueOperand(inst.operands[0]);
|
|
72
|
+
const src = coerceValueOperand(inst.operands[1]);
|
|
73
|
+
const dstResolved = dst.kind === 'Mem' ? resolveEa(dst.expr, inst.span) : undefined;
|
|
74
|
+
const srcResolved = src.kind === 'Mem' ? resolveEa(src.expr, inst.span) : undefined;
|
|
75
|
+
return {
|
|
76
|
+
inst,
|
|
77
|
+
dst,
|
|
78
|
+
src,
|
|
79
|
+
dstResolved,
|
|
80
|
+
srcResolved,
|
|
81
|
+
srcHasRegisterLikeEaBase: src.kind === 'Mem' ? hasRegisterLikeEaBase(src.expr) : false,
|
|
82
|
+
dstHasRegisterLikeEaBase: dst.kind === 'Mem' ? hasRegisterLikeEaBase(dst.expr) : false,
|
|
83
|
+
srcIsIxIyDispMem: isIxIyDispMem(src),
|
|
84
|
+
dstIsIxIyDispMem: isIxIyDispMem(dst),
|
|
85
|
+
srcIsEaNameHL: src.kind === 'Mem' ? isEaNameHL(src.expr) : false,
|
|
86
|
+
dstIsEaNameHL: dst.kind === 'Mem' ? isEaNameHL(dst.expr) : false,
|
|
87
|
+
srcIsEaNameBCorDE: src.kind === 'Mem' ? isEaNameBCorDE(src.expr) : false,
|
|
88
|
+
dstIsEaNameBCorDE: dst.kind === 'Mem' ? isEaNameBCorDE(dst.expr) : false,
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
return { analyzeLdInstruction };
|
|
92
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LdEncodingContext } from './ldEncoding.js';
|
|
2
|
+
import type { LdFormSelectionContext } from './ldFormSelection.js';
|
|
3
|
+
type LdLoweringContext = LdFormSelectionContext & LdEncodingContext;
|
|
4
|
+
export declare function createLdLoweringHelpers(ctx: LdLoweringContext): {
|
|
5
|
+
lowerLdWithEa: (inst: Parameters<(inst: import("../frontend/ast.js").AsmInstructionNode) => import("./ldFormSelection.js").LdForm | null>[0]) => boolean;
|
|
6
|
+
};
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createLdEncodingHelpers } from './ldEncoding.js';
|
|
2
|
+
import { createLdFormSelectionHelpers } from './ldFormSelection.js';
|
|
3
|
+
export function createLdLoweringHelpers(ctx) {
|
|
4
|
+
const { analyzeLdInstruction } = createLdFormSelectionHelpers(ctx);
|
|
5
|
+
const { emitLdForm } = createLdEncodingHelpers(ctx);
|
|
6
|
+
const lowerLdWithEa = (inst) => {
|
|
7
|
+
const form = analyzeLdInstruction(inst);
|
|
8
|
+
if (!form)
|
|
9
|
+
return false;
|
|
10
|
+
return emitLdForm(form);
|
|
11
|
+
};
|
|
12
|
+
return { lowerLdWithEa };
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Diagnostic } from '../diagnosticTypes.js';
|
|
2
|
+
import type { CompileEnv } from '../semantics/env.js';
|
|
3
|
+
import type { LoweredAsmProgram } from './loweredAsmTypes.js';
|
|
4
|
+
type LoweredAsmByteEmissionContext = {
|
|
5
|
+
diagnostics: Diagnostic[];
|
|
6
|
+
diag: (diagnostics: Diagnostic[], file: string, message: string) => void;
|
|
7
|
+
primaryFile: string;
|
|
8
|
+
env: CompileEnv;
|
|
9
|
+
};
|
|
10
|
+
type LoweredAsmByteEmissionResult = {
|
|
11
|
+
codeBytes: Map<number, number>;
|
|
12
|
+
dataBytes: Map<number, number>;
|
|
13
|
+
blockSizesByKey: Map<string, number>;
|
|
14
|
+
maxAddress: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* After link-time fixups are applied to `finalBytes`, patch lowered `instr` byte arrays
|
|
18
|
+
* (including `@raw` placeholders from abs16/rel8 fixups) so ASM80 listings match the
|
|
19
|
+
* merged image.
|
|
20
|
+
*/
|
|
21
|
+
export declare function syncLoweredAsmInstructionBytesFromFinalBytes(program: LoweredAsmProgram, finalBytes: Map<number, number>, env: CompileEnv): void;
|
|
22
|
+
export declare function emitLoweredAsmProgramBytes(program: LoweredAsmProgram, ctx: LoweredAsmByteEmissionContext): LoweredAsmByteEmissionResult;
|
|
23
|
+
export {};
|