@jhlagado/azm 0.2.7 → 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 +2 -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
|
@@ -1,7 +1,26 @@
|
|
|
1
|
-
import { evaluateExpression, } from '../semantics/expression-evaluation.js';
|
|
2
1
|
import { instructionSize } from '../assembly/fixup-emission.js';
|
|
2
|
+
import { evaluateLoweredConstant, formatExpression, formatLoweredNumber, } from './asm80-expressions.js';
|
|
3
|
+
import { formatInstruction } from './asm80-instructions.js';
|
|
4
|
+
import { stringDirectiveBytes } from './asm80-strings.js';
|
|
3
5
|
const asm80Header = '; AZM lowered ASM80 output';
|
|
4
|
-
const
|
|
6
|
+
const FORMATTERS = {
|
|
7
|
+
org: formatOrg,
|
|
8
|
+
equ: formatEqu,
|
|
9
|
+
comment: formatComment,
|
|
10
|
+
label: formatLabel,
|
|
11
|
+
db: formatDbItem,
|
|
12
|
+
dw: formatDwItem,
|
|
13
|
+
ds: formatDsItem,
|
|
14
|
+
align: formatAlignItem,
|
|
15
|
+
'string-data': formatStringDataItem,
|
|
16
|
+
instruction: formatInstructionItem,
|
|
17
|
+
enum: formatIgnoredItem,
|
|
18
|
+
type: formatIgnoredItem,
|
|
19
|
+
'type-alias': formatIgnoredItem,
|
|
20
|
+
end: formatIgnoredItem,
|
|
21
|
+
binfrom: formatIgnoredItem,
|
|
22
|
+
binto: formatIgnoredItem,
|
|
23
|
+
};
|
|
5
24
|
export class UnsupportedAsm80LoweringError extends Error {
|
|
6
25
|
item;
|
|
7
26
|
constructor(message, item) {
|
|
@@ -72,52 +91,54 @@ function collectLayouts(items) {
|
|
|
72
91
|
return layouts;
|
|
73
92
|
}
|
|
74
93
|
function formatItem(item, evalContext, state) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
state.emittedOrg = true;
|
|
84
|
-
return { text: `ORG ${expression}`, size: 0 };
|
|
85
|
-
}
|
|
86
|
-
case 'equ': {
|
|
87
|
-
const expression = formatExpression(item.expression, evalContext, 'auto');
|
|
88
|
-
return expression === undefined
|
|
89
|
-
? undefined
|
|
90
|
-
: withImplicitOrg(state, `${item.name} EQU ${expression}`, 0);
|
|
91
|
-
}
|
|
92
|
-
case 'comment':
|
|
93
|
-
return {
|
|
94
|
-
text: item.origin === 'user' ? `; ${item.text}` : `; AZM: ${item.text}`,
|
|
95
|
-
size: 0,
|
|
96
|
-
};
|
|
97
|
-
case 'label':
|
|
98
|
-
return withImplicitOrg(state, `${item.name}:`, 0);
|
|
99
|
-
case 'db':
|
|
100
|
-
return formatDb(item.values, evalContext, state);
|
|
101
|
-
case 'dw':
|
|
102
|
-
return formatDw(item.values, evalContext, state);
|
|
103
|
-
case 'ds':
|
|
104
|
-
return formatDs(item.size, item.fill, evalContext, state);
|
|
105
|
-
case 'align':
|
|
106
|
-
return formatAlign(item.alignment, evalContext, state);
|
|
107
|
-
case 'string-data':
|
|
108
|
-
return formatStringData(item.directive, item.value, state);
|
|
109
|
-
case 'instruction':
|
|
110
|
-
return withImplicitOrg(state, formatInstruction(item.instruction, evalContext)?.text, instructionSize(item.instruction));
|
|
111
|
-
case 'enum':
|
|
112
|
-
case 'type':
|
|
113
|
-
case 'type-alias':
|
|
114
|
-
case 'end':
|
|
115
|
-
case 'binfrom':
|
|
116
|
-
case 'binto':
|
|
117
|
-
return { text: '', size: 0 };
|
|
118
|
-
default:
|
|
119
|
-
return undefined;
|
|
94
|
+
const formatter = FORMATTERS[item.kind];
|
|
95
|
+
return formatter(item, evalContext, state);
|
|
96
|
+
}
|
|
97
|
+
function formatOrg(item, evalContext, state) {
|
|
98
|
+
const expression = formatExpression(item.expression, evalContext, 'word');
|
|
99
|
+
const address = evaluateLoweredConstant(item.expression, evalContext);
|
|
100
|
+
if (expression === undefined || address === undefined) {
|
|
101
|
+
return undefined;
|
|
120
102
|
}
|
|
103
|
+
state.address = address;
|
|
104
|
+
state.emittedOrg = true;
|
|
105
|
+
return { text: `ORG ${expression}`, size: 0 };
|
|
106
|
+
}
|
|
107
|
+
function formatEqu(item, evalContext, state) {
|
|
108
|
+
const expression = formatExpression(item.expression, evalContext, 'auto');
|
|
109
|
+
return expression === undefined
|
|
110
|
+
? undefined
|
|
111
|
+
: withImplicitOrg(state, `${item.name} EQU ${expression}`, 0);
|
|
112
|
+
}
|
|
113
|
+
function formatComment(item) {
|
|
114
|
+
return {
|
|
115
|
+
text: item.origin === 'user' ? `; ${item.text}` : `; AZM: ${item.text}`,
|
|
116
|
+
size: 0,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function formatLabel(item, _evalContext, state) {
|
|
120
|
+
return withImplicitOrg(state, `${item.name}:`, 0);
|
|
121
|
+
}
|
|
122
|
+
function formatDbItem(item, evalContext, state) {
|
|
123
|
+
return formatDb(item.values, evalContext, state);
|
|
124
|
+
}
|
|
125
|
+
function formatDwItem(item, evalContext, state) {
|
|
126
|
+
return formatDw(item.values, evalContext, state);
|
|
127
|
+
}
|
|
128
|
+
function formatDsItem(item, evalContext, state) {
|
|
129
|
+
return formatDs(item.size, item.fill, evalContext, state);
|
|
130
|
+
}
|
|
131
|
+
function formatAlignItem(item, evalContext, state) {
|
|
132
|
+
return formatAlign(item.alignment, evalContext, state);
|
|
133
|
+
}
|
|
134
|
+
function formatStringDataItem(item, _evalContext, state) {
|
|
135
|
+
return formatStringData(item.directive, item.value, state);
|
|
136
|
+
}
|
|
137
|
+
function formatInstructionItem(item, evalContext, state) {
|
|
138
|
+
return withImplicitOrg(state, formatInstruction(item.instruction, evalContext)?.text, instructionSize(item.instruction));
|
|
139
|
+
}
|
|
140
|
+
function formatIgnoredItem() {
|
|
141
|
+
return { text: '', size: 0 };
|
|
121
142
|
}
|
|
122
143
|
function formatDb(values, evalContext, state) {
|
|
123
144
|
const parts = [];
|
|
@@ -182,265 +203,6 @@ function formatStringData(directive, value, state) {
|
|
|
182
203
|
}
|
|
183
204
|
return withImplicitOrg(state, `DB ${bytes.map((byte) => formatLoweredNumber(byte, 'byte')).join(', ')}`, bytes.length);
|
|
184
205
|
}
|
|
185
|
-
function formatInstruction(instruction, evalContext) {
|
|
186
|
-
const size = instructionSize(instruction);
|
|
187
|
-
void size;
|
|
188
|
-
switch (instruction.mnemonic) {
|
|
189
|
-
case 'ld-a-imm': {
|
|
190
|
-
const expression = formatExpression(instruction.expression, evalContext, 'byte');
|
|
191
|
-
if (expression === undefined) {
|
|
192
|
-
return undefined;
|
|
193
|
-
}
|
|
194
|
-
return {
|
|
195
|
-
text: `ld a, ${expression}`,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
case 'ld':
|
|
199
|
-
return formatLd(instruction.target, instruction.source, evalContext);
|
|
200
|
-
case 'nop':
|
|
201
|
-
return { text: 'nop' };
|
|
202
|
-
case 'ret':
|
|
203
|
-
return { text: 'ret' };
|
|
204
|
-
case 'di':
|
|
205
|
-
case 'ei':
|
|
206
|
-
case 'scf':
|
|
207
|
-
case 'ccf':
|
|
208
|
-
case 'cpl':
|
|
209
|
-
case 'daa':
|
|
210
|
-
case 'exx':
|
|
211
|
-
case 'halt':
|
|
212
|
-
case 'rlca':
|
|
213
|
-
case 'rrca':
|
|
214
|
-
case 'rla':
|
|
215
|
-
case 'rra':
|
|
216
|
-
case 'neg':
|
|
217
|
-
case 'rrd':
|
|
218
|
-
case 'rld':
|
|
219
|
-
case 'ldi':
|
|
220
|
-
case 'ldir':
|
|
221
|
-
case 'ldd':
|
|
222
|
-
case 'lddr':
|
|
223
|
-
case 'cpi':
|
|
224
|
-
case 'cpir':
|
|
225
|
-
case 'cpd':
|
|
226
|
-
case 'cpdr':
|
|
227
|
-
case 'ini':
|
|
228
|
-
case 'inir':
|
|
229
|
-
case 'ind':
|
|
230
|
-
case 'indr':
|
|
231
|
-
case 'outi':
|
|
232
|
-
case 'otir':
|
|
233
|
-
case 'outd':
|
|
234
|
-
case 'otdr':
|
|
235
|
-
case 'reti':
|
|
236
|
-
case 'retn':
|
|
237
|
-
return { text: instruction.mnemonic };
|
|
238
|
-
case 'im':
|
|
239
|
-
return { text: `im ${formatLoweredNumber(instruction.mode, 'byte')}` };
|
|
240
|
-
case 'rst':
|
|
241
|
-
return { text: `rst ${formatLoweredNumber(instruction.vector, 'byte')}` };
|
|
242
|
-
case 'add':
|
|
243
|
-
if ('target' in instruction) {
|
|
244
|
-
return formatReg16Alu('add', instruction.target, instruction.source);
|
|
245
|
-
}
|
|
246
|
-
return formatAlu('add', instruction.source, evalContext);
|
|
247
|
-
case 'adc':
|
|
248
|
-
case 'sbc':
|
|
249
|
-
if ('target' in instruction) {
|
|
250
|
-
return formatReg16Alu(instruction.mnemonic, instruction.target, instruction.source);
|
|
251
|
-
}
|
|
252
|
-
return formatAlu(instruction.mnemonic, instruction.source, evalContext);
|
|
253
|
-
case 'sub':
|
|
254
|
-
case 'and':
|
|
255
|
-
case 'or':
|
|
256
|
-
case 'xor':
|
|
257
|
-
case 'cp':
|
|
258
|
-
return formatAlu(instruction.mnemonic, instruction.source, evalContext);
|
|
259
|
-
case 'bit':
|
|
260
|
-
case 'res':
|
|
261
|
-
case 'set':
|
|
262
|
-
return formatBitOp(instruction, evalContext);
|
|
263
|
-
case 'rlc':
|
|
264
|
-
case 'rrc':
|
|
265
|
-
case 'rl':
|
|
266
|
-
case 'rr':
|
|
267
|
-
case 'sla':
|
|
268
|
-
case 'sra':
|
|
269
|
-
case 'sll':
|
|
270
|
-
case 'sls':
|
|
271
|
-
case 'srl':
|
|
272
|
-
return formatRotateShift(instruction, evalContext);
|
|
273
|
-
case 'in':
|
|
274
|
-
return formatIn(instruction, evalContext);
|
|
275
|
-
case 'out':
|
|
276
|
-
return formatOut(instruction, evalContext);
|
|
277
|
-
case 'inc':
|
|
278
|
-
case 'dec':
|
|
279
|
-
return formatIncDec(instruction, evalContext);
|
|
280
|
-
case 'ex':
|
|
281
|
-
return formatEx(instruction.form);
|
|
282
|
-
case 'jp':
|
|
283
|
-
return formatBranch('jp', instruction.expression, evalContext);
|
|
284
|
-
case 'jp-cc':
|
|
285
|
-
return formatBranch(`jp ${instruction.condition},`, instruction.expression, evalContext);
|
|
286
|
-
case 'jp-indirect':
|
|
287
|
-
return { text: `jp (${instruction.register})` };
|
|
288
|
-
case 'jr':
|
|
289
|
-
return formatBranch('jr', instruction.expression, evalContext);
|
|
290
|
-
case 'jr-cc':
|
|
291
|
-
return formatBranch(`jr ${instruction.condition},`, instruction.expression, evalContext);
|
|
292
|
-
case 'call':
|
|
293
|
-
return formatBranch('call', instruction.expression, evalContext);
|
|
294
|
-
case 'call-cc':
|
|
295
|
-
return formatBranch(`call ${instruction.condition},`, instruction.expression, evalContext);
|
|
296
|
-
case 'djnz':
|
|
297
|
-
return formatBranch('djnz', instruction.expression, evalContext);
|
|
298
|
-
case 'push':
|
|
299
|
-
case 'pop':
|
|
300
|
-
return { text: `${instruction.mnemonic} ${instruction.register}` };
|
|
301
|
-
case 'ret-cc':
|
|
302
|
-
return { text: `ret ${instruction.condition}` };
|
|
303
|
-
default:
|
|
304
|
-
return undefined;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
function formatAlu(mnemonic, source, evalContext) {
|
|
308
|
-
const operand = formatAluOperand(source, evalContext);
|
|
309
|
-
if (operand === undefined) {
|
|
310
|
-
return undefined;
|
|
311
|
-
}
|
|
312
|
-
if (mnemonic === 'add' || mnemonic === 'adc' || mnemonic === 'sbc') {
|
|
313
|
-
return { text: `${mnemonic} a, ${operand}` };
|
|
314
|
-
}
|
|
315
|
-
if (mnemonic === 'xor' && source.kind === 'reg8' && source.register === 'a') {
|
|
316
|
-
return { text: 'xor a' };
|
|
317
|
-
}
|
|
318
|
-
return { text: `${mnemonic} ${operand}` };
|
|
319
|
-
}
|
|
320
|
-
function formatAluOperand(source, evalContext) {
|
|
321
|
-
if (source.kind === 'reg8' || source.kind === 'reg-half-index') {
|
|
322
|
-
return source.register;
|
|
323
|
-
}
|
|
324
|
-
if (source.kind === 'reg-indirect' && source.register === 'hl') {
|
|
325
|
-
return '(HL)';
|
|
326
|
-
}
|
|
327
|
-
if (source.kind === 'imm') {
|
|
328
|
-
return formatExpression(source.expression, evalContext, 'byte');
|
|
329
|
-
}
|
|
330
|
-
return undefined;
|
|
331
|
-
}
|
|
332
|
-
function formatReg16Alu(mnemonic, target, source) {
|
|
333
|
-
const targetText = formatReg16PairOperand(target);
|
|
334
|
-
const sourceText = formatReg16PairOperand(source);
|
|
335
|
-
return targetText === undefined || sourceText === undefined
|
|
336
|
-
? undefined
|
|
337
|
-
: { text: `${mnemonic} ${targetText}, ${sourceText}` };
|
|
338
|
-
}
|
|
339
|
-
function formatReg16PairOperand(operand) {
|
|
340
|
-
if (operand.kind === 'reg16') {
|
|
341
|
-
return operand.register;
|
|
342
|
-
}
|
|
343
|
-
if (operand.kind === 'reg-index16') {
|
|
344
|
-
return operand.register;
|
|
345
|
-
}
|
|
346
|
-
return undefined;
|
|
347
|
-
}
|
|
348
|
-
function formatEx(form) {
|
|
349
|
-
switch (form) {
|
|
350
|
-
case 'af-af':
|
|
351
|
-
return { text: "ex af, af'" };
|
|
352
|
-
case 'de-hl':
|
|
353
|
-
return { text: 'ex de, hl' };
|
|
354
|
-
case 'sp-hl':
|
|
355
|
-
return { text: 'ex (sp), hl' };
|
|
356
|
-
case 'sp-ix':
|
|
357
|
-
return { text: 'ex (SP), ix' };
|
|
358
|
-
case 'sp-iy':
|
|
359
|
-
return { text: 'ex (SP), iy' };
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
function formatLd(target, source, evalContext) {
|
|
363
|
-
if (target.kind === 'reg8' && source.kind === 'imm') {
|
|
364
|
-
return formatLdText(target.register, formatExpression(source.expression, evalContext, 'byte'));
|
|
365
|
-
}
|
|
366
|
-
if (target.kind === 'reg8' && source.kind === 'reg8') {
|
|
367
|
-
return { text: `ld ${target.register}, ${source.register}` };
|
|
368
|
-
}
|
|
369
|
-
if (target.kind === 'reg8' && source.kind === 'reg-half-index') {
|
|
370
|
-
return { text: `ld ${target.register}, ${source.register}` };
|
|
371
|
-
}
|
|
372
|
-
if (target.kind === 'reg8' && target.register === 'a' && source.kind === 'special8') {
|
|
373
|
-
return { text: `ld a, ${source.register}` };
|
|
374
|
-
}
|
|
375
|
-
if (target.kind === 'special8' && source.kind === 'reg8' && source.register === 'a') {
|
|
376
|
-
return { text: `ld ${target.register}, a` };
|
|
377
|
-
}
|
|
378
|
-
if (target.kind === 'reg-index16' && source.kind === 'imm') {
|
|
379
|
-
return formatLdText(target.register, formatExpression(source.expression, evalContext, 'word'));
|
|
380
|
-
}
|
|
381
|
-
if (target.kind === 'reg16' && source.kind === 'imm') {
|
|
382
|
-
return formatLdText(target.register, formatExpression(source.expression, evalContext, 'word'));
|
|
383
|
-
}
|
|
384
|
-
if (target.kind === 'reg16' && source.kind === 'mem-abs') {
|
|
385
|
-
return formatLdText(target.register, formatParenthesizedExpression(source.expression, evalContext, 'auto'));
|
|
386
|
-
}
|
|
387
|
-
if (target.kind === 'reg8' && target.register === 'a' && source.kind === 'reg-indirect') {
|
|
388
|
-
return { text: `ld a, (${source.register})` };
|
|
389
|
-
}
|
|
390
|
-
if (target.kind === 'reg-indirect' &&
|
|
391
|
-
(target.register === 'bc' || target.register === 'de') &&
|
|
392
|
-
source.kind === 'reg8' &&
|
|
393
|
-
source.register === 'a') {
|
|
394
|
-
return { text: `ld (${target.register}), a` };
|
|
395
|
-
}
|
|
396
|
-
if (target.kind === 'reg8' && source.kind === 'reg-indirect' && source.register === 'hl') {
|
|
397
|
-
return { text: `ld ${target.register}, (hl)` };
|
|
398
|
-
}
|
|
399
|
-
if (target.kind === 'reg-indirect' && target.register === 'hl' && source.kind === 'reg8') {
|
|
400
|
-
return { text: `ld (hl), ${source.register}` };
|
|
401
|
-
}
|
|
402
|
-
if (target.kind === 'reg-indirect' && target.register === 'hl' && source.kind === 'imm') {
|
|
403
|
-
const value = formatExpression(source.expression, evalContext, 'byte');
|
|
404
|
-
return value === undefined ? undefined : { text: `ld (hl), ${value}` };
|
|
405
|
-
}
|
|
406
|
-
if (target.kind === 'reg8' && source.kind === 'indexed') {
|
|
407
|
-
const memory = formatIndexedMemory(source.register, source.displacement, evalContext);
|
|
408
|
-
return memory === undefined ? undefined : { text: `ld ${target.register}, ${memory}` };
|
|
409
|
-
}
|
|
410
|
-
if (target.kind === 'indexed' && source.kind === 'reg8') {
|
|
411
|
-
const memory = formatIndexedMemory(target.register, target.displacement, evalContext);
|
|
412
|
-
return memory === undefined ? undefined : { text: `ld ${memory}, ${source.register}` };
|
|
413
|
-
}
|
|
414
|
-
if (target.kind === 'reg8' && source.kind === 'mem-abs') {
|
|
415
|
-
return formatLdText(target.register, formatParenthesizedExpression(source.expression, evalContext, 'auto'));
|
|
416
|
-
}
|
|
417
|
-
if (target.kind === 'mem-abs' && source.kind === 'reg8') {
|
|
418
|
-
const targetText = formatParenthesizedExpression(target.expression, evalContext, 'auto');
|
|
419
|
-
return targetText === undefined
|
|
420
|
-
? undefined
|
|
421
|
-
: { text: `ld ${targetText}, ${source.register}` };
|
|
422
|
-
}
|
|
423
|
-
if (target.kind === 'mem-abs' && source.kind === 'reg16') {
|
|
424
|
-
const targetText = formatParenthesizedExpression(target.expression, evalContext, 'auto');
|
|
425
|
-
return targetText === undefined
|
|
426
|
-
? undefined
|
|
427
|
-
: { text: `ld ${targetText}, ${source.register}` };
|
|
428
|
-
}
|
|
429
|
-
if (target.kind === 'mem-abs' && source.kind === 'reg-index16') {
|
|
430
|
-
const targetText = formatParenthesizedExpression(target.expression, evalContext, 'auto');
|
|
431
|
-
return targetText === undefined
|
|
432
|
-
? undefined
|
|
433
|
-
: { text: `ld ${targetText}, ${source.register}` };
|
|
434
|
-
}
|
|
435
|
-
return undefined;
|
|
436
|
-
}
|
|
437
|
-
function formatLdText(target, source) {
|
|
438
|
-
return source === undefined ? undefined : { text: `ld ${target}, ${source}` };
|
|
439
|
-
}
|
|
440
|
-
function formatParenthesizedExpression(expression, evalContext, width) {
|
|
441
|
-
const formatted = formatExpression(expression, evalContext, width);
|
|
442
|
-
return formatted === undefined ? undefined : `(${formatted})`;
|
|
443
|
-
}
|
|
444
206
|
function withImplicitOrg(state, text, size) {
|
|
445
207
|
if (text === undefined) {
|
|
446
208
|
return undefined;
|
|
@@ -451,297 +213,6 @@ function withImplicitOrg(state, text, size) {
|
|
|
451
213
|
state.emittedOrg = true;
|
|
452
214
|
return { text: `ORG $00\n${text}`, size };
|
|
453
215
|
}
|
|
454
|
-
function formatBranch(mnemonic, expression, evalContext) {
|
|
455
|
-
const target = formatExpression(expression, evalContext, 'word');
|
|
456
|
-
return target === undefined ? undefined : { text: `${mnemonic} ${target}` };
|
|
457
|
-
}
|
|
458
|
-
function formatExpression(expression, evalContext, width) {
|
|
459
|
-
const value = evaluateLoweredConstant(expression, evalContext);
|
|
460
|
-
if (value !== undefined) {
|
|
461
|
-
return formatLoweredNumber(value, width);
|
|
462
|
-
}
|
|
463
|
-
if (expression.kind === 'symbol') {
|
|
464
|
-
return expression.name;
|
|
465
|
-
}
|
|
466
|
-
if (expression.kind === 'type-size') {
|
|
467
|
-
const value = evaluateLoweredConstant(expression, evalContext);
|
|
468
|
-
return value === undefined ? expression.typeExpr.name : formatLoweredNumber(value, width);
|
|
469
|
-
}
|
|
470
|
-
if (expression.kind === 'current-location') {
|
|
471
|
-
return '$';
|
|
472
|
-
}
|
|
473
|
-
if (expression.kind === 'unary') {
|
|
474
|
-
const inner = formatExpression(expression.expression, evalContext, width);
|
|
475
|
-
if (inner === undefined) {
|
|
476
|
-
return undefined;
|
|
477
|
-
}
|
|
478
|
-
switch (expression.operator) {
|
|
479
|
-
case '+':
|
|
480
|
-
return inner;
|
|
481
|
-
case '-':
|
|
482
|
-
return `-${inner}`;
|
|
483
|
-
case '~': {
|
|
484
|
-
const value = evaluateLoweredConstant(expression, evalContext);
|
|
485
|
-
return value === undefined ? undefined : formatLoweredNumber(value, width);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
if (expression.kind === 'binary') {
|
|
490
|
-
const left = formatExpression(expression.left, evalContext, width);
|
|
491
|
-
const right = formatExpression(expression.right, evalContext, width);
|
|
492
|
-
if (left === undefined || right === undefined) {
|
|
493
|
-
return undefined;
|
|
494
|
-
}
|
|
495
|
-
return `${left}${expression.operator}${right}`;
|
|
496
|
-
}
|
|
497
|
-
return undefined;
|
|
498
|
-
}
|
|
499
|
-
function evaluateLoweredConstant(expression, evalContext) {
|
|
500
|
-
switch (expression.kind) {
|
|
501
|
-
case 'number':
|
|
502
|
-
return expression.value;
|
|
503
|
-
case 'symbol':
|
|
504
|
-
return evalContext.constants.get(expression.name);
|
|
505
|
-
case 'type-size': {
|
|
506
|
-
const constant = evalContext.constants.get(expression.typeExpr.name);
|
|
507
|
-
if (constant !== undefined) {
|
|
508
|
-
return constant;
|
|
509
|
-
}
|
|
510
|
-
return evaluateExpression(expression, {}, new Map(), silentSpan, [], {
|
|
511
|
-
currentLocation: 0,
|
|
512
|
-
layouts: evalContext.layouts,
|
|
513
|
-
reportUnknown: false,
|
|
514
|
-
});
|
|
515
|
-
}
|
|
516
|
-
case 'offset':
|
|
517
|
-
case 'sizeof':
|
|
518
|
-
return evaluateExpression(expression, {}, new Map(), silentSpan, [], {
|
|
519
|
-
currentLocation: 0,
|
|
520
|
-
layouts: evalContext.layouts,
|
|
521
|
-
reportUnknown: false,
|
|
522
|
-
});
|
|
523
|
-
case 'byte-function': {
|
|
524
|
-
const value = evaluateLoweredResolvedConstant(expression.expression, evalContext);
|
|
525
|
-
if (value === undefined) {
|
|
526
|
-
return undefined;
|
|
527
|
-
}
|
|
528
|
-
return expression.function === 'LSB' ? value & 0xff : (value >> 8) & 0xff;
|
|
529
|
-
}
|
|
530
|
-
case 'unary': {
|
|
531
|
-
const value = evaluateLoweredConstant(expression.expression, evalContext);
|
|
532
|
-
if (value === undefined) {
|
|
533
|
-
return undefined;
|
|
534
|
-
}
|
|
535
|
-
switch (expression.operator) {
|
|
536
|
-
case '+':
|
|
537
|
-
return value;
|
|
538
|
-
case '-':
|
|
539
|
-
return -value;
|
|
540
|
-
case '~':
|
|
541
|
-
return ~value;
|
|
542
|
-
}
|
|
543
|
-
break;
|
|
544
|
-
}
|
|
545
|
-
case 'binary': {
|
|
546
|
-
const left = evaluateLoweredConstant(expression.left, evalContext);
|
|
547
|
-
const right = evaluateLoweredConstant(expression.right, evalContext);
|
|
548
|
-
if (left === undefined || right === undefined) {
|
|
549
|
-
return undefined;
|
|
550
|
-
}
|
|
551
|
-
switch (expression.operator) {
|
|
552
|
-
case '+':
|
|
553
|
-
return left + right;
|
|
554
|
-
case '-':
|
|
555
|
-
return left - right;
|
|
556
|
-
case '*':
|
|
557
|
-
return left * right;
|
|
558
|
-
case '/':
|
|
559
|
-
return right === 0 ? undefined : Math.trunc(left / right);
|
|
560
|
-
case '%':
|
|
561
|
-
return right === 0 ? undefined : left % right;
|
|
562
|
-
case '&':
|
|
563
|
-
return left & right;
|
|
564
|
-
case '^':
|
|
565
|
-
return left ^ right;
|
|
566
|
-
case '|':
|
|
567
|
-
return left | right;
|
|
568
|
-
case '<<':
|
|
569
|
-
return left << right;
|
|
570
|
-
case '>>':
|
|
571
|
-
return left >> right;
|
|
572
|
-
}
|
|
573
|
-
break;
|
|
574
|
-
}
|
|
575
|
-
default:
|
|
576
|
-
return undefined;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
function evaluateLoweredResolvedConstant(expression, evalContext) {
|
|
580
|
-
switch (expression.kind) {
|
|
581
|
-
case 'symbol':
|
|
582
|
-
return evalContext.symbols.get(expression.name);
|
|
583
|
-
case 'unary': {
|
|
584
|
-
const value = evaluateLoweredResolvedConstant(expression.expression, evalContext);
|
|
585
|
-
if (value === undefined) {
|
|
586
|
-
return undefined;
|
|
587
|
-
}
|
|
588
|
-
switch (expression.operator) {
|
|
589
|
-
case '+':
|
|
590
|
-
return value;
|
|
591
|
-
case '-':
|
|
592
|
-
return -value;
|
|
593
|
-
case '~':
|
|
594
|
-
return ~value;
|
|
595
|
-
}
|
|
596
|
-
break;
|
|
597
|
-
}
|
|
598
|
-
case 'binary': {
|
|
599
|
-
const left = evaluateLoweredResolvedConstant(expression.left, evalContext);
|
|
600
|
-
const right = evaluateLoweredResolvedConstant(expression.right, evalContext);
|
|
601
|
-
if (left === undefined || right === undefined) {
|
|
602
|
-
return undefined;
|
|
603
|
-
}
|
|
604
|
-
switch (expression.operator) {
|
|
605
|
-
case '+':
|
|
606
|
-
return left + right;
|
|
607
|
-
case '-':
|
|
608
|
-
return left - right;
|
|
609
|
-
case '*':
|
|
610
|
-
return left * right;
|
|
611
|
-
case '/':
|
|
612
|
-
return right === 0 ? undefined : Math.trunc(left / right);
|
|
613
|
-
case '%':
|
|
614
|
-
return right === 0 ? undefined : left % right;
|
|
615
|
-
case '&':
|
|
616
|
-
return left & right;
|
|
617
|
-
case '^':
|
|
618
|
-
return left ^ right;
|
|
619
|
-
case '|':
|
|
620
|
-
return left | right;
|
|
621
|
-
case '<<':
|
|
622
|
-
return left << right;
|
|
623
|
-
case '>>':
|
|
624
|
-
return left >> right;
|
|
625
|
-
}
|
|
626
|
-
break;
|
|
627
|
-
}
|
|
628
|
-
case 'byte-function': {
|
|
629
|
-
const value = evaluateLoweredResolvedConstant(expression.expression, evalContext);
|
|
630
|
-
if (value === undefined) {
|
|
631
|
-
return undefined;
|
|
632
|
-
}
|
|
633
|
-
return expression.function === 'LSB' ? value & 0xff : (value >> 8) & 0xff;
|
|
634
|
-
}
|
|
635
|
-
default:
|
|
636
|
-
return evaluateLoweredConstant(expression, evalContext);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
function formatLoweredNumber(value, width) {
|
|
640
|
-
const normalized = value < 0 ? 0x10000 + (value & 0xffff) : value;
|
|
641
|
-
const digits = normalized.toString(16).toUpperCase();
|
|
642
|
-
const minWidth = width === 'word' || (width === 'auto' && normalized > 0xff) ? 4 : 2;
|
|
643
|
-
return `$${digits.padStart(minWidth, '0')}`;
|
|
644
|
-
}
|
|
645
|
-
function formatRotateShift(instruction, evalContext) {
|
|
646
|
-
const operand = formatBitOperand(instruction.operand, evalContext);
|
|
647
|
-
if (operand === undefined) {
|
|
648
|
-
return undefined;
|
|
649
|
-
}
|
|
650
|
-
const parts = [operand];
|
|
651
|
-
if (instruction.destination) {
|
|
652
|
-
parts.push(instruction.destination.register);
|
|
653
|
-
}
|
|
654
|
-
return { text: `${instruction.mnemonic} ${parts.join(', ')}` };
|
|
655
|
-
}
|
|
656
|
-
function formatBitOp(instruction, evalContext) {
|
|
657
|
-
const bit = formatLoweredNumber(instruction.bit, 'byte');
|
|
658
|
-
const operand = formatBitOperand(instruction.operand, evalContext);
|
|
659
|
-
if (operand === undefined) {
|
|
660
|
-
return undefined;
|
|
661
|
-
}
|
|
662
|
-
const parts = [bit, operand];
|
|
663
|
-
if (instruction.destination) {
|
|
664
|
-
parts.push(instruction.destination.register);
|
|
665
|
-
}
|
|
666
|
-
return { text: `${instruction.mnemonic} ${parts.join(', ')}` };
|
|
667
|
-
}
|
|
668
|
-
function formatBitOperand(operand, evalContext) {
|
|
669
|
-
if (operand.kind === 'reg8') {
|
|
670
|
-
return operand.register;
|
|
671
|
-
}
|
|
672
|
-
if (operand.kind === 'reg-indirect' && operand.register === 'hl') {
|
|
673
|
-
return '(HL)';
|
|
674
|
-
}
|
|
675
|
-
if (operand.kind === 'indexed') {
|
|
676
|
-
return formatIndexedMemory(operand.register, operand.displacement, evalContext);
|
|
677
|
-
}
|
|
678
|
-
return undefined;
|
|
679
|
-
}
|
|
680
|
-
function formatIndexedMemory(register, displacement, evalContext) {
|
|
681
|
-
const value = evaluateLoweredConstant(displacement, evalContext);
|
|
682
|
-
if (value === undefined) {
|
|
683
|
-
return undefined;
|
|
684
|
-
}
|
|
685
|
-
const magnitude = formatLoweredNumber(Math.abs(value), 'byte');
|
|
686
|
-
if (value === 0) {
|
|
687
|
-
return `(${register}+$00)`;
|
|
688
|
-
}
|
|
689
|
-
if (value > 0) {
|
|
690
|
-
return `(${register}+${magnitude})`;
|
|
691
|
-
}
|
|
692
|
-
return `(${register}-${magnitude})`;
|
|
693
|
-
}
|
|
694
|
-
function formatIn(instruction, evalContext) {
|
|
695
|
-
const port = formatPort(instruction.port, evalContext);
|
|
696
|
-
if (port === undefined) {
|
|
697
|
-
return undefined;
|
|
698
|
-
}
|
|
699
|
-
const target = instruction.target?.register ?? 'a';
|
|
700
|
-
return { text: `in ${target}, ${port}` };
|
|
701
|
-
}
|
|
702
|
-
function formatOut(instruction, evalContext) {
|
|
703
|
-
const port = formatPort(instruction.port, evalContext);
|
|
704
|
-
if (port === undefined) {
|
|
705
|
-
return undefined;
|
|
706
|
-
}
|
|
707
|
-
const source = instruction.source.kind === 'zero' ? '0' : instruction.source.register;
|
|
708
|
-
return { text: `out ${port}, ${source}` };
|
|
709
|
-
}
|
|
710
|
-
function formatPort(port, evalContext) {
|
|
711
|
-
if (port.kind === 'c') {
|
|
712
|
-
return '(c)';
|
|
713
|
-
}
|
|
714
|
-
const expression = formatExpression(port.expression, evalContext, 'byte');
|
|
715
|
-
return expression === undefined ? undefined : `(${expression})`;
|
|
716
|
-
}
|
|
717
|
-
function formatIncDec(instruction, evalContext) {
|
|
718
|
-
const operand = instruction.operand;
|
|
719
|
-
if (operand.kind === 'reg8' || operand.kind === 'reg16') {
|
|
720
|
-
return { text: `${instruction.mnemonic} ${operand.register}` };
|
|
721
|
-
}
|
|
722
|
-
if (operand.kind === 'reg-indirect' && operand.register === 'hl') {
|
|
723
|
-
return { text: `${instruction.mnemonic} (HL)` };
|
|
724
|
-
}
|
|
725
|
-
if (operand.kind === 'indexed') {
|
|
726
|
-
const memory = formatIndexedMemory(operand.register, operand.displacement, evalContext);
|
|
727
|
-
return memory === undefined ? undefined : { text: `${instruction.mnemonic} ${memory}` };
|
|
728
|
-
}
|
|
729
|
-
return undefined;
|
|
730
|
-
}
|
|
731
|
-
function stringDirectiveBytes(directive, value) {
|
|
732
|
-
const bytes = [...value].map((char) => char.codePointAt(0) ?? 0);
|
|
733
|
-
switch (directive) {
|
|
734
|
-
case 'cstr':
|
|
735
|
-
return [...bytes, 0];
|
|
736
|
-
case 'pstr':
|
|
737
|
-
return [bytes.length & 0xff, ...bytes];
|
|
738
|
-
case 'istr':
|
|
739
|
-
if (bytes.length === 0) {
|
|
740
|
-
return [];
|
|
741
|
-
}
|
|
742
|
-
return bytes.map((byte, index) => (index === bytes.length - 1 ? byte | 0x80 : byte));
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
216
|
function describeItem(item) {
|
|
746
217
|
if (item.kind === 'instruction') {
|
|
747
218
|
return `instruction "${item.instruction.mnemonic}"`;
|