@aptre/v86 0.6.1 → 0.6.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aptre/v86",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "license": "BSD-2-Clause",
5
5
  "description": "x86 PC emulator and x86-to-wasm JIT, running in the browser",
6
6
  "homepage": "https://github.com/aperturerobotics/v86",
@@ -1,7 +1,12 @@
1
1
  declare let DEBUG: boolean
2
2
 
3
3
  import { v86 } from '../main.js'
4
- import { LOG_CPU, WASM_TABLE_OFFSET, WASM_TABLE_SIZE } from '../const.js'
4
+ import {
5
+ LOG_CPU,
6
+ WASM_PAGE_SIZE,
7
+ WASM_TABLE_OFFSET,
8
+ WASM_TABLE_SIZE,
9
+ } from '../const.js'
5
10
  import { get_rand_int, load_file, read_sized_string_from_mem } from '../lib.js'
6
11
  import { dbg_assert, dbg_trace, dbg_log, set_log_level } from '../log.js'
7
12
  import * as print_stats from './print_stats.js'
@@ -112,7 +117,6 @@ export class V86 {
112
117
  const vga_memory_size = options.vga_memory_size || 8 * 1024 * 1024
113
118
  const memory_max =
114
119
  options.memory_max || (memory_size + vga_memory_size) * 4
115
- const WASM_PAGE_SIZE = 65536
116
120
  const wasm_initial_pages = 256
117
121
  const wasm_max_pages = Math.max(
118
122
  wasm_initial_pages,
package/src/cpu.ts CHANGED
@@ -155,7 +155,6 @@ export class CPU {
155
155
  memory_size!: Int32Array
156
156
 
157
157
  mem8: Uint8Array
158
- mem8_offset: number = 0
159
158
  mem32s: Int32Array
160
159
 
161
160
  segment_is_null!: Uint8Array
@@ -348,111 +347,134 @@ export class CPU {
348
347
  this.wasm_patch()
349
348
  this.create_jit_imports()
350
349
 
351
- this.mem8 = new Uint8Array(0)
352
- this.mem32s = new Int32Array(this.mem8.buffer)
353
-
354
- this.rebuild_wasm_views()
355
-
356
- // @ts-expect-error Devices are populated during init()
357
- this.devices = {}
358
-
359
- // managed in io.js
360
- this.memory_map_read8 = []
361
- this.memory_map_write8 = []
362
- this.memory_map_read32 = []
363
- this.memory_map_write32 = []
364
-
365
- this.bios = {
366
- main: null,
367
- vga: null,
368
- }
369
-
370
- this.fpu_stack_empty[0] = 0xff
371
- this.fpu_stack_ptr[0] = 0
372
-
373
- this.fpu_control_word[0] = 0x37f
374
- this.fpu_status_word[0] = 0
375
- this.fpu_ip[0] = 0
376
- this.fpu_ip_selector[0] = 0
377
- this.fpu_opcode[0] = 0
378
- this.fpu_dp[0] = 0
379
- this.fpu_dp_selector[0] = 0
380
-
381
- this.fw_value = []
382
- this.fw_pointer = 0
383
- this.option_roms = []
384
-
385
- this.io = undefined!
386
-
387
- this.bus = bus
350
+ const memory = this.wasm_memory
388
351
 
389
- this.set_tsc(0, 0)
352
+ this.memory_size = view(Uint32Array, memory, 812, 1)
390
353
 
391
- if (DEBUG) {
392
- this.seen_code = {}
393
- this.seen_code_uncompiled = {}
394
- }
395
- }
354
+ this.mem8 = new Uint8Array(0)
355
+ this.mem32s = new Int32Array(this.mem8.buffer)
396
356
 
397
- /**
398
- * Rebuild all TypedArray views into WASM linear memory.
399
- * Must be called after any wasm_memory.grow() since growth
400
- * detaches the old ArrayBuffer, invalidating all views.
401
- */
402
- rebuild_wasm_views(): void {
403
- const memory = this.wasm_memory
404
- this.memory_size = view(Uint32Array, memory, 812, 1)
405
357
  this.segment_is_null = view(Uint8Array, memory, 724, 8)
406
358
  this.segment_offsets = view(Int32Array, memory, 736, 8)
407
359
  this.segment_limits = view(Uint32Array, memory, 768, 8)
408
360
  this.segment_access_bytes = view(Uint8Array, memory, 512, 8)
361
+
409
362
  this.protected_mode = view(Int32Array, memory, 800, 1)
363
+
410
364
  this.idtr_size = view(Int32Array, memory, 564, 1)
411
365
  this.idtr_offset = view(Int32Array, memory, 568, 1)
366
+
412
367
  this.gdtr_size = view(Int32Array, memory, 572, 1)
413
368
  this.gdtr_offset = view(Int32Array, memory, 576, 1)
369
+
414
370
  this.tss_size_32 = view(Int32Array, memory, 1128, 1)
371
+
415
372
  this.page_fault = view(Uint32Array, memory, 540, 8)
373
+
416
374
  this.cr = view(Int32Array, memory, 580, 8)
375
+
417
376
  this.cpl = view(Uint8Array, memory, 612, 1)
377
+
418
378
  this.is_32 = view(Int32Array, memory, 804, 1)
379
+
419
380
  this.stack_size_32 = view(Int32Array, memory, 808, 1)
381
+
420
382
  this.in_hlt = view(Uint8Array, memory, 616, 1)
383
+
421
384
  this.last_virt_eip = view(Int32Array, memory, 620, 1)
422
385
  this.eip_phys = view(Int32Array, memory, 624, 1)
386
+
423
387
  this.sysenter_cs = view(Int32Array, memory, 636, 1)
388
+
424
389
  this.sysenter_esp = view(Int32Array, memory, 640, 1)
390
+
425
391
  this.sysenter_eip = view(Int32Array, memory, 644, 1)
392
+
426
393
  this.prefixes = view(Int32Array, memory, 648, 1)
394
+
427
395
  this.flags = view(Int32Array, memory, 120, 1)
396
+
428
397
  this.flags_changed = view(Int32Array, memory, 100, 1)
398
+
429
399
  this.last_op_size = view(Int32Array, memory, 96, 1)
430
400
  this.last_op1 = view(Int32Array, memory, 104, 1)
431
401
  this.last_result = view(Int32Array, memory, 112, 1)
402
+
432
403
  this.current_tsc = view(Uint32Array, memory, 960, 2)
404
+
405
+ // @ts-expect-error Devices are populated during init()
406
+ this.devices = {}
407
+
433
408
  this.instruction_pointer = view(Int32Array, memory, 556, 1)
434
409
  this.previous_ip = view(Int32Array, memory, 560, 1)
410
+
435
411
  this.apic_enabled = view(Uint8Array, memory, 548, 1)
436
412
  this.acpi_enabled = view(Uint8Array, memory, 552, 1)
413
+
414
+ // managed in io.js
415
+ this.memory_map_read8 = []
416
+ this.memory_map_write8 = []
417
+ this.memory_map_read32 = []
418
+ this.memory_map_write32 = []
419
+
420
+ this.bios = {
421
+ main: null,
422
+ vga: null,
423
+ }
424
+
437
425
  this.instruction_counter = view(Uint32Array, memory, 664, 1)
426
+
438
427
  this.reg32 = view(Int32Array, memory, 64, 8)
428
+
439
429
  this.fpu_st = view(Int32Array, memory, 1152, 4 * 8)
430
+
440
431
  this.fpu_stack_empty = view(Uint8Array, memory, 816, 1)
432
+ this.fpu_stack_empty[0] = 0xff
441
433
  this.fpu_stack_ptr = view(Uint8Array, memory, 1032, 1)
434
+ this.fpu_stack_ptr[0] = 0
435
+
442
436
  this.fpu_control_word = view(Uint16Array, memory, 1036, 1)
437
+ this.fpu_control_word[0] = 0x37f
443
438
  this.fpu_status_word = view(Uint16Array, memory, 1040, 1)
439
+ this.fpu_status_word[0] = 0
444
440
  this.fpu_ip = view(Int32Array, memory, 1048, 1)
441
+ this.fpu_ip[0] = 0
445
442
  this.fpu_ip_selector = view(Int32Array, memory, 1052, 1)
443
+ this.fpu_ip_selector[0] = 0
446
444
  this.fpu_opcode = view(Int32Array, memory, 1044, 1)
445
+ this.fpu_opcode[0] = 0
447
446
  this.fpu_dp = view(Int32Array, memory, 1056, 1)
447
+ this.fpu_dp[0] = 0
448
448
  this.fpu_dp_selector = view(Int32Array, memory, 1060, 1)
449
+ this.fpu_dp_selector[0] = 0
450
+
449
451
  this.reg_xmm32s = view(Int32Array, memory, 832, 8 * 4)
452
+
450
453
  this.mxcsr = view(Int32Array, memory, 824, 1)
454
+
451
455
  this.sreg = view(Uint16Array, memory, 668, 8)
456
+
452
457
  this.dreg = view(Int32Array, memory, 684, 8)
458
+
453
459
  this.reg_pdpte = view(Int32Array, memory, 968, 8)
460
+
454
461
  this.svga_dirty_bitmap_min_offset = view(Uint32Array, memory, 716, 1)
455
462
  this.svga_dirty_bitmap_max_offset = view(Uint32Array, memory, 720, 1)
463
+
464
+ this.fw_value = []
465
+ this.fw_pointer = 0
466
+ this.option_roms = []
467
+
468
+ this.io = undefined!
469
+
470
+ this.bus = bus
471
+
472
+ this.set_tsc(0, 0)
473
+
474
+ if (DEBUG) {
475
+ this.seen_code = {}
476
+ this.seen_code_uncompiled = {}
477
+ }
456
478
  }
457
479
 
458
480
  mmap_read8(addr: number): number {
@@ -704,7 +726,7 @@ export class CPU {
704
726
  state[26] = this.flags[0]
705
727
  state[27] = this.flags_changed[0]
706
728
  state[28] = this.last_op1[0]
707
-
729
+ state[29] = this.last_result[0]
708
730
  state[30] = this.last_op_size[0]
709
731
 
710
732
  state[37] = this.instruction_pointer[0]
@@ -851,23 +873,15 @@ export class CPU {
851
873
  }
852
874
 
853
875
  resize_memory(new_size: number): void {
854
- const mem8_offset = this.mem8_offset
855
- const needed_total = mem8_offset + new_size
856
- const current_buffer = this.wasm_memory.buffer.byteLength
857
- if (needed_total > current_buffer) {
858
- const grow_pages = Math.ceil(
859
- (needed_total - current_buffer) / WASM_PAGE_SIZE,
860
- )
861
- this.wasm_memory.grow(grow_pages)
862
- this.rebuild_wasm_views()
863
- }
864
- this.mem8 = view(Uint8Array, this.wasm_memory, mem8_offset, new_size)
865
- this.mem32s = view(
866
- Int32Array,
867
- this.wasm_memory,
868
- mem8_offset,
869
- new_size >> 2,
870
- )
876
+ const offset = this.mem8.byteOffset
877
+ const needed = offset + new_size
878
+ const current = this.wasm_memory.buffer.byteLength
879
+ if (needed > current) {
880
+ const pages = Math.ceil((needed - current) / WASM_PAGE_SIZE)
881
+ this.wasm_memory.grow(pages)
882
+ }
883
+ this.mem8 = view(Uint8Array, this.wasm_memory, offset, new_size)
884
+ this.mem32s = view(Uint32Array, this.wasm_memory, offset, new_size >> 2)
871
885
  this.memory_size[0] = new_size
872
886
  }
873
887
 
@@ -931,7 +945,7 @@ export class CPU {
931
945
  this.flags[0] = state[26]
932
946
  this.flags_changed[0] = state[27]
933
947
  this.last_op1[0] = state[28]
934
-
948
+ if (state[29] !== undefined) this.last_result[0] = state[29]
935
949
  this.last_op_size[0] = state[30]
936
950
 
937
951
  this.instruction_pointer[0] = state[37]
@@ -1245,10 +1259,9 @@ export class CPU {
1245
1259
  'Expected uninitialised memory',
1246
1260
  )
1247
1261
 
1248
- const memory_offset = this.allocate_memory(size)
1249
- this.rebuild_wasm_views()
1250
1262
  this.memory_size[0] = size
1251
- this.mem8_offset = memory_offset
1263
+
1264
+ const memory_offset = this.allocate_memory(size)
1252
1265
 
1253
1266
  this.mem8 = view(Uint8Array, this.wasm_memory, memory_offset, size)
1254
1267
  this.mem32s = view(
@@ -1557,25 +1570,6 @@ export class CPU {
1557
1570
  }
1558
1571
 
1559
1572
  this.debug_init()
1560
-
1561
- // Rebuild all WASM memory views. During init, allocate_memory
1562
- // and svga_allocate_memory may trigger memory.grow (from Rust),
1563
- // which detaches the old ArrayBuffer and invalidates all views.
1564
- this.rebuild_wasm_views()
1565
- if (this.mem8_offset > 0) {
1566
- this.mem8 = view(
1567
- Uint8Array,
1568
- this.wasm_memory,
1569
- this.mem8_offset,
1570
- this.memory_size[0],
1571
- )
1572
- this.mem32s = view(
1573
- Uint32Array,
1574
- this.wasm_memory,
1575
- this.mem8_offset,
1576
- this.memory_size[0] >> 2,
1577
- )
1578
- }
1579
1573
  }
1580
1574
 
1581
1575
  load_multiboot(buffer: ArrayBuffer): void {