@dcorp80/z80cpu 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
package/NOTICE ADDED
@@ -0,0 +1,2 @@
1
+ z80cpu
2
+ Copyright 2026 dcorp80
package/README.md ADDED
@@ -0,0 +1,317 @@
1
+ # @dcorp80/z80cpu
2
+
3
+ ### For the 50th anniversary of the Z80 CPU
4
+
5
+ A hardware-accurate half-cycle Z80 emulator for JavaScript and TypeScript.
6
+ Models the original NMOS Z80 (Zilog Z8400 family).
7
+
8
+ ## What this library is
9
+
10
+ `@dcorp80/z80cpu` is a low-level, hardware-oriented Z80 core for:
11
+ - emulators
12
+ - debuggers
13
+ - reverse-engineering tools
14
+ - timing-sensitive simulation
15
+
16
+ It models half-cycle edges, bus-level behavior, interrupts, WAIT/BUSREQ timing,
17
+ and undocumented behavior while exposing enough state for external tooling.
18
+
19
+ ## Features
20
+
21
+ - Half-cycle timing accuracy — every rising and falling edge is a distinct simulation step.
22
+ - Full instruction set, including undocumented opcodes.
23
+ - Documented **and** undocumented flag behavior.
24
+ - Hardware-accurate RESET, interrupt, WAIT, and BUSREQ processing.
25
+ - Models the Special Reset feature plus all NMOS-Z80 RESET quirks beyond
26
+ the datasheet — see [RESET behavior](#reset-behavior).
27
+ - Fast: ~20 MHz effective Z80 throughput in Node.js on Apple M1.
28
+ - JIT-friendly — no allocations on the hot path.
29
+ - Pure ESM — works in Node and the browser, no CommonJS build.
30
+ - TypeScript types included.
31
+ - Introspectable — exposes internal state, upcoming sequencer step, and
32
+ architectural snapshots for debugger tooling.
33
+
34
+ ## Validation
35
+
36
+ - 7000+ tests, with behavior validated against the Visual6502 Z80 netlist.
37
+ - Extensive coverage of undocumented and timing-sensitive behavior.
38
+
39
+ "Hardware-accurate" here refers to **externally observable** behavior:
40
+ bus pins, instruction effects, M-cycle and T-state timing visible to the
41
+ host. Internal state organization — the step pipeline, the bank-swap
42
+ encoding, sub-edge sequencing details — is the emulator's own design
43
+ and may differ from the real chip internals, even where external
44
+ behavior matches at every edge.
45
+
46
+ ## Install
47
+
48
+ ```bash
49
+ npm install @dcorp80/z80cpu
50
+ ```
51
+
52
+ ## Usage
53
+
54
+ ```ts
55
+ import { Z80Cpu } from "@dcorp80/z80cpu";
56
+
57
+ const cpu = new Z80Cpu();
58
+ const mem = new Uint8Array(0x10000);
59
+ mem[0] = 0x3E; mem[1] = 0x42; // LD A,42h
60
+
61
+ const resolve = () => {
62
+ const { nMREQ, nRD, nWR, addr, data } = cpu.bus;
63
+ if (nMREQ === 0) {
64
+ if (nRD === 0) cpu.bus.data = mem[addr];
65
+ if (nWR === 0) mem[addr] = data;
66
+ }
67
+ };
68
+
69
+ for (let i = 0; i < 16; i++) {
70
+ resolve();
71
+ cpu.clockEdge();
72
+ }
73
+ ```
74
+
75
+ Each `clockEdge()` advances the CPU by one half-cycle (rising or falling). Run
76
+ your bus resolver *before* each edge: read the CPU's outputs, and on a read
77
+ cycle set `cpu.bus.data` to the value the CPU should sample.
78
+
79
+ ## Introspection
80
+
81
+ The CPU exposes enough of itself for external observers (debuggers,
82
+ visualizers, tracers) to be built without reaching into the simulator's
83
+ implementation details.
84
+
85
+ ### Architectural snapshot
86
+
87
+ ```ts
88
+ import { Z80Cpu, type CpuState } from "@dcorp80/z80cpu";
89
+
90
+ const cpu = new Z80Cpu();
91
+ // …run for a while…
92
+
93
+ const s = cpu.snapshot(); // fresh CpuState each call
94
+ console.log(s.pc, s.main.a, s.alt.b, s.im, s.iff1);
95
+
96
+ // In tight loops, allocate once and reuse:
97
+ const buf: CpuState = cpu.snapshot();
98
+ for (let i = 0; i < N; i++) {
99
+ cpu.clockEdge();
100
+ cpu.snapshot(buf); // writes into buf, no allocation
101
+ }
102
+ ```
103
+
104
+ `CpuState` decodes the bank-swap encoding (`exAf`, `exx`, `exDe`) into
105
+ named `main` / `alt` register banks, flattens the IM flip-flops to `0|1|2`
106
+ and IFFs to booleans.
107
+ Numeric fields are plain JS numbers. Values are explicitly constrained
108
+ at CPU writeback sites, so out-of-range values indicate a bug rather than
109
+ runtime state. See **Plain arrays** below.
110
+
111
+ ```ts
112
+ interface RegBank {
113
+ b: number; c: number; d: number; e: number;
114
+ h: number; l: number; a: number; f: number;
115
+ }
116
+
117
+ interface CpuState {
118
+ pc: number;
119
+ sp: number;
120
+ ix: number;
121
+ iy: number;
122
+ i: number;
123
+ r: number;
124
+ wz: number; // internal "MEMPTR"
125
+
126
+ main: RegBank; // currently-visible bank
127
+ alt: RegBank; // what EXX / EX AF,AF' would expose
128
+
129
+ im: 0 | 1 | 2;
130
+ /**
131
+ * `true` when the IM flip-flops are in the undocumented
132
+ * `imFa=0, imFb=1` state — behaves as IM 0, `im` still reads `0`;
133
+ * this flag is the only way to tell the two IM-0 states apart.
134
+ */
135
+ imUndocumented: boolean;
136
+
137
+ iff1: boolean;
138
+ iff2: boolean; // restored to IFF1 by RETN; exposed via P/V on LD A,I/R
139
+ nmiPending: boolean;
140
+ }
141
+ ```
142
+
143
+ Use `decodeFlags(f)` to unpack an `F` byte into named bits when you
144
+ need the individual sign / zero / half-carry / etc. flags.
145
+
146
+ `halted` is intentionally omitted from `CpuState` — the HALT state is
147
+ surfaced through `cpu.ctl.haltLatch` (see the *Hardware-level state flags*
148
+ table below) and the `cpu.bus.nHALT` pin.
149
+
150
+ ### Upcoming step
151
+
152
+ ```ts
153
+ import { StepId } from "@dcorp80/z80cpu";
154
+
155
+ if (cpu.nextStep === StepId.M1_T1_0) {
156
+ // about to start new instruction — a clean boundary for breakpoints, etc.
157
+ }
158
+ ```
159
+
160
+ `cpu.nextStep` returns the `StepId` of the step the sequencer will execute on
161
+ the next `clockEdge()`. Stable enum — the only public API for observing the
162
+ upcoming sequencer step. The sequencer's internal `cpu.next` function pointer stays
163
+ out of the public surface.
164
+
165
+ ### Raw state
166
+
167
+ `cpu.regs`, `cpu.bus`, `cpu.seq`, and `cpu.ctl` are all public objects.
168
+ You can read any of them at any half-cycle edge.
169
+
170
+ The register file `cpu.regs.file: number[]` is a **hardware-like flat
171
+ view** — hardware slot positions rather than architectural register names.
172
+ The bank-swap state lives elsewhere:
173
+
174
+ - `cpu.seq.prefix` — bits `0` / `1` / `2` are the `exAf` / `exx` / `exDe`
175
+ flip-flops; bits `3` / `4` flag the IX / IY substitution active for the
176
+ current DD / FD prefix.
177
+ - `cpu.seq.exDe0` and `cpu.seq.exDe1` — the per-bank DE↔HL swap flip-flops
178
+ (multiplexed onto bit 2 of `prefix` by `exx`).
179
+
180
+ For most consumers, `cpu.snapshot()` is the right answer — it decodes
181
+ all of that into named `main` / `alt` register banks. Going through
182
+ `regs.file` directly is for code that needs to track or reproduce the
183
+ bank-routing logic itself (e.g. a netlist comparator).
184
+
185
+ ### Hardware-level state flags
186
+
187
+ A few internal flip-flops are useful for instrumentation:
188
+
189
+ | Field | Meaning |
190
+ |--------------------------------|----------------------------------------------------------------------------------------------------------------------------|
191
+ | `cpu.seq.lastOpTState` | `true` during the last T-state of the current instruction — a convenient point to log state or single-step execution. |
192
+ | `cpu.seq.phase` | Clock phase, matches CLK: `true` after a rising edge (CLK high), `false` after a falling edge (CLK low). |
193
+ | `cpu.ctl.haltLatch` | Internal HALT state, set by the `HALT` instruction and cleared by RESET / INT / NMI. Distinct from the `nHALT` output pin. |
194
+ | `cpu.ctl.nres` | Normal-reset latch — set when RESET was sampled, cleared once recovery completes. |
195
+ | `cpu.ctl.sres` | Special-reset flip-flop — set when RESET is sampled during M1 T2. See [RESET behavior](#reset-behavior) section below |
196
+ | `cpu.ctl.iff1`, `cpu.ctl.iff2` | Interrupt-enable flip-flops (also surfaced in `CpuState`). |
197
+ | `cpu.ctl.nmiFf` | NMI pending — set by `cpu.nmi()`, cleared at the NMI M1. Surfaced as `nmiPending` in `CpuState`. |
198
+
199
+ ## Bus and signals
200
+
201
+ The CPU exposes its pins through `cpu.bus`. The host advances time by
202
+ calling `cpu.clockEdge()` — that call *is* one half-cycle of CLK, so
203
+ there's no `nCLK` pin on the bus. Bus signals are exchanged between
204
+ those edges.
205
+
206
+ Active-low convention throughout: `0` = asserted, `1` = released. The
207
+ transaction signals (MREQ, IORQ, RD, WR) tri-state
208
+ represented as `undefined`, therefore typed `0 | 1 | undefined`. The
209
+ address bus (`number | undefined`, 16-bit) and data bus (`number | undefined`,
210
+ 8-bit) tri-state alongside them. The status signals (M1, RFSH, HALT) and
211
+ BUSACK stay driven throughout — typed `0 | 1`.
212
+
213
+ ```ts
214
+ cpu.bus.nM1 // 0 during M1 fetch
215
+ cpu.bus.nMREQ // memory request; undefined while granted
216
+ cpu.bus.nIORQ // I/O request; undefined while granted
217
+ cpu.bus.nRD // read strobe; undefined while granted
218
+ cpu.bus.nWR // write strobe; undefined while granted
219
+ cpu.bus.nRFSH // refresh (DRAM refresh during M1 T3/T4)
220
+ cpu.bus.nHALT // HALT acknowledged on the pin
221
+ cpu.bus.nBUSACK // bus-grant acknowledge
222
+ cpu.bus.addr // 16-bit address bus; undefined while granted
223
+ cpu.bus.data // 8-bit data bus; CPU drives during writes, host fills during reads
224
+ ```
225
+
226
+ Inputs are typed `0 | 1` — the host sets them, the CPU samples them at
227
+ the modeled sampling edges:
228
+
229
+ ```ts
230
+ cpu.bus.nRESET = 0; // assert RESET
231
+ cpu.bus.nINT = 0; // level-triggered interrupt request
232
+ cpu.bus.nWAIT = 0; // stretch the current memory / IO cycle
233
+ cpu.bus.nBUSRQ = 0; // request a bus grant
234
+ ```
235
+
236
+ NMI is the exception. The real Z80 NMI pin is **edge-triggered** — a
237
+ falling edge latches a request internally. To model that faithfully
238
+ through a level pin you'd need the host to toggle it and the CPU to
239
+ detect the transition, which adds friction in a synchronous emulator.
240
+ Instead, NMI is a method:
241
+
242
+ ```ts
243
+ cpu.nmi();
244
+ ```
245
+
246
+ One call = one edge = one latched NMI, serviced at the end of the
247
+ current instruction. Calling again while a previous NMI hasn't been
248
+ acknowledged is a no-op.
249
+
250
+ ## RESET behavior
251
+
252
+ The reset path has more nuance than typical references suggest:
253
+
254
+ ### Special Reset
255
+
256
+ A designed but historically obscure feature. If RESET is sampled during
257
+ `M1 T2`, the CPU performs a partial reset: only `PC` is cleared to `0`,
258
+ while registers and most internal state are preserved — *not* a full
259
+ reset. Documented by Tony Brewer at
260
+ [primrosebank.net](http://www.primrosebank.net/computers/z80/z80_special_reset.htm).
261
+ Surfaced as `cpu.ctl.sres`.
262
+
263
+ ### Beyond-the-datasheet quirks
264
+
265
+ The Z80 datasheet warns that if RESET is sampled during `T2` or `T4`
266
+ of a cycle, `MREQ` may become indeterminate for one
267
+ T-state shortly afterward. In systems with dynamic RAM this can potentially
268
+ corrupt memory contents, which is why the datasheet recommends synchronizing
269
+ RESET with the falling edge of `M1` when RAM must be preserved.
270
+
271
+ The transistor-level netlist suggests broader behavior:
272
+ - **Sampled on the last T-state of any M-cycle**, not only `T2` or `T4`.
273
+ - **`RD` also becomes indeterminate**, alongside `MREQ`, during the next
274
+ `M1 T1`.
275
+ - **A spurious `RD` low pulse appears** on the following reset recovery
276
+ edge.
277
+
278
+ These effects may be netlist artifacts rather than real silicon
279
+ behavior, but are modeled for completeness.
280
+
281
+ ## Plain arrays inside the CPU
282
+
283
+ The CPU's internal register state — `cpu.regs.file`, `cpu.regs.f` — is
284
+ plain `number[]`. `Uint8Array` is intentionally avoided here.
285
+
286
+ Why: V8 specializes object/array shapes by element-kind. Mixing typed
287
+ arrays with `number[]` on the same hot path tends to introduce element-kind
288
+ transitions ("type churn") that defeat inline caching. Sticking to
289
+ SMI-tagged 32-bit integers in plain arrays through the register file
290
+ keeps everything on one fast path.
291
+
292
+ Host-side storage is the host's choice. The bus resolver runs outside
293
+ the CPU — it can back memory and I/O ports with `Uint8Array`,
294
+ `Uint16Array`, plain `number[]`, or anything else that responds to
295
+ `addr` and yields a number.
296
+
297
+ Side effect of the plain-array choice: register values aren't
298
+ *automatically* truncated to 8/16 bits — the CPU does that explicitly
299
+ at every writeback site, and `cpu.snapshot()` trusts that invariant.
300
+ Consumers reading raw state shouldn't need to mask either, as long as
301
+ the CPU stays correct.
302
+
303
+ ## Companion toolkit
304
+
305
+ Higher-level tooling built on top of this library — an interactive
306
+ debugger, a disassembler, and a REPL — lives in the
307
+ [z80cpu-lab](https://github.com/dcorp80/z80cpu-lab) sibling repo.
308
+
309
+ ## License
310
+
311
+ Apache-2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE).
312
+
313
+ ## Acknowledgements
314
+
315
+ Inspired by the Visual6502 and VisualZ80 Remixed projects.
316
+ - [www.visual6502.org](http://www.visual6502.org/welcome.html)
317
+ - [floooh/v6502r](https://github.com/floooh/v6502r).
@@ -0,0 +1,280 @@
1
+ type ExecutorFn = (cpu: Z80Cpu) => void;
2
+
3
+ /**
4
+ * One Z80 register bank: B/C/D/E/H/L/A/F as seen by the programmer.
5
+ * `CpuState.main` is the currently-visible bank; `CpuState.alt` is the
6
+ * one that would become visible after `EXX` (and `EX AF,AF'` for A/F).
7
+ */
8
+ interface RegBank {
9
+ b: number;
10
+ c: number;
11
+ d: number;
12
+ e: number;
13
+ h: number;
14
+ l: number;
15
+ a: number;
16
+ f: number;
17
+ }
18
+ interface CpuState {
19
+ pc: number;
20
+ sp: number;
21
+ ix: number;
22
+ iy: number;
23
+ i: number;
24
+ r: number;
25
+ wz: number;
26
+ main: RegBank;
27
+ alt: RegBank;
28
+ im: 0 | 1 | 2;
29
+ /**
30
+ * True when the IM flip-flops are in the undocumented `imFa=0, imFb=1`
31
+ * state — which behaves as IM 0 `im` reports `0`; consumers that care
32
+ * about the distinction read this flag.
33
+ */
34
+ imUndocumented: boolean;
35
+ /** Interrupt enable flip-flops. */
36
+ iff1: boolean;
37
+ iff2: boolean;
38
+ /** NMI latched and waiting to be acknowledged at the next instruction boundary. */
39
+ nmiPending: boolean;
40
+ }
41
+ interface DecodedFlags {
42
+ s: boolean;
43
+ z: boolean;
44
+ x5: boolean;
45
+ h: boolean;
46
+ x3: boolean;
47
+ pv: boolean;
48
+ n: boolean;
49
+ c: boolean;
50
+ }
51
+ /**
52
+ * Decode an 8-bit Z80 flag register into individual booleans. Use on
53
+ * `snapshot().main.f` or `snapshot().alt.f` — kept out of the snapshot
54
+ * itself so `CpuState` stays a minimal, canonical representation.
55
+ */
56
+ declare function decodeFlags(f: number): DecodedFlags;
57
+ /**
58
+ * Fill `out` (or a fresh object) with the CPU's architectural state.
59
+ * Pass a pre-allocated `CpuState` to avoid the per-call allocation in
60
+ * tight loops — `out.main` and `out.alt` must be present.
61
+ */
62
+ declare function snapshotCpu(cpu: Z80Cpu, out?: CpuState): CpuState;
63
+
64
+ /**
65
+ * Identifier for every step function the sequencer can land on. Exposed as
66
+ * `cpu.nextStep` for external observers (debuggers, tracers); the simulator
67
+ * itself uses function pointers internally because identity-compare beats
68
+ * enum switching on the hot path. Consumers gate on `StepId.*` values
69
+ * instead of importing step functions directly.
70
+ */
71
+ declare enum StepId {
72
+ M1_T1_0 = 0,
73
+ M1_T1_1 = 1,
74
+ M1_T2_0 = 2,
75
+ M1_T2_1 = 3,
76
+ M1_T3_0 = 4,
77
+ M1_T3_1 = 5,
78
+ M1_T4_0 = 6,
79
+ M1_T4_1 = 7,
80
+ OP_RD_T1_0 = 8,
81
+ OP_RD_T1_1 = 9,
82
+ M_RD_T1_0 = 10,
83
+ M_RD_T1_1 = 11,
84
+ RD_T2_0 = 12,
85
+ RD_T2_1 = 13,
86
+ RD_T3_0 = 14,
87
+ RD_T3_1 = 15,
88
+ M_WR_T1_0 = 16,
89
+ M_WR_T1_1 = 17,
90
+ M_WR_T2_0 = 18,
91
+ M_WR_T2_1 = 19,
92
+ M_WR_T3_0 = 20,
93
+ M_WR_T3_1 = 21,
94
+ INTERNAL_T1_0 = 22,
95
+ INTERNAL_T1_1 = 23,
96
+ INTERNAL_3T_T1_0 = 24,
97
+ INTERNAL_3T_T1_1 = 25,
98
+ INTERNAL_3T_T2_0 = 26,
99
+ INTERNAL_3T_T2_1 = 27,
100
+ INTERNAL_3T_T3_0 = 28,
101
+ INTERNAL_3T_T3_1 = 29,
102
+ INTERNAL_4T_T1_0 = 30,
103
+ INTERNAL_4T_T1_1 = 31,
104
+ INTERNAL_4T_T2_0 = 32,
105
+ INTERNAL_4T_T2_1 = 33,
106
+ INTERNAL_4T_T3_0 = 34,
107
+ INTERNAL_4T_T3_1 = 35,
108
+ INTERNAL_4T_T4_0 = 36,
109
+ INTERNAL_4T_T4_1 = 37,
110
+ IO_RD_T1_0 = 38,
111
+ IO_RD_T1_1 = 39,
112
+ IO_RD_T2_0 = 40,
113
+ IO_RD_T2_1 = 41,
114
+ IO_RD_TW_0 = 42,
115
+ IO_RD_TW_1 = 43,
116
+ IO_RD_T3_0 = 44,
117
+ IO_RD_T3_1 = 45,
118
+ IO_WR_T1_0 = 46,
119
+ IO_WR_T1_1 = 47,
120
+ IO_WR_T2_0 = 48,
121
+ IO_WR_T2_1 = 49,
122
+ IO_WR_TW_0 = 50,
123
+ IO_WR_TW_1 = 51,
124
+ IO_WR_T3_0 = 52,
125
+ IO_WR_T3_1 = 53,
126
+ NMI_M1_T1_0 = 54,
127
+ NMI_M1_T1_1 = 55,
128
+ NMI_M1_T2_0 = 56,
129
+ NMI_M1_T2_1 = 57,
130
+ NMI_M1_T3_0 = 58,
131
+ INT_M1_T1_0 = 59,
132
+ INT_M1_T1_1 = 60,
133
+ INT_M1_T2_0 = 61,
134
+ INT_M1_T2_1 = 62,
135
+ INT_M1_T3_0 = 63,
136
+ INT_M1_TW1_0 = 64,
137
+ INT_M1_TW1_1 = 65,
138
+ INT_M1_TW2_0 = 66,
139
+ INT_M1_TW2_1 = 67,
140
+ ENTER_RESET_1 = 68,
141
+ RESET_HOLD_0 = 69,
142
+ RESET_HOLD_1 = 70,
143
+ RESET_RECOVER_0 = 71,
144
+ RESET_RECOVER_1 = 72,
145
+ BUS_GRANT_0 = 73,
146
+ BUS_GRANT_1 = 74
147
+ }
148
+ /**
149
+ * A sequencer step. Plain `(cpu) => void` at the type level so internal
150
+ * assignments stay terse. At runtime every step function carries an
151
+ * `.id: StepId` property (attached by the tagging block at the bottom of
152
+ * this file) — `cpu.nextStep` reads it via a controlled cast so external
153
+ * code can compare via `cpu.nextStep === StepId.X` without ever needing
154
+ * to import a step function pointer.
155
+ */
156
+ type StepFn = (cpu: Z80Cpu) => void;
157
+
158
+ declare const B = 0;
159
+ declare const C = 1;
160
+ declare const D = 2;
161
+ declare const E = 3;
162
+ declare const H = 4;
163
+ declare const L = 5;
164
+ declare const A = 7;
165
+ declare const B_ = 8;
166
+ declare const C_ = 9;
167
+ declare const D_ = 10;
168
+ declare const E_ = 11;
169
+ declare const H_ = 12;
170
+ declare const L_ = 13;
171
+ declare const A_ = 15;
172
+ declare const IXH = 20;
173
+ declare const IXL = 21;
174
+ declare const IYH = 28;
175
+ declare const IYL = 29;
176
+ declare class Registers {
177
+ file: number[];
178
+ f: number[];
179
+ sp: number;
180
+ pc: number;
181
+ i: number;
182
+ r: number;
183
+ r7: number;
184
+ wz: number;
185
+ }
186
+ declare class Bus {
187
+ addr: number | undefined;
188
+ data: number | undefined;
189
+ nM1: 0 | 1;
190
+ nMREQ: 0 | 1 | undefined;
191
+ nIORQ: 0 | 1 | undefined;
192
+ nRD: 0 | 1 | undefined;
193
+ nWR: 0 | 1 | undefined;
194
+ nRFSH: 0 | 1;
195
+ nHALT: 0 | 1;
196
+ nBUSACK: 0 | 1;
197
+ nRESET: 0 | 1;
198
+ nINT: 0 | 1;
199
+ nWAIT: 0 | 1;
200
+ nBUSRQ: 0 | 1;
201
+ }
202
+ declare class Seq {
203
+ op: number;
204
+ y: number;
205
+ z: number;
206
+ executor: ExecutorFn;
207
+ hasMoreMCycles: boolean;
208
+ hasExtraT: boolean;
209
+ mAddr: number;
210
+ aluDst: number | undefined;
211
+ aluVal: number;
212
+ aluF: number | undefined;
213
+ aluFMask: number;
214
+ fWritten: boolean;
215
+ cbFf: number;
216
+ edFf: number;
217
+ m1T2Exec: ExecutorFn;
218
+ prefix: number;
219
+ exDe0: number;
220
+ exDe1: number;
221
+ lastOpTState: boolean;
222
+ phase: boolean;
223
+ }
224
+ declare class Ctl {
225
+ skipInts: boolean;
226
+ iff1: number;
227
+ iff2: number;
228
+ intFf: boolean;
229
+ nmiFf: boolean;
230
+ nmiAck: boolean;
231
+ imFa: number;
232
+ imFb: number;
233
+ haltLatch: boolean;
234
+ resi: boolean;
235
+ nres: boolean;
236
+ sres: boolean;
237
+ throwAwayM1: boolean;
238
+ qres: boolean;
239
+ resetAtT1: boolean;
240
+ busrqFf: boolean;
241
+ busGrantResume: StepFn | undefined;
242
+ }
243
+ declare class Z80Cpu {
244
+ regs: Registers;
245
+ bus: Bus;
246
+ seq: Seq;
247
+ ctl: Ctl;
248
+ /**
249
+ * @internal — the sequencer's step pointer. Internal code uses identity
250
+ * compares (`this.next === m1_t1_0`) because they're faster than enum
251
+ * switching on the hot path. External consumers (debuggers, tracers)
252
+ * should compare via {@link Z80Cpu["nextStep"]} instead.
253
+ */
254
+ next: StepFn;
255
+ /**
256
+ * Identifier of the step the sequencer will run on the next
257
+ * `clockEdge()`. Stable enum value — `cpu.nextStep === StepId.M1_T1_0`
258
+ * is the public way to gate on the upcoming step.
259
+ *
260
+ * The cast is safe by construction: every value stored in `this.next`
261
+ * comes from z80tPhase.ts, which tags every step function with its
262
+ * `id` at module init.
263
+ */
264
+ get nextStep(): StepId;
265
+ clockEdge(): void;
266
+ /** Assert NMI (edge-triggered). Sets internal NMI flip-flop;
267
+ * will be serviced at the end of the current instruction. */
268
+ nmi(): void;
269
+ /**
270
+ * Architectural-level snapshot — registers, IM, IFFs, NMI-pending —
271
+ * with the internal bank-swap encoding decoded into `main` / `alt`.
272
+ * Pass a pre-allocated `CpuState` to avoid the per-call allocation.
273
+ *
274
+ * Defined as a thin wrapper to keep z80cpu.ts focused on simulation;
275
+ * the actual decoding lives in z80state.ts.
276
+ */
277
+ snapshot(out?: CpuState): CpuState;
278
+ }
279
+
280
+ export { A, A_, B, B_, C, C_, type CpuState, D, D_, type DecodedFlags, E, E_, H, H_, IXH, IXL, IYH, IYL, L, L_, type RegBank, StepId, Z80Cpu, decodeFlags, snapshotCpu };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ var le=(r=>(r[r.M1_T1_0=0]="M1_T1_0",r[r.M1_T1_1=1]="M1_T1_1",r[r.M1_T2_0=2]="M1_T2_0",r[r.M1_T2_1=3]="M1_T2_1",r[r.M1_T3_0=4]="M1_T3_0",r[r.M1_T3_1=5]="M1_T3_1",r[r.M1_T4_0=6]="M1_T4_0",r[r.M1_T4_1=7]="M1_T4_1",r[r.OP_RD_T1_0=8]="OP_RD_T1_0",r[r.OP_RD_T1_1=9]="OP_RD_T1_1",r[r.M_RD_T1_0=10]="M_RD_T1_0",r[r.M_RD_T1_1=11]="M_RD_T1_1",r[r.RD_T2_0=12]="RD_T2_0",r[r.RD_T2_1=13]="RD_T2_1",r[r.RD_T3_0=14]="RD_T3_0",r[r.RD_T3_1=15]="RD_T3_1",r[r.M_WR_T1_0=16]="M_WR_T1_0",r[r.M_WR_T1_1=17]="M_WR_T1_1",r[r.M_WR_T2_0=18]="M_WR_T2_0",r[r.M_WR_T2_1=19]="M_WR_T2_1",r[r.M_WR_T3_0=20]="M_WR_T3_0",r[r.M_WR_T3_1=21]="M_WR_T3_1",r[r.INTERNAL_T1_0=22]="INTERNAL_T1_0",r[r.INTERNAL_T1_1=23]="INTERNAL_T1_1",r[r.INTERNAL_3T_T1_0=24]="INTERNAL_3T_T1_0",r[r.INTERNAL_3T_T1_1=25]="INTERNAL_3T_T1_1",r[r.INTERNAL_3T_T2_0=26]="INTERNAL_3T_T2_0",r[r.INTERNAL_3T_T2_1=27]="INTERNAL_3T_T2_1",r[r.INTERNAL_3T_T3_0=28]="INTERNAL_3T_T3_0",r[r.INTERNAL_3T_T3_1=29]="INTERNAL_3T_T3_1",r[r.INTERNAL_4T_T1_0=30]="INTERNAL_4T_T1_0",r[r.INTERNAL_4T_T1_1=31]="INTERNAL_4T_T1_1",r[r.INTERNAL_4T_T2_0=32]="INTERNAL_4T_T2_0",r[r.INTERNAL_4T_T2_1=33]="INTERNAL_4T_T2_1",r[r.INTERNAL_4T_T3_0=34]="INTERNAL_4T_T3_0",r[r.INTERNAL_4T_T3_1=35]="INTERNAL_4T_T3_1",r[r.INTERNAL_4T_T4_0=36]="INTERNAL_4T_T4_0",r[r.INTERNAL_4T_T4_1=37]="INTERNAL_4T_T4_1",r[r.IO_RD_T1_0=38]="IO_RD_T1_0",r[r.IO_RD_T1_1=39]="IO_RD_T1_1",r[r.IO_RD_T2_0=40]="IO_RD_T2_0",r[r.IO_RD_T2_1=41]="IO_RD_T2_1",r[r.IO_RD_TW_0=42]="IO_RD_TW_0",r[r.IO_RD_TW_1=43]="IO_RD_TW_1",r[r.IO_RD_T3_0=44]="IO_RD_T3_0",r[r.IO_RD_T3_1=45]="IO_RD_T3_1",r[r.IO_WR_T1_0=46]="IO_WR_T1_0",r[r.IO_WR_T1_1=47]="IO_WR_T1_1",r[r.IO_WR_T2_0=48]="IO_WR_T2_0",r[r.IO_WR_T2_1=49]="IO_WR_T2_1",r[r.IO_WR_TW_0=50]="IO_WR_TW_0",r[r.IO_WR_TW_1=51]="IO_WR_TW_1",r[r.IO_WR_T3_0=52]="IO_WR_T3_0",r[r.IO_WR_T3_1=53]="IO_WR_T3_1",r[r.NMI_M1_T1_0=54]="NMI_M1_T1_0",r[r.NMI_M1_T1_1=55]="NMI_M1_T1_1",r[r.NMI_M1_T2_0=56]="NMI_M1_T2_0",r[r.NMI_M1_T2_1=57]="NMI_M1_T2_1",r[r.NMI_M1_T3_0=58]="NMI_M1_T3_0",r[r.INT_M1_T1_0=59]="INT_M1_T1_0",r[r.INT_M1_T1_1=60]="INT_M1_T1_1",r[r.INT_M1_T2_0=61]="INT_M1_T2_0",r[r.INT_M1_T2_1=62]="INT_M1_T2_1",r[r.INT_M1_T3_0=63]="INT_M1_T3_0",r[r.INT_M1_TW1_0=64]="INT_M1_TW1_0",r[r.INT_M1_TW1_1=65]="INT_M1_TW1_1",r[r.INT_M1_TW2_0=66]="INT_M1_TW2_0",r[r.INT_M1_TW2_1=67]="INT_M1_TW2_1",r[r.ENTER_RESET_1=68]="ENTER_RESET_1",r[r.RESET_HOLD_0=69]="RESET_HOLD_0",r[r.RESET_HOLD_1=70]="RESET_HOLD_1",r[r.RESET_RECOVER_0=71]="RESET_RECOVER_0",r[r.RESET_RECOVER_1=72]="RESET_RECOVER_1",r[r.BUS_GRANT_0=73]="BUS_GRANT_0",r[r.BUS_GRANT_1=74]="BUS_GRANT_1",r))(le||{});function G(e){let s=e.seq.executor;e.seq.executor=w,e.seq.hasMoreMCycles=false,s(e);}function J(e){if(e.seq.hasExtraT){e.seq.hasExtraT=false;return}e.ctl.busrqFf=!e.bus.nBUSRQ,e.ctl.qres=e.ctl.resi;}var Os=e=>{e.bus.nMREQ=void 0,e.bus.nIORQ=void 0,e.bus.nRD=void 0,e.bus.nWR=void 0,e.bus.addr=void 0,e.bus.data=void 0;},H=e=>{e.bus.nMREQ=1,e.bus.nIORQ=1,e.bus.nWR=1,e.bus.nRD=e.ctl.qres&&!e.ctl.nres?0:1;},oe=e=>{e.bus.nMREQ=e.ctl.qres?void 0:1,e.bus.nIORQ=1,e.bus.nRD=e.ctl.qres?void 0:1,e.bus.nWR=1,e.bus.nBUSACK=1,e.bus.data=void 0,e.regs.pc=0,e.regs.i=0,e.regs.r=0,e.regs.r7=0,e.seq.executor=w,e.seq.hasMoreMCycles=false,e.seq.hasExtraT=false,e.seq.aluDst=void 0,e.seq.aluF=void 0,e.seq.aluFMask=0,e.ctl.haltLatch=false,e.ctl.busGrantResume=void 0,e.ctl.throwAwayM1=false,e.next=e.ctl.resetAtT1?ie:_e,e.ctl.resetAtT1=false;},ie=e=>{e.bus.nM1=1,e.bus.nRFSH=1,e.bus.addr=void 0,e.ctl.nres=false,e.next=qe;},qe=e=>{e.bus.nRD=1,e.ctl.resi?e.next=ie:e.next=_e;},_e=e=>{e.bus.nM1=1,e.bus.nRFSH=1,e.bus.nMREQ=1,e.bus.nIORQ=1,e.bus.nWR=1,e.bus.nRD=e.ctl.qres?0:1,e.bus.addr=void 0,e.ctl.nres=false,e.ctl.resi?e.next=qe:e.next=Ie;},Ie=e=>{e.next=D;};function Q(e,s){e.bus.nBUSRQ&&(e.ctl.busrqFf=false),e.bus.nBUSACK=0,e.bus.nRFSH=1,Os(e),e.ctl.busGrantResume=s,e.next=Ce;}var Oe=e=>{e.bus.nBUSRQ&&(e.ctl.busrqFf=false),e.next=Ce;},Ce=e=>{e.ctl.busrqFf?e.next=Oe:(e.bus.nBUSACK=1,e.next=e.ctl.busGrantResume,e.ctl.busGrantResume=void 0);},K=e=>{e.ctl.haltLatch=false,e.bus.nHALT=1,e.ctl.iff1=0,G(e),e.ctl.intFf?(e.ctl.iff2=0,e.next=me):e.next=he;},Me=e=>{if(e.regs.file[n[e.seq.prefix][e.seq.aluDst]]=e.seq.aluVal,e.seq.aluDst===o&&(e.seq.op===87||e.seq.op===95)){let s=e.seq.aluF;e.ctl.iff2&&(s|=A),e.seq.aluF=s;}e.seq.aluDst=void 0;},$=e=>{e.seq.lastOpTState=true,e.ctl.skipInts?e.ctl.skipInts=false:e.ctl.nmiAck?e.ctl.nmiAck=false:e.ctl.nmiFf?e.ctl.nmiAck=true:e.ctl.iff1&&!e.bus.nINT&&(e.ctl.intFf=true);},D=e=>{if(e.seq.lastOpTState=false,e.ctl.busrqFf){Q(e,D);return}e.bus.addr=e.regs.pc,e.bus.nM1=0,e.bus.nRFSH=1,H(e),e.next=Le;},Le=e=>{e.bus.nMREQ=0,e.bus.nRD=0,e.ctl.haltLatch||(e.regs.pc=e.regs.pc+1&65535),e.ctl.sres&&(e.regs.pc=0),e.ctl.qres=false,e.next=de;},de=e=>{e.next=He;},He=e=>{if(e.ctl.sres&&(e.ctl.throwAwayM1=true),e.ctl.nres||(e.ctl.sres=e.ctl.resi),!e.bus.nWAIT){e.next=de;return}e.seq.aluDst!==void 0&&Me(e),e.seq.m1T2Exec(e),e.next=Qe;},Qe=e=>{ye(e.bus.data,e),e.bus.nM1=1,e.bus.nMREQ=1,e.bus.nRD=1,e.bus.addr=e.regs.i<<8|e.regs.r&127|e.regs.r7,e.bus.nRFSH=0,e.next=re;},re=e=>{e.bus.nMREQ=0,e.regs.r=e.regs.r+1&127,e.seq.aluF!==void 0?(e.seq.fWritten=true,e.regs.f[e.seq.prefix&1]=e.regs.f[e.seq.prefix&1]&~e.seq.aluFMask|e.seq.aluF&e.seq.aluFMask,e.seq.aluF=void 0,e.seq.aluFMask=0):e.seq.fWritten=false,e.next=Be;},Be=e=>{J(e),e.seq.hasMoreMCycles||$(e),e.next=Se;},Se=e=>{if(e.bus.nMREQ=1,e.ctl.throwAwayM1){e.ctl.throwAwayM1=false,e.seq.executor=w,e.seq.hasMoreMCycles=false,e.next=D;return}if(e.seq.lastOpTState&&(e.ctl.nmiAck||e.ctl.intFf)){K(e);return}if(e.ctl.haltLatch){e.seq.executor=w,e.seq.hasMoreMCycles=false,e.next=D;return}e.next=D,G(e);},d=e=>{if(e.ctl.busrqFf){Q(e,d);return}e.bus.addr=e.regs.pc,e.bus.nRFSH=1,H(e),e.next=ve;},ve=e=>{e.bus.nMREQ=0,e.bus.nRD=0,e.regs.pc=e.regs.pc+1&65535,e.next=ne;},T=e=>{if(e.ctl.busrqFf){Q(e,T);return}e.bus.addr=e.seq.mAddr,e.bus.nRFSH=1,H(e),e.next=Pe;},Pe=e=>{e.bus.nMREQ=0,e.bus.nRD=0,e.next=ne;},ne=e=>{e.next=Ge;},Ge=e=>{if(!e.bus.nWAIT){e.next=ne;return}e.next=Ue;},Ue=e=>{J(e),e.seq.hasMoreMCycles||$(e),e.next=Xe;},Xe=e=>{if(e.bus.nMREQ=1,e.bus.nRD=1,e.seq.aluVal=e.bus.data&255,e.seq.lastOpTState&&(e.ctl.nmiAck||e.ctl.intFf)){K(e);return}e.next=D,G(e);},m=e=>{if(e.ctl.busrqFf){Q(e,m);return}e.bus.addr=e.seq.mAddr,e.bus.nRFSH=1,H(e),e.next=je;},je=e=>{e.bus.nMREQ=0,e.bus.data=e.seq.aluVal&255,e.next=Te;},Te=e=>{e.next=Ye;},Ye=e=>{if(e.bus.nWR=0,!e.bus.nWAIT){e.next=Te;return}e.next=Je;},Je=e=>{J(e),e.seq.hasMoreMCycles||$(e),e.next=Ke;},Ke=e=>{if(e.bus.nMREQ=1,e.bus.nWR=1,e.bus.data=void 0,e.seq.lastOpTState&&(e.ctl.nmiAck||e.ctl.intFf)){K(e);return}e.next=D,G(e);},i=e=>{if(e.ctl.busrqFf){Q(e,i);return}e.bus.nRFSH=1,H(e),J(e),e.seq.hasMoreMCycles||$(e),e.next=$e;},$e=e=>{if(e.seq.lastOpTState&&(e.ctl.nmiAck||e.ctl.intFf)){K(e);return}e.next=D,G(e);},V=e=>{if(e.ctl.busrqFf){Q(e,V);return}e.bus.nRFSH=1,H(e),e.next=ce;},ce=e=>{e.next=ue;},ue=e=>{e.next=pe;},pe=e=>{e.next=es;},es=e=>{e.next=ss;},ss=e=>{e.next=ts;},ts=e=>{J(e),e.seq.hasMoreMCycles||$(e),e.next=rs;},rs=e=>{if(e.seq.lastOpTState&&(e.ctl.nmiAck||e.ctl.intFf)){K(e);return}e.next=D,G(e);},se=e=>{if(e.ctl.busrqFf){Q(e,se);return}e.bus.nRFSH=1,H(e),e.next=ns;},ns=e=>{e.next=fs;},fs=e=>{e.next=as;},as=e=>{e.next=xs;},xs=e=>{J(e),e.seq.hasMoreMCycles||$(e),e.next=ls;},ls=e=>{if(e.seq.lastOpTState&&(e.ctl.nmiAck||e.ctl.intFf)){K(e);return}e.next=D,G(e);},u=e=>{if(e.ctl.busrqFf){Q(e,u);return}e.bus.addr=e.seq.mAddr,e.bus.nRFSH=1,H(e),e.next=os;},os=e=>{e.next=is;},is=e=>{e.bus.nIORQ=0,e.bus.nRD=0,e.next=qs;},qs=e=>{e.next=ge;},ge=e=>{e.next=_s;},_s=e=>{if(!e.bus.nWAIT){e.next=ge;return}e.next=Cs;},Cs=e=>{J(e),e.seq.hasMoreMCycles||$(e),e.next=Ms;},Ms=e=>{if(e.bus.nIORQ=1,e.bus.nRD=1,e.seq.aluVal=e.bus.data&255,e.seq.lastOpTState&&(e.ctl.nmiAck||e.ctl.intFf)){K(e);return}e.next=D,G(e);},p=e=>{if(e.ctl.busrqFf){Q(e,p);return}e.bus.addr=e.seq.mAddr,e.bus.nRFSH=1,H(e),e.next=ds;},ds=e=>{e.bus.data=e.seq.aluVal&255,e.next=Ts;},Ts=e=>{e.bus.nIORQ=0,e.bus.nWR=0,e.next=gs;},gs=e=>{e.next=Re;},Re=e=>{e.next=Rs;},Rs=e=>{if(!e.bus.nWAIT){e.next=Re;return}e.next=hs;},hs=e=>{J(e),e.seq.hasMoreMCycles||$(e),e.next=bs;},bs=e=>{if(e.bus.nIORQ=1,e.bus.nWR=1,e.bus.data=void 0,e.seq.lastOpTState&&(e.ctl.nmiAck||e.ctl.intFf)){K(e);return}e.next=D,G(e);},he=e=>{if(e.seq.lastOpTState=false,e.ctl.busrqFf){Q(e,he);return}e.ctl.nmiFf=false,e.bus.addr=e.regs.pc,e.bus.nM1=0,e.bus.nRFSH=1,H(e),e.next=ms;},ms=e=>{e.bus.nMREQ=0,e.bus.nRD=0,e.ctl.sres&&(e.regs.pc=0),e.next=be;},be=e=>{e.next=Zs;},Zs=e=>{if(e.ctl.sres&&(e.ctl.throwAwayM1=true),e.ctl.nres||(e.ctl.sres=e.ctl.resi),!e.bus.nWAIT){e.next=be;return}e.seq.aluDst!==void 0&&Me(e),e.seq.m1T2Exec(e),e.next=ys;},ys=e=>{e.regs.wz=102,e.seq.aluVal=0,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=ee,e.bus.nM1=1,e.bus.nMREQ=1,e.bus.nRD=1,e.bus.addr=e.regs.i<<8|e.regs.r&127|e.regs.r7,e.bus.nRFSH=0,e.next=re;},me=e=>{if(e.seq.lastOpTState=false,e.ctl.busrqFf){Q(e,me);return}e.ctl.intFf=false,e.bus.addr=e.regs.pc,e.bus.nM1=0,e.bus.nRFSH=1,H(e),e.next=Es;},Es=e=>{e.ctl.sres&&(e.regs.pc=0),e.next=As;},As=e=>{e.next=Fs;},Fs=e=>{e.ctl.sres&&(e.ctl.throwAwayM1=true),e.ctl.nres||(e.ctl.sres=e.ctl.resi),e.seq.aluDst!==void 0&&Me(e),e.seq.m1T2Exec(e),e.next=ks;},ks=e=>{e.next=Ns;},Ns=e=>{e.bus.nIORQ=0,e.next=Ze;},Ze=e=>{e.next=Ds;},Ds=e=>{if(!e.bus.nWAIT){e.next=Ze;return}e.next=Vs;},Vs=e=>{e.ctl.imFa?e.ctl.imFb?(e.regs.wz=e.bus.data&255,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=ws):(e.regs.wz=56,e.seq.aluVal=0,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=ee):ye(e.bus.data,e),e.bus.nM1=1,e.bus.nIORQ=1,e.bus.addr=e.regs.i<<8|e.regs.r&127|e.regs.r7,e.bus.nRFSH=0,e.next=re;},l=(e,s)=>{e.id=s;};l(D,0);l(Le,1);l(de,2);l(He,3);l(Qe,4);l(re,5);l(Be,6);l(Se,7);l(d,8);l(ve,9);l(T,10);l(Pe,11);l(ne,12);l(Ge,13);l(Ue,14);l(Xe,15);l(m,16);l(je,17);l(Te,18);l(Ye,19);l(Je,20);l(Ke,21);l(i,22);l($e,23);l(se,24);l(ns,25);l(fs,26);l(as,27);l(xs,28);l(ls,29);l(V,30);l(ce,31);l(ue,32);l(pe,33);l(es,34);l(ss,35);l(ts,36);l(rs,37);l(u,38);l(os,39);l(is,40);l(qs,41);l(ge,42);l(_s,43);l(Cs,44);l(Ms,45);l(p,46);l(ds,47);l(Ts,48);l(gs,49);l(Re,50);l(Rs,51);l(hs,52);l(bs,53);l(he,54);l(ms,55);l(be,56);l(Zs,57);l(ys,58);l(me,59);l(Es,60);l(As,61);l(Fs,62);l(Vs,63);l(ks,64);l(Ns,65);l(Ze,66);l(Ds,67);l(oe,68);l(ie,69);l(qe,70);l(_e,71);l(Ie,72);l(Oe,73);l(Ce,74);var E=128,y=64,M=40,Z=16,A=4,N=2,R=1,w=()=>{},te=e=>(e^=e>>4,154020>>(e&15)&A),Ls=e=>{let{y:s,aluVal:t}=e.seq,f=e.regs.f[e.seq.prefix&1]&R,a,x;switch(s){case 0:a=t>>>7,x=(t<<1|a)&255;break;case 1:a=t&1,x=(a<<7|t>>>1)&255;break;case 2:a=t>>>7,x=(t<<1|f)&255;break;case 3:a=t&1,x=(f<<7|t>>>1)&255;break;default:return}e.seq.aluF=x&M|a,e.seq.aluVal=x;},Ee=e=>{let{y:s,aluVal:t}=e.seq,f=e.regs.f[e.seq.prefix&1]&R,a,x;switch(s){case 0:a=t>>>7,x=(t<<1|a)&255;break;case 1:a=t&1,x=(a<<7|t>>>1)&255;break;case 2:a=t>>>7,x=(t<<1|f)&255;break;case 3:a=t&1,x=(f<<7|t>>>1)&255;break;case 4:a=t>>>7,x=t<<1&255;break;case 5:a=t&1,x=(t&128|t>>>1)&255;break;case 6:a=t>>>7,x=(t<<1|1)&255;break;case 7:a=t&1,x=t>>>1&255;break;default:return}let C=x&(E|M);x===0&&(C|=y),C|=te(x),e.seq.aluF=C|a,e.seq.aluFMask=255,e.seq.aluVal=x;},Hs=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Qs;},Qs=e=>{e.regs.wz=e.seq.aluVal,e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Bs;},Bs=e=>{let s=e.seq.aluVal<<8|e.regs.wz&255;switch(e.seq.mAddr=s,e.seq.y){case 4:e.regs.wz=s+1&65535,e.next=m,e.seq.aluVal=e.regs.file[n[e.seq.prefix][q]],e.seq.hasMoreMCycles=true,e.seq.executor=Ss;break;case 5:e.regs.wz=s+1&65535,e.next=T,e.seq.hasMoreMCycles=true,e.seq.executor=vs;break;case 6:e.regs.wz=e.regs.file[n[e.seq.prefix][o]]<<8|s+1&255,e.next=m,e.seq.aluVal=e.regs.file[n[e.seq.prefix][o]];break;case 7:e.regs.wz=s+1&65535,e.next=T,e.seq.executor=Ae;break}},Ss=e=>{e.seq.mAddr=e.regs.wz,e.seq.aluVal=e.regs.file[n[e.seq.prefix][_]],e.next=m;},vs=e=>{e.regs.file[n[e.seq.prefix][q]]=e.seq.aluVal,e.seq.mAddr=e.regs.wz,e.next=T,e.seq.executor=Ps;},Ps=e=>{e.regs.file[n[e.seq.prefix][_]]=e.seq.aluVal;},Ae=e=>{e.regs.file[n[e.seq.prefix][o]]=e.seq.aluVal;},Gs=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Us;},Us=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Xs;},Xs=e=>{e.next=i,e.seq.executor=js;},js=e=>{let s=e.seq.aluVal<<24>>24,t=e.regs.pc+s&65535;e.regs.wz=t,e.regs.pc=t;},zs=e=>{let s=1;switch(e.seq.y){case 3:break;case 2:{let t=e.regs.file[n[e.seq.prefix][h]]-1&255;e.regs.file[n[e.seq.prefix][h]]=t,s=t;break}case 4:s=~e.regs.f[e.seq.prefix&1]&y;break;case 5:s=e.regs.f[e.seq.prefix&1]&y;break;case 6:s=~e.regs.f[e.seq.prefix&1]&R;break;case 7:s=e.regs.f[e.seq.prefix&1]&R;}s?Gs(e):e.next=d;},Ys=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Js;},Js=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Ks;},Ks=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=$s;},$s=e=>{let s=(e.seq.prefix&24)+12,t=e.regs.file[s]<<8|e.regs.file[s+1],f=e.seq.aluVal<<24>>24;t=t+f&65535,e.regs.wz=t,e.seq.mAddr=t,e.next=T,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=cs;},cs=e=>{e.next=i;let s=e.seq.aluVal,t=e.seq.z&1,f=s+1-(t<<1)&255;e.seq.aluF=f&(E|M)|(f===0?y:0)|(s^f)&Z|(s===127+t?A:0)|t<<1,e.seq.aluFMask=~R&255,e.seq.aluVal=f,e.seq.hasMoreMCycles=true,e.seq.executor=fe;},fe=e=>{e.next=m;},us=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=ps;},ps=e=>{let s=(e.seq.prefix&24)+13,t=e.seq.aluVal<<24>>24;e.regs.wz=e.regs.file[s]+t,e.next=d,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=et;},et=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=st;},st=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=tt;},tt=e=>{let s=(e.seq.prefix&24)+12,t=(e.regs.file[s]<<8)+e.regs.wz&65535;e.regs.wz=t,e.seq.mAddr=t,e.next=m;},rt=e=>{e.seq.prefix=e.seq.prefix^1;},nt=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=zs;},ft=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.executor=at;},at=e=>{e.next=se,e.seq.executor=xt;},xt=e=>{let s=e.seq.y&6,t=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]];e.regs.wz=t+1&65535;let f=s===6?e.regs.sp:e.regs.file[n[e.seq.prefix][s]]<<8|e.regs.file[n[e.seq.prefix][s+1]],a=t+f,x=(t^f^a)>>>8;e.regs.file[n[e.seq.prefix][q]]=a&255;let C=a>>>8&255;e.seq.aluF=C&M|x&Z|x>>>8&R,e.regs.file[n[e.seq.prefix][_]]=C,e.seq.aluFMask=M|Z|N|R;},lt=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=ot;},ot=e=>{let s=e.seq.y&6;s===6?e.regs.sp=e.seq.aluVal:e.regs.file[n[e.seq.prefix][s+1]]=e.seq.aluVal,e.next=d,e.seq.executor=it;},it=e=>{let s=e.seq.y&6;s===6?e.regs.sp=e.seq.aluVal<<8|e.regs.sp&255:e.regs.file[n[e.seq.prefix][s]]=e.seq.aluVal;},qt=e=>{let s=e.seq.y&2,t=s|1,f=e.regs.file[n[e.seq.prefix][s]]<<8|e.regs.file[n[e.seq.prefix][t]],a=e.regs.file[n[e.seq.prefix][o]];e.seq.mAddr=f,e.regs.wz=a<<8|f+1&255,e.seq.aluVal=a,e.next=m;},_t=e=>{let s=e.seq.y&2,t=s|1,f=e.regs.file[n[e.seq.prefix][s]]<<8|e.regs.file[n[e.seq.prefix][t]];e.seq.mAddr=f,e.regs.wz=f+1&65535,e.next=T,e.seq.executor=Ae;},Ct=e=>{let{y:s}=e.seq,t=s&1,f=s&6,a=f+1,x=f===6?e.regs.sp:e.regs.file[n[e.seq.prefix][f]]<<8|e.regs.file[n[e.seq.prefix][a]];x=x+1-(t<<1)&65535,f===6?e.regs.sp=x:(e.regs.file[n[e.seq.prefix][f]]=x>>>8,e.regs.file[n[e.seq.prefix][a]]=x&255),e.next=i,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Mt;},Mt=e=>{e.next=i;},dt=e=>{e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.next=T,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Tt;},Tt=e=>{let s=e.seq.aluVal,t=e.seq.z&1,f=s+1-(t<<1)&255;e.seq.aluF=f&(E|M)|(f===0?y:0)|(s^f)&Z|(s===127+t?A:0)|t<<1,e.seq.aluFMask=~R&255,e.seq.aluVal=f,e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=fe;},gt=e=>{let{y:s,z:t}=e.seq,f=e.regs.file[n[e.seq.prefix][s]],a=t&1,x=f+1-(a<<1)&255;e.seq.aluDst=s,e.seq.aluVal=x,e.seq.aluF=x&(E|M)|(x===0?y:0)|(f^x)&Z|(f===127+a?A:0)|a<<1,e.seq.aluFMask=~R&255;},Rt=e=>{let{y:s}=e.seq;e.next=d,e.seq.hasMoreMCycles=s===6,e.seq.executor=ht;},ht=e=>{let{y:s}=e.seq;if(s===6){e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.next=m;return}e.seq.aluDst=s;},bt=e=>{let{y:s}=e.seq,t=M|Z|N|R,f=e.regs.file[n[e.seq.prefix][o]],a=e.regs.f[e.seq.prefix&1];switch(s){case 4:{t=255;let x=0,C=a&R;(a&Z||(f&15)>9)&&(x=6),(C||f>153)&&(x|=96,C=R);let b=f;f=a&N?f-x&255:f+x&255;let F=a&N|C;F|=f&(E|M),f===0&&(F|=y),F|=te(f),F|=(b^f)&Z,a=F,e.seq.aluVal=f,e.seq.aluDst=o;break}case 5:{t=M|Z|N;let x=~f&255;a=x&M|Z|N,e.seq.aluVal=x,e.seq.aluDst=o;break}case 6:a=(e.seq.fWritten?f:f|a)&M|R;break;case 7:{let x=a&R;a=(e.seq.fWritten?f:f|a)&M,a|=x===0?R:Z;break}}e.seq.aluF=a,e.seq.aluFMask=t;};function mt(e){let{y:s,z:t}=e.seq;if(t===0){if(s===0)return;if(s===1){e.seq.executor=rt;return}e.seq.hasMoreMCycles=true,s===2?(e.seq.hasExtraT=true,e.seq.executor=nt):e.seq.executor=zs;return}if(t===1){e.seq.hasMoreMCycles=true,s&1?e.seq.executor=ft:e.seq.executor=lt;return}if(t===2)switch(e.seq.hasMoreMCycles=true,s){case 0:case 2:e.seq.executor=qt;return;case 1:case 3:e.seq.executor=_t;return;case 4:case 5:case 6:case 7:e.seq.executor=Hs;return}if(t===3){e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Ct;return}if(t===4||t===5){if(s===6){e.seq.hasMoreMCycles=true,e.seq.executor=e.seq.prefix&24?Ys:dt;return}e.seq.executor=gt;}if(t===6){if(e.seq.hasMoreMCycles=true,s===6&&e.seq.prefix&24){e.seq.executor=us;return}e.seq.executor=Rt;return}if(t===7){if(s<4){e.seq.aluDst=7,e.seq.aluVal=e.regs.file[n[e.seq.prefix][o]],e.seq.aluFMask=M|Z|N|R,e.seq.executor=Ls;return}e.seq.executor=bt;}}var Zt=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=yt;},yt=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Et;},Et=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=At;},At=e=>{let s=(e.seq.prefix&24)+12,t=e.regs.file[s]<<8|e.regs.file[s+1],f=e.seq.aluVal<<24>>24;t=t+f&65535,e.regs.wz=t,e.seq.mAddr=t,e.next=T,e.seq.executor=Ft;},Ft=e=>{e.seq.prefix=e.seq.prefix&7,e.seq.aluDst=e.seq.y;},kt=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Nt;},Nt=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Dt;},Dt=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=Vt;},Vt=e=>{let s=(e.seq.prefix&24)+12,t=e.regs.file[s]<<8|e.regs.file[s+1],f=e.seq.aluVal<<24>>24;t=t+f&65535,e.regs.wz=t,e.seq.mAddr=t,e.seq.aluVal=e.regs.file[n[e.seq.prefix&7][e.seq.z]],e.next=m;},wt=e=>{e.ctl.haltLatch=true,e.bus.nHALT=0;},zt=e=>{e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.seq.aluVal=e.regs.file[n[e.seq.prefix][e.seq.z]],e.next=m;},Wt=e=>{e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.next=T,e.seq.executor=It;},It=e=>{e.seq.aluDst=e.seq.y;},Ot=e=>{let{y:s,z:t}=e.seq;e.seq.aluDst=s,e.seq.aluVal=e.regs.file[n[e.seq.prefix][t]];};function Lt(e){let{y:s,z:t}=e.seq;if(s===6&&t===6){e.seq.executor=wt;return}if(s===6){e.seq.hasMoreMCycles=true,e.seq.executor=e.seq.prefix&24?kt:zt;return}if(t===6){e.seq.hasMoreMCycles=true,e.seq.executor=e.seq.prefix&24?Zt:Wt;return}e.seq.executor=Ot;}var ae=e=>{let{y:s}=e.seq,t=e.regs.file[n[e.seq.prefix][o]],f=e.seq.aluVal,a=0,x=0;s===4&&(a=t&f,x=Z),s===5&&(a=t^f),s===6&&(a=t|f),x|=a&(E|M),a===0&&(x|=y),x|=te(a),e.seq.aluFMask=255,e.seq.aluF=x,e.seq.aluDst=o,e.seq.aluVal=a&255;},xe=e=>{let{y:s}=e.seq,t=e.regs.file[n[e.seq.prefix][o]],f=e.seq.aluVal,a=t^f,x=f,C=s===1||s===3?e.regs.f[e.seq.prefix&1]&R:0;(s===2||s===3||s===7)&&(f=~f,C=C?0:1);let b=t+f+C;C=a^b;let F=b&255;s!==7&&(e.seq.aluDst=o,x=F),x&=M,(s===2||s===3||s===7)&&(x|=N),F===0&&(x|=y),x|=F&E|C&Z|(~(t^f)&(t^F)&128)>>>5|C>>>8&R,e.seq.aluFMask=255,e.seq.aluF=x,e.seq.aluVal=F;},Ht=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Qt;},Qt=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Bt;},Bt=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=St;},St=e=>{let{y:s}=e.seq,t=(e.seq.prefix&24)+12,f=e.regs.file[t]<<8|e.regs.file[t+1],a=e.seq.aluVal<<24>>24;f=f+a&65535,e.regs.wz=f,e.seq.mAddr=f,e.next=T,e.seq.executor=s<7&&s>3?ae:xe;},vt=e=>{let{y:s}=e.seq;e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.next=T,e.seq.executor=s<7&&s>3?ae:xe;};function Pt(e){let{y:s,z:t}=e.seq;t===6?(e.seq.hasMoreMCycles=true,e.seq.executor=e.seq.prefix&24?Ht:vt):(e.seq.aluVal=e.regs.file[n[e.seq.prefix][t]],e.seq.executor=s<7&&s>3?ae:xe);}var Fe=e=>{e.seq.mAddr=e.regs.sp,e.seq.hasMoreMCycles=true,e.next=T,e.seq.executor=Gt;},Gt=e=>{e.regs.wz=e.seq.aluVal,e.seq.mAddr=e.regs.sp+1&65535,e.next=T,e.seq.executor=Ut;},Ut=e=>{let s=e.seq.aluVal<<8|e.regs.wz&255;e.regs.sp=e.regs.sp+2&65535,e.regs.wz=s,e.regs.pc=s;},ee=e=>{e.regs.wz=e.seq.aluVal<<8|e.regs.wz&255,e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=Xt;},Xt=e=>{e.seq.mAddr=e.regs.sp-1&65535,e.seq.aluVal=e.regs.pc>>>8,e.seq.hasMoreMCycles=true,e.next=m,e.seq.executor=jt;},jt=e=>{let s=e.regs.sp-2&65535;e.seq.mAddr=s,e.regs.sp=s,e.seq.aluVal=e.regs.pc&255,e.regs.pc=e.regs.wz,e.next=m;},Yt=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Jt;},Jt=e=>{let s=(e.seq.prefix&24)+13,t=e.seq.aluVal<<24>>24;e.regs.wz=e.regs.file[s]+t,e.next=d,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Kt;},Kt=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=$t;},$t=e=>{e.seq.op=e.seq.aluVal,e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=ct;},ct=e=>{let s=(e.seq.prefix&24)+12,t=(e.regs.file[s]<<8)+e.regs.wz&65535;e.regs.wz=t,e.seq.mAddr=t,e.next=T,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,(e.seq.op&192)===64?e.seq.executor=ut:e.seq.executor=pt,e.seq.cbFf=0,e.seq.m1T2Exec=w;},ut=e=>{e.seq.y=e.seq.op>>3&7,ke(e,e.seq.aluVal,e.regs.wz>>>8),e.next=i;},pt=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=er;},er=e=>{let{op:s}=e.seq,t=s>>6&3;e.seq.y=s>>3&7;let f=s&7;switch(t){case 0:Ee(e);break;case 2:case 3:{let a=1<<e.seq.y;e.seq.aluVal=s&64?e.seq.aluVal|a:e.seq.aluVal&~a&255;}}e.next=m,f!==6&&(e.seq.aluDst=f,e.seq.prefix=e.seq.prefix&7);},sr=e=>{let s=e.regs.f[e.seq.prefix&1];switch(e.seq.y){case 0:s=~s&y;break;case 1:s&=y;break;case 2:s=~s&R;break;case 3:s&=R;break;case 4:s=~s&A;break;case 5:s&=A;break;case 6:s=~s&E;break;case 7:s&=E;break}e.next=i,s&&(e.seq.hasMoreMCycles=true,e.seq.executor=Fe);},tr=e=>{e.seq.prefix=e.seq.prefix^2,e.seq.prefix=e.seq.prefix&27|(e.seq.prefix&2?e.seq.exDe1:e.seq.exDe0);},rr=e=>{e.regs.pc=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]];},nr=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=fr;},fr=e=>{e.next=i,e.seq.executor=ar;},ar=e=>{e.regs.sp=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]];},xr=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=lr;},lr=e=>{e.regs.wz=e.seq.aluVal,e.next=d,e.seq.executor=or;},or=e=>{let s=e.regs.f[e.seq.prefix&1],{y:t}=e.seq,f=e.seq.aluVal<<8|e.regs.wz&255;switch(e.regs.wz=f,t){case 0:s=~s&y;break;case 1:s&=y;break;case 2:s=~s&R;break;case 3:s&=R;break;case 4:s=~s&A;break;case 5:s&=A;break;case 6:s=~s&E;break;case 7:s&=E;break}s&&(e.regs.pc=f);},ir=e=>{e.seq.cbFf=1,e.seq.m1T2Exec=qr;},qr=e=>{e.seq.cbFf=0,e.seq.prefix=e.seq.prefix&7,e.seq.m1T2Exec=w;},_r=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Cr;},Cr=e=>{e.regs.wz=e.seq.aluVal,e.next=d,e.seq.executor=Mr;},Mr=e=>{let s=e.seq.aluVal<<8|e.regs.wz&255;e.regs.wz=s,e.regs.pc=s;},dr=e=>{e.seq.mAddr=e.regs.sp,e.seq.hasMoreMCycles=true,e.next=T,e.seq.executor=Tr;},Tr=e=>{e.regs.wz=e.seq.aluVal,e.seq.mAddr=e.regs.sp+1&65535,e.next=T,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=gr;},gr=e=>{e.regs.wz=e.seq.aluVal<<8|e.regs.wz&255,e.seq.hasMoreMCycles=true,e.next=i,e.seq.executor=Rr;},Rr=e=>{e.seq.mAddr=e.regs.sp+1&65535,e.seq.aluVal=e.regs.file[n[e.seq.prefix][_]],e.seq.hasMoreMCycles=true,e.next=m,e.seq.executor=hr;},hr=e=>{e.seq.mAddr=e.regs.sp,e.seq.aluVal=e.regs.file[n[e.seq.prefix][q]],e.next=m,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=br;},br=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=mr;},mr=e=>{e.regs.file[n[e.seq.prefix][_]]=e.regs.wz>>>8,e.regs.file[n[e.seq.prefix][q]]=e.regs.wz&255,e.next=i;},Zr=e=>{e.seq.prefix&2?(e.seq.exDe1^=4,e.seq.prefix=e.seq.prefix&27|e.seq.exDe1):(e.seq.exDe0^=4,e.seq.prefix=e.seq.prefix&27|e.seq.exDe0);},yr=e=>{e.ctl.iff1=e.ctl.iff2=e.seq.y&1;},Er=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Ar;},Ar=e=>{let s=e.regs.file[n[e.seq.prefix][o]]<<8|e.seq.aluVal;e.seq.mAddr=s,e.regs.wz=s+1&65535,e.next=u,e.seq.executor=Ae;},Fr=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=kr;},kr=e=>{let s=e.regs.file[n[e.seq.prefix][o]],t=s<<8|e.seq.aluVal;e.seq.mAddr=t++,e.regs.wz=s<<8|t&255,e.seq.aluVal=s,e.next=p;},Nr=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Dr;},Dr=e=>{let s=e.regs.f[e.seq.prefix&1],{y:t}=e.seq;switch(e.regs.wz=e.seq.aluVal,e.next=d,t){case 0:s=~s&y;break;case 1:s&=y;break;case 2:s=~s&R;break;case 3:s&=R;break;case 4:s=~s&A;break;case 5:s&=A;break;case 6:s=~s&E;break;case 7:s&=E;break}s?(e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=ee):e.seq.executor=Vr;},Vr=e=>{e.regs.wz=e.seq.aluVal<<8|e.regs.wz&255;},wr=e=>{e.seq.prefix=e.seq.prefix&7,e.seq.edFf=1,e.seq.m1T2Exec=zr;},zr=e=>{e.seq.edFf=0,e.seq.m1T2Exec=w;},Wr=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Ir;},Ir=e=>{e.regs.wz=e.seq.aluVal,e.next=d,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=ee;},Or=e=>{e.seq.prefix=e.seq.prefix&7|8,e.seq.m1T2Exec=Ws;},Lr=e=>{e.seq.prefix=e.seq.prefix&7|16,e.seq.m1T2Exec=Ws;},Ws=e=>{e.seq.prefix=e.seq.prefix&7,e.seq.m1T2Exec=w;},Hr=e=>{e.seq.hasMoreMCycles=true,e.next=i,e.seq.executor=Qr;},Qr=e=>{e.seq.mAddr=e.regs.sp-1&65535;let s=e.seq.y&6;e.seq.aluVal=s===6?e.regs.file[n[e.seq.prefix][o]]:e.regs.file[n[e.seq.prefix][s]],e.seq.hasMoreMCycles=true,e.next=m,e.seq.executor=Br;},Br=e=>{let s=e.regs.sp-2&65535;e.seq.mAddr=s,e.regs.sp=s;let t=(e.seq.y&6)+1;e.seq.aluVal=t===7?e.regs.f[e.seq.prefix&1]:e.regs.file[n[e.seq.prefix][t]],e.next=m;},Sr=e=>{e.next=d;let{y:s}=e.seq;e.seq.executor=s<7&&s>3?ae:xe;},vr=e=>{e.seq.mAddr=e.regs.sp,e.seq.hasMoreMCycles=true,e.next=T,e.seq.executor=Pr;},Pr=e=>{let s=(e.seq.y&6)+1;s===7?e.regs.f[e.seq.prefix&1]=e.seq.aluVal:e.regs.file[n[e.seq.prefix][s]]=e.seq.aluVal,e.seq.mAddr=e.regs.sp+1&65535,e.next=T,e.seq.executor=Gr;},Gr=e=>{let s=e.seq.y&6;s===6?e.regs.file[n[e.seq.prefix][o]]=e.seq.aluVal:e.regs.file[n[e.seq.prefix][s]]=e.seq.aluVal,e.regs.sp=e.regs.sp+2&65535;};function Ur(e){let{y:s,z:t}=e.seq;if(t===0){e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=sr;return}if(t===1){switch(s){case 1:e.seq.hasMoreMCycles=true,e.seq.executor=Fe;return;case 3:e.seq.executor=tr;return;case 5:e.seq.executor=rr;return;case 7:e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=nr;return}e.seq.hasMoreMCycles=true,e.seq.executor=vr;return}if(t===2){e.seq.hasMoreMCycles=true,e.seq.executor=xr;return}if(t===3){if(s===1){e.seq.hasMoreMCycles=true,e.seq.prefix&24&&(e.seq.executor=Yt),e.seq.m1T2Exec=ir;return}if(s===0){e.seq.hasMoreMCycles=true,e.seq.executor=_r;return}if(s===4){e.seq.hasMoreMCycles=true,e.seq.executor=dr;return}if(s===5){e.seq.executor=Zr;return}if(s===6||s===7){e.ctl.skipInts=true,e.seq.executor=yr;return}if(s===3){e.seq.hasMoreMCycles=true,e.seq.executor=Er;return}if(s===2){e.seq.hasMoreMCycles=true,e.seq.executor=Fr;return}}if(t===4){e.seq.hasMoreMCycles=true,e.seq.executor=Nr;return}if(t===5){switch(s){case 5:e.seq.hasMoreMCycles=true,e.seq.m1T2Exec=wr;return;case 1:e.seq.hasMoreMCycles=true,e.seq.executor=Wr;return;case 3:e.seq.hasMoreMCycles=true,e.seq.m1T2Exec=Or;return;case 7:e.seq.hasMoreMCycles=true,e.seq.m1T2Exec=Lr;return}e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Hr;return}if(t===6){e.seq.hasMoreMCycles=true,e.seq.executor=Sr;return}t===7&&(e.regs.wz=s<<3,e.seq.aluVal=0,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=ee);}var ke=(e,s,t)=>{let f=e.seq.y,a=s&1<<f,x=t&M|Z;a===0&&(x|=y|A),a&128&&(x|=E),e.seq.aluF=x,e.seq.aluFMask=~R&255;},Xr=e=>{e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.next=T,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=jr;},jr=e=>{Ee(e),e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=fe;},Yr=e=>{let{z:s}=e.seq;if(s===6){e.seq.hasMoreMCycles=true,e.seq.executor=Xr;return}e.seq.aluDst=s,e.seq.aluVal=e.regs.file[n[e.seq.prefix][s]],e.seq.executor=Ee;},Jr=e=>{e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.next=T,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Kr;},Kr=e=>{ke(e,e.seq.aluVal,e.regs.wz>>>8),e.next=i;},$r=e=>{let s=e.regs.file[n[e.seq.prefix][e.seq.z]];ke(e,s,s);},cr=e=>{let{z:s}=e.seq;if(s===6){e.seq.hasMoreMCycles=true,e.seq.executor=Jr;return}e.seq.executor=$r;},ur=e=>{e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.next=T,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=pr;},pr=e=>{let s=1<<e.seq.y;e.seq.aluVal=e.seq.op&64?e.seq.aluVal|s:e.seq.aluVal&~s&255,e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=fe;},en=e=>{let s=1<<e.seq.y;e.seq.aluVal=e.seq.op&64?e.seq.aluVal|s:e.seq.aluVal&~s&255;},sn=e=>{let{z:s}=e.seq;if(s===6){e.seq.hasMoreMCycles=true,e.seq.executor=ur;return}e.seq.aluDst=s,e.seq.aluVal=e.regs.file[n[e.seq.prefix][e.seq.z]],e.seq.executor=en;},tn=e=>{e.ctl.iff1=e.ctl.iff2,e.seq.edFf=0,e.seq.m1T2Exec=w;},rn=e=>{let{y:s}=e.seq;e.ctl.imFa=s>>1&1,e.ctl.imFb=s&1;},nn=e=>{e.seq.mAddr=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]],e.next=T,e.seq.hasMoreMCycles=true,e.seq.executor=fn;},fn=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.executor=an;},an=e=>{let s=e.regs.file[n[e.seq.prefix][o]],t=s&240,f=s&15,a=e.seq.aluVal>>>4,x=e.seq.aluVal&15;e.seq.aluVal=e.seq.y&1?(t|a)<<8|x<<4|f:(t|x)<<8|f<<4|a,e.next=m,e.seq.executor=xn;},xn=e=>{e.regs.wz=e.seq.mAddr+1&65535;let s=e.seq.aluVal>>>8,t=s&(E|M);s===0&&(t|=y),t|=te(s),e.seq.aluVal=s,e.seq.aluDst=o,e.seq.aluF=t,e.seq.aluFMask=254;},ln=e=>{let{y:s}=e.seq;switch(e.next=i,s){case 0:e.regs.i=e.regs.file[n[e.seq.prefix][o]];return;case 1:e.regs.r=e.regs.file[n[e.seq.prefix][o]]&127,e.regs.r7=e.regs.file[n[e.seq.prefix][o]]&128;return;case 2:case 3:{let t=s&1?e.regs.r|e.regs.r7:e.regs.i;e.seq.aluVal=t,e.seq.aluDst=o;let f=t&(E|M);t===0&&(f|=y),e.seq.aluF=f,e.seq.aluFMask=254;return}}},on=e=>{let s=e.regs.file[n[e.seq.prefix][h]]<<8|e.regs.file[n[e.seq.prefix][k]]&255;if(e.seq.mAddr=s,e.regs.wz=s+1&65535,e.seq.z){e.seq.aluVal=e.regs.file[n[e.seq.prefix][e.seq.y]],e.next=p;return}e.next=u,e.seq.executor=qn;},qn=e=>{let{y:s}=e.seq,t=e.seq.aluVal,f=t&(M|E);t===0&&(f|=y),f|=te(t),e.seq.aluFMask=254,e.seq.aluF=f,s!==6&&(e.seq.aluVal=t,e.seq.aluDst=s);},_n=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.executor=Cn;},Cn=e=>{e.next=se,e.seq.executor=Mn;},Mn=e=>{let{y:s}=e.seq,t=s&6,f=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]];e.regs.wz=f+1&65535;let a=t===6?e.regs.sp:e.regs.file[n[e.seq.prefix][t]]<<8|e.regs.file[n[e.seq.prefix][t+1]],x=e.regs.f[e.seq.prefix&1]&R,C=f^a;(s&1)===0&&(a=~a,x=x?0:1);let b=f+a+x;x=(C^b)>>>8,e.regs.file[n[e.seq.prefix][q]]=b&255;let F=b>>>8&255;e.regs.file[n[e.seq.prefix][_]]=F;let c=F&(E|M);(s&1)===0&&(c|=N),(b&65535)===0&&(c|=y),c|=x&Z|(~(f^a)&(f^b)&32768)>>>13|x>>>8&R,e.seq.aluFMask=255,e.seq.aluF=c;},dn=e=>{e.next=d,e.seq.hasMoreMCycles=true,e.seq.executor=Tn;},Tn=e=>{if(e.regs.wz=e.seq.aluVal,e.next=d,e.seq.hasMoreMCycles=true,e.seq.y&1){e.seq.executor=gn;return}e.seq.executor=bn;},gn=e=>{e.seq.mAddr=e.seq.aluVal<<8|e.regs.wz&255,e.next=T,e.seq.hasMoreMCycles=true,e.seq.executor=Rn;},Rn=e=>{let s=e.seq.y&6;s===6?e.regs.sp=e.seq.aluVal&255:e.regs.file[n[e.seq.prefix][s+1]]=e.seq.aluVal;let t=e.seq.mAddr+1&65535;e.seq.mAddr=t,e.regs.wz=t,e.next=T,e.seq.executor=hn;},hn=e=>{let s=e.seq.y&6;s===6?e.regs.sp=e.seq.aluVal<<8|e.regs.sp:e.regs.file[n[e.seq.prefix][s]]=e.seq.aluVal;},bn=e=>{e.seq.mAddr=e.seq.aluVal<<8|e.regs.wz&255;let s=e.seq.y&6;e.seq.aluVal=s===6?e.regs.sp&255:e.regs.file[n[e.seq.prefix][s+1]],e.next=m,e.seq.hasMoreMCycles=true,e.seq.executor=mn;},mn=e=>{let s=e.seq.mAddr+1&65535;e.seq.mAddr=s,e.regs.wz=s;let t=e.seq.y&6;e.seq.aluVal=t===6?e.regs.sp>>>8:e.regs.file[n[e.seq.prefix][t]],e.next=m;},Zn=e=>{let s=e.regs.file[n[e.seq.prefix][o]],t=~s+1,f=s^t,a=t&255,x=a&M|N;a===0&&(x|=y),x|=a&E|f&Z|(s&a&128)>>>5|f>>>8&R,e.seq.aluFMask=255,e.seq.aluF=x,e.seq.aluDst=o,e.seq.aluVal=a;},yn=e=>{let{y:s,z:t}=e.seq;switch(t){case 0:case 1:e.seq.hasMoreMCycles=true,e.seq.executor=on;return;case 2:e.seq.hasMoreMCycles=true,e.seq.executor=_n;return;case 3:e.seq.hasMoreMCycles=true,e.seq.executor=dn;return;case 4:e.seq.executor=Zn;return;case 5:e.seq.hasMoreMCycles=true,e.seq.executor=Fe,e.seq.m1T2Exec=tn;return;case 6:e.seq.executor=rn;return;case 7:if((s&6)===6)return;if(s&4){e.seq.hasMoreMCycles=true,e.seq.executor=nn;return}e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=ln;}},Is=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=En;},En=e=>{e.next=i,e.seq.executor=An;},An=e=>{let s=e.regs.pc;e.regs.wz=--s&65535,e.regs.pc=--s&65535;let t=e.seq.aluF&199|e.regs.pc>>>8&M,f=e.regs.file[n[e.seq.prefix][h]]&15;t&R&&(f=t&N?--f:++f,t|=f&Z);let a=f&7;t^=(a^a<<1^a<<2)&A,e.seq.aluF=t;},Fn=e=>{let s=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]];e.seq.mAddr=e.seq.y&1?s--:s++,e.regs.file[n[e.seq.prefix][q]]=s&255,e.regs.file[n[e.seq.prefix][_]]=s>>>8&255,e.next=T,e.seq.hasMoreMCycles=true,e.seq.executor=kn;},kn=e=>{let s=e.regs.file[n[e.seq.prefix][O]]<<8|e.regs.file[n[e.seq.prefix][L]];e.seq.mAddr=e.seq.y&1?s--:s++,e.regs.file[n[e.seq.prefix][L]]=s&255,e.regs.file[n[e.seq.prefix][O]]=s>>>8&255,e.next=m,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Nn;},Nn=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Dn;},Dn=e=>{let s=(e.regs.file[n[e.seq.prefix][h]]<<8|e.regs.file[n[e.seq.prefix][k]])-1&65535;e.regs.file[n[e.seq.prefix][k]]=s&255,e.regs.file[n[e.seq.prefix][h]]=s>>>8,e.next=i,e.seq.y&2&&s&&(e.seq.hasMoreMCycles=true,e.seq.executor=Vn);let t=e.regs.file[n[e.seq.prefix][o]],f=s===0?0:A,a=t+e.seq.aluVal;e.seq.aluF=(a<<4|a&15)&M|f,e.seq.aluFMask=M|Z|N|A;},Vn=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=wn;},wn=e=>{e.next=i,e.seq.executor=zn;},zn=e=>{let s=e.regs.pc;e.regs.wz=--s&65535,e.regs.pc=--s&65535,e.seq.aluF=e.regs.pc>>>8&M|A,e.seq.aluFMask=M|Z|N|A;},Wn=e=>{let s=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]];e.seq.mAddr=e.seq.y&1?s--:s++,e.regs.file[n[e.seq.prefix][q]]=s&255,e.regs.file[n[e.seq.prefix][_]]=s>>>8&255,e.next=T,e.seq.hasMoreMCycles=true,e.seq.executor=In;},In=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=On;},On=e=>{let{y:s}=e.seq,t=(e.regs.file[n[e.seq.prefix][h]]<<8|e.regs.file[n[e.seq.prefix][k]])-1&65535;e.regs.file[n[e.seq.prefix][k]]=t&255,e.regs.file[n[e.seq.prefix][h]]=t>>>8;let f=e.regs.file[n[e.seq.prefix][o]],a=f+~e.seq.aluVal+1;e.next=i,s&2&&t&&a&&(e.seq.aluVal=a,e.seq.hasMoreMCycles=true,e.seq.executor=Ln);let x=(f^e.seq.aluVal^a)&Z,C=x?a-1<<4|a-1&15:a<<4|a&15;C&=M,a===0&&(C|=y),t&&(C|=A),C|=N|x,C|=a&E,e.seq.aluF=C,e.seq.aluFMask=254;},Ln=e=>{e.next=V,e.seq.hasMoreMCycles=true,e.seq.hasExtraT=true,e.seq.executor=Hn;},Hn=e=>{e.next=i,e.seq.executor=Qn;},Qn=e=>{let s=e.regs.pc;e.regs.wz=--s&65535,e.regs.pc=--s&65535;let t=e.regs.pc>>>8&M|A,f=M|Z|N|A;t|=e.seq.aluVal&(E|Z),t|=N,f|=E|y,e.seq.aluF=t,e.seq.aluFMask=f;},Bn=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=Sn;},Sn=e=>{let s=e.regs.file[n[e.seq.prefix][h]],t=e.regs.file[n[e.seq.prefix][k]],f=s<<8|t;e.seq.mAddr=f,e.regs.file[n[e.seq.prefix][h]]=s-1&255,e.regs.wz=(e.seq.y&1?--f:++f)&65535,e.next=u,e.seq.hasMoreMCycles=true,e.seq.executor=vn;},vn=e=>{let s=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]];e.seq.mAddr=e.seq.y&1?s--:s++,e.regs.file[n[e.seq.prefix][q]]=s&255,e.regs.file[n[e.seq.prefix][_]]=s>>>8&255;let t=e.regs.file[n[e.seq.prefix][h]],f=t&(E|M);t===0&&(f|=y),f|=e.seq.aluVal>>>6&N;let a=e.seq.aluVal+(e.regs.wz&255);f|=a>>>8,f|=a>>>4&Z;let x=t;x^=t>>4,x^=a&7,x^=x<<2,x^=x>>1,f|=~x&A,e.seq.aluF=f,e.seq.aluFMask=255,e.next=m,e.seq.y&2&&t&&(e.seq.hasMoreMCycles=true,e.seq.executor=Is);},Pn=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=Gn;},Gn=e=>{let s=e.regs.file[n[e.seq.prefix][_]]<<8|e.regs.file[n[e.seq.prefix][q]];e.seq.mAddr=e.seq.y&1?s--:s++,e.regs.file[n[e.seq.prefix][q]]=s&255,e.regs.file[n[e.seq.prefix][_]]=s>>>8&255,e.next=T,e.seq.hasMoreMCycles=true,e.seq.executor=Un;},Un=e=>{let s=--e.regs.file[n[e.seq.prefix][h]]&255,t=e.regs.file[n[e.seq.prefix][k]],f=s<<8|t;e.seq.mAddr=f,e.regs.file[n[e.seq.prefix][h]]=s,e.regs.wz=(e.seq.y&1?--f:++f)&65535;let a=e.regs.file[n[e.seq.prefix][q]],x=s&(E|M);s===0&&(x|=y),x|=e.seq.aluVal>>>6&N;let C=e.seq.aluVal+a;x|=C>>>8,x|=C>>>4&Z;let b=s;b^=s>>4,b^=C&7,b^=b<<2,b^=b>>1,x|=~b&A,e.seq.aluF=x,e.seq.aluFMask=255,e.next=p,e.seq.y&2&&s&&(e.seq.hasMoreMCycles=true,e.seq.executor=Is);},Xn=e=>{let{y:s,z:t}=e.seq;if(s&4)switch(e.seq.hasMoreMCycles=true,t){case 0:e.seq.executor=Fn;return;case 1:e.seq.executor=Wn;return;case 2:e.seq.hasExtraT=true,e.seq.executor=Bn;return;case 3:e.seq.hasExtraT=true,e.seq.executor=Pn;}},ye=(e,s)=>{let t=e>>6&3;if(s.seq.op=e&255,s.seq.y=e>>3&7,s.seq.z=e&7,s.seq.executor=w,s.seq.hasMoreMCycles=false,s.seq.cbFf){switch(t){case 0:Yr(s);break;case 1:cr(s);break;case 2:case 3:sn(s);break}return}if(s.seq.edFf){switch(t){case 1:yn(s);break;case 2:Xn(s);break}return}switch(t){case 0:mt(s);break;case 1:Lt(s);break;case 2:Pt(s);break;case 3:Ur(s);break}},ws=e=>{e.next=i,e.seq.hasMoreMCycles=true,e.seq.executor=jn;},jn=e=>{e.seq.mAddr=e.regs.sp-1&65535,e.seq.aluVal=e.regs.pc>>>8,e.next=m,e.seq.hasMoreMCycles=true,e.seq.executor=Yn;},Yn=e=>{let s=e.regs.sp-2&65535;e.seq.mAddr=s,e.regs.sp=s,e.seq.aluVal=e.regs.pc&255,e.next=m,e.seq.hasMoreMCycles=true,e.seq.executor=Jn;},Jn=e=>{let s=e.regs.i<<8|e.regs.wz;e.seq.mAddr=s,e.regs.wz=s+1&65535,e.next=T,e.seq.hasMoreMCycles=true,e.seq.executor=Kn;},Kn=e=>{e.seq.mAddr=e.regs.wz,e.regs.wz=e.seq.aluVal,e.next=T,e.seq.executor=$n;},$n=e=>{let s=(e.seq.aluVal<<8|e.regs.wz)&65535;e.regs.wz=s,e.regs.pc=s;};function cn(e){return {s:(e&128)!==0,z:(e&64)!==0,x5:(e&32)!==0,h:(e&16)!==0,x3:(e&8)!==0,pv:(e&4)!==0,n:(e&2)!==0,c:(e&1)!==0}}function Ne(e,s={main:{},alt:{}}){let t=e.regs.file,f=e.regs.f,a=e.seq.prefix&7,x=a&2,C=x?e.seq.exDe0:e.seq.exDe1,b=n[a],F=n[a&1|x^2|C],c=n[a^1],g=s;return g.pc=e.regs.pc,g.sp=e.regs.sp,g.ix=t[B]<<8|t[S],g.iy=t[v]<<8|t[P],g.i=e.regs.i,g.r=e.regs.r&127|e.regs.r7,g.wz=e.regs.wz,g.main.b=t[b[0]],g.main.c=t[b[1]],g.main.d=t[b[2]],g.main.e=t[b[3]],g.main.h=t[b[4]],g.main.l=t[b[5]],g.main.a=t[b[7]],g.main.f=f[a&1],g.alt.b=t[F[0]],g.alt.c=t[F[1]],g.alt.d=t[F[2]],g.alt.e=t[F[3]],g.alt.h=t[F[4]],g.alt.l=t[F[5]],g.alt.a=t[c[7]],g.alt.f=f[a&1^1],g.im=e.ctl.imFa===0?0:e.ctl.imFb===0?1:2,g.imUndocumented=e.ctl.imFa===0&&e.ctl.imFb!==0,g.iff1=!!e.ctl.iff1,g.iff2=!!e.ctl.iff2,g.nmiPending=!!e.ctl.nmiFf,g}var h=0,k=1,O=2,L=3,_=4,q=5,o=7,z=8,W=9,U=10,X=11,j=12,Y=13,I=15,B=20,S=21,v=28,P=29,n=[[h,k,O,L,_,q,6,o],[h,k,O,L,_,q,6,I],[z,W,U,X,j,Y,6,o],[z,W,U,X,j,Y,6,I],[h,k,_,q,O,L,6,o],[h,k,_,q,O,L,6,I],[z,W,j,Y,U,X,6,o],[z,W,j,Y,U,X,6,I],[h,k,O,L,B,S,-1,o],[h,k,O,L,B,S,-1,I],[z,W,U,X,B,S,-1,o],[z,W,U,X,B,S,-1,I],[h,k,_,q,B,S,-1,o],[h,k,_,q,B,S,-1,I],[z,W,j,Y,B,S,-1,o],[z,W,j,Y,B,S,-1,I],[h,k,O,L,v,P,-1,o],[h,k,O,L,v,P,-1,I],[z,W,U,X,v,P,-1,o],[z,W,U,X,v,P,-1,I],[h,k,_,q,v,P,-1,o],[h,k,_,q,v,P,-1,I],[z,W,j,Y,v,P,-1,o],[z,W,j,Y,v,P,-1,I]],De=class{file=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];f=[0,0];sp=0;pc=0;i=0;r=0;r7=0;wz=0},Ve=class{addr=0;data=void 0;nM1=1;nMREQ=1;nIORQ=1;nRD=1;nWR=1;nRFSH=1;nHALT=1;nBUSACK=1;nRESET=1;nINT=1;nWAIT=1;nBUSRQ=1},we=class{op=0;y=0;z=0;executor=w;hasMoreMCycles=false;hasExtraT=false;mAddr=0;aluDst=void 0;aluVal=0;aluF=void 0;aluFMask=0;fWritten=false;cbFf=0;edFf=0;m1T2Exec=w;prefix=0;exDe0=0;exDe1=0;lastOpTState=false;phase=true},ze=class{skipInts=false;iff1=0;iff2=0;intFf=false;nmiFf=false;nmiAck=false;imFa=0;imFb=0;haltLatch=false;resi=false;nres=false;sres=false;throwAwayM1=false;qres=false;resetAtT1=false;busrqFf=false;busGrantResume=void 0},We=class{regs=new De;bus=new Ve;seq=new we;ctl=new ze;next=D;get nextStep(){return this.next.id}clockEdge(){if(this.seq.phase=!this.seq.phase,!this.seq.phase)this.ctl.resi=!this.bus.nRESET;else if(this.ctl.nres)this.next=oe;else if(this.ctl.resi&&!(this.nextStep===3||this.nextStep===57||this.nextStep===62)){this.ctl.nres=true,this.ctl.sres=false;let s=this.nextStep;this.ctl.resetAtT1=s===1||s===55||s===60,this.ctl.iff1=0,this.ctl.iff2=0,this.ctl.imFa=0,this.ctl.imFb=0,this.seq.cbFf=0,this.seq.edFf=0,this.bus.nHALT=1;}this.next(this);}nmi(){this.ctl.nmiAck||(this.ctl.nmiFf=true);}snapshot(s){return Ne(this,s)}};export{o as A,I as A_,h as B,z as B_,k as C,W as C_,O as D,U as D_,L as E,X as E_,_ as H,j as H_,B as IXH,S as IXL,v as IYH,P as IYL,q as L,Y as L_,le as StepId,We as Z80Cpu,cn as decodeFlags,Ne as snapshotCpu};
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@dcorp80/z80cpu",
3
+ "version": "0.1.0",
4
+ "description": "The hardware-accurate Z80 CPU emulator",
5
+ "keywords": [
6
+ "z80",
7
+ "zilog",
8
+ "cpu",
9
+ "emulator",
10
+ "z80-emulator",
11
+ "zx-spectrum",
12
+ "retrocomputing",
13
+ "emulation",
14
+ "8-bit",
15
+ "typescript",
16
+ "javascript",
17
+ "browser",
18
+ "cycle-accurate",
19
+ "hardware-emulation"
20
+ ],
21
+ "bugs": {
22
+ "url": "https://github.com/dcorp80/z80cpu-lab/issues"
23
+ },
24
+ "license": "Apache-2.0",
25
+ "author": "dcorp80",
26
+ "type": "module",
27
+ "sideEffects": false,
28
+ "main": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "NOTICE"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public"
42
+ }
43
+ }