@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,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
- switch (instruction.mnemonic) {
3
- case 'nop':
4
- return { size: 1, fragments: [{ kind: 'bytes', bytes: [0x00] }] };
5
- case 'ret':
6
- return { size: 1, fragments: [{ kind: 'bytes', bytes: [0xc9] }] };
7
- case 'ret-cc':
8
- return {
9
- size: 1,
10
- fragments: [{ kind: 'bytes', bytes: [retConditionOpcode(instruction.condition)] }],
11
- };
12
- case 'di':
13
- case 'ei':
14
- case 'scf':
15
- case 'ccf':
16
- case 'cpl':
17
- case 'daa':
18
- case 'exx':
19
- case 'halt':
20
- case 'rlca':
21
- case 'rrca':
22
- case 'rla':
23
- case 'rra':
24
- case 'neg':
25
- case 'rrd':
26
- case 'rld':
27
- case 'ldi':
28
- case 'ldir':
29
- case 'ldd':
30
- case 'lddr':
31
- case 'cpi':
32
- case 'cpir':
33
- case 'cpd':
34
- case 'cpdr':
35
- case 'ini':
36
- case 'inir':
37
- case 'ind':
38
- case 'indr':
39
- case 'outi':
40
- case 'otir':
41
- case 'outd':
42
- case 'otdr':
43
- case 'reti':
44
- case 'retn':
45
- return encodeCore(instruction.mnemonic);
46
- case 'ex':
47
- return encodeExchange(instruction.form);
48
- case 'im':
49
- return {
50
- size: 2,
51
- fragments: [{ kind: 'bytes', bytes: [0xed, imOpcode(instruction.mode)] }],
52
- };
53
- case 'rst':
54
- return {
55
- size: 1,
56
- fragments: [{ kind: 'bytes', bytes: [rstOpcode(instruction.vector)] }],
57
- };
58
- case 'inc':
59
- case 'dec':
60
- return encodeIncDec(instruction.mnemonic, instruction.operand);
61
- case 'push':
62
- case 'pop':
63
- return encodeStack(instruction.mnemonic, instruction.register);
64
- case 'ld-a-imm':
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
- switch (mnemonic) {
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,