@jhlagado/azm 0.2.6 → 0.2.8
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/README.md +170 -69
- package/dist/src/api-artifacts.d.ts +20 -0
- package/dist/src/api-artifacts.js +165 -0
- package/dist/src/api-compile.d.ts +8 -2
- package/dist/src/api-compile.js +31 -230
- package/dist/src/api-register-contracts.d.ts +9 -0
- package/dist/src/api-register-contracts.js +77 -0
- package/dist/src/api-tooling.d.ts +2 -2
- package/dist/src/api-tooling.js +1 -1
- package/dist/src/assembly/address-planning.d.ts +1 -2
- package/dist/src/assembly/address-planning.js +119 -218
- package/dist/src/assembly/address-symbols.d.ts +12 -0
- package/dist/src/assembly/address-symbols.js +118 -0
- package/dist/src/assembly/fixup-emission.js +30 -48
- package/dist/src/assembly/program-emission.js +163 -164
- package/dist/src/cli/artifact-files.d.ts +15 -0
- package/dist/src/cli/artifact-files.js +86 -0
- package/dist/src/cli/parse-args.d.ts +6 -5
- package/dist/src/cli/parse-args.js +162 -136
- package/dist/src/cli/run.js +4 -1
- package/dist/src/cli/usage.d.ts +1 -0
- package/dist/src/cli/usage.js +33 -0
- package/dist/src/cli/write-artifacts.js +18 -91
- package/dist/src/core/compile.js +51 -274
- package/dist/src/core/conditional-assembly.d.ts +6 -0
- package/dist/src/core/conditional-assembly.js +181 -0
- package/dist/src/expansion/op-constant-expression.d.ts +3 -0
- package/dist/src/expansion/op-constant-expression.js +52 -0
- package/dist/src/expansion/op-expand-selected.d.ts +5 -0
- package/dist/src/expansion/op-expand-selected.js +143 -0
- package/dist/src/expansion/op-expansion.d.ts +5 -53
- package/dist/src/expansion/op-expansion.js +85 -815
- package/dist/src/expansion/op-instruction-instantiation.d.ts +3 -0
- package/dist/src/expansion/op-instruction-instantiation.js +194 -0
- package/dist/src/expansion/op-local-labels.d.ts +8 -0
- package/dist/src/expansion/op-local-labels.js +166 -0
- package/dist/src/expansion/op-operand-splitting.d.ts +1 -0
- package/dist/src/expansion/op-operand-splitting.js +44 -0
- package/dist/src/expansion/op-operands.d.ts +53 -0
- package/dist/src/expansion/op-operands.js +66 -0
- package/dist/src/expansion/op-selection.d.ts +18 -0
- package/dist/src/expansion/op-selection.js +172 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/model/diagnostic.d.ts +4 -0
- package/dist/src/model/diagnostic.js +4 -0
- package/dist/src/outputs/asm80-expression-evaluation.d.ts +10 -0
- package/dist/src/outputs/asm80-expression-evaluation.js +75 -0
- package/dist/src/outputs/asm80-expressions.d.ts +5 -0
- package/dist/src/outputs/asm80-expressions.js +47 -0
- package/dist/src/outputs/asm80-instruction-operands.d.ts +16 -0
- package/dist/src/outputs/asm80-instruction-operands.js +38 -0
- package/dist/src/outputs/asm80-instructions.d.ts +5 -0
- package/dist/src/outputs/asm80-instructions.js +272 -0
- package/dist/src/outputs/asm80-ld-operands.d.ts +10 -0
- package/dist/src/outputs/asm80-ld-operands.js +157 -0
- package/dist/src/outputs/asm80-strings.d.ts +4 -0
- package/dist/src/outputs/asm80-strings.js +14 -0
- package/dist/src/outputs/d8-files.d.ts +10 -0
- package/dist/src/outputs/d8-files.js +103 -0
- package/dist/src/outputs/d8-helpers.d.ts +21 -0
- package/dist/src/outputs/d8-helpers.js +136 -0
- package/dist/src/outputs/hex.js +26 -18
- package/dist/src/outputs/types.d.ts +16 -10
- package/dist/src/outputs/write-asm80.js +68 -597
- package/dist/src/outputs/write-d8.js +6 -216
- package/dist/src/register-contracts/accept-output.d.ts +2 -0
- package/dist/src/register-contracts/analyze-helpers.d.ts +29 -0
- package/dist/src/register-contracts/analyze-helpers.js +162 -0
- package/dist/src/{register-care → register-contracts}/analyze.d.ts +6 -6
- package/dist/src/register-contracts/analyze.js +73 -0
- package/dist/src/register-contracts/annotate.d.ts +11 -0
- package/dist/src/{register-care → register-contracts}/annotate.js +3 -3
- package/dist/src/register-contracts/annotations.d.ts +8 -0
- package/dist/src/{register-care → register-contracts}/annotations.js +3 -3
- package/dist/src/register-contracts/boundaryHints.d.ts +3 -0
- package/dist/src/register-contracts/boundaryHints.js +24 -0
- package/dist/src/register-contracts/carriers.d.ts +2 -0
- package/dist/src/register-contracts/constants.d.ts +4 -0
- package/dist/src/register-contracts/constants.js +51 -0
- package/dist/src/register-contracts/controlFlow.d.ts +5 -0
- package/dist/src/register-contracts/controlFlow.js +55 -0
- package/dist/src/register-contracts/fix.d.ts +11 -0
- package/dist/src/{register-care → register-contracts}/fix.js +47 -30
- package/dist/src/register-contracts/instruction-head.d.ts +2 -0
- package/dist/src/register-contracts/instruction-head.js +3 -0
- package/dist/src/register-contracts/instruction-operands.d.ts +3 -0
- package/dist/src/register-contracts/instruction-operands.js +101 -0
- package/dist/src/register-contracts/instruction-predicates.d.ts +6 -0
- package/dist/src/register-contracts/instruction-predicates.js +44 -0
- package/dist/src/register-contracts/interfaceContracts.d.ts +2 -0
- package/dist/src/register-contracts/interfaceContracts.js +68 -0
- package/dist/src/register-contracts/liveness.d.ts +3 -0
- package/dist/src/{register-care → register-contracts}/liveness.js +111 -79
- package/dist/src/register-contracts/operand-register-name.d.ts +2 -0
- package/dist/src/register-contracts/operand-register-name.js +13 -0
- package/dist/src/{register-care → register-contracts}/profiles.d.ts +5 -5
- package/dist/src/{register-care → register-contracts}/profiles.js +13 -2
- package/dist/src/register-contracts/programModel-boundaries.d.ts +6 -0
- package/dist/src/register-contracts/programModel-boundaries.js +64 -0
- package/dist/src/register-contracts/programModel-routines.d.ts +7 -0
- package/dist/src/register-contracts/programModel-routines.js +128 -0
- package/dist/src/register-contracts/programModel.d.ts +3 -0
- package/dist/src/register-contracts/programModel.js +14 -0
- package/dist/src/register-contracts/report.d.ts +5 -0
- package/dist/src/{register-care → register-contracts}/report.js +34 -17
- package/dist/src/register-contracts/routine-summaries.d.ts +6 -0
- package/dist/src/{register-care → register-contracts}/routine-summaries.js +11 -1
- package/dist/src/register-contracts/smartCommentBlocks.d.ts +5 -0
- package/dist/src/register-contracts/smartCommentBlocks.js +30 -0
- package/dist/src/register-contracts/smartCommentParsing.d.ts +3 -0
- package/dist/src/register-contracts/smartCommentParsing.js +80 -0
- package/dist/src/register-contracts/smartComments.d.ts +5 -0
- package/dist/src/register-contracts/smartComments.js +92 -0
- package/dist/src/register-contracts/summaries.d.ts +12 -0
- package/dist/src/{register-care → register-contracts}/summaries.js +7 -7
- package/dist/src/register-contracts/summary-boundary.d.ts +2 -0
- package/dist/src/register-contracts/summary-boundary.js +40 -0
- package/dist/src/register-contracts/summary-contract.d.ts +2 -0
- package/dist/src/register-contracts/summary-contract.js +45 -0
- package/dist/src/register-contracts/summary-result.d.ts +7 -0
- package/dist/src/register-contracts/summary-result.js +122 -0
- package/dist/src/register-contracts/summary-state.d.ts +23 -0
- package/dist/src/register-contracts/summary-state.js +88 -0
- package/dist/src/register-contracts/summary-token-transfer.d.ts +3 -0
- package/dist/src/register-contracts/summary-token-transfer.js +67 -0
- package/dist/src/register-contracts/summary.d.ts +3 -0
- package/dist/src/register-contracts/summary.js +266 -0
- package/dist/src/register-contracts/tooling.d.ts +57 -0
- package/dist/src/{register-care → register-contracts}/tooling.js +8 -6
- package/dist/src/register-contracts/types.d.ts +188 -0
- package/dist/src/semantics/binary-operators.d.ts +2 -0
- package/dist/src/semantics/binary-operators.js +15 -0
- package/dist/src/semantics/byte-functions.d.ts +2 -0
- package/dist/src/semantics/byte-functions.js +7 -0
- package/dist/src/semantics/constant-operator-types.d.ts +10 -0
- package/dist/src/semantics/constant-operator-types.js +1 -0
- package/dist/src/semantics/constant-operators.d.ts +3 -0
- package/dist/src/semantics/constant-operators.js +3 -0
- package/dist/src/semantics/diagnostics.d.ts +3 -0
- package/dist/src/semantics/diagnostics.js +10 -0
- package/dist/src/semantics/expression-evaluation.d.ts +11 -19
- package/dist/src/semantics/expression-evaluation.js +22 -334
- package/dist/src/semantics/layout-evaluation.d.ts +23 -0
- package/dist/src/semantics/layout-evaluation.js +202 -0
- package/dist/src/semantics/layout-format.d.ts +5 -0
- package/dist/src/semantics/layout-format.js +31 -0
- package/dist/src/semantics/layout-path.d.ts +24 -0
- package/dist/src/semantics/layout-path.js +58 -0
- package/dist/src/semantics/unary-operators.d.ts +2 -0
- package/dist/src/semantics/unary-operators.js +8 -0
- package/dist/src/source/line-comment-scanner.d.ts +1 -0
- package/dist/src/source/line-comment-scanner.js +51 -0
- package/dist/src/source/strip-line-comment.js +8 -44
- package/dist/src/syntax/directive-aliases.js +36 -22
- package/dist/src/syntax/expression-tokenizer.d.ts +30 -0
- package/dist/src/syntax/expression-tokenizer.js +310 -0
- package/dist/src/syntax/parse-directive-statement.d.ts +14 -0
- package/dist/src/syntax/parse-directive-statement.js +307 -0
- package/dist/src/syntax/parse-expression.d.ts +2 -2
- package/dist/src/syntax/parse-expression.js +7 -568
- package/dist/src/syntax/parse-layout-declarations.d.ts +9 -0
- package/dist/src/syntax/parse-layout-declarations.js +180 -0
- package/dist/src/syntax/parse-layout-expression.d.ts +5 -0
- package/dist/src/syntax/parse-layout-expression.js +175 -0
- package/dist/src/syntax/parse-line.js +4 -272
- package/dist/src/syntax/parse-token-expression.d.ts +3 -0
- package/dist/src/syntax/parse-token-expression.js +133 -0
- package/dist/src/tooling/case-style.js +47 -30
- package/dist/src/z80/effect-groups.d.ts +38 -0
- package/dist/src/z80/effect-groups.js +265 -0
- package/dist/src/z80/effect-units.d.ts +18 -0
- package/dist/src/z80/effect-units.js +165 -0
- package/dist/src/z80/effects.d.ts +1 -1
- package/dist/src/z80/effects.js +94 -557
- package/dist/src/z80/encode-core.d.ts +2 -0
- package/dist/src/z80/encode-core.js +42 -0
- package/dist/src/z80/encode-ld-helpers.d.ts +25 -0
- package/dist/src/z80/encode-ld-helpers.js +172 -0
- package/dist/src/z80/encode-ld.d.ts +2 -0
- package/dist/src/z80/encode-ld.js +285 -0
- package/dist/src/z80/encode.js +190 -542
- package/dist/src/z80/ld-support.d.ts +3 -0
- package/dist/src/z80/ld-support.js +146 -0
- package/dist/src/z80/operand-split-state.d.ts +8 -0
- package/dist/src/z80/operand-split-state.js +46 -0
- package/dist/src/z80/operand-split.d.ts +1 -0
- package/dist/src/z80/operand-split.js +13 -0
- package/dist/src/z80/parse-basic.d.ts +4 -0
- package/dist/src/z80/parse-basic.js +39 -0
- package/dist/src/z80/parse-branch.d.ts +4 -0
- package/dist/src/z80/parse-branch.js +218 -0
- package/dist/src/z80/parse-conditions.d.ts +6 -0
- package/dist/src/z80/parse-conditions.js +10 -0
- package/dist/src/z80/parse-exchange.d.ts +2 -0
- package/dist/src/z80/parse-exchange.js +30 -0
- package/dist/src/z80/parse-instruction.js +224 -1010
- package/dist/src/z80/parse-io-control.d.ts +5 -0
- package/dist/src/z80/parse-io-control.js +108 -0
- package/dist/src/z80/parse-ld.d.ts +2 -0
- package/dist/src/z80/parse-ld.js +83 -0
- package/dist/src/z80/parse-operands.d.ts +41 -0
- package/dist/src/z80/parse-operands.js +259 -0
- package/docs/reference/cli.md +42 -35
- package/docs/reference/tooling-api.md +20 -16
- package/package.json +1 -1
- package/dist/src/register-care/accept-output.d.ts +0 -2
- package/dist/src/register-care/analyze.js +0 -166
- package/dist/src/register-care/annotate.d.ts +0 -11
- package/dist/src/register-care/annotations.d.ts +0 -8
- package/dist/src/register-care/boundaryHints.d.ts +0 -3
- package/dist/src/register-care/boundaryHints.js +0 -80
- package/dist/src/register-care/carriers.d.ts +0 -2
- package/dist/src/register-care/controlFlow.d.ts +0 -5
- package/dist/src/register-care/controlFlow.js +0 -38
- package/dist/src/register-care/fix.d.ts +0 -11
- package/dist/src/register-care/instruction-shape.d.ts +0 -11
- package/dist/src/register-care/instruction-shape.js +0 -129
- package/dist/src/register-care/liveness.d.ts +0 -3
- package/dist/src/register-care/programModel.d.ts +0 -3
- package/dist/src/register-care/programModel.js +0 -266
- package/dist/src/register-care/report.d.ts +0 -5
- package/dist/src/register-care/routine-summaries.d.ts +0 -6
- package/dist/src/register-care/smartComments.d.ts +0 -5
- package/dist/src/register-care/smartComments.js +0 -243
- package/dist/src/register-care/summaries.d.ts +0 -12
- package/dist/src/register-care/summary.d.ts +0 -3
- package/dist/src/register-care/summary.js +0 -474
- package/dist/src/register-care/tooling.d.ts +0 -43
- package/dist/src/register-care/types.d.ts +0 -172
- /package/dist/src/{register-care → register-contracts}/accept-output.js +0 -0
- /package/dist/src/{register-care → register-contracts}/carriers.js +0 -0
- /package/dist/src/{register-care → register-contracts}/sourceText.d.ts +0 -0
- /package/dist/src/{register-care → register-contracts}/sourceText.js +0 -0
- /package/dist/src/{register-care → register-contracts}/types.js +0 -0
|
@@ -24,10 +24,14 @@ Debug80 should link through the public package entry points, not internal
|
|
|
24
24
|
`dist/src/...` paths.
|
|
25
25
|
|
|
26
26
|
Use this path when Debug80 needs editor-style diagnostics, symbols, or
|
|
27
|
-
register
|
|
27
|
+
register contracts information without writing files:
|
|
28
28
|
|
|
29
29
|
```ts
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
analyzeProgram,
|
|
32
|
+
analyzeRegisterContractsForTools,
|
|
33
|
+
loadProgram,
|
|
34
|
+
} from '@jhlagado/azm/tooling';
|
|
31
35
|
|
|
32
36
|
const loaded = await loadProgram({
|
|
33
37
|
entryFile: '/abs/path/to/main.asm',
|
|
@@ -43,9 +47,9 @@ const analysis = analyzeProgram(loaded.loadedProgram, {
|
|
|
43
47
|
requireMain: false,
|
|
44
48
|
});
|
|
45
49
|
|
|
46
|
-
const
|
|
50
|
+
const registerContracts = analyzeRegisterContractsForTools(loaded.loadedProgram, {
|
|
47
51
|
mode: 'audit',
|
|
48
|
-
|
|
52
|
+
registerContractsProfile: 'mon3',
|
|
49
53
|
});
|
|
50
54
|
```
|
|
51
55
|
|
|
@@ -67,8 +71,8 @@ const result = await compile(
|
|
|
67
71
|
emitBin: true,
|
|
68
72
|
emitHex: true,
|
|
69
73
|
emitD8m: true,
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
registerContracts: 'audit',
|
|
75
|
+
registerContractsInterfaces: ['/abs/path/to/mon3.asmi'],
|
|
72
76
|
},
|
|
73
77
|
{ formats: defaultFormatWriters },
|
|
74
78
|
);
|
|
@@ -81,7 +85,7 @@ const binary = result.artifacts.find((artifact) => artifact.kind === 'bin');
|
|
|
81
85
|
The integration contract is:
|
|
82
86
|
|
|
83
87
|
- source entries are `.asm` or `.z80`
|
|
84
|
-
- external register
|
|
88
|
+
- external register contracts are `.asmi`
|
|
85
89
|
- include search paths are supplied explicitly with `includeDirs`
|
|
86
90
|
- directive alias JSON files are supplied explicitly with `directiveAliasFiles`
|
|
87
91
|
- `compile()` returns artifacts in memory; the CLI is only responsible for
|
|
@@ -203,24 +207,24 @@ console.log(analysis.diagnostics);
|
|
|
203
207
|
|
|
204
208
|
`analysis.env` is returned only when semantic analysis completes without errors.
|
|
205
209
|
|
|
206
|
-
## Register
|
|
210
|
+
## Register Contracts Tooling
|
|
207
211
|
|
|
208
|
-
Use `
|
|
212
|
+
Use `analyzeRegisterContractsForTools()` after `loadProgram()` when an editor, lint runner, or future LSP server needs register contracts diagnostics without parsing report text. The function returns the same inferred output candidates used by the CLI report, plus ready-to-apply quick-fix metadata for confirming intent at the call site.
|
|
209
213
|
|
|
210
214
|
```ts
|
|
211
|
-
import {
|
|
215
|
+
import { analyzeRegisterContractsForTools, loadProgram } from '@jhlagado/azm/tooling';
|
|
212
216
|
|
|
213
217
|
const loaded = await loadProgram({ entryFile: '/abs/path/to/main.z80' });
|
|
214
218
|
if (!loaded.loadedProgram) {
|
|
215
219
|
throw new Error('Parse/load failed');
|
|
216
220
|
}
|
|
217
221
|
|
|
218
|
-
const
|
|
222
|
+
const registerContracts = analyzeRegisterContractsForTools(loaded.loadedProgram, {
|
|
219
223
|
mode: 'audit',
|
|
220
|
-
|
|
224
|
+
registerContractsProfile: 'mon3',
|
|
221
225
|
});
|
|
222
226
|
|
|
223
|
-
for (const diagnostic of
|
|
227
|
+
for (const diagnostic of registerContracts.candidateDiagnostics) {
|
|
224
228
|
console.log(diagnostic.file, diagnostic.line, diagnostic.message);
|
|
225
229
|
console.log(diagnostic.autoFixable); // true when CLI --fix can safely add the hint
|
|
226
230
|
if (diagnostic.autoFixable && diagnostic.codeAction) {
|
|
@@ -229,7 +233,7 @@ for (const diagnostic of registerCare.candidateDiagnostics) {
|
|
|
229
233
|
}
|
|
230
234
|
```
|
|
231
235
|
|
|
232
|
-
Candidate diagnostics use `kind: "register-
|
|
236
|
+
Candidate diagnostics use `kind: "register-contracts-output-candidate"` and `severity: "info"`.
|
|
233
237
|
The `autoFixable` flag distinguishes direct continuation reads that `--fix` may
|
|
234
238
|
confirm automatically from cases that need programmer review. Code actions are
|
|
235
239
|
intentionally simple text insertions: insert the supplied newline-terminated
|
|
@@ -258,7 +262,7 @@ returns bin/hex/d8 artifacts alongside the asm80 error. Run
|
|
|
258
262
|
`npm run check:asm80-coverage` on your sources before relying on lowered output.
|
|
259
263
|
|
|
260
264
|
The compiler accepts flat `.asm` / `.z80` source, retained AZM assembler
|
|
261
|
-
features, and the same output writers used by the CLI. External register
|
|
265
|
+
features, and the same output writers used by the CLI. External register contracts
|
|
262
266
|
interfaces are `.asmi` metadata files, not compile entry files.
|
|
263
267
|
|
|
264
268
|
Retained AZM features include the ASM80 baseline, compact AZMDoc `;!` comments,
|
|
@@ -277,7 +281,7 @@ The public tooling surface includes:
|
|
|
277
281
|
- `Diagnostic`, `DiagnosticIds`, severity/id types
|
|
278
282
|
- `LoadedProgram`
|
|
279
283
|
- `AnalyzeProgramResult`, `LoadProgramResult`
|
|
280
|
-
- `
|
|
284
|
+
- `RegisterContractsCandidateDiagnostic`, `RegisterContractsCodeAction`, `RegisterContractsOutputCandidate`
|
|
281
285
|
|
|
282
286
|
The public tooling contract is the package export surface, not deep internal
|
|
283
287
|
paths. Do not document retired internal modules as public API.
|
package/package.json
CHANGED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { buildRegisterCareProgramModel } from './programModel.js';
|
|
2
|
-
import { buildRoutineContracts, parseSmartComments } from './smartComments.js';
|
|
3
|
-
import { renderRegisterCareInterface, renderRegisterCareReport } from './report.js';
|
|
4
|
-
import { autoFixableCandidateKeys, findExpectOutFixesForCandidates } from './fix.js';
|
|
5
|
-
import { findCallerOutputCandidateObservations, findRegisterCareConflicts, } from './liveness.js';
|
|
6
|
-
import { buildAnnotations } from './annotations.js';
|
|
7
|
-
import { buildOutputCandidateFixability, buildProfileSummaries, buildProfileSummaryLookup, buildSummaries, buildSummaryByName, outputCandidateKey, routineNames, unknownBoundaryDiagnostics, unknownCallList, withAcceptedOutputs, } from './summaries.js';
|
|
8
|
-
function candidateMessageWithFixability(candidate, autoFixable) {
|
|
9
|
-
const carriers = candidate.carriers.join(',');
|
|
10
|
-
const expectation = candidate.carriers.length === 1 ? candidate.carriers[0] : `{${carriers}}`;
|
|
11
|
-
const base = `CALL ${candidate.routine} writes ${carriers} and caller reads it later`;
|
|
12
|
-
return autoFixable
|
|
13
|
-
? `${base}; generated contracts promote this to \`out ${expectation}\` automatically.`
|
|
14
|
-
: `${base}; manual review required before adding \`; expects out ${expectation}\` because the later read is not a simple direct continuation.`;
|
|
15
|
-
}
|
|
16
|
-
export function analyzeRegisterCare(loaded, options) {
|
|
17
|
-
const file = loaded.program.files[0];
|
|
18
|
-
const items = file?.items ?? [];
|
|
19
|
-
const program = buildRegisterCareProgramModel(items);
|
|
20
|
-
const smartComments = parseSmartComments(loaded.sourceLineComments);
|
|
21
|
-
const contractMap = buildRoutineContracts(smartComments, program.routines, loaded.sourceTexts);
|
|
22
|
-
if (options.interfaceContracts !== undefined) {
|
|
23
|
-
for (const contract of options.interfaceContracts) {
|
|
24
|
-
contractMap.set(contract.name, contract);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const profileSummaries = buildProfileSummaries(options.registerCareProfile);
|
|
28
|
-
let summaries = buildSummaries(program.routines, contractMap, profileSummaries);
|
|
29
|
-
summaries = withAcceptedOutputs(summaries, options.acceptedOutputCandidates);
|
|
30
|
-
let summariesByName = buildSummaryByName(program.routines, summaries, profileSummaries);
|
|
31
|
-
const knownRoutines = new Set(routineNames(program.routines));
|
|
32
|
-
for (const [name] of contractMap) {
|
|
33
|
-
knownRoutines.add(name);
|
|
34
|
-
}
|
|
35
|
-
for (const name of buildProfileSummaryLookup(options.registerCareProfile).keys()) {
|
|
36
|
-
knownRoutines.add(name);
|
|
37
|
-
}
|
|
38
|
-
const diagnostics = [];
|
|
39
|
-
const shouldBuildOutputCandidates = options.mode !== 'off' ||
|
|
40
|
-
options.emitAnnotations === true ||
|
|
41
|
-
options.fixRegisterContracts === true;
|
|
42
|
-
const outputCandidates = shouldBuildOutputCandidates
|
|
43
|
-
? findCallerOutputCandidateObservations(program.routines, summariesByName)
|
|
44
|
-
: [];
|
|
45
|
-
const autoAcceptedOutputs = autoAcceptedOutputCandidateMap(program.routines, outputCandidates, loaded.sourceTexts);
|
|
46
|
-
if (autoAcceptedOutputs.size > 0) {
|
|
47
|
-
summaries = withAcceptedOutputs(summaries, autoAcceptedOutputs);
|
|
48
|
-
summariesByName = buildSummaryByName(program.routines, summaries, profileSummaries);
|
|
49
|
-
}
|
|
50
|
-
const allSummaries = [...summaries, ...profileSummaries];
|
|
51
|
-
const conflicts = shouldBuildOutputCandidates
|
|
52
|
-
? program.routines.flatMap((routine) => findRegisterCareConflicts(routine, summariesByName, smartComments))
|
|
53
|
-
: [];
|
|
54
|
-
const outputCandidateFixability = buildOutputCandidateFixability(program.routines, outputCandidates, autoFixableCandidateKeys);
|
|
55
|
-
const outputCandidatesWithFixability = outputCandidates.map((candidate) => {
|
|
56
|
-
const autoFixable = outputCandidateFixability.get(outputCandidateKey(candidate.file, candidate.line, candidate.column)) ?? false;
|
|
57
|
-
return {
|
|
58
|
-
...candidate,
|
|
59
|
-
autoFixable,
|
|
60
|
-
message: candidateMessageWithFixability(candidate, autoFixable),
|
|
61
|
-
};
|
|
62
|
-
});
|
|
63
|
-
if (options.mode !== 'audit') {
|
|
64
|
-
for (const conflict of conflicts) {
|
|
65
|
-
diagnostics.push({
|
|
66
|
-
severity: options.mode === 'error' ? 'error' : 'warning',
|
|
67
|
-
code: 'AZMN_REGISTER_CARE',
|
|
68
|
-
sourceName: conflict.file,
|
|
69
|
-
line: conflict.line,
|
|
70
|
-
column: conflict.column,
|
|
71
|
-
message: conflict.message,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
if (options.mode === 'strict') {
|
|
76
|
-
diagnostics.push(...unknownBoundaryDiagnostics(program.directBoundaries, knownRoutines));
|
|
77
|
-
}
|
|
78
|
-
const reportModel = {
|
|
79
|
-
entryFile: loaded.program.entryFile,
|
|
80
|
-
mode: options.mode,
|
|
81
|
-
summaries: allSummaries,
|
|
82
|
-
conflicts,
|
|
83
|
-
outputCandidates: outputCandidatesWithFixability,
|
|
84
|
-
...(options.registerCareProfile !== undefined ? { profile: options.registerCareProfile } : {}),
|
|
85
|
-
unknownCalls: options.mode === 'off' ? [] : unknownCallList(program.directBoundaries, knownRoutines),
|
|
86
|
-
};
|
|
87
|
-
const summariesForAnnotations = new Map(summariesByName);
|
|
88
|
-
const outputCandidatesByRoutine = new Map();
|
|
89
|
-
for (const candidate of outputCandidatesWithFixability) {
|
|
90
|
-
const existing = outputCandidatesByRoutine.get(candidate.routine) ?? [];
|
|
91
|
-
for (const unit of candidate.carriers) {
|
|
92
|
-
if (!existing.includes(unit))
|
|
93
|
-
existing.push(unit);
|
|
94
|
-
}
|
|
95
|
-
outputCandidatesByRoutine.set(candidate.routine, existing);
|
|
96
|
-
}
|
|
97
|
-
for (const [name, summary] of summariesForAnnotations) {
|
|
98
|
-
const candidates = outputCandidatesByRoutine.get(name);
|
|
99
|
-
if (candidates !== undefined && candidates.length > 0) {
|
|
100
|
-
summariesForAnnotations.set(name, { ...summary, outputCandidates: candidates });
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
const annotations = options.emitAnnotations
|
|
104
|
-
? buildAnnotations(loaded, program.routines, summariesForAnnotations, outputCandidatesWithFixability, {
|
|
105
|
-
fixOutputCandidates: options.fixRegisterContracts === true,
|
|
106
|
-
outputCandidateFixability,
|
|
107
|
-
outputCandidateKey,
|
|
108
|
-
})
|
|
109
|
-
: [];
|
|
110
|
-
return {
|
|
111
|
-
diagnostics,
|
|
112
|
-
outputCandidates: outputCandidatesWithFixability,
|
|
113
|
-
...(options.emitReport ? { reportText: renderRegisterCareReport(reportModel) } : {}),
|
|
114
|
-
...(options.emitInterface ? { interfaceText: renderRegisterCareInterface(summaries) } : {}),
|
|
115
|
-
...(annotations.length > 0 ? { annotations } : {}),
|
|
116
|
-
...(reportModel.unknownCalls.length > 0 ? { unknownCalls: reportModel.unknownCalls } : {}),
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
function autoAcceptedOutputCandidateMap(routines, outputCandidates, sourceTexts) {
|
|
120
|
-
const out = new Map();
|
|
121
|
-
const sourceMaybeOut = sourceMaybeOutByRoutine(routines, sourceTexts);
|
|
122
|
-
for (const fix of findExpectOutFixesForCandidates([...routines], [...outputCandidates])) {
|
|
123
|
-
const declaredMaybeOut = sourceMaybeOut.get(fix.routine) ?? [];
|
|
124
|
-
const eligibleCarriers = fix.carriers.filter((carrier) => declaredMaybeOut.includes(carrier));
|
|
125
|
-
if (eligibleCarriers.length === 0)
|
|
126
|
-
continue;
|
|
127
|
-
const carriers = out.get(fix.routine) ?? [];
|
|
128
|
-
for (const carrier of eligibleCarriers) {
|
|
129
|
-
if (!carriers.includes(carrier))
|
|
130
|
-
carriers.push(carrier);
|
|
131
|
-
}
|
|
132
|
-
out.set(fix.routine, carriers);
|
|
133
|
-
}
|
|
134
|
-
return out;
|
|
135
|
-
}
|
|
136
|
-
function sourceMaybeOutByRoutine(routines, sourceTexts) {
|
|
137
|
-
const out = new Map();
|
|
138
|
-
for (const routine of routines) {
|
|
139
|
-
const source = sourceTexts.get(routine.span.file);
|
|
140
|
-
if (source === undefined)
|
|
141
|
-
continue;
|
|
142
|
-
const lines = source.split(/\r?\n/);
|
|
143
|
-
const units = [];
|
|
144
|
-
for (let index = routine.span.start.line - 2; index >= 0; index -= 1) {
|
|
145
|
-
const text = lines[index] ?? '';
|
|
146
|
-
if (!/^\s*;/.test(text))
|
|
147
|
-
break;
|
|
148
|
-
const match = /^\s*;\s*!\s*maybe-out\s+(.+)$/i.exec(text);
|
|
149
|
-
if (!match)
|
|
150
|
-
continue;
|
|
151
|
-
for (const token of match[1].split(',')) {
|
|
152
|
-
const unit = token.trim();
|
|
153
|
-
if (unit.length > 0 && !units.includes(unit))
|
|
154
|
-
units.push(unit);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
if (units.length === 0)
|
|
158
|
-
continue;
|
|
159
|
-
out.set(routine.name, units);
|
|
160
|
-
for (const label of routine.labels)
|
|
161
|
-
out.set(label, units);
|
|
162
|
-
for (const label of routine.entryLabels)
|
|
163
|
-
out.set(label, units);
|
|
164
|
-
}
|
|
165
|
-
return out;
|
|
166
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { RegisterCareRoutine, RoutineSummary } from './types.js';
|
|
2
|
-
export interface RegisterCareAnnotatedFile {
|
|
3
|
-
path: string;
|
|
4
|
-
text: string;
|
|
5
|
-
}
|
|
6
|
-
interface RegisterCareAnnotationInput {
|
|
7
|
-
routine: RegisterCareRoutine;
|
|
8
|
-
summary: RoutineSummary;
|
|
9
|
-
}
|
|
10
|
-
export declare function annotateRegisterCareContracts(sourceTexts: ReadonlyMap<string, string>, routines: RegisterCareAnnotationInput[]): RegisterCareAnnotatedFile[];
|
|
11
|
-
export {};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { RegisterCareAnnotationFile, RegisterCareOutputCandidate, RegisterCareRoutine, RoutineSummary } from './types.js';
|
|
2
|
-
export declare function buildAnnotations(loaded: {
|
|
3
|
-
sourceTexts: ReadonlyMap<string, string>;
|
|
4
|
-
}, programRoutines: readonly RegisterCareRoutine[], summariesByName: ReadonlyMap<string, RoutineSummary>, outputCandidates: readonly RegisterCareOutputCandidate[], options: {
|
|
5
|
-
fixOutputCandidates: boolean;
|
|
6
|
-
outputCandidateFixability: ReadonlyMap<string, boolean>;
|
|
7
|
-
outputCandidateKey: (file: string, line: number, column: number) => string;
|
|
8
|
-
}): readonly RegisterCareAnnotationFile[];
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { RegisterCareInstruction } from './types.js';
|
|
2
|
-
export declare function precedingCServiceName(item: RegisterCareInstruction | undefined): string | undefined;
|
|
3
|
-
export declare function precedingRegisterImmediateValue(item: RegisterCareInstruction | undefined, register: string): number | undefined;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
export function precedingCServiceName(item) {
|
|
2
|
-
const instruction = item?.instruction;
|
|
3
|
-
if (!instruction || instruction.mnemonic !== 'ld')
|
|
4
|
-
return undefined;
|
|
5
|
-
if (instruction.target?.kind !== 'reg8' || instruction.target.register !== 'c')
|
|
6
|
-
return undefined;
|
|
7
|
-
if (instruction.source.kind === 'imm' && instruction.source.expression.kind === 'symbol') {
|
|
8
|
-
return instruction.source.expression.name;
|
|
9
|
-
}
|
|
10
|
-
return undefined;
|
|
11
|
-
}
|
|
12
|
-
function evaluateKnownConstant(expression, constants) {
|
|
13
|
-
switch (expression.kind) {
|
|
14
|
-
case 'number':
|
|
15
|
-
return expression.value;
|
|
16
|
-
case 'symbol':
|
|
17
|
-
return constants.get(expression.name);
|
|
18
|
-
case 'unary': {
|
|
19
|
-
const value = evaluateKnownConstant(expression.expression, constants);
|
|
20
|
-
if (value === undefined)
|
|
21
|
-
return undefined;
|
|
22
|
-
switch (expression.operator) {
|
|
23
|
-
case '+':
|
|
24
|
-
return value;
|
|
25
|
-
case '-':
|
|
26
|
-
return -value;
|
|
27
|
-
case '~':
|
|
28
|
-
return ~value;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
case 'binary': {
|
|
32
|
-
const left = evaluateKnownConstant(expression.left, constants);
|
|
33
|
-
const right = evaluateKnownConstant(expression.right, constants);
|
|
34
|
-
if (left === undefined || right === undefined)
|
|
35
|
-
return undefined;
|
|
36
|
-
switch (expression.operator) {
|
|
37
|
-
case '+':
|
|
38
|
-
return left + right;
|
|
39
|
-
case '-':
|
|
40
|
-
return left - right;
|
|
41
|
-
case '*':
|
|
42
|
-
return left * right;
|
|
43
|
-
case '/':
|
|
44
|
-
return right === 0 ? undefined : Math.trunc(left / right);
|
|
45
|
-
case '%':
|
|
46
|
-
return right === 0 ? undefined : left % right;
|
|
47
|
-
case '&':
|
|
48
|
-
return left & right;
|
|
49
|
-
case '^':
|
|
50
|
-
return left ^ right;
|
|
51
|
-
case '|':
|
|
52
|
-
return left | right;
|
|
53
|
-
case '<<':
|
|
54
|
-
return left << right;
|
|
55
|
-
case '>>':
|
|
56
|
-
return left >> right;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
case 'byte-function': {
|
|
60
|
-
const value = evaluateKnownConstant(expression.expression, constants);
|
|
61
|
-
if (value === undefined)
|
|
62
|
-
return undefined;
|
|
63
|
-
return expression.function === 'LSB' ? value & 0xff : (value >> 8) & 0xff;
|
|
64
|
-
}
|
|
65
|
-
default:
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
export function precedingRegisterImmediateValue(item, register) {
|
|
70
|
-
const instruction = item?.instruction;
|
|
71
|
-
if (!instruction || instruction.mnemonic !== 'ld')
|
|
72
|
-
return undefined;
|
|
73
|
-
if (instruction.target?.kind !== 'reg8' ||
|
|
74
|
-
instruction.target.register !== register.toLowerCase()) {
|
|
75
|
-
return undefined;
|
|
76
|
-
}
|
|
77
|
-
if (instruction.source.kind !== 'imm')
|
|
78
|
-
return undefined;
|
|
79
|
-
return evaluateKnownConstant(instruction.source.expression, item.constants ?? new Map());
|
|
80
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { InstructionEffect, RegisterCareRoutine } from './types.js';
|
|
2
|
-
export declare function labelIndex(routine: RegisterCareRoutine): Map<string, number>;
|
|
3
|
-
export declare function instructionSuccessors(routine: RegisterCareRoutine, index: number, effect: InstructionEffect, labels: ReadonlyMap<string, number>, options?: {
|
|
4
|
-
boundaryFallthrough?: boolean;
|
|
5
|
-
}): number[];
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
function unique(items) {
|
|
2
|
-
return [...new Set(items)];
|
|
3
|
-
}
|
|
4
|
-
export function labelIndex(routine) {
|
|
5
|
-
const out = new Map();
|
|
6
|
-
routine.instructions.forEach((item, index) => {
|
|
7
|
-
for (const label of item.labels)
|
|
8
|
-
out.set(label, index);
|
|
9
|
-
});
|
|
10
|
-
return out;
|
|
11
|
-
}
|
|
12
|
-
function localTargetIndex(labels, target) {
|
|
13
|
-
if (!target)
|
|
14
|
-
return undefined;
|
|
15
|
-
return labels.get(target);
|
|
16
|
-
}
|
|
17
|
-
export function instructionSuccessors(routine, index, effect, labels, options = {}) {
|
|
18
|
-
const next = index + 1 < routine.instructions.length ? index + 1 : undefined;
|
|
19
|
-
if (effect.control.kind === 'fallthrough' ||
|
|
20
|
-
(options.boundaryFallthrough &&
|
|
21
|
-
(effect.control.kind === 'call' || effect.control.kind === 'rst'))) {
|
|
22
|
-
return next === undefined ? [] : [next];
|
|
23
|
-
}
|
|
24
|
-
if (effect.control.kind === 'jump') {
|
|
25
|
-
const target = localTargetIndex(labels, effect.control.target);
|
|
26
|
-
if (effect.control.conditional) {
|
|
27
|
-
return unique([
|
|
28
|
-
...(target === undefined ? [] : [target]),
|
|
29
|
-
...(next === undefined ? [] : [next]),
|
|
30
|
-
]);
|
|
31
|
-
}
|
|
32
|
-
return target === undefined ? [] : [target];
|
|
33
|
-
}
|
|
34
|
-
if (effect.control.kind === 'return') {
|
|
35
|
-
return effect.control.conditional && next !== undefined ? [next] : [];
|
|
36
|
-
}
|
|
37
|
-
return [];
|
|
38
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { RegisterCareOutputCandidate, RegisterCareRoutine, RegisterCareUnit } from './types.js';
|
|
2
|
-
export interface RegisterCareExpectOutFix {
|
|
3
|
-
file: string;
|
|
4
|
-
line: number;
|
|
5
|
-
column: number;
|
|
6
|
-
routine: string;
|
|
7
|
-
carriers: RegisterCareUnit[];
|
|
8
|
-
}
|
|
9
|
-
export declare function findExpectOutFixesForCandidates(routines: RegisterCareRoutine[], candidates: RegisterCareOutputCandidate[]): RegisterCareExpectOutFix[];
|
|
10
|
-
export declare function autoFixableCandidateKeys(routines: RegisterCareRoutine[], candidates: RegisterCareOutputCandidate[]): Set<string>;
|
|
11
|
-
export declare function applyExpectOutFixesToSource(source: string, fixes: RegisterCareExpectOutFix[], referenceSource?: string): string;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { Z80Instruction, Z80Operand } from '../z80/instruction.js';
|
|
2
|
-
import type { RegisterCareInstruction } from './types.js';
|
|
3
|
-
export declare function instructionHead(item: RegisterCareInstruction): string;
|
|
4
|
-
export declare function regName(operand: Z80Operand | undefined): string | undefined;
|
|
5
|
-
export declare function instructionOperandCount(instruction: Z80Instruction): number;
|
|
6
|
-
export declare function instructionOperand(instruction: Z80Instruction, index: number): Z80Operand | undefined;
|
|
7
|
-
export declare function isUnconditionalReturnInstruction(item: RegisterCareInstruction): boolean;
|
|
8
|
-
export declare function isPureTokenTransferInstruction(item: RegisterCareInstruction): boolean;
|
|
9
|
-
export declare function isAccumulatorSelfOperand(item: RegisterCareInstruction): boolean;
|
|
10
|
-
export declare function isImmediateZeroOperand(item: RegisterCareInstruction): boolean;
|
|
11
|
-
export declare function isRegisterOperand(item: RegisterCareInstruction | undefined, index: number, name: string): boolean;
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
export function instructionHead(item) {
|
|
2
|
-
return item.instruction.mnemonic.toLowerCase();
|
|
3
|
-
}
|
|
4
|
-
export function regName(operand) {
|
|
5
|
-
if (operand === undefined)
|
|
6
|
-
return undefined;
|
|
7
|
-
switch (operand.kind) {
|
|
8
|
-
case 'reg8':
|
|
9
|
-
return operand.register.toUpperCase();
|
|
10
|
-
case 'reg16':
|
|
11
|
-
return operand.register.toUpperCase();
|
|
12
|
-
case 'reg-index16':
|
|
13
|
-
return operand.register.toUpperCase();
|
|
14
|
-
case 'reg-half-index':
|
|
15
|
-
return operand.register.toUpperCase();
|
|
16
|
-
default:
|
|
17
|
-
return undefined;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
function immValue(operand) {
|
|
21
|
-
if (operand?.kind !== 'imm')
|
|
22
|
-
return undefined;
|
|
23
|
-
const expression = operand.expression;
|
|
24
|
-
return expression.kind === 'number' ? expression.value : undefined;
|
|
25
|
-
}
|
|
26
|
-
export function instructionOperandCount(instruction) {
|
|
27
|
-
switch (instruction.mnemonic) {
|
|
28
|
-
case 'ret':
|
|
29
|
-
case 'ret-cc':
|
|
30
|
-
return instruction.mnemonic === 'ret' ? 0 : 1;
|
|
31
|
-
case 'ld':
|
|
32
|
-
return 2;
|
|
33
|
-
case 'ex':
|
|
34
|
-
return 2;
|
|
35
|
-
case 'jp':
|
|
36
|
-
case 'jp-cc':
|
|
37
|
-
case 'jr':
|
|
38
|
-
case 'jr-cc':
|
|
39
|
-
case 'djnz':
|
|
40
|
-
case 'call':
|
|
41
|
-
case 'call-cc':
|
|
42
|
-
return 1;
|
|
43
|
-
case 'add':
|
|
44
|
-
case 'adc':
|
|
45
|
-
case 'sbc':
|
|
46
|
-
return 'target' in instruction ? 2 : 1;
|
|
47
|
-
case 'sub':
|
|
48
|
-
case 'and':
|
|
49
|
-
case 'or':
|
|
50
|
-
case 'xor':
|
|
51
|
-
case 'cp':
|
|
52
|
-
return 1;
|
|
53
|
-
default:
|
|
54
|
-
return 0;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
export function instructionOperand(instruction, index) {
|
|
58
|
-
switch (instruction.mnemonic) {
|
|
59
|
-
case 'ld':
|
|
60
|
-
return index === 0 ? instruction.target : index === 1 ? instruction.source : undefined;
|
|
61
|
-
case 'ex': {
|
|
62
|
-
if (index === 0) {
|
|
63
|
-
return instruction.form === 'de-hl'
|
|
64
|
-
? { kind: 'reg16', register: 'de' }
|
|
65
|
-
: instruction.form === 'af-af'
|
|
66
|
-
? { kind: 'reg16', register: 'af' }
|
|
67
|
-
: undefined;
|
|
68
|
-
}
|
|
69
|
-
if (index === 1) {
|
|
70
|
-
return instruction.form === 'de-hl'
|
|
71
|
-
? { kind: 'reg16', register: 'hl' }
|
|
72
|
-
: undefined;
|
|
73
|
-
}
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
|
-
case 'add':
|
|
77
|
-
case 'adc':
|
|
78
|
-
case 'sbc':
|
|
79
|
-
if ('target' in instruction) {
|
|
80
|
-
return index === 0 ? instruction.target : index === 1 ? instruction.source : undefined;
|
|
81
|
-
}
|
|
82
|
-
return index === 0 ? instruction.source : undefined;
|
|
83
|
-
case 'sub':
|
|
84
|
-
case 'and':
|
|
85
|
-
case 'or':
|
|
86
|
-
case 'xor':
|
|
87
|
-
case 'cp':
|
|
88
|
-
return index === 0 ? instruction.source : undefined;
|
|
89
|
-
default:
|
|
90
|
-
return undefined;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
export function isUnconditionalReturnInstruction(item) {
|
|
94
|
-
const head = instructionHead(item);
|
|
95
|
-
if (head === 'ret')
|
|
96
|
-
return item.instruction.mnemonic === 'ret';
|
|
97
|
-
return head === 'retn' || head === 'reti';
|
|
98
|
-
}
|
|
99
|
-
export function isPureTokenTransferInstruction(item) {
|
|
100
|
-
const head = instructionHead(item);
|
|
101
|
-
if (head === 'ex')
|
|
102
|
-
return true;
|
|
103
|
-
if (head !== 'ld' || instructionOperandCount(item.instruction) !== 2)
|
|
104
|
-
return false;
|
|
105
|
-
const dst = instructionOperand(item.instruction, 0);
|
|
106
|
-
const src = instructionOperand(item.instruction, 1);
|
|
107
|
-
if (regName(dst) === undefined)
|
|
108
|
-
return false;
|
|
109
|
-
return regName(src) !== undefined || src?.kind === 'imm';
|
|
110
|
-
}
|
|
111
|
-
export function isAccumulatorSelfOperand(item) {
|
|
112
|
-
const inst = item.instruction;
|
|
113
|
-
if (inst.mnemonic === 'or' || inst.mnemonic === 'and' || inst.mnemonic === 'xor') {
|
|
114
|
-
return inst.source.kind === 'reg8' && inst.source.register === 'a';
|
|
115
|
-
}
|
|
116
|
-
return false;
|
|
117
|
-
}
|
|
118
|
-
export function isImmediateZeroOperand(item) {
|
|
119
|
-
const inst = item.instruction;
|
|
120
|
-
if (inst.mnemonic !== 'cp')
|
|
121
|
-
return false;
|
|
122
|
-
return immValue(inst.source) === 0;
|
|
123
|
-
}
|
|
124
|
-
export function isRegisterOperand(item, index, name) {
|
|
125
|
-
if (item === undefined)
|
|
126
|
-
return false;
|
|
127
|
-
const operand = instructionOperand(item.instruction, index);
|
|
128
|
-
return regName(operand) === name.toUpperCase();
|
|
129
|
-
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { LocatedSmartComment, RegisterCareConflict, RegisterCareOutputCandidate, RegisterCareRoutine, RoutineSummary } from './types.js';
|
|
2
|
-
export declare function findRegisterCareConflicts(routine: RegisterCareRoutine, summaries: Map<string, RoutineSummary>, hints: LocatedSmartComment[]): RegisterCareConflict[];
|
|
3
|
-
export declare function findCallerOutputCandidateObservations(routines: RegisterCareRoutine[], summaries: Map<string, RoutineSummary>): RegisterCareOutputCandidate[];
|