@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.
Files changed (235) hide show
  1. package/README.md +170 -69
  2. package/dist/src/api-artifacts.d.ts +20 -0
  3. package/dist/src/api-artifacts.js +165 -0
  4. package/dist/src/api-compile.d.ts +8 -2
  5. package/dist/src/api-compile.js +31 -230
  6. package/dist/src/api-register-contracts.d.ts +9 -0
  7. package/dist/src/api-register-contracts.js +77 -0
  8. package/dist/src/api-tooling.d.ts +2 -2
  9. package/dist/src/api-tooling.js +1 -1
  10. package/dist/src/assembly/address-planning.d.ts +1 -2
  11. package/dist/src/assembly/address-planning.js +119 -218
  12. package/dist/src/assembly/address-symbols.d.ts +12 -0
  13. package/dist/src/assembly/address-symbols.js +118 -0
  14. package/dist/src/assembly/fixup-emission.js +30 -48
  15. package/dist/src/assembly/program-emission.js +163 -164
  16. package/dist/src/cli/artifact-files.d.ts +15 -0
  17. package/dist/src/cli/artifact-files.js +86 -0
  18. package/dist/src/cli/parse-args.d.ts +6 -5
  19. package/dist/src/cli/parse-args.js +162 -136
  20. package/dist/src/cli/run.js +4 -1
  21. package/dist/src/cli/usage.d.ts +1 -0
  22. package/dist/src/cli/usage.js +33 -0
  23. package/dist/src/cli/write-artifacts.js +18 -91
  24. package/dist/src/core/compile.js +51 -274
  25. package/dist/src/core/conditional-assembly.d.ts +6 -0
  26. package/dist/src/core/conditional-assembly.js +181 -0
  27. package/dist/src/expansion/op-constant-expression.d.ts +3 -0
  28. package/dist/src/expansion/op-constant-expression.js +52 -0
  29. package/dist/src/expansion/op-expand-selected.d.ts +5 -0
  30. package/dist/src/expansion/op-expand-selected.js +143 -0
  31. package/dist/src/expansion/op-expansion.d.ts +5 -53
  32. package/dist/src/expansion/op-expansion.js +85 -815
  33. package/dist/src/expansion/op-instruction-instantiation.d.ts +3 -0
  34. package/dist/src/expansion/op-instruction-instantiation.js +194 -0
  35. package/dist/src/expansion/op-local-labels.d.ts +8 -0
  36. package/dist/src/expansion/op-local-labels.js +166 -0
  37. package/dist/src/expansion/op-operand-splitting.d.ts +1 -0
  38. package/dist/src/expansion/op-operand-splitting.js +44 -0
  39. package/dist/src/expansion/op-operands.d.ts +53 -0
  40. package/dist/src/expansion/op-operands.js +66 -0
  41. package/dist/src/expansion/op-selection.d.ts +18 -0
  42. package/dist/src/expansion/op-selection.js +172 -0
  43. package/dist/src/index.d.ts +2 -1
  44. package/dist/src/index.js +1 -1
  45. package/dist/src/model/diagnostic.d.ts +4 -0
  46. package/dist/src/model/diagnostic.js +4 -0
  47. package/dist/src/outputs/asm80-expression-evaluation.d.ts +10 -0
  48. package/dist/src/outputs/asm80-expression-evaluation.js +75 -0
  49. package/dist/src/outputs/asm80-expressions.d.ts +5 -0
  50. package/dist/src/outputs/asm80-expressions.js +47 -0
  51. package/dist/src/outputs/asm80-instruction-operands.d.ts +16 -0
  52. package/dist/src/outputs/asm80-instruction-operands.js +38 -0
  53. package/dist/src/outputs/asm80-instructions.d.ts +5 -0
  54. package/dist/src/outputs/asm80-instructions.js +272 -0
  55. package/dist/src/outputs/asm80-ld-operands.d.ts +10 -0
  56. package/dist/src/outputs/asm80-ld-operands.js +157 -0
  57. package/dist/src/outputs/asm80-strings.d.ts +4 -0
  58. package/dist/src/outputs/asm80-strings.js +14 -0
  59. package/dist/src/outputs/d8-files.d.ts +10 -0
  60. package/dist/src/outputs/d8-files.js +103 -0
  61. package/dist/src/outputs/d8-helpers.d.ts +21 -0
  62. package/dist/src/outputs/d8-helpers.js +136 -0
  63. package/dist/src/outputs/hex.js +26 -18
  64. package/dist/src/outputs/types.d.ts +16 -10
  65. package/dist/src/outputs/write-asm80.js +68 -597
  66. package/dist/src/outputs/write-d8.js +6 -216
  67. package/dist/src/register-contracts/accept-output.d.ts +2 -0
  68. package/dist/src/register-contracts/analyze-helpers.d.ts +29 -0
  69. package/dist/src/register-contracts/analyze-helpers.js +162 -0
  70. package/dist/src/{register-care → register-contracts}/analyze.d.ts +6 -6
  71. package/dist/src/register-contracts/analyze.js +73 -0
  72. package/dist/src/register-contracts/annotate.d.ts +11 -0
  73. package/dist/src/{register-care → register-contracts}/annotate.js +3 -3
  74. package/dist/src/register-contracts/annotations.d.ts +8 -0
  75. package/dist/src/{register-care → register-contracts}/annotations.js +3 -3
  76. package/dist/src/register-contracts/boundaryHints.d.ts +3 -0
  77. package/dist/src/register-contracts/boundaryHints.js +24 -0
  78. package/dist/src/register-contracts/carriers.d.ts +2 -0
  79. package/dist/src/register-contracts/constants.d.ts +4 -0
  80. package/dist/src/register-contracts/constants.js +51 -0
  81. package/dist/src/register-contracts/controlFlow.d.ts +5 -0
  82. package/dist/src/register-contracts/controlFlow.js +55 -0
  83. package/dist/src/register-contracts/fix.d.ts +11 -0
  84. package/dist/src/{register-care → register-contracts}/fix.js +47 -30
  85. package/dist/src/register-contracts/instruction-head.d.ts +2 -0
  86. package/dist/src/register-contracts/instruction-head.js +3 -0
  87. package/dist/src/register-contracts/instruction-operands.d.ts +3 -0
  88. package/dist/src/register-contracts/instruction-operands.js +101 -0
  89. package/dist/src/register-contracts/instruction-predicates.d.ts +6 -0
  90. package/dist/src/register-contracts/instruction-predicates.js +44 -0
  91. package/dist/src/register-contracts/interfaceContracts.d.ts +2 -0
  92. package/dist/src/register-contracts/interfaceContracts.js +68 -0
  93. package/dist/src/register-contracts/liveness.d.ts +3 -0
  94. package/dist/src/{register-care → register-contracts}/liveness.js +111 -79
  95. package/dist/src/register-contracts/operand-register-name.d.ts +2 -0
  96. package/dist/src/register-contracts/operand-register-name.js +13 -0
  97. package/dist/src/{register-care → register-contracts}/profiles.d.ts +5 -5
  98. package/dist/src/{register-care → register-contracts}/profiles.js +2 -2
  99. package/dist/src/register-contracts/programModel-boundaries.d.ts +6 -0
  100. package/dist/src/register-contracts/programModel-boundaries.js +64 -0
  101. package/dist/src/register-contracts/programModel-routines.d.ts +7 -0
  102. package/dist/src/register-contracts/programModel-routines.js +128 -0
  103. package/dist/src/register-contracts/programModel.d.ts +3 -0
  104. package/dist/src/register-contracts/programModel.js +14 -0
  105. package/dist/src/register-contracts/report.d.ts +5 -0
  106. package/dist/src/{register-care → register-contracts}/report.js +34 -17
  107. package/dist/src/register-contracts/routine-summaries.d.ts +6 -0
  108. package/dist/src/{register-care → register-contracts}/routine-summaries.js +11 -1
  109. package/dist/src/register-contracts/smartCommentBlocks.d.ts +5 -0
  110. package/dist/src/register-contracts/smartCommentBlocks.js +30 -0
  111. package/dist/src/register-contracts/smartCommentParsing.d.ts +3 -0
  112. package/dist/src/register-contracts/smartCommentParsing.js +80 -0
  113. package/dist/src/register-contracts/smartComments.d.ts +5 -0
  114. package/dist/src/register-contracts/smartComments.js +92 -0
  115. package/dist/src/register-contracts/summaries.d.ts +12 -0
  116. package/dist/src/{register-care → register-contracts}/summaries.js +7 -7
  117. package/dist/src/register-contracts/summary-boundary.d.ts +2 -0
  118. package/dist/src/register-contracts/summary-boundary.js +40 -0
  119. package/dist/src/register-contracts/summary-contract.d.ts +2 -0
  120. package/dist/src/register-contracts/summary-contract.js +45 -0
  121. package/dist/src/register-contracts/summary-result.d.ts +7 -0
  122. package/dist/src/register-contracts/summary-result.js +122 -0
  123. package/dist/src/register-contracts/summary-state.d.ts +23 -0
  124. package/dist/src/register-contracts/summary-state.js +88 -0
  125. package/dist/src/register-contracts/summary-token-transfer.d.ts +3 -0
  126. package/dist/src/register-contracts/summary-token-transfer.js +67 -0
  127. package/dist/src/register-contracts/summary.d.ts +3 -0
  128. package/dist/src/register-contracts/summary.js +266 -0
  129. package/dist/src/register-contracts/tooling.d.ts +57 -0
  130. package/dist/src/{register-care → register-contracts}/tooling.js +8 -6
  131. package/dist/src/register-contracts/types.d.ts +188 -0
  132. package/dist/src/semantics/binary-operators.d.ts +2 -0
  133. package/dist/src/semantics/binary-operators.js +15 -0
  134. package/dist/src/semantics/byte-functions.d.ts +2 -0
  135. package/dist/src/semantics/byte-functions.js +7 -0
  136. package/dist/src/semantics/constant-operator-types.d.ts +10 -0
  137. package/dist/src/semantics/constant-operator-types.js +1 -0
  138. package/dist/src/semantics/constant-operators.d.ts +3 -0
  139. package/dist/src/semantics/constant-operators.js +3 -0
  140. package/dist/src/semantics/diagnostics.d.ts +3 -0
  141. package/dist/src/semantics/diagnostics.js +10 -0
  142. package/dist/src/semantics/expression-evaluation.d.ts +11 -19
  143. package/dist/src/semantics/expression-evaluation.js +22 -334
  144. package/dist/src/semantics/layout-evaluation.d.ts +23 -0
  145. package/dist/src/semantics/layout-evaluation.js +202 -0
  146. package/dist/src/semantics/layout-format.d.ts +5 -0
  147. package/dist/src/semantics/layout-format.js +31 -0
  148. package/dist/src/semantics/layout-path.d.ts +24 -0
  149. package/dist/src/semantics/layout-path.js +58 -0
  150. package/dist/src/semantics/unary-operators.d.ts +2 -0
  151. package/dist/src/semantics/unary-operators.js +8 -0
  152. package/dist/src/source/line-comment-scanner.d.ts +1 -0
  153. package/dist/src/source/line-comment-scanner.js +51 -0
  154. package/dist/src/source/strip-line-comment.js +8 -44
  155. package/dist/src/syntax/directive-aliases.js +36 -22
  156. package/dist/src/syntax/expression-tokenizer.d.ts +30 -0
  157. package/dist/src/syntax/expression-tokenizer.js +310 -0
  158. package/dist/src/syntax/parse-directive-statement.d.ts +14 -0
  159. package/dist/src/syntax/parse-directive-statement.js +307 -0
  160. package/dist/src/syntax/parse-expression.d.ts +2 -2
  161. package/dist/src/syntax/parse-expression.js +7 -568
  162. package/dist/src/syntax/parse-layout-declarations.d.ts +9 -0
  163. package/dist/src/syntax/parse-layout-declarations.js +180 -0
  164. package/dist/src/syntax/parse-layout-expression.d.ts +5 -0
  165. package/dist/src/syntax/parse-layout-expression.js +175 -0
  166. package/dist/src/syntax/parse-line.js +4 -272
  167. package/dist/src/syntax/parse-token-expression.d.ts +3 -0
  168. package/dist/src/syntax/parse-token-expression.js +133 -0
  169. package/dist/src/tooling/case-style.js +47 -30
  170. package/dist/src/z80/effect-groups.d.ts +38 -0
  171. package/dist/src/z80/effect-groups.js +265 -0
  172. package/dist/src/z80/effect-units.d.ts +18 -0
  173. package/dist/src/z80/effect-units.js +165 -0
  174. package/dist/src/z80/effects.d.ts +1 -1
  175. package/dist/src/z80/effects.js +94 -557
  176. package/dist/src/z80/encode-core.d.ts +2 -0
  177. package/dist/src/z80/encode-core.js +42 -0
  178. package/dist/src/z80/encode-ld-helpers.d.ts +25 -0
  179. package/dist/src/z80/encode-ld-helpers.js +172 -0
  180. package/dist/src/z80/encode-ld.d.ts +2 -0
  181. package/dist/src/z80/encode-ld.js +285 -0
  182. package/dist/src/z80/encode.js +190 -542
  183. package/dist/src/z80/ld-support.d.ts +3 -0
  184. package/dist/src/z80/ld-support.js +146 -0
  185. package/dist/src/z80/operand-split-state.d.ts +8 -0
  186. package/dist/src/z80/operand-split-state.js +46 -0
  187. package/dist/src/z80/operand-split.d.ts +1 -0
  188. package/dist/src/z80/operand-split.js +13 -0
  189. package/dist/src/z80/parse-basic.d.ts +4 -0
  190. package/dist/src/z80/parse-basic.js +39 -0
  191. package/dist/src/z80/parse-branch.d.ts +4 -0
  192. package/dist/src/z80/parse-branch.js +218 -0
  193. package/dist/src/z80/parse-conditions.d.ts +6 -0
  194. package/dist/src/z80/parse-conditions.js +10 -0
  195. package/dist/src/z80/parse-exchange.d.ts +2 -0
  196. package/dist/src/z80/parse-exchange.js +30 -0
  197. package/dist/src/z80/parse-instruction.js +224 -1010
  198. package/dist/src/z80/parse-io-control.d.ts +5 -0
  199. package/dist/src/z80/parse-io-control.js +108 -0
  200. package/dist/src/z80/parse-ld.d.ts +2 -0
  201. package/dist/src/z80/parse-ld.js +83 -0
  202. package/dist/src/z80/parse-operands.d.ts +41 -0
  203. package/dist/src/z80/parse-operands.js +259 -0
  204. package/docs/reference/cli.md +42 -35
  205. package/docs/reference/tooling-api.md +20 -16
  206. package/package.json +1 -1
  207. package/dist/src/register-care/accept-output.d.ts +0 -2
  208. package/dist/src/register-care/analyze.js +0 -166
  209. package/dist/src/register-care/annotate.d.ts +0 -11
  210. package/dist/src/register-care/annotations.d.ts +0 -8
  211. package/dist/src/register-care/boundaryHints.d.ts +0 -3
  212. package/dist/src/register-care/boundaryHints.js +0 -80
  213. package/dist/src/register-care/carriers.d.ts +0 -2
  214. package/dist/src/register-care/controlFlow.d.ts +0 -5
  215. package/dist/src/register-care/controlFlow.js +0 -38
  216. package/dist/src/register-care/fix.d.ts +0 -11
  217. package/dist/src/register-care/instruction-shape.d.ts +0 -11
  218. package/dist/src/register-care/instruction-shape.js +0 -129
  219. package/dist/src/register-care/liveness.d.ts +0 -3
  220. package/dist/src/register-care/programModel.d.ts +0 -3
  221. package/dist/src/register-care/programModel.js +0 -266
  222. package/dist/src/register-care/report.d.ts +0 -5
  223. package/dist/src/register-care/routine-summaries.d.ts +0 -6
  224. package/dist/src/register-care/smartComments.d.ts +0 -5
  225. package/dist/src/register-care/smartComments.js +0 -243
  226. package/dist/src/register-care/summaries.d.ts +0 -12
  227. package/dist/src/register-care/summary.d.ts +0 -3
  228. package/dist/src/register-care/summary.js +0 -474
  229. package/dist/src/register-care/tooling.d.ts +0 -43
  230. package/dist/src/register-care/types.d.ts +0 -172
  231. /package/dist/src/{register-care → register-contracts}/accept-output.js +0 -0
  232. /package/dist/src/{register-care → register-contracts}/carriers.js +0 -0
  233. /package/dist/src/{register-care → register-contracts}/sourceText.d.ts +0 -0
  234. /package/dist/src/{register-care → register-contracts}/sourceText.js +0 -0
  235. /package/dist/src/{register-care → register-contracts}/types.js +0 -0
@@ -1,563 +1,100 @@
1
- const FLAG_WRITES = ['sign', 'zero', 'halfCarry', 'parity', 'carry'];
2
- const INC_DEC_FLAG_WRITES = ['sign', 'zero', 'halfCarry', 'parity'];
3
- const ROTATE_SHIFT_FLAG_WRITES = [
4
- 'sign',
5
- 'zero',
6
- 'halfCarry',
7
- 'parity',
8
- 'carry',
1
+ import { accumulatorRotateEffect, aluEffect, bitEffect, blockTransferEffect, callControl, controlEffect, exEffect, inEffect, incDecEffect, jumpControl, ldEffect, outEffect, popEffect, pushEffect, rotateShiftEffect, rstControl, stackControlEffect, } from './effect-groups.js';
2
+ import { FLAG_WRITES, baseEffect, conditionFlagRead, concatUnique, expressionSymbol, reg16Units, unknownEffect, } from './effect-units.js';
3
+ const BASE_EFFECT_MNEMONICS = ['nop', 'halt', 'di', 'ei', 'im'];
4
+ const STACK_RETURN_MNEMONICS = ['reti', 'retn'];
5
+ const ALU_MNEMONICS = ['add', 'adc', 'sbc', 'sub', 'and', 'or', 'xor', 'cp'];
6
+ const ROTATE_SHIFT_MNEMONICS = [
7
+ 'rlc',
8
+ 'rrc',
9
+ 'rl',
10
+ 'rr',
11
+ 'sla',
12
+ 'sra',
13
+ 'sll',
14
+ 'sls',
15
+ 'srl',
9
16
  ];
10
- const BIT_FLAG_WRITES = ['sign', 'zero', 'halfCarry', 'parity'];
11
- const STACK_POINTER_UNITS = ['SPH', 'SPL'];
12
- const UNKNOWN_UNITS = [
13
- 'A',
14
- 'B',
15
- 'C',
16
- 'D',
17
- 'E',
18
- 'H',
19
- 'L',
20
- 'IXH',
21
- 'IXL',
22
- 'IYH',
23
- 'IYL',
24
- 'SPH',
25
- 'SPL',
26
- 'carry',
27
- 'zero',
28
- 'sign',
29
- 'parity',
30
- 'halfCarry',
17
+ const ACCUMULATOR_ROTATE_MNEMONICS = ['rlca', 'rrca', 'rla', 'rra'];
18
+ const BIT_MNEMONICS = ['bit', 'res', 'set'];
19
+ const BLOCK_TRANSFER_MNEMONICS = [
20
+ 'ldi',
21
+ 'ldir',
22
+ 'ldd',
23
+ 'lddr',
24
+ 'cpi',
25
+ 'cpir',
26
+ 'cpd',
27
+ 'cpdr',
28
+ 'ini',
29
+ 'inir',
30
+ 'ind',
31
+ 'indr',
32
+ 'outi',
33
+ 'otir',
34
+ 'outd',
35
+ 'otdr',
31
36
  ];
32
- function baseEffect() {
33
- return {
34
- reads: [],
35
- writes: [],
36
- stack: { kind: 'none' },
37
- control: { kind: 'fallthrough' },
38
- };
39
- }
40
- function unknownEffect() {
41
- return {
42
- reads: UNKNOWN_UNITS,
43
- writes: UNKNOWN_UNITS,
44
- stack: { kind: 'unknown' },
45
- control: { kind: 'unknown' },
46
- };
47
- }
48
- function appendUnique(out, units) {
49
- for (const unit of units) {
50
- if (!out.includes(unit))
51
- out.push(unit);
52
- }
53
- }
54
- function concatUnique(...groups) {
55
- const out = [];
56
- for (const group of groups)
57
- appendUnique(out, group);
58
- return out;
59
- }
60
- function reg8Units(raw) {
61
- const reg = raw.toLowerCase();
62
- if (reg === 'a')
63
- return ['A'];
64
- if (reg === 'b')
65
- return ['B'];
66
- if (reg === 'c')
67
- return ['C'];
68
- if (reg === 'd')
69
- return ['D'];
70
- if (reg === 'e')
71
- return ['E'];
72
- if (reg === 'h')
73
- return ['H'];
74
- if (reg === 'l')
75
- return ['L'];
76
- return [];
77
- }
78
- function reg16Units(raw) {
79
- const reg = raw.toLowerCase();
80
- if (reg === 'bc')
81
- return ['B', 'C'];
82
- if (reg === 'de')
83
- return ['D', 'E'];
84
- if (reg === 'hl')
85
- return ['H', 'L'];
86
- if (reg === 'sp')
87
- return ['SPH', 'SPL'];
88
- if (reg === 'ix')
89
- return ['IXH', 'IXL'];
90
- if (reg === 'iy')
91
- return ['IYH', 'IYL'];
92
- if (reg === 'af')
93
- return ['A', ...FLAG_WRITES];
94
- return [];
95
- }
96
- function regHalfUnits(raw) {
97
- const reg = raw.toLowerCase();
98
- if (reg === 'ixh')
99
- return ['IXH'];
100
- if (reg === 'ixl')
101
- return ['IXL'];
102
- if (reg === 'iyh')
103
- return ['IYH'];
104
- if (reg === 'iyl')
105
- return ['IYL'];
106
- return [];
107
- }
108
- function expressionSymbol(expression) {
109
- return expression.kind === 'symbol' ? expression.name : undefined;
110
- }
111
- function conditionFlagRead(condition) {
112
- switch (condition) {
113
- case 'z':
114
- case 'nz':
115
- return ['zero'];
116
- case 'c':
117
- case 'nc':
118
- return ['carry'];
119
- case 'm':
120
- case 'p':
121
- return ['sign'];
122
- case 'pe':
123
- case 'po':
124
- return ['parity'];
125
- default:
126
- return [];
127
- }
128
- }
129
- function operandReads(op) {
130
- switch (op.kind) {
131
- case 'reg8':
132
- return reg8Units(op.register);
133
- case 'reg16':
134
- case 'reg-index16':
135
- return reg16Units(op.register);
136
- case 'reg-half-index':
137
- return regHalfUnits(op.register);
138
- case 'special8':
139
- return [];
140
- case 'reg-indirect':
141
- return reg16Units(op.register);
142
- case 'indexed':
143
- return reg16Units(op.register);
144
- case 'mem-abs':
145
- case 'imm':
146
- return [];
147
- default:
148
- return undefined;
149
- }
150
- }
151
- function operandWrites(op) {
152
- switch (op.kind) {
153
- case 'reg8':
154
- return reg8Units(op.register);
155
- case 'reg16':
156
- return reg16Units(op.register);
157
- case 'reg-index16':
158
- return reg16Units(op.register);
159
- case 'reg-half-index':
160
- return regHalfUnits(op.register);
161
- default:
162
- return undefined;
163
- }
164
- }
165
- function callControl(target, conditional) {
166
- return target === undefined
167
- ? { kind: 'call', conditional }
168
- : { kind: 'call', target, conditional };
169
- }
170
- function rstControl(vector) {
171
- return vector === undefined ? { kind: 'rst' } : { kind: 'rst', vector };
172
- }
173
- function jumpControl(target, conditional) {
174
- return target === undefined
175
- ? { kind: 'jump', conditional }
176
- : { kind: 'jump', target, conditional };
177
- }
178
- function controlEffect(control, reads = []) {
179
- return {
180
- ...baseEffect(),
181
- reads,
182
- control,
183
- };
184
- }
185
- function stackControlEffect(control, reads = []) {
186
- return {
187
- ...controlEffect(control, reads),
188
- writes: STACK_POINTER_UNITS,
189
- stack: { kind: 'unknown' },
190
- };
191
- }
192
- function ldEffect(instruction) {
193
- const srcReads = operandReads(instruction.source);
194
- if (srcReads === undefined)
195
- return unknownEffect();
196
- const dstWrites = operandWrites(instruction.target);
197
- if (instruction.target.kind === 'reg8' || instruction.target.kind === 'reg16') {
198
- if (dstWrites === undefined)
199
- return unknownEffect();
200
- return {
201
- ...baseEffect(),
202
- reads: srcReads,
203
- writes: dstWrites,
204
- };
205
- }
206
- if (instruction.target.kind === 'reg-index16' ||
207
- instruction.target.kind === 'reg-half-index') {
208
- if (dstWrites === undefined)
209
- return unknownEffect();
210
- return {
211
- ...baseEffect(),
212
- reads: srcReads,
213
- writes: dstWrites,
214
- };
215
- }
216
- if (instruction.target.kind === 'reg-indirect' || instruction.target.kind === 'indexed') {
217
- const dstReads = operandReads(instruction.target);
218
- if (dstReads === undefined)
219
- return unknownEffect();
220
- return {
221
- ...baseEffect(),
222
- reads: concatUnique(dstReads, srcReads),
223
- };
224
- }
225
- if (instruction.target.kind === 'mem-abs') {
226
- return {
227
- ...baseEffect(),
228
- reads: srcReads,
229
- };
230
- }
231
- return unknownEffect();
232
- }
233
- function incDecEffect(instruction) {
234
- const operand = instruction.operand;
235
- if (operand.kind === 'reg8') {
236
- const units = reg8Units(operand.register);
237
- return {
238
- ...baseEffect(),
239
- reads: units,
240
- writes: concatUnique(units, INC_DEC_FLAG_WRITES),
241
- };
242
- }
243
- if (operand.kind === 'reg16') {
244
- const units = reg16Units(operand.register);
245
- return {
246
- ...baseEffect(),
247
- reads: units,
248
- writes: units,
249
- };
250
- }
251
- if (operand.kind === 'reg-half-index') {
252
- const units = regHalfUnits(operand.register);
253
- return {
254
- ...baseEffect(),
255
- reads: units,
256
- writes: concatUnique(units, INC_DEC_FLAG_WRITES),
257
- };
258
- }
259
- const reads = operandReads(operand);
260
- if (reads === undefined)
261
- return unknownEffect();
262
- return {
263
- ...baseEffect(),
264
- reads,
265
- writes: INC_DEC_FLAG_WRITES,
266
- };
267
- }
268
- function aluEffect(instruction) {
269
- if (instruction.mnemonic === 'add' &&
270
- 'target' in instruction &&
271
- (instruction.target.kind === 'reg16' || instruction.target.kind === 'reg-index16')) {
272
- const targetReads = operandReads(instruction.target);
273
- const sourceReads = operandReads(instruction.source);
274
- if (targetReads === undefined || sourceReads === undefined)
275
- return unknownEffect();
276
- return {
277
- ...baseEffect(),
278
- reads: concatUnique(targetReads, sourceReads),
279
- writes: concatUnique(operandWrites(instruction.target) ?? [], FLAG_WRITES),
280
- };
281
- }
282
- if (instruction.mnemonic === 'adc' &&
283
- 'target' in instruction &&
284
- (instruction.target.kind === 'reg16' || instruction.target.kind === 'reg-index16')) {
285
- const targetReads = operandReads(instruction.target);
286
- const sourceReads = operandReads(instruction.source);
287
- if (targetReads === undefined || sourceReads === undefined)
288
- return unknownEffect();
289
- return {
290
- ...baseEffect(),
291
- reads: concatUnique(targetReads, sourceReads, ['carry']),
292
- writes: concatUnique(operandWrites(instruction.target) ?? [], FLAG_WRITES),
293
- };
294
- }
295
- if (instruction.mnemonic === 'sbc' &&
296
- 'target' in instruction &&
297
- (instruction.target.kind === 'reg16' || instruction.target.kind === 'reg-index16')) {
298
- const targetReads = operandReads(instruction.target);
299
- const sourceReads = operandReads(instruction.source);
300
- if (targetReads === undefined || sourceReads === undefined)
301
- return unknownEffect();
302
- return {
303
- ...baseEffect(),
304
- reads: concatUnique(targetReads, sourceReads, ['carry']),
305
- writes: concatUnique(operandWrites(instruction.target) ?? [], FLAG_WRITES),
306
- };
307
- }
308
- if (!('source' in instruction))
309
- return unknownEffect();
310
- const source = instruction.source;
311
- let sourceReads;
312
- if (source.kind === 'reg8') {
313
- sourceReads = reg8Units(source.register);
314
- }
315
- else if (source.kind === 'reg-indirect' || source.kind === 'indexed') {
316
- sourceReads = operandReads(source) ?? [];
317
- }
318
- else if (source.kind === 'mem-abs' || source.kind === 'imm') {
319
- sourceReads = [];
320
- }
321
- else if (source.kind === 'reg16' || source.kind === 'reg-index16') {
322
- sourceReads = reg16Units(source.register);
323
- }
324
- else if (source.kind === 'reg-half-index') {
325
- sourceReads = regHalfUnits(source.register);
326
- }
327
- else {
328
- sourceReads = [];
329
- }
330
- const xorSelfZero = instruction.mnemonic === 'xor' &&
331
- source.kind === 'reg8' &&
332
- source.register === 'a';
333
- const reads = xorSelfZero ? [] : concatUnique(['A'], sourceReads);
334
- const carryReads = instruction.mnemonic === 'adc' || instruction.mnemonic === 'sbc' ? ['carry'] : [];
335
- if (instruction.mnemonic === 'cp') {
336
- return {
337
- ...baseEffect(),
338
- reads: concatUnique(reads, carryReads),
339
- writes: FLAG_WRITES,
340
- };
341
- }
342
- return {
343
- ...baseEffect(),
344
- reads: concatUnique(reads, carryReads),
345
- writes: concatUnique(['A'], FLAG_WRITES),
346
- };
347
- }
348
- function stackRegisterUnits(register) {
349
- return reg16Units(register);
350
- }
351
- function pushEffect(register) {
352
- const units = stackRegisterUnits(register);
353
- return {
354
- ...baseEffect(),
355
- reads: units,
356
- writes: STACK_POINTER_UNITS,
357
- stack: { kind: 'push', units },
358
- };
359
- }
360
- function popEffect(register) {
361
- const units = stackRegisterUnits(register);
362
- return {
363
- ...baseEffect(),
364
- writes: concatUnique(units, STACK_POINTER_UNITS),
365
- stack: { kind: 'pop', units },
366
- };
367
- }
368
- function rotateShiftEffect(instruction) {
369
- const reads = operandReads(instruction.operand);
370
- const writes = operandWrites(instruction.operand);
371
- if (reads === undefined || writes === undefined)
372
- return unknownEffect();
373
- return {
374
- ...baseEffect(),
375
- reads,
376
- writes: concatUnique(writes, ROTATE_SHIFT_FLAG_WRITES),
377
- };
378
- }
379
- function bitEffect(instruction) {
380
- const reads = operandReads(instruction.operand);
381
- if (reads === undefined)
382
- return unknownEffect();
383
- if (instruction.mnemonic === 'bit') {
384
- return {
385
- ...baseEffect(),
386
- reads,
387
- writes: BIT_FLAG_WRITES,
388
- };
389
- }
390
- const writes = operandWrites(instruction.operand);
391
- if (writes === undefined)
392
- return unknownEffect();
393
- return {
394
- ...baseEffect(),
395
- reads,
396
- writes,
397
- };
398
- }
399
- function inEffect(instruction) {
400
- const targetWrites = instruction.target?.kind === 'reg8' ? reg8Units(instruction.target.register) : undefined;
401
- if (instruction.port.kind === 'imm') {
402
- return {
403
- ...baseEffect(),
404
- reads: ['A'],
405
- writes: targetWrites ?? [],
406
- };
407
- }
408
- return {
409
- ...baseEffect(),
410
- reads: ['C'],
411
- writes: concatUnique(targetWrites ?? [], BIT_FLAG_WRITES),
412
- };
413
- }
414
- function outEffect(instruction) {
415
- const valueReads = instruction.source.kind === 'reg8' ? reg8Units(instruction.source.register) : [];
416
- if (instruction.port.kind === 'c') {
417
- return {
418
- ...baseEffect(),
419
- reads: concatUnique(['C'], valueReads),
420
- };
421
- }
422
- return {
423
- ...baseEffect(),
424
- reads: valueReads,
425
- };
426
- }
427
- function blockTransferEffect() {
428
- return {
429
- ...baseEffect(),
430
- reads: ['H', 'L', 'D', 'E', 'B', 'C'],
431
- writes: ['H', 'L', 'D', 'E', 'B', 'C', 'halfCarry', 'parity'],
432
- };
433
- }
434
- function exEffect(instruction) {
435
- if (instruction.form === 'de-hl') {
436
- return {
437
- ...baseEffect(),
438
- reads: ['D', 'E', 'H', 'L'],
439
- writes: ['D', 'E', 'H', 'L'],
440
- };
441
- }
442
- return unknownEffect();
443
- }
444
- function accumulatorRotateEffect(mnemonic) {
445
- const reads = mnemonic === 'rla' || mnemonic === 'rra' ? ['A', 'carry'] : ['A'];
446
- return {
37
+ const EFFECT_HANDLERS = {
38
+ 'ld-a-imm': () => ({ ...baseEffect(), writes: ['A'] }),
39
+ ld: (instruction) => ldEffect(instruction),
40
+ inc: (instruction) => incDecEffect(instruction),
41
+ dec: (instruction) => incDecEffect(instruction),
42
+ push: (instruction) => pushEffect(instruction.register),
43
+ pop: (instruction) => popEffect(instruction.register),
44
+ call: (instruction) => stackControlEffect(callControl(expressionSymbol(instruction.expression), false)),
45
+ 'call-cc': (instruction) => {
46
+ const call = instruction;
47
+ return stackControlEffect(callControl(expressionSymbol(call.expression), true), conditionFlagRead(call.condition));
48
+ },
49
+ rst: (instruction) => stackControlEffect(rstControl(instruction.vector)),
50
+ ret: () => stackControlEffect({ kind: 'return', conditional: false }),
51
+ 'ret-cc': (instruction) => stackControlEffect({ kind: 'return', conditional: true }, conditionFlagRead(instruction.condition)),
52
+ jp: (instruction) => controlEffect(jumpControl(expressionSymbol(instruction.expression), false)),
53
+ 'jp-cc': (instruction) => {
54
+ const jump = instruction;
55
+ return controlEffect(jumpControl(expressionSymbol(jump.expression), true), conditionFlagRead(jump.condition));
56
+ },
57
+ 'jp-indirect': (instruction) => controlEffect(jumpControl(undefined, false), reg16Units(instruction.register)),
58
+ jr: (instruction) => controlEffect(jumpControl(expressionSymbol(instruction.expression), false)),
59
+ 'jr-cc': (instruction) => {
60
+ const jump = instruction;
61
+ return controlEffect(jumpControl(expressionSymbol(jump.expression), true), conditionFlagRead(jump.condition));
62
+ },
63
+ djnz: (instruction) => ({
447
64
  ...baseEffect(),
448
- reads,
449
- writes: ['A', 'carry', 'halfCarry'],
450
- };
65
+ reads: ['B'],
66
+ writes: ['B'],
67
+ control: jumpControl(expressionSymbol(instruction.expression), true),
68
+ }),
69
+ scf: () => ({ ...baseEffect(), writes: ['carry', 'halfCarry'] }),
70
+ ccf: () => ({ ...baseEffect(), reads: ['carry'], writes: ['carry', 'halfCarry'] }),
71
+ cpl: () => ({ ...baseEffect(), reads: ['A'], writes: ['A', 'halfCarry'] }),
72
+ neg: () => ({ ...baseEffect(), reads: ['A'], writes: concatUnique(['A'], FLAG_WRITES) }),
73
+ out: (instruction) => outEffect(instruction),
74
+ in: (instruction) => inEffect(instruction),
75
+ ex: (instruction) => exEffect(instruction),
76
+ };
77
+ for (const mnemonic of BASE_EFFECT_MNEMONICS) {
78
+ EFFECT_HANDLERS[mnemonic] = () => baseEffect();
79
+ }
80
+ for (const mnemonic of STACK_RETURN_MNEMONICS) {
81
+ EFFECT_HANDLERS[mnemonic] = () => stackControlEffect({ kind: 'return', conditional: false });
82
+ }
83
+ for (const mnemonic of ALU_MNEMONICS) {
84
+ EFFECT_HANDLERS[mnemonic] = (instruction) => aluEffect(instruction);
85
+ }
86
+ for (const mnemonic of ROTATE_SHIFT_MNEMONICS) {
87
+ EFFECT_HANDLERS[mnemonic] = (instruction) => rotateShiftEffect(instruction);
88
+ }
89
+ for (const mnemonic of ACCUMULATOR_ROTATE_MNEMONICS) {
90
+ EFFECT_HANDLERS[mnemonic] = () => accumulatorRotateEffect(mnemonic);
91
+ }
92
+ for (const mnemonic of BIT_MNEMONICS) {
93
+ EFFECT_HANDLERS[mnemonic] = (instruction) => bitEffect(instruction);
94
+ }
95
+ for (const mnemonic of BLOCK_TRANSFER_MNEMONICS) {
96
+ EFFECT_HANDLERS[mnemonic] = () => blockTransferEffect();
451
97
  }
452
98
  export function getZ80InstructionEffect(instruction) {
453
- switch (instruction.mnemonic) {
454
- case 'nop':
455
- case 'halt':
456
- case 'di':
457
- case 'ei':
458
- case 'im':
459
- return baseEffect();
460
- case 'reti':
461
- case 'retn':
462
- return stackControlEffect({ kind: 'return', conditional: false });
463
- case 'ld-a-imm':
464
- return { ...baseEffect(), writes: ['A'] };
465
- case 'ld':
466
- return ldEffect(instruction);
467
- case 'inc':
468
- case 'dec':
469
- return incDecEffect(instruction);
470
- case 'add':
471
- case 'adc':
472
- case 'sbc':
473
- case 'sub':
474
- case 'and':
475
- case 'or':
476
- case 'xor':
477
- case 'cp':
478
- return aluEffect(instruction);
479
- case 'push':
480
- return pushEffect(instruction.register);
481
- case 'pop':
482
- return popEffect(instruction.register);
483
- case 'call':
484
- return stackControlEffect(callControl(expressionSymbol(instruction.expression), false));
485
- case 'call-cc':
486
- return stackControlEffect(callControl(expressionSymbol(instruction.expression), true), conditionFlagRead(instruction.condition));
487
- case 'rst':
488
- return stackControlEffect(rstControl(instruction.vector));
489
- case 'ret':
490
- return stackControlEffect({ kind: 'return', conditional: false });
491
- case 'ret-cc':
492
- return stackControlEffect({ kind: 'return', conditional: true }, conditionFlagRead(instruction.condition));
493
- case 'jp':
494
- return controlEffect(jumpControl(expressionSymbol(instruction.expression), false));
495
- case 'jp-cc':
496
- return controlEffect(jumpControl(expressionSymbol(instruction.expression), true), conditionFlagRead(instruction.condition));
497
- case 'jp-indirect':
498
- return controlEffect(jumpControl(undefined, false), reg16Units(instruction.register));
499
- case 'jr':
500
- return controlEffect(jumpControl(expressionSymbol(instruction.expression), false));
501
- case 'jr-cc':
502
- return controlEffect(jumpControl(expressionSymbol(instruction.expression), true), conditionFlagRead(instruction.condition));
503
- case 'djnz':
504
- return {
505
- ...baseEffect(),
506
- reads: ['B'],
507
- writes: ['B'],
508
- control: jumpControl(expressionSymbol(instruction.expression), true),
509
- };
510
- case 'rlc':
511
- case 'rrc':
512
- case 'rl':
513
- case 'rr':
514
- case 'sla':
515
- case 'sra':
516
- case 'sll':
517
- case 'sls':
518
- case 'srl':
519
- return rotateShiftEffect(instruction);
520
- case 'rlca':
521
- case 'rrca':
522
- case 'rla':
523
- case 'rra':
524
- return accumulatorRotateEffect(instruction.mnemonic);
525
- case 'bit':
526
- case 'res':
527
- case 'set':
528
- return bitEffect(instruction);
529
- case 'scf':
530
- return { ...baseEffect(), writes: ['carry', 'halfCarry'] };
531
- case 'ccf':
532
- return { ...baseEffect(), reads: ['carry'], writes: ['carry', 'halfCarry'] };
533
- case 'cpl':
534
- return { ...baseEffect(), reads: ['A'], writes: ['A', 'halfCarry'] };
535
- case 'neg':
536
- return { ...baseEffect(), reads: ['A'], writes: concatUnique(['A'], FLAG_WRITES) };
537
- case 'out':
538
- return outEffect(instruction);
539
- case 'in':
540
- return inEffect(instruction);
541
- case 'ldi':
542
- case 'ldir':
543
- case 'ldd':
544
- case 'lddr':
545
- case 'cpi':
546
- case 'cpir':
547
- case 'cpd':
548
- case 'cpdr':
549
- case 'ini':
550
- case 'inir':
551
- case 'ind':
552
- case 'indr':
553
- case 'outi':
554
- case 'otir':
555
- case 'outd':
556
- case 'otdr':
557
- return blockTransferEffect();
558
- case 'ex':
559
- return exEffect(instruction);
560
- default:
561
- return unknownEffect();
562
- }
99
+ return EFFECT_HANDLERS[instruction.mnemonic]?.(instruction) ?? unknownEffect();
563
100
  }
@@ -0,0 +1,2 @@
1
+ import type { EncodedZ80Instruction, Z80CoreMnemonic } from './instruction.js';
2
+ export declare function encodeCore(mnemonic: Z80CoreMnemonic): EncodedZ80Instruction;