@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
package/dist/src/z80/encode.js
CHANGED
|
@@ -1,128 +1,194 @@
|
|
|
1
|
+
import { encodeCore } from './encode-core.js';
|
|
2
|
+
import { encodeLd } from './encode-ld.js';
|
|
3
|
+
const ROTATE_SHIFT_OPCODE_BASES = {
|
|
4
|
+
rlc: 0x00,
|
|
5
|
+
rrc: 0x08,
|
|
6
|
+
rl: 0x10,
|
|
7
|
+
rr: 0x18,
|
|
8
|
+
sla: 0x20,
|
|
9
|
+
sra: 0x28,
|
|
10
|
+
sll: 0x30,
|
|
11
|
+
sls: 0x30,
|
|
12
|
+
srl: 0x38,
|
|
13
|
+
};
|
|
14
|
+
function oneByteInstruction(opcode) {
|
|
15
|
+
return { size: 1, fragments: [{ kind: 'bytes', bytes: [opcode] }] };
|
|
16
|
+
}
|
|
17
|
+
const Z80_ENCODERS = {
|
|
18
|
+
nop: () => oneByteInstruction(0x00),
|
|
19
|
+
ret: () => oneByteInstruction(0xc9),
|
|
20
|
+
'ret-cc': encodeRetConditionInstruction,
|
|
21
|
+
di: encodeCoreInstruction,
|
|
22
|
+
ei: encodeCoreInstruction,
|
|
23
|
+
scf: encodeCoreInstruction,
|
|
24
|
+
ccf: encodeCoreInstruction,
|
|
25
|
+
cpl: encodeCoreInstruction,
|
|
26
|
+
daa: encodeCoreInstruction,
|
|
27
|
+
exx: encodeCoreInstruction,
|
|
28
|
+
halt: encodeCoreInstruction,
|
|
29
|
+
rlca: encodeCoreInstruction,
|
|
30
|
+
rrca: encodeCoreInstruction,
|
|
31
|
+
rla: encodeCoreInstruction,
|
|
32
|
+
rra: encodeCoreInstruction,
|
|
33
|
+
neg: encodeCoreInstruction,
|
|
34
|
+
rrd: encodeCoreInstruction,
|
|
35
|
+
rld: encodeCoreInstruction,
|
|
36
|
+
ldi: encodeCoreInstruction,
|
|
37
|
+
ldir: encodeCoreInstruction,
|
|
38
|
+
ldd: encodeCoreInstruction,
|
|
39
|
+
lddr: encodeCoreInstruction,
|
|
40
|
+
cpi: encodeCoreInstruction,
|
|
41
|
+
cpir: encodeCoreInstruction,
|
|
42
|
+
cpd: encodeCoreInstruction,
|
|
43
|
+
cpdr: encodeCoreInstruction,
|
|
44
|
+
ini: encodeCoreInstruction,
|
|
45
|
+
inir: encodeCoreInstruction,
|
|
46
|
+
ind: encodeCoreInstruction,
|
|
47
|
+
indr: encodeCoreInstruction,
|
|
48
|
+
outi: encodeCoreInstruction,
|
|
49
|
+
otir: encodeCoreInstruction,
|
|
50
|
+
outd: encodeCoreInstruction,
|
|
51
|
+
otdr: encodeCoreInstruction,
|
|
52
|
+
reti: encodeCoreInstruction,
|
|
53
|
+
retn: encodeCoreInstruction,
|
|
54
|
+
ex: encodeExchangeInstruction,
|
|
55
|
+
im: encodeInterruptModeInstruction,
|
|
56
|
+
rst: encodeRstInstruction,
|
|
57
|
+
inc: encodeIncDecInstruction,
|
|
58
|
+
dec: encodeIncDecInstruction,
|
|
59
|
+
push: encodeStackInstruction,
|
|
60
|
+
pop: encodeStackInstruction,
|
|
61
|
+
'ld-a-imm': encodeLdAImmediateInstruction,
|
|
62
|
+
ld: encodeLdInstruction,
|
|
63
|
+
in: encodeInInstruction,
|
|
64
|
+
out: encodeOutInstruction,
|
|
65
|
+
bit: encodeBitLikeInstruction,
|
|
66
|
+
res: encodeBitLikeInstruction,
|
|
67
|
+
set: encodeBitLikeInstruction,
|
|
68
|
+
rlc: encodeRotateShiftInstruction,
|
|
69
|
+
rrc: encodeRotateShiftInstruction,
|
|
70
|
+
rl: encodeRotateShiftInstruction,
|
|
71
|
+
rr: encodeRotateShiftInstruction,
|
|
72
|
+
sla: encodeRotateShiftInstruction,
|
|
73
|
+
sra: encodeRotateShiftInstruction,
|
|
74
|
+
sll: encodeRotateShiftInstruction,
|
|
75
|
+
sls: encodeRotateShiftInstruction,
|
|
76
|
+
srl: encodeRotateShiftInstruction,
|
|
77
|
+
add: encodeAluInstruction,
|
|
78
|
+
adc: encodeAluInstruction,
|
|
79
|
+
sub: encodeAluInstruction,
|
|
80
|
+
sbc: encodeAluInstruction,
|
|
81
|
+
and: encodeAluInstruction,
|
|
82
|
+
or: encodeAluInstruction,
|
|
83
|
+
xor: encodeAluInstruction,
|
|
84
|
+
cp: encodeAluInstruction,
|
|
85
|
+
jp: encodeJumpInstruction,
|
|
86
|
+
'jp-cc': encodeConditionalJumpInstruction,
|
|
87
|
+
'jp-indirect': encodeIndirectJumpInstruction,
|
|
88
|
+
call: encodeCallInstruction,
|
|
89
|
+
'call-cc': encodeConditionalCallInstruction,
|
|
90
|
+
jr: encodeRelativeJumpInstruction,
|
|
91
|
+
'jr-cc': encodeConditionalRelativeJumpInstruction,
|
|
92
|
+
djnz: encodeDjnzInstruction,
|
|
93
|
+
};
|
|
1
94
|
export function encodeZ80Instruction(instruction) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
size: 2,
|
|
67
|
-
fragments: [
|
|
68
|
-
{ kind: 'bytes', bytes: [0x3e] },
|
|
69
|
-
{ kind: 'imm8', expression: instruction.expression },
|
|
70
|
-
],
|
|
71
|
-
};
|
|
72
|
-
case 'ld':
|
|
73
|
-
return encodeLd(instruction.target, instruction.source);
|
|
74
|
-
case 'in':
|
|
75
|
-
return encodeIn(instruction.target, instruction.port);
|
|
76
|
-
case 'out':
|
|
77
|
-
return encodeOut(instruction.port, instruction.source);
|
|
78
|
-
case 'bit':
|
|
79
|
-
case 'res':
|
|
80
|
-
case 'set':
|
|
81
|
-
return encodeBitLike(instruction.mnemonic, instruction.bit, instruction.operand, instruction.destination);
|
|
82
|
-
case 'rlc':
|
|
83
|
-
case 'rrc':
|
|
84
|
-
case 'rl':
|
|
85
|
-
case 'rr':
|
|
86
|
-
case 'sla':
|
|
87
|
-
case 'sra':
|
|
88
|
-
case 'sll':
|
|
89
|
-
case 'sls':
|
|
90
|
-
case 'srl':
|
|
91
|
-
return encodeRotateShift(instruction.mnemonic, instruction.operand, instruction.destination);
|
|
92
|
-
case 'add':
|
|
93
|
-
case 'adc':
|
|
94
|
-
if ('target' in instruction) {
|
|
95
|
-
return encode16BitAlu(instruction.mnemonic, instruction.target.register, instruction.source.register);
|
|
96
|
-
}
|
|
97
|
-
return encodeAlu(instruction.mnemonic, instruction.source);
|
|
98
|
-
case 'sub':
|
|
99
|
-
case 'sbc':
|
|
100
|
-
if ('target' in instruction) {
|
|
101
|
-
return encode16BitAlu(instruction.mnemonic, instruction.target.register, instruction.source.register);
|
|
102
|
-
}
|
|
103
|
-
return encodeAlu(instruction.mnemonic, instruction.source);
|
|
104
|
-
case 'and':
|
|
105
|
-
case 'or':
|
|
106
|
-
case 'xor':
|
|
107
|
-
case 'cp':
|
|
108
|
-
return encodeAlu(instruction.mnemonic, instruction.source);
|
|
109
|
-
case 'jp':
|
|
110
|
-
return absoluteTarget(0xc3, instruction.expression);
|
|
111
|
-
case 'jp-cc':
|
|
112
|
-
return absoluteTarget(jpConditionOpcode(instruction.condition), instruction.expression);
|
|
113
|
-
case 'jp-indirect':
|
|
114
|
-
return jumpIndirect(instruction.register);
|
|
115
|
-
case 'call':
|
|
116
|
-
return absoluteTarget(0xcd, instruction.expression);
|
|
117
|
-
case 'call-cc':
|
|
118
|
-
return absoluteTarget(callConditionOpcode(instruction.condition), instruction.expression);
|
|
119
|
-
case 'jr':
|
|
120
|
-
return relativeTarget(0x18, 'jr', instruction.expression);
|
|
121
|
-
case 'jr-cc':
|
|
122
|
-
return relativeTarget(jrConditionOpcode(instruction.condition), `jr ${instruction.condition}`, instruction.expression);
|
|
123
|
-
case 'djnz':
|
|
124
|
-
return relativeTarget(0x10, 'djnz', instruction.expression);
|
|
95
|
+
return Z80_ENCODERS[instruction.mnemonic](instruction);
|
|
96
|
+
}
|
|
97
|
+
function encodeRetConditionInstruction(instruction) {
|
|
98
|
+
const ret = instruction;
|
|
99
|
+
return oneByteInstruction(retConditionOpcode(ret.condition));
|
|
100
|
+
}
|
|
101
|
+
function encodeCoreInstruction(instruction) {
|
|
102
|
+
return encodeCore(instruction.mnemonic);
|
|
103
|
+
}
|
|
104
|
+
function encodeExchangeInstruction(instruction) {
|
|
105
|
+
const exchange = instruction;
|
|
106
|
+
return encodeExchange(exchange.form);
|
|
107
|
+
}
|
|
108
|
+
function encodeInterruptModeInstruction(instruction) {
|
|
109
|
+
const im = instruction;
|
|
110
|
+
return { size: 2, fragments: [{ kind: 'bytes', bytes: [0xed, imOpcode(im.mode)] }] };
|
|
111
|
+
}
|
|
112
|
+
function encodeRstInstruction(instruction) {
|
|
113
|
+
const rst = instruction;
|
|
114
|
+
return oneByteInstruction(rstOpcode(rst.vector));
|
|
115
|
+
}
|
|
116
|
+
function encodeIncDecInstruction(instruction) {
|
|
117
|
+
const incDec = instruction;
|
|
118
|
+
return encodeIncDec(incDec.mnemonic, incDec.operand);
|
|
119
|
+
}
|
|
120
|
+
function encodeStackInstruction(instruction) {
|
|
121
|
+
const stack = instruction;
|
|
122
|
+
return encodeStack(stack.mnemonic, stack.register);
|
|
123
|
+
}
|
|
124
|
+
function encodeLdAImmediateInstruction(instruction) {
|
|
125
|
+
const ldA = instruction;
|
|
126
|
+
return {
|
|
127
|
+
size: 2,
|
|
128
|
+
fragments: [
|
|
129
|
+
{ kind: 'bytes', bytes: [0x3e] },
|
|
130
|
+
{ kind: 'imm8', expression: ldA.expression },
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function encodeLdInstruction(instruction) {
|
|
135
|
+
const ld = instruction;
|
|
136
|
+
return encodeLd(ld.target, ld.source);
|
|
137
|
+
}
|
|
138
|
+
function encodeInInstruction(instruction) {
|
|
139
|
+
const input = instruction;
|
|
140
|
+
return encodeIn(input.target, input.port);
|
|
141
|
+
}
|
|
142
|
+
function encodeOutInstruction(instruction) {
|
|
143
|
+
const output = instruction;
|
|
144
|
+
return encodeOut(output.port, output.source);
|
|
145
|
+
}
|
|
146
|
+
function encodeBitLikeInstruction(instruction) {
|
|
147
|
+
const bitLike = instruction;
|
|
148
|
+
return encodeBitLike(bitLike.mnemonic, bitLike.bit, bitLike.operand, bitLike.destination);
|
|
149
|
+
}
|
|
150
|
+
function encodeRotateShiftInstruction(instruction) {
|
|
151
|
+
const rotateShift = instruction;
|
|
152
|
+
return encodeRotateShift(rotateShift.mnemonic, rotateShift.operand, rotateShift.destination);
|
|
153
|
+
}
|
|
154
|
+
function encodeAluInstruction(instruction) {
|
|
155
|
+
const alu = instruction;
|
|
156
|
+
if ('target' in alu) {
|
|
157
|
+
return encode16BitAlu(alu.mnemonic, alu.target.register, alu.source.register);
|
|
125
158
|
}
|
|
159
|
+
return encodeAlu(alu.mnemonic, alu.source);
|
|
160
|
+
}
|
|
161
|
+
function encodeJumpInstruction(instruction) {
|
|
162
|
+
const jump = instruction;
|
|
163
|
+
return absoluteTarget(0xc3, jump.expression);
|
|
164
|
+
}
|
|
165
|
+
function encodeConditionalJumpInstruction(instruction) {
|
|
166
|
+
const jump = instruction;
|
|
167
|
+
return absoluteTarget(jpConditionOpcode(jump.condition), jump.expression);
|
|
168
|
+
}
|
|
169
|
+
function encodeIndirectJumpInstruction(instruction) {
|
|
170
|
+
const jump = instruction;
|
|
171
|
+
return jumpIndirect(jump.register);
|
|
172
|
+
}
|
|
173
|
+
function encodeCallInstruction(instruction) {
|
|
174
|
+
const call = instruction;
|
|
175
|
+
return absoluteTarget(0xcd, call.expression);
|
|
176
|
+
}
|
|
177
|
+
function encodeConditionalCallInstruction(instruction) {
|
|
178
|
+
const call = instruction;
|
|
179
|
+
return absoluteTarget(callConditionOpcode(call.condition), call.expression);
|
|
180
|
+
}
|
|
181
|
+
function encodeRelativeJumpInstruction(instruction) {
|
|
182
|
+
const jump = instruction;
|
|
183
|
+
return relativeTarget(0x18, 'jr', jump.expression);
|
|
184
|
+
}
|
|
185
|
+
function encodeConditionalRelativeJumpInstruction(instruction) {
|
|
186
|
+
const jump = instruction;
|
|
187
|
+
return relativeTarget(jrConditionOpcode(jump.condition), `jr ${jump.condition}`, jump.expression);
|
|
188
|
+
}
|
|
189
|
+
function encodeDjnzInstruction(instruction) {
|
|
190
|
+
const djnz = instruction;
|
|
191
|
+
return relativeTarget(0x10, 'djnz', djnz.expression);
|
|
126
192
|
}
|
|
127
193
|
function encodeExchange(form) {
|
|
128
194
|
switch (form) {
|
|
@@ -138,83 +204,6 @@ function encodeExchange(form) {
|
|
|
138
204
|
return { size: 2, fragments: [{ kind: 'bytes', bytes: [0xfd, 0xe3] }] };
|
|
139
205
|
}
|
|
140
206
|
}
|
|
141
|
-
function encodeCore(mnemonic) {
|
|
142
|
-
const opcode = coreOpcode(mnemonic);
|
|
143
|
-
return {
|
|
144
|
-
size: opcode.length,
|
|
145
|
-
fragments: [{ kind: 'bytes', bytes: opcode }],
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
function coreOpcode(mnemonic) {
|
|
149
|
-
switch (mnemonic) {
|
|
150
|
-
case 'di':
|
|
151
|
-
return [0xf3];
|
|
152
|
-
case 'ei':
|
|
153
|
-
return [0xfb];
|
|
154
|
-
case 'scf':
|
|
155
|
-
return [0x37];
|
|
156
|
-
case 'ccf':
|
|
157
|
-
return [0x3f];
|
|
158
|
-
case 'cpl':
|
|
159
|
-
return [0x2f];
|
|
160
|
-
case 'daa':
|
|
161
|
-
return [0x27];
|
|
162
|
-
case 'exx':
|
|
163
|
-
return [0xd9];
|
|
164
|
-
case 'halt':
|
|
165
|
-
return [0x76];
|
|
166
|
-
case 'rlca':
|
|
167
|
-
return [0x07];
|
|
168
|
-
case 'rrca':
|
|
169
|
-
return [0x0f];
|
|
170
|
-
case 'rla':
|
|
171
|
-
return [0x17];
|
|
172
|
-
case 'rra':
|
|
173
|
-
return [0x1f];
|
|
174
|
-
case 'neg':
|
|
175
|
-
return [0xed, 0x44];
|
|
176
|
-
case 'rrd':
|
|
177
|
-
return [0xed, 0x67];
|
|
178
|
-
case 'rld':
|
|
179
|
-
return [0xed, 0x6f];
|
|
180
|
-
case 'ldi':
|
|
181
|
-
return [0xed, 0xa0];
|
|
182
|
-
case 'ldir':
|
|
183
|
-
return [0xed, 0xb0];
|
|
184
|
-
case 'ldd':
|
|
185
|
-
return [0xed, 0xa8];
|
|
186
|
-
case 'lddr':
|
|
187
|
-
return [0xed, 0xb8];
|
|
188
|
-
case 'cpi':
|
|
189
|
-
return [0xed, 0xa1];
|
|
190
|
-
case 'cpir':
|
|
191
|
-
return [0xed, 0xb1];
|
|
192
|
-
case 'cpd':
|
|
193
|
-
return [0xed, 0xa9];
|
|
194
|
-
case 'cpdr':
|
|
195
|
-
return [0xed, 0xb9];
|
|
196
|
-
case 'ini':
|
|
197
|
-
return [0xed, 0xa2];
|
|
198
|
-
case 'inir':
|
|
199
|
-
return [0xed, 0xb2];
|
|
200
|
-
case 'ind':
|
|
201
|
-
return [0xed, 0xaa];
|
|
202
|
-
case 'indr':
|
|
203
|
-
return [0xed, 0xba];
|
|
204
|
-
case 'outi':
|
|
205
|
-
return [0xed, 0xa3];
|
|
206
|
-
case 'otir':
|
|
207
|
-
return [0xed, 0xb3];
|
|
208
|
-
case 'outd':
|
|
209
|
-
return [0xed, 0xab];
|
|
210
|
-
case 'otdr':
|
|
211
|
-
return [0xed, 0xbb];
|
|
212
|
-
case 'reti':
|
|
213
|
-
return [0xed, 0x4d];
|
|
214
|
-
case 'retn':
|
|
215
|
-
return [0xed, 0x45];
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
207
|
function encodeIn(target, port) {
|
|
219
208
|
if (port.kind === 'c') {
|
|
220
209
|
const opcode = target ? 0x40 + register8Code(target.register) * 8 : 0x70;
|
|
@@ -398,25 +387,7 @@ function bitLikeOpcodeBase(mnemonic) {
|
|
|
398
387
|
}
|
|
399
388
|
}
|
|
400
389
|
function rotateShiftOpcodeBase(mnemonic) {
|
|
401
|
-
|
|
402
|
-
case 'rlc':
|
|
403
|
-
return 0x00;
|
|
404
|
-
case 'rrc':
|
|
405
|
-
return 0x08;
|
|
406
|
-
case 'rl':
|
|
407
|
-
return 0x10;
|
|
408
|
-
case 'rr':
|
|
409
|
-
return 0x18;
|
|
410
|
-
case 'sla':
|
|
411
|
-
return 0x20;
|
|
412
|
-
case 'sra':
|
|
413
|
-
return 0x28;
|
|
414
|
-
case 'sll':
|
|
415
|
-
case 'sls':
|
|
416
|
-
return 0x30;
|
|
417
|
-
case 'srl':
|
|
418
|
-
return 0x38;
|
|
419
|
-
}
|
|
390
|
+
return ROTATE_SHIFT_OPCODE_BASES[mnemonic];
|
|
420
391
|
}
|
|
421
392
|
function cbOperandCode(operand) {
|
|
422
393
|
return operand.kind === 'reg8' ? register8Code(operand.register) : 0x06;
|
|
@@ -550,284 +521,9 @@ function aluOpcodes(mnemonic) {
|
|
|
550
521
|
return { registerBase: 0xb8, immediate: 0xfe, memHl: 0xbe };
|
|
551
522
|
}
|
|
552
523
|
}
|
|
553
|
-
const LD_UNSUPPORTED_FORM_MESSAGE = 'ld expects a supported register/memory/immediate transfer form';
|
|
554
|
-
function encodeLd(target, source) {
|
|
555
|
-
const legacyReg16Pair = encodeLegacyReg16ByteTransferLd(target, source);
|
|
556
|
-
if (legacyReg16Pair) {
|
|
557
|
-
return legacyReg16Pair;
|
|
558
|
-
}
|
|
559
|
-
const specialRegisterLd = encodeSpecialRegisterLd(target, source);
|
|
560
|
-
if (specialRegisterLd) {
|
|
561
|
-
return specialRegisterLd;
|
|
562
|
-
}
|
|
563
|
-
if (target.kind === 'reg8' && source.kind === 'imm') {
|
|
564
|
-
return {
|
|
565
|
-
size: 2,
|
|
566
|
-
fragments: [
|
|
567
|
-
{ kind: 'bytes', bytes: [0x06 + register8Code(target.register) * 8] },
|
|
568
|
-
{
|
|
569
|
-
kind: 'imm8',
|
|
570
|
-
expression: source.expression,
|
|
571
|
-
failureMessage: LD_UNSUPPORTED_FORM_MESSAGE,
|
|
572
|
-
},
|
|
573
|
-
],
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
if (target.kind === 'reg8' && source.kind === 'reg8') {
|
|
577
|
-
return {
|
|
578
|
-
size: 1,
|
|
579
|
-
fragments: [
|
|
580
|
-
{
|
|
581
|
-
kind: 'bytes',
|
|
582
|
-
bytes: [0x40 + register8Code(target.register) * 8 + register8Code(source.register)],
|
|
583
|
-
},
|
|
584
|
-
],
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
if (target.kind === 'reg8' && target.register === 'a' && source.kind === 'mem-abs') {
|
|
588
|
-
return absoluteLd(0x3a, source.expression);
|
|
589
|
-
}
|
|
590
|
-
if (target.kind === 'mem-abs' && source.kind === 'reg8' && source.register === 'a') {
|
|
591
|
-
return absoluteLd(0x32, target.expression);
|
|
592
|
-
}
|
|
593
|
-
if ((target.kind === 'reg8' || target.kind === 'reg-half-index') &&
|
|
594
|
-
(source.kind === 'reg8' || source.kind === 'reg-half-index') &&
|
|
595
|
-
isEncodableHalfIndexLd(target, source)) {
|
|
596
|
-
const prefix = halfIndexPrefix(target, source);
|
|
597
|
-
return {
|
|
598
|
-
size: 2,
|
|
599
|
-
fragments: [
|
|
600
|
-
{
|
|
601
|
-
kind: 'bytes',
|
|
602
|
-
bytes: [prefix, 0x40 + byteRegisterCode(target) * 8 + byteRegisterCode(source)],
|
|
603
|
-
},
|
|
604
|
-
],
|
|
605
|
-
};
|
|
606
|
-
}
|
|
607
|
-
if (target.kind === 'reg16' && source.kind === 'imm') {
|
|
608
|
-
return {
|
|
609
|
-
size: 3,
|
|
610
|
-
fragments: [
|
|
611
|
-
{ kind: 'bytes', bytes: [0x01 + register16Code(target.register) * 0x10] },
|
|
612
|
-
{ kind: 'abs16', expression: source.expression },
|
|
613
|
-
],
|
|
614
|
-
};
|
|
615
|
-
}
|
|
616
|
-
if (target.kind === 'reg-index16' && source.kind === 'imm') {
|
|
617
|
-
return {
|
|
618
|
-
size: 4,
|
|
619
|
-
fragments: [
|
|
620
|
-
{ kind: 'bytes', bytes: [indexPrefix(target.register), 0x21] },
|
|
621
|
-
{ kind: 'abs16', expression: source.expression },
|
|
622
|
-
],
|
|
623
|
-
};
|
|
624
|
-
}
|
|
625
|
-
if (target.kind === 'reg16' &&
|
|
626
|
-
target.register === 'sp' &&
|
|
627
|
-
((source.kind === 'reg16' && source.register === 'hl') || source.kind === 'reg-index16')) {
|
|
628
|
-
return {
|
|
629
|
-
size: source.kind === 'reg-index16' ? 2 : 1,
|
|
630
|
-
fragments: [{ kind: 'bytes', bytes: loadSpOpcode(source.register) }],
|
|
631
|
-
};
|
|
632
|
-
}
|
|
633
|
-
if (target.kind === 'reg16' && source.kind === 'mem-abs') {
|
|
634
|
-
return absoluteRegister16Load(target.register, source.expression);
|
|
635
|
-
}
|
|
636
|
-
if (target.kind === 'reg-index16' && source.kind === 'mem-abs') {
|
|
637
|
-
return prefixedAbsoluteLd(indexPrefix(target.register), 0x2a, source.expression);
|
|
638
|
-
}
|
|
639
|
-
if (target.kind === 'mem-abs' && source.kind === 'reg16') {
|
|
640
|
-
return absoluteRegister16Store(source.register, target.expression);
|
|
641
|
-
}
|
|
642
|
-
if (target.kind === 'mem-abs' && source.kind === 'reg-index16') {
|
|
643
|
-
return prefixedAbsoluteLd(indexPrefix(source.register), 0x22, target.expression);
|
|
644
|
-
}
|
|
645
|
-
if (target.kind === 'reg8' && target.register === 'a' && source.kind === 'reg-indirect') {
|
|
646
|
-
return {
|
|
647
|
-
size: 1,
|
|
648
|
-
fragments: [{ kind: 'bytes', bytes: [loadAFromIndirectOpcode(source.register)] }],
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
if (target.kind === 'reg-indirect' && source.kind === 'reg8' && source.register === 'a') {
|
|
652
|
-
return {
|
|
653
|
-
size: 1,
|
|
654
|
-
fragments: [{ kind: 'bytes', bytes: [storeAToIndirectOpcode(target.register)] }],
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
if (target.kind === 'reg-indirect' && target.register === 'hl' && source.kind === 'reg8') {
|
|
658
|
-
return {
|
|
659
|
-
size: 1,
|
|
660
|
-
fragments: [{ kind: 'bytes', bytes: [0x70 + register8Code(source.register)] }],
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
if (target.kind === 'reg-indirect' && target.register === 'hl' && source.kind === 'imm') {
|
|
664
|
-
return {
|
|
665
|
-
size: 2,
|
|
666
|
-
fragments: [
|
|
667
|
-
{ kind: 'bytes', bytes: [0x36] },
|
|
668
|
-
{
|
|
669
|
-
kind: 'imm8',
|
|
670
|
-
expression: source.expression,
|
|
671
|
-
failureMessage: LD_UNSUPPORTED_FORM_MESSAGE,
|
|
672
|
-
},
|
|
673
|
-
],
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
|
-
if (target.kind === 'reg8' && source.kind === 'reg-indirect' && source.register === 'hl') {
|
|
677
|
-
return {
|
|
678
|
-
size: 1,
|
|
679
|
-
fragments: [{ kind: 'bytes', bytes: [0x46 + register8Code(target.register) * 8] }],
|
|
680
|
-
};
|
|
681
|
-
}
|
|
682
|
-
if (target.kind === 'reg8' && source.kind === 'indexed') {
|
|
683
|
-
return {
|
|
684
|
-
size: 3,
|
|
685
|
-
fragments: [
|
|
686
|
-
{
|
|
687
|
-
kind: 'bytes',
|
|
688
|
-
bytes: [indexPrefix(source.register), 0x46 + register8Code(target.register) * 8],
|
|
689
|
-
},
|
|
690
|
-
{
|
|
691
|
-
kind: 'disp8',
|
|
692
|
-
expression: source.displacement,
|
|
693
|
-
message: 'ld (ix/iy+disp) expects disp8',
|
|
694
|
-
},
|
|
695
|
-
],
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
if (target.kind === 'indexed' && source.kind === 'reg8') {
|
|
699
|
-
return {
|
|
700
|
-
size: 3,
|
|
701
|
-
fragments: [
|
|
702
|
-
{
|
|
703
|
-
kind: 'bytes',
|
|
704
|
-
bytes: [indexPrefix(target.register), 0x70 + register8Code(source.register)],
|
|
705
|
-
},
|
|
706
|
-
{
|
|
707
|
-
kind: 'disp8',
|
|
708
|
-
expression: target.displacement,
|
|
709
|
-
message: 'ld (ix/iy+disp) expects disp8',
|
|
710
|
-
},
|
|
711
|
-
],
|
|
712
|
-
};
|
|
713
|
-
}
|
|
714
|
-
if (target.kind === 'indexed' && source.kind === 'imm') {
|
|
715
|
-
return {
|
|
716
|
-
size: 4,
|
|
717
|
-
fragments: [
|
|
718
|
-
{ kind: 'bytes', bytes: [indexPrefix(target.register), 0x36] },
|
|
719
|
-
{
|
|
720
|
-
kind: 'disp8',
|
|
721
|
-
expression: target.displacement,
|
|
722
|
-
message: 'ld (ix/iy+disp), n expects disp8',
|
|
723
|
-
},
|
|
724
|
-
{
|
|
725
|
-
kind: 'imm8',
|
|
726
|
-
expression: source.expression,
|
|
727
|
-
failureMessage: LD_UNSUPPORTED_FORM_MESSAGE,
|
|
728
|
-
},
|
|
729
|
-
],
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
return {
|
|
733
|
-
size: 0,
|
|
734
|
-
fragments: [],
|
|
735
|
-
};
|
|
736
|
-
}
|
|
737
|
-
function encodeLegacyReg16ByteTransferLd(target, source) {
|
|
738
|
-
if (target.kind !== 'reg16' || source.kind !== 'reg16') {
|
|
739
|
-
return undefined;
|
|
740
|
-
}
|
|
741
|
-
const transfers = legacyReg16ByteTransferOpcodes(target.register, source.register);
|
|
742
|
-
if (!transfers) {
|
|
743
|
-
return undefined;
|
|
744
|
-
}
|
|
745
|
-
return {
|
|
746
|
-
size: transfers.length,
|
|
747
|
-
fragments: [{ kind: 'bytes', bytes: transfers }],
|
|
748
|
-
};
|
|
749
|
-
}
|
|
750
|
-
function legacyReg16ByteTransferOpcodes(target, source) {
|
|
751
|
-
if (target === 'hl' && source === 'de') {
|
|
752
|
-
return [0x62, 0x6b];
|
|
753
|
-
}
|
|
754
|
-
if (target === 'bc' && source === 'de') {
|
|
755
|
-
return [0x42, 0x4b];
|
|
756
|
-
}
|
|
757
|
-
return undefined;
|
|
758
|
-
}
|
|
759
|
-
function encodeSpecialRegisterLd(target, source) {
|
|
760
|
-
if (target.kind === 'special8' && source.kind === 'reg8' && source.register === 'a') {
|
|
761
|
-
return {
|
|
762
|
-
size: 2,
|
|
763
|
-
fragments: [{ kind: 'bytes', bytes: [0xed, target.register === 'i' ? 0x47 : 0x4f] }],
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
if (target.kind === 'reg8' && target.register === 'a' && source.kind === 'special8') {
|
|
767
|
-
return {
|
|
768
|
-
size: 2,
|
|
769
|
-
fragments: [{ kind: 'bytes', bytes: [0xed, source.register === 'i' ? 0x57 : 0x5f] }],
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
return undefined;
|
|
773
|
-
}
|
|
774
|
-
function absoluteLd(opcode, expression) {
|
|
775
|
-
return {
|
|
776
|
-
size: 3,
|
|
777
|
-
fragments: [
|
|
778
|
-
{ kind: 'bytes', bytes: [opcode] },
|
|
779
|
-
{ kind: 'abs16', expression },
|
|
780
|
-
],
|
|
781
|
-
};
|
|
782
|
-
}
|
|
783
|
-
function prefixedAbsoluteLd(prefix, opcode, expression) {
|
|
784
|
-
return {
|
|
785
|
-
size: 4,
|
|
786
|
-
fragments: [
|
|
787
|
-
{ kind: 'bytes', bytes: [prefix, opcode] },
|
|
788
|
-
{ kind: 'abs16', expression },
|
|
789
|
-
],
|
|
790
|
-
};
|
|
791
|
-
}
|
|
792
|
-
function absoluteRegister16Load(register, expression) {
|
|
793
|
-
switch (register) {
|
|
794
|
-
case 'hl':
|
|
795
|
-
return absoluteLd(0x2a, expression);
|
|
796
|
-
case 'bc':
|
|
797
|
-
return prefixedAbsoluteLd(0xed, 0x4b, expression);
|
|
798
|
-
case 'de':
|
|
799
|
-
return prefixedAbsoluteLd(0xed, 0x5b, expression);
|
|
800
|
-
case 'sp':
|
|
801
|
-
return prefixedAbsoluteLd(0xed, 0x7b, expression);
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
function absoluteRegister16Store(register, expression) {
|
|
805
|
-
switch (register) {
|
|
806
|
-
case 'hl':
|
|
807
|
-
return absoluteLd(0x22, expression);
|
|
808
|
-
case 'bc':
|
|
809
|
-
return prefixedAbsoluteLd(0xed, 0x43, expression);
|
|
810
|
-
case 'de':
|
|
811
|
-
return prefixedAbsoluteLd(0xed, 0x53, expression);
|
|
812
|
-
case 'sp':
|
|
813
|
-
return prefixedAbsoluteLd(0xed, 0x73, expression);
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
524
|
function indexPrefix(register) {
|
|
817
525
|
return register === 'ix' ? 0xdd : 0xfd;
|
|
818
526
|
}
|
|
819
|
-
function loadSpOpcode(register) {
|
|
820
|
-
switch (register) {
|
|
821
|
-
case 'hl':
|
|
822
|
-
return [0xf9];
|
|
823
|
-
case 'ix':
|
|
824
|
-
return [0xdd, 0xf9];
|
|
825
|
-
case 'iy':
|
|
826
|
-
return [0xfd, 0xf9];
|
|
827
|
-
default:
|
|
828
|
-
throw new Error(`unsupported LD SP source register: ${register}`);
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
527
|
function halfIndexPrefix(target, source) {
|
|
832
528
|
const register = target.kind === 'reg-half-index'
|
|
833
529
|
? target.register
|
|
@@ -839,34 +535,6 @@ function halfIndexPrefix(target, source) {
|
|
|
839
535
|
}
|
|
840
536
|
return register.startsWith('ix') ? 0xdd : 0xfd;
|
|
841
537
|
}
|
|
842
|
-
function isEncodableHalfIndexLd(target, source) {
|
|
843
|
-
if (target.kind !== 'reg-half-index' && source.kind !== 'reg-half-index') {
|
|
844
|
-
return false;
|
|
845
|
-
}
|
|
846
|
-
return (isSameHalfIndexFamily(target, source) &&
|
|
847
|
-
isHalfIndexCompatibleByteOperand(target) &&
|
|
848
|
-
isHalfIndexCompatibleByteOperand(source));
|
|
849
|
-
}
|
|
850
|
-
function isSameHalfIndexFamily(target, source) {
|
|
851
|
-
const targetFamily = halfIndexFamily(target);
|
|
852
|
-
const sourceFamily = halfIndexFamily(source);
|
|
853
|
-
return !targetFamily || !sourceFamily || targetFamily === sourceFamily;
|
|
854
|
-
}
|
|
855
|
-
function halfIndexFamily(operand) {
|
|
856
|
-
if (operand.kind !== 'reg-half-index') {
|
|
857
|
-
return undefined;
|
|
858
|
-
}
|
|
859
|
-
return operand.register.startsWith('ix') ? 'ix' : 'iy';
|
|
860
|
-
}
|
|
861
|
-
function isHalfIndexCompatibleByteOperand(operand) {
|
|
862
|
-
return (operand.kind === 'reg-half-index' ||
|
|
863
|
-
(operand.kind === 'reg8' && operand.register !== 'h' && operand.register !== 'l'));
|
|
864
|
-
}
|
|
865
|
-
function byteRegisterCode(operand) {
|
|
866
|
-
return operand.kind === 'reg8'
|
|
867
|
-
? register8Code(operand.register)
|
|
868
|
-
: halfIndexRegisterCode(operand.register);
|
|
869
|
-
}
|
|
870
538
|
function halfIndexRegisterCode(register) {
|
|
871
539
|
switch (register) {
|
|
872
540
|
case 'ixh':
|
|
@@ -907,26 +575,6 @@ function register16Code(register) {
|
|
|
907
575
|
return 3;
|
|
908
576
|
}
|
|
909
577
|
}
|
|
910
|
-
function loadAFromIndirectOpcode(register) {
|
|
911
|
-
switch (register) {
|
|
912
|
-
case 'bc':
|
|
913
|
-
return 0x0a;
|
|
914
|
-
case 'de':
|
|
915
|
-
return 0x1a;
|
|
916
|
-
case 'hl':
|
|
917
|
-
return 0x7e;
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
function storeAToIndirectOpcode(register) {
|
|
921
|
-
switch (register) {
|
|
922
|
-
case 'bc':
|
|
923
|
-
return 0x02;
|
|
924
|
-
case 'de':
|
|
925
|
-
return 0x12;
|
|
926
|
-
case 'hl':
|
|
927
|
-
return 0x77;
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
578
|
function absoluteTarget(opcode, expression) {
|
|
931
579
|
return {
|
|
932
580
|
size: 3,
|