@jhlagado/azm 0.2.7 → 0.2.9

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 (253) hide show
  1. package/README.md +239 -76
  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 +55 -227
  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/assemble-program.js +5 -0
  15. package/dist/src/assembly/fixup-emission.js +30 -48
  16. package/dist/src/assembly/import-visibility.d.ts +3 -0
  17. package/dist/src/assembly/import-visibility.js +204 -0
  18. package/dist/src/assembly/program-emission.js +163 -164
  19. package/dist/src/cli/artifact-files.d.ts +15 -0
  20. package/dist/src/cli/artifact-files.js +86 -0
  21. package/dist/src/cli/parse-args.d.ts +6 -5
  22. package/dist/src/cli/parse-args.js +162 -136
  23. package/dist/src/cli/run.js +4 -1
  24. package/dist/src/cli/usage.d.ts +1 -0
  25. package/dist/src/cli/usage.js +33 -0
  26. package/dist/src/cli/write-artifacts.js +18 -91
  27. package/dist/src/core/compile.js +51 -274
  28. package/dist/src/core/conditional-assembly.d.ts +6 -0
  29. package/dist/src/core/conditional-assembly.js +181 -0
  30. package/dist/src/expansion/op-constant-expression.d.ts +3 -0
  31. package/dist/src/expansion/op-constant-expression.js +52 -0
  32. package/dist/src/expansion/op-expand-selected.d.ts +5 -0
  33. package/dist/src/expansion/op-expand-selected.js +143 -0
  34. package/dist/src/expansion/op-expansion.d.ts +5 -53
  35. package/dist/src/expansion/op-expansion.js +85 -815
  36. package/dist/src/expansion/op-instruction-instantiation.d.ts +3 -0
  37. package/dist/src/expansion/op-instruction-instantiation.js +194 -0
  38. package/dist/src/expansion/op-local-labels.d.ts +8 -0
  39. package/dist/src/expansion/op-local-labels.js +166 -0
  40. package/dist/src/expansion/op-operand-splitting.d.ts +1 -0
  41. package/dist/src/expansion/op-operand-splitting.js +44 -0
  42. package/dist/src/expansion/op-operands.d.ts +53 -0
  43. package/dist/src/expansion/op-operands.js +66 -0
  44. package/dist/src/expansion/op-selection.d.ts +18 -0
  45. package/dist/src/expansion/op-selection.js +172 -0
  46. package/dist/src/index.d.ts +2 -1
  47. package/dist/src/index.js +1 -1
  48. package/dist/src/model/diagnostic.d.ts +4 -0
  49. package/dist/src/model/diagnostic.js +4 -0
  50. package/dist/src/node/source-host.js +40 -13
  51. package/dist/src/outputs/asm80-expression-evaluation.d.ts +10 -0
  52. package/dist/src/outputs/asm80-expression-evaluation.js +75 -0
  53. package/dist/src/outputs/asm80-expressions.d.ts +5 -0
  54. package/dist/src/outputs/asm80-expressions.js +47 -0
  55. package/dist/src/outputs/asm80-instruction-operands.d.ts +16 -0
  56. package/dist/src/outputs/asm80-instruction-operands.js +38 -0
  57. package/dist/src/outputs/asm80-instructions.d.ts +5 -0
  58. package/dist/src/outputs/asm80-instructions.js +272 -0
  59. package/dist/src/outputs/asm80-ld-operands.d.ts +10 -0
  60. package/dist/src/outputs/asm80-ld-operands.js +157 -0
  61. package/dist/src/outputs/asm80-strings.d.ts +4 -0
  62. package/dist/src/outputs/asm80-strings.js +14 -0
  63. package/dist/src/outputs/d8-files.d.ts +10 -0
  64. package/dist/src/outputs/d8-files.js +103 -0
  65. package/dist/src/outputs/d8-helpers.d.ts +21 -0
  66. package/dist/src/outputs/d8-helpers.js +136 -0
  67. package/dist/src/outputs/hex.js +26 -18
  68. package/dist/src/outputs/types.d.ts +16 -10
  69. package/dist/src/outputs/write-asm80.js +72 -597
  70. package/dist/src/outputs/write-d8.js +6 -216
  71. package/dist/src/register-contracts/accept-output.d.ts +2 -0
  72. package/dist/src/register-contracts/analyze-helpers.d.ts +29 -0
  73. package/dist/src/register-contracts/analyze-helpers.js +162 -0
  74. package/dist/src/{register-care → register-contracts}/analyze.d.ts +6 -6
  75. package/dist/src/register-contracts/analyze.js +73 -0
  76. package/dist/src/register-contracts/annotate.d.ts +11 -0
  77. package/dist/src/{register-care → register-contracts}/annotate.js +3 -3
  78. package/dist/src/register-contracts/annotations.d.ts +8 -0
  79. package/dist/src/{register-care → register-contracts}/annotations.js +3 -3
  80. package/dist/src/register-contracts/boundaryHints.d.ts +3 -0
  81. package/dist/src/register-contracts/boundaryHints.js +24 -0
  82. package/dist/src/register-contracts/carriers.d.ts +2 -0
  83. package/dist/src/register-contracts/constants.d.ts +4 -0
  84. package/dist/src/register-contracts/constants.js +51 -0
  85. package/dist/src/register-contracts/controlFlow.d.ts +5 -0
  86. package/dist/src/register-contracts/controlFlow.js +55 -0
  87. package/dist/src/register-contracts/fix.d.ts +11 -0
  88. package/dist/src/{register-care → register-contracts}/fix.js +47 -30
  89. package/dist/src/register-contracts/instruction-head.d.ts +2 -0
  90. package/dist/src/register-contracts/instruction-head.js +3 -0
  91. package/dist/src/register-contracts/instruction-operands.d.ts +3 -0
  92. package/dist/src/register-contracts/instruction-operands.js +101 -0
  93. package/dist/src/register-contracts/instruction-predicates.d.ts +6 -0
  94. package/dist/src/register-contracts/instruction-predicates.js +44 -0
  95. package/dist/src/register-contracts/interfaceContracts.d.ts +2 -0
  96. package/dist/src/register-contracts/interfaceContracts.js +68 -0
  97. package/dist/src/register-contracts/liveness.d.ts +3 -0
  98. package/dist/src/{register-care → register-contracts}/liveness.js +111 -79
  99. package/dist/src/register-contracts/operand-register-name.d.ts +2 -0
  100. package/dist/src/register-contracts/operand-register-name.js +13 -0
  101. package/dist/src/{register-care → register-contracts}/profiles.d.ts +5 -5
  102. package/dist/src/{register-care → register-contracts}/profiles.js +2 -2
  103. package/dist/src/register-contracts/programModel-boundaries.d.ts +6 -0
  104. package/dist/src/register-contracts/programModel-boundaries.js +64 -0
  105. package/dist/src/register-contracts/programModel-routines.d.ts +7 -0
  106. package/dist/src/register-contracts/programModel-routines.js +144 -0
  107. package/dist/src/register-contracts/programModel.d.ts +3 -0
  108. package/dist/src/register-contracts/programModel.js +14 -0
  109. package/dist/src/register-contracts/report.d.ts +5 -0
  110. package/dist/src/{register-care → register-contracts}/report.js +34 -17
  111. package/dist/src/register-contracts/routine-summaries.d.ts +6 -0
  112. package/dist/src/{register-care → register-contracts}/routine-summaries.js +11 -1
  113. package/dist/src/register-contracts/smartCommentBlocks.d.ts +5 -0
  114. package/dist/src/register-contracts/smartCommentBlocks.js +30 -0
  115. package/dist/src/register-contracts/smartCommentParsing.d.ts +3 -0
  116. package/dist/src/register-contracts/smartCommentParsing.js +80 -0
  117. package/dist/src/register-contracts/smartComments.d.ts +5 -0
  118. package/dist/src/register-contracts/smartComments.js +92 -0
  119. package/dist/src/register-contracts/summaries.d.ts +12 -0
  120. package/dist/src/{register-care → register-contracts}/summaries.js +7 -7
  121. package/dist/src/register-contracts/summary-boundary.d.ts +2 -0
  122. package/dist/src/register-contracts/summary-boundary.js +40 -0
  123. package/dist/src/register-contracts/summary-contract.d.ts +2 -0
  124. package/dist/src/register-contracts/summary-contract.js +45 -0
  125. package/dist/src/register-contracts/summary-result.d.ts +7 -0
  126. package/dist/src/register-contracts/summary-result.js +122 -0
  127. package/dist/src/register-contracts/summary-state.d.ts +23 -0
  128. package/dist/src/register-contracts/summary-state.js +88 -0
  129. package/dist/src/register-contracts/summary-token-transfer.d.ts +3 -0
  130. package/dist/src/register-contracts/summary-token-transfer.js +67 -0
  131. package/dist/src/register-contracts/summary.d.ts +3 -0
  132. package/dist/src/register-contracts/summary.js +266 -0
  133. package/dist/src/register-contracts/tooling.d.ts +57 -0
  134. package/dist/src/{register-care → register-contracts}/tooling.js +8 -6
  135. package/dist/src/register-contracts/types.d.ts +188 -0
  136. package/dist/src/semantics/binary-operators.d.ts +2 -0
  137. package/dist/src/semantics/binary-operators.js +15 -0
  138. package/dist/src/semantics/byte-functions.d.ts +2 -0
  139. package/dist/src/semantics/byte-functions.js +7 -0
  140. package/dist/src/semantics/constant-operator-types.d.ts +10 -0
  141. package/dist/src/semantics/constant-operator-types.js +1 -0
  142. package/dist/src/semantics/constant-operators.d.ts +3 -0
  143. package/dist/src/semantics/constant-operators.js +3 -0
  144. package/dist/src/semantics/diagnostics.d.ts +3 -0
  145. package/dist/src/semantics/diagnostics.js +10 -0
  146. package/dist/src/semantics/expression-evaluation.d.ts +11 -19
  147. package/dist/src/semantics/expression-evaluation.js +22 -334
  148. package/dist/src/semantics/layout-evaluation.d.ts +23 -0
  149. package/dist/src/semantics/layout-evaluation.js +202 -0
  150. package/dist/src/semantics/layout-format.d.ts +5 -0
  151. package/dist/src/semantics/layout-format.js +31 -0
  152. package/dist/src/semantics/layout-path.d.ts +24 -0
  153. package/dist/src/semantics/layout-path.js +58 -0
  154. package/dist/src/semantics/unary-operators.d.ts +2 -0
  155. package/dist/src/semantics/unary-operators.js +8 -0
  156. package/dist/src/source/line-comment-scanner.d.ts +1 -0
  157. package/dist/src/source/line-comment-scanner.js +51 -0
  158. package/dist/src/source/logical-lines.d.ts +3 -0
  159. package/dist/src/source/source-span.d.ts +2 -0
  160. package/dist/src/source/strip-line-comment.js +8 -44
  161. package/dist/src/syntax/directive-aliases.js +36 -22
  162. package/dist/src/syntax/expression-tokenizer.d.ts +30 -0
  163. package/dist/src/syntax/expression-tokenizer.js +310 -0
  164. package/dist/src/syntax/parse-directive-statement.d.ts +9 -0
  165. package/dist/src/syntax/parse-directive-statement.js +309 -0
  166. package/dist/src/syntax/parse-expression.d.ts +2 -2
  167. package/dist/src/syntax/parse-expression.js +7 -568
  168. package/dist/src/syntax/parse-layout-declarations.d.ts +9 -0
  169. package/dist/src/syntax/parse-layout-declarations.js +189 -0
  170. package/dist/src/syntax/parse-layout-expression.d.ts +5 -0
  171. package/dist/src/syntax/parse-layout-expression.js +175 -0
  172. package/dist/src/syntax/parse-line.js +21 -273
  173. package/dist/src/syntax/parse-token-expression.d.ts +3 -0
  174. package/dist/src/syntax/parse-token-expression.js +133 -0
  175. package/dist/src/tooling/api.js +1 -1
  176. package/dist/src/tooling/case-style.js +47 -30
  177. package/dist/src/z80/effect-groups.d.ts +38 -0
  178. package/dist/src/z80/effect-groups.js +265 -0
  179. package/dist/src/z80/effect-units.d.ts +18 -0
  180. package/dist/src/z80/effect-units.js +165 -0
  181. package/dist/src/z80/effects.d.ts +1 -1
  182. package/dist/src/z80/effects.js +94 -557
  183. package/dist/src/z80/encode-core.d.ts +2 -0
  184. package/dist/src/z80/encode-core.js +42 -0
  185. package/dist/src/z80/encode-ld-helpers.d.ts +25 -0
  186. package/dist/src/z80/encode-ld-helpers.js +172 -0
  187. package/dist/src/z80/encode-ld.d.ts +2 -0
  188. package/dist/src/z80/encode-ld.js +285 -0
  189. package/dist/src/z80/encode.js +190 -542
  190. package/dist/src/z80/ld-support.d.ts +3 -0
  191. package/dist/src/z80/ld-support.js +146 -0
  192. package/dist/src/z80/operand-split-state.d.ts +8 -0
  193. package/dist/src/z80/operand-split-state.js +46 -0
  194. package/dist/src/z80/operand-split.d.ts +1 -0
  195. package/dist/src/z80/operand-split.js +13 -0
  196. package/dist/src/z80/parse-basic.d.ts +4 -0
  197. package/dist/src/z80/parse-basic.js +39 -0
  198. package/dist/src/z80/parse-branch.d.ts +4 -0
  199. package/dist/src/z80/parse-branch.js +218 -0
  200. package/dist/src/z80/parse-conditions.d.ts +6 -0
  201. package/dist/src/z80/parse-conditions.js +10 -0
  202. package/dist/src/z80/parse-exchange.d.ts +2 -0
  203. package/dist/src/z80/parse-exchange.js +30 -0
  204. package/dist/src/z80/parse-instruction.js +224 -1010
  205. package/dist/src/z80/parse-io-control.d.ts +5 -0
  206. package/dist/src/z80/parse-io-control.js +108 -0
  207. package/dist/src/z80/parse-ld.d.ts +2 -0
  208. package/dist/src/z80/parse-ld.js +83 -0
  209. package/dist/src/z80/parse-operands.d.ts +41 -0
  210. package/dist/src/z80/parse-operands.js +259 -0
  211. package/docs/codebase/01-orientation-and-repository-layout.md +192 -0
  212. package/docs/codebase/02-source-loading-and-parsing.md +263 -0
  213. package/docs/codebase/03-assembly-and-z80-emission.md +251 -0
  214. package/docs/codebase/04-ops-and-register-contracts.md +237 -0
  215. package/docs/codebase/05-interfaces-and-output-artifacts.md +253 -0
  216. package/docs/codebase/06-verification-and-maintenance.md +202 -0
  217. package/docs/codebase/appendices/a-directory-file-reference.md +253 -0
  218. package/docs/codebase/appendices/b-compile-flow-reference.md +103 -0
  219. package/docs/codebase/appendices/c-public-surface-reference.md +106 -0
  220. package/docs/codebase/appendices/index.md +16 -0
  221. package/docs/codebase/index.md +46 -0
  222. package/package.json +2 -3
  223. package/dist/src/register-care/accept-output.d.ts +0 -2
  224. package/dist/src/register-care/analyze.js +0 -166
  225. package/dist/src/register-care/annotate.d.ts +0 -11
  226. package/dist/src/register-care/annotations.d.ts +0 -8
  227. package/dist/src/register-care/boundaryHints.d.ts +0 -3
  228. package/dist/src/register-care/boundaryHints.js +0 -80
  229. package/dist/src/register-care/carriers.d.ts +0 -2
  230. package/dist/src/register-care/controlFlow.d.ts +0 -5
  231. package/dist/src/register-care/controlFlow.js +0 -38
  232. package/dist/src/register-care/fix.d.ts +0 -11
  233. package/dist/src/register-care/instruction-shape.d.ts +0 -11
  234. package/dist/src/register-care/instruction-shape.js +0 -129
  235. package/dist/src/register-care/liveness.d.ts +0 -3
  236. package/dist/src/register-care/programModel.d.ts +0 -3
  237. package/dist/src/register-care/programModel.js +0 -266
  238. package/dist/src/register-care/report.d.ts +0 -5
  239. package/dist/src/register-care/routine-summaries.d.ts +0 -6
  240. package/dist/src/register-care/smartComments.d.ts +0 -5
  241. package/dist/src/register-care/smartComments.js +0 -243
  242. package/dist/src/register-care/summaries.d.ts +0 -12
  243. package/dist/src/register-care/summary.d.ts +0 -3
  244. package/dist/src/register-care/summary.js +0 -474
  245. package/dist/src/register-care/tooling.d.ts +0 -43
  246. package/dist/src/register-care/types.d.ts +0 -172
  247. package/docs/reference/cli.md +0 -151
  248. package/docs/reference/tooling-api.md +0 -316
  249. /package/dist/src/{register-care → register-contracts}/accept-output.js +0 -0
  250. /package/dist/src/{register-care → register-contracts}/carriers.js +0 -0
  251. /package/dist/src/{register-care → register-contracts}/sourceText.d.ts +0 -0
  252. /package/dist/src/{register-care → register-contracts}/sourceText.js +0 -0
  253. /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;