@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/rtc.ts ADDED
@@ -0,0 +1,537 @@
1
+ import { v86 } from './main.js'
2
+ import { LOG_RTC } from './const.js'
3
+ import { h } from './lib.js'
4
+ import { dbg_assert, dbg_log } from './log.js'
5
+ import { IO } from './io.js'
6
+
7
+ // Minimal interface for CPU fields RTC uses
8
+ interface RTCCpu {
9
+ io: IO
10
+ device_raise_irq(irq: number): void
11
+ device_lower_irq(irq: number): void
12
+ }
13
+
14
+ export const CMOS_RTC_SECONDS = 0x00
15
+ export const CMOS_RTC_SECONDS_ALARM = 0x01
16
+ export const CMOS_RTC_MINUTES = 0x02
17
+ export const CMOS_RTC_MINUTES_ALARM = 0x03
18
+ export const CMOS_RTC_HOURS = 0x04
19
+ export const CMOS_RTC_HOURS_ALARM = 0x05
20
+ export const CMOS_RTC_DAY_WEEK = 0x06
21
+ export const CMOS_RTC_DAY_MONTH = 0x07
22
+ export const CMOS_RTC_MONTH = 0x08
23
+ export const CMOS_RTC_YEAR = 0x09
24
+ export const CMOS_STATUS_A = 0x0a
25
+ export const CMOS_STATUS_B = 0x0b
26
+ export const CMOS_STATUS_C = 0x0c
27
+ export const CMOS_STATUS_D = 0x0d
28
+ export const CMOS_DIAG_STATUS = 0x0e
29
+ export const CMOS_RESET_CODE = 0x0f
30
+
31
+ export const CMOS_FLOPPY_DRIVE_TYPE = 0x10
32
+ export const CMOS_DISK_DATA = 0x12
33
+ export const CMOS_EQUIPMENT_INFO = 0x14
34
+ export const CMOS_MEM_BASE_LOW = 0x15
35
+ export const CMOS_MEM_BASE_HIGH = 0x16
36
+ export const CMOS_MEM_OLD_EXT_LOW = 0x17
37
+ export const CMOS_MEM_OLD_EXT_HIGH = 0x18
38
+ export const CMOS_DISK_DRIVE1_TYPE = 0x19
39
+ export const CMOS_DISK_DRIVE2_TYPE = 0x1a
40
+ export const CMOS_DISK_DRIVE1_CYL = 0x1b
41
+ export const CMOS_DISK_DRIVE2_CYL = 0x24
42
+ export const CMOS_MEM_EXTMEM_LOW = 0x30
43
+ export const CMOS_MEM_EXTMEM_HIGH = 0x31
44
+ export const CMOS_CENTURY = 0x32
45
+ export const CMOS_MEM_EXTMEM2_LOW = 0x34
46
+ export const CMOS_MEM_EXTMEM2_HIGH = 0x35
47
+ export const CMOS_CENTURY2 = 0x37
48
+ export const CMOS_BIOS_BOOTFLAG1 = 0x38
49
+ export const CMOS_BIOS_DISKTRANSFLAG = 0x39
50
+ export const CMOS_BIOS_BOOTFLAG2 = 0x3d
51
+ export const CMOS_MEM_HIGHMEM_LOW = 0x5b
52
+ export const CMOS_MEM_HIGHMEM_MID = 0x5c
53
+ export const CMOS_MEM_HIGHMEM_HIGH = 0x5d
54
+ export const CMOS_BIOS_SMP_COUNT = 0x5f
55
+
56
+ // see CPU.prototype.fill_cmos
57
+ export const BOOT_ORDER_CD_FIRST = 0x123
58
+ export const BOOT_ORDER_HD_FIRST = 0x312
59
+ export const BOOT_ORDER_FD_FIRST = 0x321
60
+
61
+ type RTCState = [
62
+ number,
63
+ Uint8Array,
64
+ number,
65
+ number,
66
+ number,
67
+ number,
68
+ boolean,
69
+ number,
70
+ number,
71
+ number,
72
+ number,
73
+ number,
74
+ boolean,
75
+ number,
76
+ number,
77
+ ]
78
+
79
+ /**
80
+ * RTC (real time clock) and CMOS
81
+ */
82
+ export class RTC {
83
+ name: string
84
+ cpu: RTCCpu
85
+ cmos_index: number
86
+ cmos_data: Uint8Array
87
+ rtc_time: number
88
+ last_update: number
89
+ next_interrupt: number
90
+ next_interrupt_alarm: number
91
+ periodic_interrupt: boolean
92
+ periodic_interrupt_time: number
93
+ cmos_a: number
94
+ cmos_b: number
95
+ cmos_c: number
96
+ cmos_diag_status: number
97
+ nmi_disabled: number
98
+ update_interrupt: boolean
99
+ update_interrupt_time: number
100
+
101
+ constructor(cpu: RTCCpu) {
102
+ this.name = 'rtc'
103
+ this.cpu = cpu
104
+
105
+ this.cmos_index = 0
106
+ this.cmos_data = new Uint8Array(128)
107
+
108
+ // used for cmos entries
109
+ this.rtc_time = Date.now()
110
+ this.last_update = this.rtc_time
111
+
112
+ // used for periodic interrupt
113
+ this.next_interrupt = 0
114
+
115
+ // next alarm interrupt
116
+ this.next_interrupt_alarm = 0
117
+
118
+ this.periodic_interrupt = false
119
+
120
+ // corresponds to default value for cmos_a
121
+ this.periodic_interrupt_time = 1000 / 1024
122
+
123
+ this.cmos_a = 0x26
124
+ this.cmos_b = 2
125
+ this.cmos_c = 0
126
+
127
+ this.cmos_diag_status = 0
128
+
129
+ this.nmi_disabled = 0
130
+
131
+ this.update_interrupt = false
132
+ this.update_interrupt_time = 0
133
+
134
+ cpu.io.register_write(0x70, this, (out_byte: number): void => {
135
+ this.cmos_index = out_byte & 0x7f
136
+ this.nmi_disabled = out_byte >> 7
137
+ })
138
+
139
+ cpu.io.register_write(0x71, this, this.cmos_port_write.bind(this))
140
+ cpu.io.register_read(0x71, this, this.cmos_port_read.bind(this))
141
+ }
142
+
143
+ get_state(): RTCState {
144
+ const state: RTCState = [
145
+ this.cmos_index,
146
+ this.cmos_data,
147
+ this.rtc_time,
148
+ this.last_update,
149
+ this.next_interrupt,
150
+ this.next_interrupt_alarm,
151
+ this.periodic_interrupt,
152
+ this.periodic_interrupt_time,
153
+ this.cmos_a,
154
+ this.cmos_b,
155
+ this.cmos_c,
156
+ this.nmi_disabled,
157
+ this.update_interrupt,
158
+ this.update_interrupt_time,
159
+ this.cmos_diag_status,
160
+ ]
161
+
162
+ return state
163
+ }
164
+
165
+ set_state(state: RTCState): void {
166
+ this.cmos_index = state[0]
167
+ this.cmos_data = state[1]
168
+ this.rtc_time = state[2]
169
+ this.last_update = state[3]
170
+ this.next_interrupt = state[4]
171
+ this.next_interrupt_alarm = state[5]
172
+ this.periodic_interrupt = state[6]
173
+ this.periodic_interrupt_time = state[7]
174
+ this.cmos_a = state[8]
175
+ this.cmos_b = state[9]
176
+ this.cmos_c = state[10]
177
+ this.nmi_disabled = state[11]
178
+ this.update_interrupt = state[12] || false
179
+ this.update_interrupt_time = state[13] || 0
180
+ this.cmos_diag_status = state[14] || 0
181
+ }
182
+
183
+ timer(time: number, _legacy_mode: boolean): number {
184
+ time = Date.now() // XXX
185
+ this.rtc_time += time - this.last_update
186
+ this.last_update = time
187
+
188
+ if (this.periodic_interrupt && this.next_interrupt < time) {
189
+ this.cpu.device_raise_irq(8)
190
+ this.cmos_c |= (1 << 6) | (1 << 7)
191
+
192
+ this.next_interrupt +=
193
+ this.periodic_interrupt_time *
194
+ Math.ceil(
195
+ (time - this.next_interrupt) / this.periodic_interrupt_time,
196
+ )
197
+ } else if (
198
+ this.next_interrupt_alarm &&
199
+ this.next_interrupt_alarm < time
200
+ ) {
201
+ this.cpu.device_raise_irq(8)
202
+ this.cmos_c |= (1 << 5) | (1 << 7)
203
+
204
+ this.next_interrupt_alarm = 0
205
+ } else if (this.update_interrupt && this.update_interrupt_time < time) {
206
+ this.cpu.device_raise_irq(8)
207
+ this.cmos_c |= (1 << 4) | (1 << 7)
208
+
209
+ this.update_interrupt_time = time + 1000 // 1 second
210
+ }
211
+
212
+ let t = 100
213
+
214
+ if (this.periodic_interrupt && this.next_interrupt) {
215
+ t = Math.min(t, Math.max(0, this.next_interrupt - time))
216
+ }
217
+ if (this.next_interrupt_alarm) {
218
+ t = Math.min(t, Math.max(0, this.next_interrupt_alarm - time))
219
+ }
220
+ if (this.update_interrupt) {
221
+ t = Math.min(t, Math.max(0, this.update_interrupt_time - time))
222
+ }
223
+
224
+ return t
225
+ }
226
+
227
+ bcd_pack(n: number): number {
228
+ let i = 0,
229
+ result = 0,
230
+ digit: number
231
+
232
+ while (n) {
233
+ digit = n % 10
234
+
235
+ result |= digit << (4 * i)
236
+ i++
237
+ n = (n - digit) / 10
238
+ }
239
+
240
+ return result
241
+ }
242
+
243
+ bcd_unpack(n: number): number {
244
+ const low = n & 0xf
245
+ const high = (n >> 4) & 0xf
246
+
247
+ dbg_assert(n < 0x100)
248
+ dbg_assert(low < 10)
249
+ dbg_assert(high < 10)
250
+
251
+ return low + 10 * high
252
+ }
253
+
254
+ encode_time(t: number): number {
255
+ if (this.cmos_b & 4) {
256
+ // binary mode
257
+ return t
258
+ } else {
259
+ return this.bcd_pack(t)
260
+ }
261
+ }
262
+
263
+ decode_time(t: number): number {
264
+ if (this.cmos_b & 4) {
265
+ // binary mode
266
+ return t
267
+ } else {
268
+ return this.bcd_unpack(t)
269
+ }
270
+ }
271
+
272
+ // TODO
273
+ // - interrupt on update
274
+ // - countdown
275
+ // - letting bios/os set values
276
+ // (none of these are used by seabios or the OSes we're
277
+ // currently testing)
278
+ cmos_port_read(): number {
279
+ const index = this.cmos_index
280
+
281
+ //this.cmos_index = 0xD;
282
+
283
+ switch (index) {
284
+ case CMOS_RTC_SECONDS:
285
+ dbg_log(
286
+ 'read second: ' +
287
+ h(
288
+ this.encode_time(
289
+ new Date(this.rtc_time).getUTCSeconds(),
290
+ ),
291
+ ),
292
+ LOG_RTC,
293
+ )
294
+ return this.encode_time(new Date(this.rtc_time).getUTCSeconds())
295
+ case CMOS_RTC_MINUTES:
296
+ dbg_log(
297
+ 'read minute: ' +
298
+ h(
299
+ this.encode_time(
300
+ new Date(this.rtc_time).getUTCMinutes(),
301
+ ),
302
+ ),
303
+ LOG_RTC,
304
+ )
305
+ return this.encode_time(new Date(this.rtc_time).getUTCMinutes())
306
+ case CMOS_RTC_HOURS:
307
+ dbg_log(
308
+ 'read hour: ' +
309
+ h(
310
+ this.encode_time(
311
+ new Date(this.rtc_time).getUTCHours(),
312
+ ),
313
+ ),
314
+ LOG_RTC,
315
+ )
316
+ // TODO: 12 hour mode
317
+ return this.encode_time(new Date(this.rtc_time).getUTCHours())
318
+ case CMOS_RTC_DAY_WEEK:
319
+ dbg_log(
320
+ 'read day: ' +
321
+ h(
322
+ this.encode_time(
323
+ new Date(this.rtc_time).getUTCDay() + 1,
324
+ ),
325
+ ),
326
+ LOG_RTC,
327
+ )
328
+ return this.encode_time(new Date(this.rtc_time).getUTCDay() + 1)
329
+ case CMOS_RTC_DAY_MONTH:
330
+ dbg_log(
331
+ 'read day of month: ' +
332
+ h(
333
+ this.encode_time(
334
+ new Date(this.rtc_time).getUTCDate(),
335
+ ),
336
+ ),
337
+ LOG_RTC,
338
+ )
339
+ return this.encode_time(new Date(this.rtc_time).getUTCDate())
340
+ case CMOS_RTC_MONTH:
341
+ dbg_log(
342
+ 'read month: ' +
343
+ h(
344
+ this.encode_time(
345
+ new Date(this.rtc_time).getUTCMonth() + 1,
346
+ ),
347
+ ),
348
+ LOG_RTC,
349
+ )
350
+ return this.encode_time(
351
+ new Date(this.rtc_time).getUTCMonth() + 1,
352
+ )
353
+ case CMOS_RTC_YEAR:
354
+ dbg_log(
355
+ 'read year: ' +
356
+ h(
357
+ this.encode_time(
358
+ new Date(this.rtc_time).getUTCFullYear() % 100,
359
+ ),
360
+ ),
361
+ LOG_RTC,
362
+ )
363
+ return this.encode_time(
364
+ new Date(this.rtc_time).getUTCFullYear() % 100,
365
+ )
366
+
367
+ case CMOS_STATUS_A:
368
+ if (v86.microtick() % 1000 >= 999) {
369
+ // Set update-in-progress for one millisecond every second (we
370
+ // may not have precision higher than that in browser
371
+ // environments)
372
+ return this.cmos_a | 0x80
373
+ }
374
+ return this.cmos_a
375
+ case CMOS_STATUS_B:
376
+ //dbg_log("cmos read from index " + h(index));
377
+ return this.cmos_b
378
+
379
+ case CMOS_STATUS_C: {
380
+ // It is important to know that upon a IRQ 8, Status Register C
381
+ // will contain a bitmask telling which interrupt happened.
382
+ // What is important is that if register C is not read after an
383
+ // IRQ 8, then the interrupt will not happen again.
384
+ this.cpu.device_lower_irq(8)
385
+
386
+ dbg_log('cmos reg C read', LOG_RTC)
387
+ // Missing IRQF flag
388
+ //return cmos_b & 0x70;
389
+ const c = this.cmos_c
390
+
391
+ this.cmos_c &= ~0xf0
392
+
393
+ return c
394
+ }
395
+
396
+ case CMOS_STATUS_D:
397
+ return 1 << 7 // CMOS battery charged
398
+
399
+ case CMOS_DIAG_STATUS:
400
+ dbg_log('cmos diagnostic status read', LOG_RTC)
401
+ return this.cmos_diag_status
402
+
403
+ case CMOS_CENTURY:
404
+ case CMOS_CENTURY2:
405
+ dbg_log(
406
+ 'read century: ' +
407
+ h(
408
+ this.encode_time(
409
+ (new Date(this.rtc_time).getUTCFullYear() /
410
+ 100) |
411
+ 0,
412
+ ),
413
+ ),
414
+ LOG_RTC,
415
+ )
416
+ return this.encode_time(
417
+ (new Date(this.rtc_time).getUTCFullYear() / 100) | 0,
418
+ )
419
+
420
+ default:
421
+ dbg_log('cmos read from index ' + h(index), LOG_RTC)
422
+ return this.cmos_data[this.cmos_index]
423
+ }
424
+ }
425
+
426
+ cmos_port_write(data_byte: number): void {
427
+ switch (this.cmos_index) {
428
+ case 0xa:
429
+ this.cmos_a = data_byte & 0x7f
430
+ this.periodic_interrupt_time =
431
+ 1000 / (32768 >> ((this.cmos_a & 0xf) - 1))
432
+
433
+ dbg_log(
434
+ 'Periodic interrupt, a=' +
435
+ h(this.cmos_a, 2) +
436
+ ' t=' +
437
+ this.periodic_interrupt_time,
438
+ LOG_RTC,
439
+ )
440
+ break
441
+ case 0xb:
442
+ this.cmos_b = data_byte
443
+ if (this.cmos_b & 0x80) {
444
+ // remove update interrupt flag
445
+ this.cmos_b &= 0xef
446
+ }
447
+ if (this.cmos_b & 0x40) {
448
+ this.next_interrupt = Date.now()
449
+ }
450
+
451
+ if (this.cmos_b & 0x20) {
452
+ const now = new Date()
453
+
454
+ const seconds = this.decode_time(
455
+ this.cmos_data[CMOS_RTC_SECONDS_ALARM],
456
+ )
457
+ const minutes = this.decode_time(
458
+ this.cmos_data[CMOS_RTC_MINUTES_ALARM],
459
+ )
460
+ const hours = this.decode_time(
461
+ this.cmos_data[CMOS_RTC_HOURS_ALARM],
462
+ )
463
+
464
+ const alarm_date = new Date(
465
+ Date.UTC(
466
+ now.getUTCFullYear(),
467
+ now.getUTCMonth(),
468
+ now.getUTCDate(),
469
+ hours,
470
+ minutes,
471
+ seconds,
472
+ ),
473
+ )
474
+
475
+ const ms_from_now = +alarm_date - +now
476
+ dbg_log(
477
+ 'RTC alarm scheduled for ' +
478
+ alarm_date +
479
+ ' hh:mm:ss=' +
480
+ hours +
481
+ ':' +
482
+ minutes +
483
+ ':' +
484
+ seconds +
485
+ ' ms_from_now=' +
486
+ ms_from_now,
487
+ LOG_RTC,
488
+ )
489
+
490
+ this.next_interrupt_alarm = +alarm_date
491
+ }
492
+
493
+ if (this.cmos_b & 0x10) {
494
+ dbg_log('update interrupt', LOG_RTC)
495
+ this.update_interrupt_time = Date.now()
496
+ }
497
+
498
+ dbg_log('cmos b=' + h(this.cmos_b, 2), LOG_RTC)
499
+ break
500
+
501
+ case CMOS_DIAG_STATUS:
502
+ this.cmos_diag_status = data_byte
503
+ break
504
+
505
+ case CMOS_RTC_SECONDS_ALARM:
506
+ case CMOS_RTC_MINUTES_ALARM:
507
+ case CMOS_RTC_HOURS_ALARM:
508
+ this.cmos_write(this.cmos_index, data_byte)
509
+ break
510
+
511
+ default:
512
+ dbg_log(
513
+ 'cmos write index ' +
514
+ h(this.cmos_index) +
515
+ ': ' +
516
+ h(data_byte),
517
+ LOG_RTC,
518
+ )
519
+ }
520
+
521
+ this.update_interrupt =
522
+ (this.cmos_b & 0x10) === 0x10 && (this.cmos_a & 0xf) > 0
523
+ this.periodic_interrupt =
524
+ (this.cmos_b & 0x40) === 0x40 && (this.cmos_a & 0xf) > 0
525
+ }
526
+
527
+ cmos_read(index: number): number {
528
+ dbg_assert(index < 128)
529
+ return this.cmos_data[index]
530
+ }
531
+
532
+ cmos_write(index: number, value: number): void {
533
+ dbg_log('cmos ' + h(index) + ' <- ' + h(value), LOG_RTC)
534
+ dbg_assert(index < 128)
535
+ this.cmos_data[index] = value
536
+ }
537
+ }
@@ -0,0 +1,101 @@
1
+ #![allow(non_snake_case)]
2
+
3
+ use crate::cpu_context::CpuContext;
4
+ use crate::gen;
5
+ use crate::modrm;
6
+ use crate::prefix::{PREFIX_66, PREFIX_67, PREFIX_F2, PREFIX_F3};
7
+ use crate::regs::{CS, DS, ES, FS, GS, SS};
8
+
9
+ #[derive(PartialEq, Eq)]
10
+ pub enum AnalysisType {
11
+ Normal,
12
+ BlockBoundary,
13
+ Jump {
14
+ offset: i32,
15
+ is_32: bool,
16
+ condition: Option<u8>,
17
+ },
18
+ STI,
19
+ }
20
+
21
+ pub struct Analysis {
22
+ pub no_next_instruction: bool,
23
+ pub absolute_jump: bool,
24
+ pub ty: AnalysisType,
25
+ }
26
+
27
+ pub fn analyze_step(mut cpu: &mut CpuContext) -> Analysis {
28
+ let mut analysis = Analysis {
29
+ no_next_instruction: false,
30
+ absolute_jump: false,
31
+ ty: AnalysisType::Normal,
32
+ };
33
+ cpu.prefixes = 0;
34
+ let opcode = cpu.read_imm8() as u32 | (cpu.osize_32() as u32) << 8;
35
+ gen::analyzer::analyzer(opcode, &mut cpu, &mut analysis);
36
+ analysis
37
+ }
38
+
39
+ pub fn analyze_step_handle_prefix(cpu: &mut CpuContext, analysis: &mut Analysis) {
40
+ gen::analyzer::analyzer(
41
+ cpu.read_imm8() as u32 | (cpu.osize_32() as u32) << 8,
42
+ cpu,
43
+ analysis,
44
+ )
45
+ }
46
+ pub fn analyze_step_handle_segment_prefix(
47
+ segment: u32,
48
+ cpu: &mut CpuContext,
49
+ analysis: &mut Analysis,
50
+ ) {
51
+ dbg_assert!(segment <= 5);
52
+ cpu.prefixes |= segment as u8 + 1;
53
+ analyze_step_handle_prefix(cpu, analysis)
54
+ }
55
+
56
+ pub fn instr16_0F_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
57
+ gen::analyzer0f::analyzer(cpu.read_imm8() as u32, cpu, analysis)
58
+ }
59
+ pub fn instr32_0F_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
60
+ gen::analyzer0f::analyzer(cpu.read_imm8() as u32 | 0x100, cpu, analysis)
61
+ }
62
+ pub fn instr_26_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
63
+ analyze_step_handle_segment_prefix(ES, cpu, analysis)
64
+ }
65
+ pub fn instr_2E_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
66
+ analyze_step_handle_segment_prefix(CS, cpu, analysis)
67
+ }
68
+ pub fn instr_36_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
69
+ analyze_step_handle_segment_prefix(SS, cpu, analysis)
70
+ }
71
+ pub fn instr_3E_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
72
+ analyze_step_handle_segment_prefix(DS, cpu, analysis)
73
+ }
74
+ pub fn instr_64_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
75
+ analyze_step_handle_segment_prefix(FS, cpu, analysis)
76
+ }
77
+ pub fn instr_65_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
78
+ analyze_step_handle_segment_prefix(GS, cpu, analysis)
79
+ }
80
+ pub fn instr_66_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
81
+ cpu.prefixes |= PREFIX_66;
82
+ analyze_step_handle_prefix(cpu, analysis)
83
+ }
84
+ pub fn instr_67_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
85
+ cpu.prefixes |= PREFIX_67;
86
+ analyze_step_handle_prefix(cpu, analysis)
87
+ }
88
+ pub fn instr_F0_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
89
+ // lock: Ignored
90
+ analyze_step_handle_prefix(cpu, analysis)
91
+ }
92
+ pub fn instr_F2_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
93
+ cpu.prefixes |= PREFIX_F2;
94
+ analyze_step_handle_prefix(cpu, analysis)
95
+ }
96
+ pub fn instr_F3_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
97
+ cpu.prefixes |= PREFIX_F3;
98
+ analyze_step_handle_prefix(cpu, analysis)
99
+ }
100
+
101
+ pub fn modrm_analyze(ctx: &mut CpuContext, modrm_byte: u8) { modrm::skip(ctx, modrm_byte); }