@aptre/v86 0.5.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.
Files changed (111) hide show
  1. package/LICENSE +22 -0
  2. package/LICENSE.MIT +22 -0
  3. package/Readme.md +237 -0
  4. package/dist/v86.browser.js +26666 -0
  5. package/dist/v86.browser.js.map +7 -0
  6. package/dist/v86.js +26632 -0
  7. package/dist/v86.js.map +7 -0
  8. package/gen/generate_analyzer.ts +512 -0
  9. package/gen/generate_interpreter.ts +522 -0
  10. package/gen/generate_jit.ts +624 -0
  11. package/gen/rust_ast.ts +107 -0
  12. package/gen/util.ts +35 -0
  13. package/gen/x86_table.ts +1836 -0
  14. package/lib/9p.ts +1547 -0
  15. package/lib/filesystem.ts +1879 -0
  16. package/lib/marshall.ts +168 -0
  17. package/lib/softfloat/softfloat.c +32501 -0
  18. package/lib/zstd/zstddeclib.c +13520 -0
  19. package/package.json +75 -0
  20. package/src/acpi.ts +267 -0
  21. package/src/browser/dummy_screen.ts +106 -0
  22. package/src/browser/fake_network.ts +1771 -0
  23. package/src/browser/fetch_network.ts +361 -0
  24. package/src/browser/filestorage.ts +124 -0
  25. package/src/browser/inbrowser_network.ts +57 -0
  26. package/src/browser/keyboard.ts +564 -0
  27. package/src/browser/main.ts +3415 -0
  28. package/src/browser/mouse.ts +255 -0
  29. package/src/browser/network.ts +142 -0
  30. package/src/browser/print_stats.ts +336 -0
  31. package/src/browser/screen.ts +978 -0
  32. package/src/browser/serial.ts +316 -0
  33. package/src/browser/speaker.ts +1223 -0
  34. package/src/browser/starter.ts +1688 -0
  35. package/src/browser/wisp_network.ts +332 -0
  36. package/src/browser/worker_bus.ts +64 -0
  37. package/src/buffer.ts +652 -0
  38. package/src/bus.ts +78 -0
  39. package/src/const.ts +128 -0
  40. package/src/cpu.ts +2891 -0
  41. package/src/dma.ts +474 -0
  42. package/src/elf.ts +251 -0
  43. package/src/floppy.ts +1778 -0
  44. package/src/ide.ts +3455 -0
  45. package/src/io.ts +504 -0
  46. package/src/iso9660.ts +317 -0
  47. package/src/kernel.ts +250 -0
  48. package/src/lib.ts +645 -0
  49. package/src/log.ts +149 -0
  50. package/src/main.ts +199 -0
  51. package/src/ne2k.ts +1589 -0
  52. package/src/pci.ts +815 -0
  53. package/src/pit.ts +406 -0
  54. package/src/ps2.ts +820 -0
  55. package/src/rtc.ts +537 -0
  56. package/src/rust/analysis.rs +101 -0
  57. package/src/rust/codegen.rs +2660 -0
  58. package/src/rust/config.rs +3 -0
  59. package/src/rust/control_flow.rs +425 -0
  60. package/src/rust/cpu/apic.rs +658 -0
  61. package/src/rust/cpu/arith.rs +1207 -0
  62. package/src/rust/cpu/call_indirect.rs +2 -0
  63. package/src/rust/cpu/cpu.rs +4501 -0
  64. package/src/rust/cpu/fpu.rs +923 -0
  65. package/src/rust/cpu/global_pointers.rs +112 -0
  66. package/src/rust/cpu/instructions.rs +2486 -0
  67. package/src/rust/cpu/instructions_0f.rs +5261 -0
  68. package/src/rust/cpu/ioapic.rs +316 -0
  69. package/src/rust/cpu/memory.rs +351 -0
  70. package/src/rust/cpu/misc_instr.rs +613 -0
  71. package/src/rust/cpu/mod.rs +16 -0
  72. package/src/rust/cpu/modrm.rs +133 -0
  73. package/src/rust/cpu/pic.rs +402 -0
  74. package/src/rust/cpu/sse_instr.rs +361 -0
  75. package/src/rust/cpu/string.rs +701 -0
  76. package/src/rust/cpu/vga.rs +175 -0
  77. package/src/rust/cpu_context.rs +69 -0
  78. package/src/rust/dbg.rs +98 -0
  79. package/src/rust/gen/analyzer.rs +3807 -0
  80. package/src/rust/gen/analyzer0f.rs +3992 -0
  81. package/src/rust/gen/interpreter.rs +4447 -0
  82. package/src/rust/gen/interpreter0f.rs +5404 -0
  83. package/src/rust/gen/jit.rs +5080 -0
  84. package/src/rust/gen/jit0f.rs +5547 -0
  85. package/src/rust/gen/mod.rs +14 -0
  86. package/src/rust/jit.rs +2443 -0
  87. package/src/rust/jit_instructions.rs +7881 -0
  88. package/src/rust/js_api.rs +6 -0
  89. package/src/rust/leb.rs +46 -0
  90. package/src/rust/lib.rs +29 -0
  91. package/src/rust/modrm.rs +330 -0
  92. package/src/rust/opstats.rs +249 -0
  93. package/src/rust/page.rs +15 -0
  94. package/src/rust/paging.rs +25 -0
  95. package/src/rust/prefix.rs +15 -0
  96. package/src/rust/profiler.rs +155 -0
  97. package/src/rust/regs.rs +38 -0
  98. package/src/rust/softfloat.rs +286 -0
  99. package/src/rust/state_flags.rs +27 -0
  100. package/src/rust/wasmgen/mod.rs +2 -0
  101. package/src/rust/wasmgen/wasm_builder.rs +1047 -0
  102. package/src/rust/wasmgen/wasm_opcodes.rs +221 -0
  103. package/src/rust/zstd.rs +105 -0
  104. package/src/sb16.ts +1928 -0
  105. package/src/state.ts +359 -0
  106. package/src/uart.ts +472 -0
  107. package/src/vga.ts +2791 -0
  108. package/src/virtio.ts +1756 -0
  109. package/src/virtio_balloon.ts +273 -0
  110. package/src/virtio_console.ts +372 -0
  111. package/src/virtio_net.ts +326 -0
package/src/uart.ts ADDED
@@ -0,0 +1,472 @@
1
+ declare let DEBUG: boolean
2
+
3
+ import { LOG_SERIAL } from './const.js'
4
+ import { h } from './lib.js'
5
+ import { dbg_log } from './log.js'
6
+ import { IO } from './io.js'
7
+ import { BusConnector } from './bus.js'
8
+
9
+ /*
10
+ * Serial ports
11
+ * http://wiki.osdev.org/UART
12
+ * https://github.com/s-macke/jor1k/blob/master/js/worker/dev/uart.js
13
+ * https://www.freebsd.org/doc/en/articles/serial-uart/
14
+ */
15
+
16
+ const DLAB = 0x80
17
+
18
+ const UART_IER_MSI = 0x08 /* Modem Status Changed int. */
19
+ const UART_IER_THRI = 0x02 /* Enable Transmitter holding register int. */
20
+ const UART_IER_RDI = 0x01 /* Enable receiver data interrupt */
21
+
22
+ const UART_IIR_MSI = 0x00 /* Modem status interrupt (Low priority) */
23
+ const UART_IIR_NO_INT = 0x01
24
+ const UART_IIR_THRI = 0x02 /* Transmitter holding register empty */
25
+ const UART_IIR_RDI = 0x04 /* Receiver data interrupt */
26
+ const _UART_IIR_RLSI = 0x06 /* Receiver line status interrupt (High p.) */
27
+ const UART_IIR_CTI = 0x0c /* Character timeout */
28
+
29
+ // Modem control register
30
+ const UART_MCR_LOOPBACK = 0x10
31
+
32
+ const UART_LSR_DATA_READY = 0x1 // data available
33
+ const UART_LSR_TX_EMPTY = 0x20 // TX (THR) buffer is empty
34
+ const UART_LSR_TRANSMITTER_EMPTY = 0x40 // TX empty and line is idle
35
+
36
+ // Modem status register
37
+ const UART_MSR_DCD = 0x7 // Data Carrier Detect
38
+ const UART_MSR_RI = 0x6 // Ring Indicator
39
+ const UART_MSR_DSR = 0x5 // Data Set Ready
40
+ const UART_MSR_CTS = 0x4 // Clear To Send
41
+ // Delta bits
42
+ const UART_MSR_DDCD = 0x3 // Delta DCD
43
+ const UART_MSR_TERI = 0x2 // Trailing Edge RI
44
+ const UART_MSR_DDSR = 0x1 // Delta DSR
45
+ const UART_MSR_DCTS = 0x0 // Delta CTS
46
+
47
+ // Minimal interface for CPU fields UART uses
48
+ interface UARTCpu {
49
+ io: IO
50
+ device_raise_irq(irq: number): void
51
+ device_lower_irq(irq: number): void
52
+ }
53
+
54
+ type UARTState = [
55
+ number,
56
+ number,
57
+ number,
58
+ number,
59
+ number,
60
+ number,
61
+ number,
62
+ number,
63
+ number,
64
+ number,
65
+ number,
66
+ ]
67
+
68
+ /**
69
+ * UART serial port controller.
70
+ */
71
+ export class UART {
72
+ name: string
73
+ bus: BusConnector
74
+ cpu: UARTCpu
75
+ ints: number
76
+ baud_rate: number
77
+ line_control: number
78
+ lsr: number
79
+ fifo_control: number
80
+ ier: number
81
+ iir: number
82
+ modem_control: number
83
+ modem_status: number
84
+ scratch_register: number
85
+ irq: number
86
+ input: number[]
87
+ current_line: string
88
+ com: number
89
+
90
+ constructor(cpu: UARTCpu, port: number, bus: BusConnector) {
91
+ this.name = 'uart'
92
+ this.bus = bus
93
+ this.cpu = cpu
94
+
95
+ this.ints = 1 << UART_IIR_THRI
96
+
97
+ this.baud_rate = 0
98
+
99
+ this.line_control = 0
100
+
101
+ // line status register
102
+ this.lsr = UART_LSR_TRANSMITTER_EMPTY | UART_LSR_TX_EMPTY
103
+
104
+ this.fifo_control = 0
105
+
106
+ // interrupts enable
107
+ this.ier = 0
108
+
109
+ // interrupt identification register
110
+ this.iir = UART_IIR_NO_INT
111
+
112
+ this.modem_control = 0
113
+ this.modem_status = 0
114
+
115
+ this.scratch_register = 0
116
+
117
+ this.irq = 0
118
+
119
+ this.input = []
120
+
121
+ this.current_line = ''
122
+
123
+ switch (port) {
124
+ case 0x3f8:
125
+ this.com = 0
126
+ this.irq = 4
127
+ break
128
+ case 0x2f8:
129
+ this.com = 1
130
+ this.irq = 3
131
+ break
132
+ case 0x3e8:
133
+ this.com = 2
134
+ this.irq = 4
135
+ break
136
+ case 0x2e8:
137
+ this.com = 3
138
+ this.irq = 3
139
+ break
140
+ default:
141
+ dbg_log('Invalid serial port: ' + h(port), LOG_SERIAL)
142
+ this.com = 0
143
+ this.irq = 4
144
+ }
145
+
146
+ this.bus.register(
147
+ 'serial' + this.com + '-input',
148
+ (data: number): void => {
149
+ this.data_received(data)
150
+ },
151
+ this,
152
+ )
153
+
154
+ this.bus.register(
155
+ 'serial' + this.com + '-modem-status-input',
156
+ (data: number): void => {
157
+ this.set_modem_status(data)
158
+ },
159
+ this,
160
+ )
161
+
162
+ // Set individual modem status bits
163
+
164
+ this.bus.register(
165
+ 'serial' + this.com + '-carrier-detect-input',
166
+ (data: number): void => {
167
+ const status = data
168
+ ? this.modem_status |
169
+ (1 << UART_MSR_DCD) |
170
+ (1 << UART_MSR_DDCD)
171
+ : this.modem_status &
172
+ ~(1 << UART_MSR_DCD) &
173
+ ~(1 << UART_MSR_DDCD)
174
+ this.set_modem_status(status)
175
+ },
176
+ this,
177
+ )
178
+
179
+ this.bus.register(
180
+ 'serial' + this.com + '-ring-indicator-input',
181
+ (data: number): void => {
182
+ const status = data
183
+ ? this.modem_status |
184
+ (1 << UART_MSR_RI) |
185
+ (1 << UART_MSR_TERI)
186
+ : this.modem_status &
187
+ ~(1 << UART_MSR_RI) &
188
+ ~(1 << UART_MSR_TERI)
189
+ this.set_modem_status(status)
190
+ },
191
+ this,
192
+ )
193
+
194
+ this.bus.register(
195
+ 'serial' + this.com + '-data-set-ready-input',
196
+ (data: number): void => {
197
+ const status = data
198
+ ? this.modem_status |
199
+ (1 << UART_MSR_DSR) |
200
+ (1 << UART_MSR_DDSR)
201
+ : this.modem_status &
202
+ ~(1 << UART_MSR_DSR) &
203
+ ~(1 << UART_MSR_DDSR)
204
+ this.set_modem_status(status)
205
+ },
206
+ this,
207
+ )
208
+
209
+ this.bus.register(
210
+ 'serial' + this.com + '-clear-to-send-input',
211
+ (data: number): void => {
212
+ const status = data
213
+ ? this.modem_status |
214
+ (1 << UART_MSR_CTS) |
215
+ (1 << UART_MSR_DCTS)
216
+ : this.modem_status &
217
+ ~(1 << UART_MSR_CTS) &
218
+ ~(1 << UART_MSR_DCTS)
219
+ this.set_modem_status(status)
220
+ },
221
+ this,
222
+ )
223
+
224
+ const io = cpu.io
225
+
226
+ io.register_write(
227
+ port,
228
+ this,
229
+ (out_byte: number): void => {
230
+ this.write_data(out_byte)
231
+ },
232
+ (out_word: number): void => {
233
+ this.write_data(out_word & 0xff)
234
+ this.write_data(out_word >> 8)
235
+ },
236
+ )
237
+
238
+ io.register_write(port | 1, this, (out_byte: number): void => {
239
+ if (this.line_control & DLAB) {
240
+ this.baud_rate = (this.baud_rate & 0xff) | (out_byte << 8)
241
+ dbg_log('baud rate: ' + h(this.baud_rate), LOG_SERIAL)
242
+ } else {
243
+ if (
244
+ (this.ier & UART_IIR_THRI) === 0 &&
245
+ out_byte & UART_IIR_THRI
246
+ ) {
247
+ // re-throw THRI if it was masked
248
+ this.ThrowInterrupt(UART_IIR_THRI)
249
+ }
250
+
251
+ this.ier = out_byte & 0xf
252
+ dbg_log('interrupt enable: ' + h(out_byte), LOG_SERIAL)
253
+ this.CheckInterrupt()
254
+ }
255
+ })
256
+
257
+ io.register_read(port, this, (): number => {
258
+ if (this.line_control & DLAB) {
259
+ return this.baud_rate & 0xff
260
+ } else {
261
+ let data = 0
262
+
263
+ if (this.input.length === 0) {
264
+ dbg_log('Read input empty', LOG_SERIAL)
265
+ } else {
266
+ data = this.input.shift()!
267
+ dbg_log('Read input: ' + h(data), LOG_SERIAL)
268
+ }
269
+
270
+ if (this.input.length === 0) {
271
+ this.lsr &= ~UART_LSR_DATA_READY
272
+ this.ClearInterrupt(UART_IIR_CTI)
273
+ this.ClearInterrupt(UART_IIR_RDI)
274
+ }
275
+
276
+ return data
277
+ }
278
+ })
279
+
280
+ io.register_read(port | 1, this, (): number => {
281
+ if (this.line_control & DLAB) {
282
+ return this.baud_rate >> 8
283
+ } else {
284
+ return this.ier & 0xf
285
+ }
286
+ })
287
+
288
+ io.register_read(port | 2, this, (): number => {
289
+ let ret = this.iir & 0xf
290
+ dbg_log('read interrupt identification: ' + h(this.iir), LOG_SERIAL)
291
+
292
+ if (this.iir === UART_IIR_THRI) {
293
+ this.ClearInterrupt(UART_IIR_THRI)
294
+ }
295
+
296
+ if (this.fifo_control & 1) ret |= 0xc0
297
+
298
+ return ret
299
+ })
300
+ io.register_write(port | 2, this, (out_byte: number): void => {
301
+ dbg_log('fifo control: ' + h(out_byte), LOG_SERIAL)
302
+ this.fifo_control = out_byte
303
+ })
304
+
305
+ io.register_read(port | 3, this, (): number => {
306
+ dbg_log('read line control: ' + h(this.line_control), LOG_SERIAL)
307
+ return this.line_control
308
+ })
309
+ io.register_write(port | 3, this, (out_byte: number): void => {
310
+ dbg_log('line control: ' + h(out_byte), LOG_SERIAL)
311
+ this.line_control = out_byte
312
+ })
313
+
314
+ io.register_read(port | 4, this, (): number => {
315
+ return this.modem_control
316
+ })
317
+ io.register_write(port | 4, this, (out_byte: number): void => {
318
+ dbg_log('modem control: ' + h(out_byte), LOG_SERIAL)
319
+ this.modem_control = out_byte
320
+ })
321
+
322
+ io.register_read(port | 5, this, (): number => {
323
+ dbg_log('read line status: ' + h(this.lsr), LOG_SERIAL)
324
+ return this.lsr
325
+ })
326
+ io.register_write(port | 5, this, (_out_byte: number): void => {
327
+ dbg_log('Factory test write', LOG_SERIAL)
328
+ })
329
+
330
+ io.register_read(port | 6, this, (): number => {
331
+ dbg_log('read modem status: ' + h(this.modem_status), LOG_SERIAL)
332
+ // Clear delta bits
333
+ this.modem_status &= 0xf0
334
+ return this.modem_status
335
+ })
336
+ io.register_write(port | 6, this, (out_byte: number): void => {
337
+ dbg_log('write modem status: ' + h(out_byte), LOG_SERIAL)
338
+ this.set_modem_status(out_byte)
339
+ })
340
+
341
+ io.register_read(port | 7, this, (): number => {
342
+ return this.scratch_register
343
+ })
344
+ io.register_write(port | 7, this, (out_byte: number): void => {
345
+ this.scratch_register = out_byte
346
+ })
347
+ }
348
+
349
+ get_state(): UARTState {
350
+ const state: UARTState = [
351
+ this.ints,
352
+ this.baud_rate,
353
+ this.line_control,
354
+ this.lsr,
355
+ this.fifo_control,
356
+ this.ier,
357
+ this.iir,
358
+ this.modem_control,
359
+ this.modem_status,
360
+ this.scratch_register,
361
+ this.irq,
362
+ ]
363
+
364
+ return state
365
+ }
366
+
367
+ set_state(state: UARTState): void {
368
+ this.ints = state[0]
369
+ this.baud_rate = state[1]
370
+ this.line_control = state[2]
371
+ this.lsr = state[3]
372
+ this.fifo_control = state[4]
373
+ this.ier = state[5]
374
+ this.iir = state[6]
375
+ this.modem_control = state[7]
376
+ this.modem_status = state[8]
377
+ this.scratch_register = state[9]
378
+ this.irq = state[10]
379
+ }
380
+
381
+ CheckInterrupt(): void {
382
+ if (this.ints & (1 << UART_IIR_CTI) && this.ier & UART_IER_RDI) {
383
+ this.iir = UART_IIR_CTI
384
+ this.cpu.device_raise_irq(this.irq)
385
+ } else if (this.ints & (1 << UART_IIR_RDI) && this.ier & UART_IER_RDI) {
386
+ this.iir = UART_IIR_RDI
387
+ this.cpu.device_raise_irq(this.irq)
388
+ } else if (
389
+ this.ints & (1 << UART_IIR_THRI) &&
390
+ this.ier & UART_IER_THRI
391
+ ) {
392
+ this.iir = UART_IIR_THRI
393
+ this.cpu.device_raise_irq(this.irq)
394
+ } else if (this.ints & (1 << UART_IIR_MSI) && this.ier & UART_IER_MSI) {
395
+ this.iir = UART_IIR_MSI
396
+ this.cpu.device_raise_irq(this.irq)
397
+ } else {
398
+ this.iir = UART_IIR_NO_INT
399
+ this.cpu.device_lower_irq(this.irq)
400
+ }
401
+ }
402
+
403
+ ThrowInterrupt(line: number): void {
404
+ this.ints |= 1 << line
405
+ this.CheckInterrupt()
406
+ }
407
+
408
+ ClearInterrupt(line: number): void {
409
+ this.ints &= ~(1 << line)
410
+ this.CheckInterrupt()
411
+ }
412
+
413
+ data_received(data: number): void {
414
+ dbg_log('input: ' + h(data), LOG_SERIAL)
415
+ this.input.push(data)
416
+
417
+ this.lsr |= UART_LSR_DATA_READY
418
+
419
+ if (this.fifo_control & 1) {
420
+ this.ThrowInterrupt(UART_IIR_CTI)
421
+ } else {
422
+ this.ThrowInterrupt(UART_IIR_RDI)
423
+ }
424
+ }
425
+
426
+ write_data(out_byte: number): void {
427
+ if (this.line_control & DLAB) {
428
+ this.baud_rate = (this.baud_rate & ~0xff) | out_byte
429
+ return
430
+ }
431
+
432
+ dbg_log('data: ' + h(out_byte), LOG_SERIAL)
433
+
434
+ this.ThrowInterrupt(UART_IIR_THRI)
435
+
436
+ if (this.modem_control & UART_MCR_LOOPBACK) {
437
+ this.data_received(out_byte)
438
+ } else {
439
+ this.bus.send('serial' + this.com + '-output-byte', out_byte)
440
+ }
441
+
442
+ if (DEBUG) {
443
+ const char = String.fromCharCode(out_byte)
444
+ this.current_line += char
445
+
446
+ if (char === '\n') {
447
+ const line = this.current_line
448
+ .trimRight()
449
+ // eslint-disable-next-line no-control-regex
450
+ .replace(/[\x00-\x08\x0b-\x1f\x7f\x80-\xff]/g, '')
451
+ dbg_log('SERIAL: ' + line)
452
+ this.current_line = ''
453
+ }
454
+ }
455
+ }
456
+
457
+ set_modem_status(status: number): void {
458
+ dbg_log('modem status: ' + h(status), LOG_SERIAL)
459
+ const prev_delta_bits = this.modem_status & 0x0f
460
+ // compare the bits that have changed and shift them into the delta bits
461
+ let delta = (this.modem_status ^ status) >> 4
462
+ // The delta should stay set if they were previously set
463
+ delta |= prev_delta_bits
464
+
465
+ // update the current modem status
466
+ this.modem_status = status
467
+ // update the delta bits based on the changes and previous
468
+ // values, but also leave the delta bits set if they were
469
+ // passed in as part of the status
470
+ this.modem_status |= delta
471
+ }
472
+ }