Switch to es6 modules.

This commit is contained in:
Rob Blanckaert 2025-03-18 00:29:11 -07:00 committed by Fabian
parent 30be975d6a
commit a9219613af
97 changed files with 1206 additions and 749 deletions

View file

@ -68,7 +68,7 @@ jobs:
run: (cd tests/kvm-unit-tests && ./configure && make x86/realmode.flat)
- name: Run kvm-unit-test
run: tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat
run: tests/kvm-unit-tests/run.mjs tests/kvm-unit-tests/x86/realmode.flat
- name: Fetch namsmtests cache
uses: actions/cache@v4

View file

@ -78,7 +78,7 @@ CARGO_FLAGS_SAFE=\
CARGO_FLAGS=$(CARGO_FLAGS_SAFE) -C target-feature=+bulk-memory -C target-feature=+multivalue -C target-feature=+simd128
CORE_FILES=const.js config.js io.js main.js lib.js buffer.js ide.js pci.js floppy.js \
CORE_FILES=cjs.js const.js config.js io.js main.js lib.js buffer.js ide.js pci.js floppy.js \
memory.js dma.js pit.js vga.js ps2.js rtc.js uart.js \
acpi.js apic.js ioapic.js \
state.js ne2k.js sb16.js virtio.js virtio_console.js virtio_net.js virtio_balloon.js \
@ -151,7 +151,7 @@ build/libv86.mjs: $(CLOSURE) src/*.js lib/*.js src/browser/*.js
$(CLOSURE_FLAGS)\
--compilation_level SIMPLE\
--jscomp_off=missingProperties\
--output_wrapper ';let module = {exports:{}}; %output%; export default module.exports.V86;'\
--output_wrapper ';let module = {exports:{}}; %output%; export default module.exports.V86; export let {V86, CPU} = module.exports;'\
--js $(CORE_FILES)\
--js $(BROWSER_FILES)\
--js $(LIB_FILES)\
@ -257,6 +257,7 @@ clean:
-rm build/libv86.js
-rm build/libv86.mjs
-rm build/libv86-debug.js
-rm build/libv86-debug.mjs
-rm build/v86_all.js
-rm build/v86.wasm
-rm build/v86-debug.wasm
@ -299,45 +300,45 @@ tests: build/libv86-debug.js build/v86-debug.wasm build/integration-test-fs/fs.j
tests-release: build/libv86.js build/v86.wasm build/integration-test-fs/fs.json
TEST_RELEASE_BUILD=1 ./tests/full/run.js
nasmtests: build/libv86-debug.js build/v86-debug.wasm
nasmtests: build/libv86-debug.mjs build/v86-debug.wasm
$(NASM_TEST_DIR)/create_tests.js
$(NASM_TEST_DIR)/gen_fixtures.js
$(NASM_TEST_DIR)/run.js
nasmtests-force-jit: build/libv86-debug.js build/v86-debug.wasm
nasmtests-force-jit: build/libv86-debug.mjs build/v86-debug.wasm
$(NASM_TEST_DIR)/create_tests.js
$(NASM_TEST_DIR)/gen_fixtures.js
$(NASM_TEST_DIR)/run.js --force-jit
jitpagingtests: build/libv86-debug.js build/v86-debug.wasm
jitpagingtests: build/libv86-debug.mjs build/v86-debug.wasm
$(MAKE) -C tests/jit-paging test-jit
./tests/jit-paging/run.js
qemutests: build/libv86-debug.js build/v86-debug.wasm
qemutests: build/libv86-debug.mjs build/v86-debug.wasm
$(MAKE) -C tests/qemu test-i386
LOG_LEVEL=3 ./tests/qemu/run.js build/qemu-test-result
./tests/qemu/run-qemu.js > build/qemu-test-reference
diff build/qemu-test-result build/qemu-test-reference
qemutests-release: build/libv86.js build/v86.wasm
qemutests-release: build/libv86.mjs build/v86.wasm
$(MAKE) -C tests/qemu test-i386
TEST_RELEASE_BUILD=1 time ./tests/qemu/run.js build/qemu-test-result
./tests/qemu/run-qemu.js > build/qemu-test-reference
diff build/qemu-test-result build/qemu-test-reference
kvm-unit-test: build/libv86-debug.js build/v86-debug.wasm
kvm-unit-test: build/libv86-debug.mjs build/v86-debug.wasm
(cd tests/kvm-unit-tests && ./configure && make x86/realmode.flat)
tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat
tests/kvm-unit-tests/run.mjs tests/kvm-unit-tests/x86/realmode.flat
kvm-unit-test-release: build/libv86.js build/v86.wasm
kvm-unit-test-release: build/libv86.mjs build/v86.wasm
(cd tests/kvm-unit-tests && ./configure && make x86/realmode.flat)
TEST_RELEASE_BUILD=1 tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat
TEST_RELEASE_BUILD=1 tests/kvm-unit-tests/run.mjs tests/kvm-unit-tests/x86/realmode.flat
expect-tests: build/libv86-debug.js build/v86-debug.wasm build/libwabt.js
expect-tests: build/libv86-debug.mjs build/v86-debug.wasm build/libwabt.cjs
make -C tests/expect/tests
./tests/expect/run.js
devices-test: build/libv86-debug.js build/v86-debug.wasm
devices-test: build/libv86-debug.mjs build/v86-debug.wasm
./tests/devices/virtio_9p.js
./tests/devices/virtio_console.js
./tests/devices/fetch_network.js
@ -352,7 +353,7 @@ rust-test: $(RUST_FILES)
rust-test-intensive:
QUICKCHECK_TESTS=100000000 make rust-test
api-tests: build/libv86-debug.js build/v86-debug.wasm
api-tests: build/libv86-debug.mjs build/v86-debug.wasm
./tests/api/clean-shutdown.js
./tests/api/state.js
./tests/api/reset.js
@ -375,10 +376,11 @@ build/capstone-x86.min.js:
mkdir -p build
wget -nv -P build https://github.com/AlexAltea/capstone.js/releases/download/v3.0.5-rc1/capstone-x86.min.js
build/libwabt.js:
build/libwabt.cjs:
mkdir -p build
wget -nv -P build https://github.com/WebAssembly/wabt/archive/1.0.6.zip
unzip -j -d build/ build/1.0.6.zip wabt-1.0.6/demo/libwabt.js
mv build/libwabt.js build/libwabt.cjs
rm build/1.0.6.zip
build/xterm.js:

View file

@ -4,58 +4,12 @@
<title>v86 (debug)</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<script src="src/const.js"></script>
<script src="src/config.js"></script>
<script src="src/log.js"></script>
<script src="src/lib.js"></script>
<script src="src/buffer.js"></script>
<script src="src/cpu.js"></script>
<script src="src/debug.js"></script>
<script src="src/io.js"></script>
<script src="src/main.js"></script>
<script src="src/ide.js"></script>
<script src="src/pci.js"></script>
<script src="src/floppy.js"></script>
<script src="src/memory.js"></script>
<script src="src/dma.js"></script>
<script src="src/pit.js"></script>
<script src="src/vga.js"></script>
<script src="src/ps2.js"></script>
<script src="src/rtc.js"></script>
<script src="src/uart.js"></script>
<script src="src/acpi.js"></script>
<script src="src/apic.js"></script>
<script src="src/ioapic.js"></script>
<script src="src/sb16.js"></script>
<script src="src/ne2k.js"></script>
<script src="src/state.js"></script>
<script src="src/virtio.js"></script>
<script src="src/virtio_balloon.js"></script>
<script src="src/virtio_console.js"></script>
<script src="src/virtio_net.js"></script>
<script src="src/bus.js"></script>
<script src="src/elf.js"></script>
<script src="src/kernel.js"></script>
<script src="src/browser/main.js"></script>
<script src="src/browser/screen.js"></script>
<script src="src/browser/keyboard.js"></script>
<script src="src/browser/mouse.js"></script>
<script src="src/browser/speaker.js"></script>
<script src="src/browser/serial.js"></script>
<script src="src/browser/network.js"></script>
<script src="src/browser/fake_network.js"></script>
<script src="src/browser/fetch_network.js"></script>
<script src="src/browser/wisp_network.js"></script>
<script src="src/browser/starter.js"></script>
<script src="src/browser/worker_bus.js"></script>
<script src="src/browser/print_stats.js"></script>
<script src="src/browser/filestorage.js"></script>
<script src="lib/jor1k.js"></script>
<script src="lib/9p.js"></script>
<script src="lib/filesystem.js"></script>
<script src="lib/marshall.js"></script>
<script>
var DEBUG = true;
</script>
<script src="build/capstone-x86.min.js"></script>
<script src="build/libwabt.js"></script>
<script src="build/libwabt.cjs"></script>
<script type="module" src="./src/browser/main.js"></script>
<link rel="stylesheet" href="v86.css">

View file

@ -1,5 +1,56 @@
export default [
{
"languageOptions": {
"globals": {
"process": "readonly",
"window": "writable",
"navigator": "writable",
"location": "writable",
"document": "readonly",
"console": "readonly",
"crypto": "readonly",
"alert": "readonly",
"performance": "readonly",
"URL": "readonly",
"WebAssembly": "readonly",
"setTimeout": "readonly",
"setInterval": "readonly",
"clearTimeout": "readonly",
"clearInterval": "readonly",
"requestAnimationFrame": "readonly",
"cancelAnimationFrame": "readonly",
"Buffer": "readonly",
"FileReader": "readonly",
"TextEncoder": "readonly",
"TextDecoder": "readonly",
"fetch": "readonly",
"Headers": "readonly",
"Response": "readonly",
"WebSocket": "readonly",
"Blob": "readonly",
"Blob": "readonly",
"File": "readonly",
"XMLHttpRequest": "readonly",
"URLSearchParams": "readonly",
"ImageData": "readonly",
"Image": "readonly",
"OffscreenCanvas": "readonly",
"BroadcastChannel": "readonly",
"AudioContext": "readonly",
"AudioWorkletProcessor": "readonly",
"webkitAudioContext": "readonly",
"AudioWorkletNode": "readonly",
"Worker": "readonly",
"postMessage": "readonly",
"importScripts": "readonly",
"DEBUG": "writable"
}
},
rules: {
"eol-last": "error",
//"no-extra-parens": "error",
@ -69,7 +120,7 @@ export default [
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-this-before-super": "error",
//"no-undef": "error",
"no-undef": "error",
"no-unexpected-multiline": "error",
//"no-unreachable": "error",
"no-unsafe-finally": "error",

View file

@ -1,8 +1,11 @@
#!/usr/bin/env node
"use strict";
var fs = require("fs");
var V86 = require("../build/libv86.js").V86;
import fs from "node:fs";
import url from "node:url";
import { V86 } from "../build/libv86.js";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
function readfile(path)
{

View file

@ -1,8 +1,10 @@
#!/usr/bin/env node
"use strict";
var fs = require("fs");
var V86 = require("../build/libv86.js").V86;
import fs from "node:fs";
import url from "node:url";
var V86 = await import("../build/libv86.js").V86;
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
function readfile(path)
{

View file

@ -1,5 +1,7 @@
importScripts("../build/libv86.js");
/* global V86 */
var emulator = new V86({
wasm_path: "../build/v86.wasm",
memory_size: 32 * 1024 * 1024,

View file

@ -1,13 +1,16 @@
#!/usr/bin/env node
"use strict";
const assert = require("assert").strict;
const fs = require("fs");
const path = require("path");
const x86_table = require("./x86_table");
const rust_ast = require("./rust_ast");
const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table_rust } = require("./util");
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import x86_table from "./x86_table.js";
const rust_ast = await import("./rust_ast.js");
const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table_rust } = await import("./util.js");
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const OUT_DIR = path.join(__dirname, "..", "src/rust/gen/");
mkdirpSync(OUT_DIR);

View file

@ -1,13 +1,16 @@
#!/usr/bin/env node
"use strict";
const assert = require("assert").strict;
const fs = require("fs");
const path = require("path");
const x86_table = require("./x86_table");
const rust_ast = require("./rust_ast");
const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table_rust } = require("./util");
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import x86_table from "./x86_table.js";
const rust_ast = await import("./rust_ast.js");
const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table_rust } = await import("./util.js");
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const OUT_DIR = path.join(__dirname, "..", "src/rust/gen/");
mkdirpSync(OUT_DIR);

View file

@ -1,15 +1,17 @@
#!/usr/bin/env node
"use strict";
const assert = require("assert").strict;
const fs = require("fs");
const path = require("path");
const x86_table = require("./x86_table");
const rust_ast = require("./rust_ast");
const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table_rust } = require("./util");
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import x86_table from "./x86_table.js";
const rust_ast = await import("./rust_ast.js");
const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table_rust } = await import("./util.js");
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const OUT_DIR = path.join(__dirname, "..", "src/rust/gen/");
mkdirpSync(OUT_DIR);
const table_arg = get_switch_value("--table");

View file

@ -1,13 +1,13 @@
"use strict";
const assert = require("assert").strict;
import assert from "node:assert/strict";
function indent(lines, how_much)
{
return lines.map(line => " ".repeat(how_much) + line);
}
function print_syntax_tree(statements)
export function print_syntax_tree(statements)
{
let code = [];
@ -77,7 +77,3 @@ function print_syntax_tree(statements)
return code;
}
module.exports = {
print_syntax_tree,
};

View file

@ -1,14 +1,13 @@
"use strict";
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const process = require("process");
const child_process = require("child_process");
import fs from "node:fs";
import path from "node:path";
import process from "node:process";
const CYAN_FMT = "\x1b[36m%s\x1b[0m";
function hex(n, pad)
export function hex(n, pad)
{
pad = pad || 0;
let s = n.toString(16).toUpperCase();
@ -16,12 +15,12 @@ function hex(n, pad)
return s;
}
function mkdirpSync(dir)
export function mkdirpSync(dir)
{
fs.mkdirSync(dir, { recursive: true });
}
function get_switch_value(arg_switch)
export function get_switch_value(arg_switch)
{
const argv = process.argv;
const switch_i = argv.indexOf(arg_switch);
@ -33,22 +32,14 @@ function get_switch_value(arg_switch)
return null;
}
function get_switch_exist(arg_switch)
export function get_switch_exist(arg_switch)
{
return process.argv.includes(arg_switch);
}
function finalize_table_rust(out_dir, name, contents)
export function finalize_table_rust(out_dir, name, contents)
{
const file_path = path.join(out_dir, name);
fs.writeFileSync(file_path, contents);
console.log(CYAN_FMT, `[+] Wrote table ${name}.`);
}
module.exports = {
hex,
mkdirpSync,
get_switch_value,
get_switch_exist,
finalize_table_rust,
};

View file

@ -1,6 +1,6 @@
"use strict";
const { hex } = require("./util");
const { hex } = await import("./util.js");
// http://ref.x86asm.net/coder32.html
@ -875,4 +875,5 @@ encodings.sort((e1, e2) => {
return o1 - o2 || e1.fixed_g - e2.fixed_g;
});
module.exports = Object.freeze(encodings.map(entry => Object.freeze(entry)));
const result = Object.freeze(encodings.map(entry => Object.freeze(entry)));
export default result;

View file

@ -6,6 +6,21 @@
"use strict";
import { TRACK_FILENAMES } from "../src/config.js";
import { VirtIO, VIRTIO_F_VERSION_1, VIRTIO_F_RING_EVENT_IDX, VIRTIO_F_RING_INDIRECT_DESC } from "../src/virtio.js";
import { S_IFREG, S_IFDIR, STATUS_UNLINKED } from "./filesystem.js";
import { hex8, message } from "./jor1k.js";
import { marshall, texten } from "./marshall.js";
import { range } from "../src/lib.js";
import { dbg_assert } from "../src/log.js";
// For Types Only
import { CPU } from "../src/cpu.js";
import { BusConnector } from "../src/bus.js";
import { FS } from "./filesystem.js";
// Feature bit (bit position) for mount tag.
const VIRTIO_9P_F_MOUNT_TAG = 0;
// Assumed max tag length in bytes.
@ -16,13 +31,13 @@ const MAX_REPLYBUFFER_SIZE = 16 * 1024 * 1024;
// TODO
// flush
var EPERM = 1; /* Operation not permitted */
var ENOENT = 2; /* No such file or directory */
var EEXIST = 17; /* File exists */
var EINVAL = 22; /* Invalid argument */
var EOPNOTSUPP = 95; /* Operation is not supported */
var ENOTEMPTY = 39; /* Directory not empty */
var EPROTO = 71; /* Protocol error */
export const EPERM = 1; /* Operation not permitted */
export const ENOENT = 2; /* No such file or directory */
export const EEXIST = 17; /* File exists */
export const EINVAL = 22; /* Invalid argument */
export const EOPNOTSUPP = 95; /* Operation is not supported */
export const ENOTEMPTY = 39; /* Directory not empty */
export const EPROTO = 71; /* Protocol error */
var P9_SETATTR_MODE = 0x00000001;
var P9_SETATTR_UID = 0x00000002;
@ -49,18 +64,18 @@ var P9_STAT_MODE_SETUID = 0x00080000;
var P9_STAT_MODE_SETGID = 0x00040000;
var P9_STAT_MODE_SETVTX = 0x00010000;
const P9_LOCK_TYPE_RDLCK = 0;
const P9_LOCK_TYPE_WRLCK = 1;
const P9_LOCK_TYPE_UNLCK = 2;
export const P9_LOCK_TYPE_RDLCK = 0;
export const P9_LOCK_TYPE_WRLCK = 1;
export const P9_LOCK_TYPE_UNLCK = 2;
const P9_LOCK_TYPES = ["shared", "exclusive", "unlock"];
const P9_LOCK_FLAGS_BLOCK = 1;
const P9_LOCK_FLAGS_RECLAIM = 2;
const P9_LOCK_SUCCESS = 0;
const P9_LOCK_BLOCKED = 1;
const P9_LOCK_ERROR = 2;
const P9_LOCK_GRACE = 3;
export const P9_LOCK_SUCCESS = 0;
export const P9_LOCK_BLOCKED = 1;
export const P9_LOCK_ERROR = 2;
export const P9_LOCK_GRACE = 3;
var FID_NONE = -1;
var FID_INODE = 1;
@ -72,7 +87,7 @@ var FID_XATTR = 2;
* @param {FS} filesystem
* @param {CPU} cpu
*/
function Virtio9p(filesystem, cpu, bus) {
export function Virtio9p(filesystem, cpu, bus) {
/** @type {FS} */
this.fs = filesystem;
@ -156,7 +171,7 @@ function Virtio9p(filesystem, cpu, bus) {
read: () => this.configspace_taglen,
write: data => { /* read only */ },
},
].concat(v86util.range(VIRTIO_9P_MAX_TAGLEN).map(index =>
].concat(range(VIRTIO_9P_MAX_TAGLEN).map(index =>
({
bytes: 1,
name: "mount tag name " + index,

View file

@ -5,14 +5,25 @@
"use strict";
var S_IRWXUGO = 0x1FF;
var S_IFMT = 0xF000;
var S_IFSOCK = 0xC000;
var S_IFLNK = 0xA000;
var S_IFREG = 0x8000;
var S_IFBLK = 0x6000;
var S_IFDIR = 0x4000;
var S_IFCHR = 0x2000;
import { LOG_9P } from "../src/const.js";
import { h } from "../src/lib.js";
import { dbg_assert, dbg_log } from "../src/log.js";
import { marshall, texten } from "../lib/marshall.js";
import { message } from "./jor1k.js";
import { EEXIST, ENOTEMPTY, ENOENT, EPERM } from "./9p.js";
import { P9_LOCK_SUCCESS, P9_LOCK_BLOCKED, P9_LOCK_TYPE_UNLCK, P9_LOCK_TYPE_WRLCK, P9_LOCK_TYPE_RDLCK } from "./9p.js";
// For Types Only
import { FileStorageInterface } from "../src/browser/filestorage.js";
export const S_IRWXUGO = 0x1FF;
export const S_IFMT = 0xF000;
export const S_IFSOCK = 0xC000;
export const S_IFLNK = 0xA000;
export const S_IFREG = 0x8000;
export const S_IFBLK = 0x6000;
export const S_IFDIR = 0x4000;
export const S_IFCHR = 0x2000;
//var S_IFIFO 0010000
//var S_ISUID 0004000
@ -24,11 +35,11 @@ var O_WRONLY = 0x0001; // open for writing only
var O_RDWR = 0x0002; // open for reading and writing
var O_ACCMODE = 0x0003; // mask for above modes
var STATUS_INVALID = -0x1;
var STATUS_OK = 0x0;
var STATUS_ON_STORAGE = 0x2;
var STATUS_UNLINKED = 0x4;
var STATUS_FORWARDING = 0x5;
export const STATUS_INVALID = -0x1;
export const STATUS_OK = 0x0;
export const STATUS_ON_STORAGE = 0x2;
export const STATUS_UNLINKED = 0x4;
export const STATUS_FORWARDING = 0x5;
/** @const */ var JSONFS_VERSION = 3;
@ -49,7 +60,7 @@ var STATUS_FORWARDING = 0x5;
* @param {!FileStorageInterface} storage
* @param {{ last_qidnumber: number }=} qidcounter Another fs's qidcounter to synchronise with.
*/
function FS(storage, qidcounter) {
export function FS(storage, qidcounter) {
/** @type {Array.<!Inode>} */
this.inodes = [];
this.events = [];

View file

@ -1,5 +1,10 @@
"use strict";
import { LOG_9P } from "../src/const.js";
import { h } from "../src/lib.js";
import { dbg_log } from "../src/log.js";
// jor1k compatibility
var VIRTIO_MAGIC_REG = 0x0;
@ -29,12 +34,12 @@ var VRING_DESC_F_WRITE = 2; /* This marks a buffer as write-only (otherwise
var VRING_DESC_F_INDIRECT = 4; /* This means the buffer contains a list of buffer descriptors. */
function hex8(n)
export function hex8(n)
{
return h(n);
}
var message = {};
export var message = {};
/** @param {...string} log */
message.Debug = function(log)
@ -92,7 +97,7 @@ else
LoadBinaryResource = function(url, OnSuccess, OnError)
{
//console.log(url);
require("fs")["readFile"](url, function(err, data)
import("node:" + "fs").then(fs => fs["readFile"](url, function(err, data)
{
if(err)
{
@ -102,6 +107,6 @@ else
{
OnSuccess(data.buffer);
}
});
}));
};
}

View file

@ -5,10 +5,12 @@
"use strict";
var marshall = {};
import { message } from "./jor1k.js";
const textde = new TextDecoder();
const texten = new TextEncoder();
export var marshall = {};
export const textde = new TextDecoder();
export const texten = new TextEncoder();
// Inserts data from an array to a byte aligned struct in memory
marshall.Marshall = function(typelist, input, struct, offset) {

View file

@ -1,97 +1,5 @@
import vm from "node:vm";
import url from "node:url";
import fs from "node:fs";
import path from "node:path";
import crypto from "node:crypto";
import perf_hooks from "node:perf_hooks";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
let files = [
"src/const.js",
"src/config.js",
"src/log.js",
"src/cpu.js",
"src/debug.js",
"src/io.js",
"src/main.js",
"src/lib.js",
"src/buffer.js",
"src/ide.js",
"src/pci.js",
"src/floppy.js",
"src/memory.js",
"src/dma.js",
"src/pit.js",
"src/vga.js",
"src/ps2.js",
"src/rtc.js",
"src/uart.js",
"src/acpi.js",
"src/apic.js",
"src/ioapic.js",
"src/state.js",
"src/ne2k.js",
"src/sb16.js",
"src/virtio.js",
"src/virtio_console.js",
"src/virtio_net.js",
"src/virtio_balloon.js",
"src/bus.js",
"src/debug.js",
"src/elf.js",
"src/kernel.js",
"lib/9p.js",
"lib/filesystem.js",
"lib/jor1k.js",
"lib/marshall.js",
"src/browser/screen.js",
"src/browser/keyboard.js",
"src/browser/mouse.js",
"src/browser/speaker.js",
"src/browser/serial.js",
"src/browser/network.js",
"src/browser/fake_network.js",
"src/browser/fetch_network.js",
"src/browser/starter.js",
"src/browser/worker_bus.js",
"src/browser/dummy_screen.js",
"src/browser/print_stats.js",
"src/browser/filestorage.js"
];
let globals = Object.create(globalThis);
let v86 = {};
let ctx = vm.createContext(globals);
globals.DEBUG = false;
globals.module = {exports:v86};
Object.defineProperty(globals, "crypto", {value: crypto});
globals.require = (what) => {
return ({
perf_hooks,
fs
})[what];
};
for( let f of files ) {
vm.runInContext(fs.readFileSync(path.join(__dirname, f), "utf8"), ctx, {
filename: f
});
}
export let {
FetchNetworkAdapter,
MemoryFileStorage,
ServerFileStorageWrapper,
} = globals;
export default globals.V86;
globalThis.DEBUG = true;
var V86 = await import("./src/browser/starter.js");
export default V86.V86;

View file

@ -12,6 +12,7 @@
"build/*.mjs",
"build/v86*.wasm"
],
"main": "build/libv86.js",
"repository": "github:copy/v86"
"main": "build/libv86.mjs",
"repository": "github:copy/v86",
"type": "module"
}

View file

@ -2,14 +2,22 @@
// http://www.uefi.org/sites/default/files/resources/ACPI_6_1.pdf
import { v86 } from "./main.js";
import { LOG_ACPI } from "../src/const.js";
import { h } from "./lib.js";
import { dbg_log, dbg_assert } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
/** @const */
var PMTIMER_FREQ_SECONDS = 3579545;
export const PMTIMER_FREQ_SECONDS = 3579545;
/**
* @constructor
* @param {CPU} cpu
*/
function ACPI(cpu)
export function ACPI(cpu)
{
/** @type {CPU} */
this.cpu = cpu;

View file

@ -2,9 +2,18 @@
// See Intel's System Programming Guide
import { v86 } from "./main.js";
import { LOG_APIC } from "../src/const.js";
import { APIC_TIMER_FREQ } from "./config.js";
import { h, int_log2 } from "./lib.js";
import { dbg_assert, dbg_log, dbg_trace } from "./log.js";
import { IOAPIC_CONFIG_MASKED, IOAPIC_DELIVERY_INIT, IOAPIC_DELIVERY_NMI, IOAPIC_DELIVERY_FIXED } from "./ioapic.js";
// For Types Only
import { CPU } from "./cpu.js";
/** @const */
var APIC_LOG_VERBOSE = false;
export const APIC_LOG_VERBOSE = false;
/** @const */
var APIC_ADDRESS = 0xFEE00000;
@ -23,7 +32,7 @@ var APIC_TIMER_MODE_TSC = 2 << 17;
/** @const */
var DELIVERY_MODES = [
export const DELIVERY_MODES = [
"Fixed (0)",
"Lowest Prio (1)",
"SMI (2)",
@ -35,13 +44,14 @@ var DELIVERY_MODES = [
];
/** @const */
var DESTINATION_MODES = ["physical", "logical"];
export const DESTINATION_MODES = ["physical", "logical"];
/**
* @constructor
* @param {CPU} cpu
*/
export
function APIC(cpu)
{
/** @type {CPU} */
@ -640,7 +650,7 @@ APIC.prototype.register_get_highest_bit = function(v)
if(word)
{
return v86util.int_log2(word >>> 0) | i << 5;
return int_log2(word >>> 0) | i << 5;
}
}

View file

@ -1,9 +1,11 @@
"use strict";
import { dbg_assert } from "../log.js";
/**
* @constructor
*/
function DummyScreenAdapter()
export function DummyScreenAdapter()
{
var
graphic_image_data,

View file

@ -1,5 +1,9 @@
"use strict";
import { LOG_FETCH } from "../const.js";
import { h } from "../lib.js";
import { dbg_assert, dbg_log } from "../log.js";
// https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml
const ETHERTYPE_IPV4 = 0x0800;
const ETHERTYPE_ARP = 0x0806;
@ -23,17 +27,17 @@ const V86_ASCII = [118, 56, 54];
*
* State TIME_WAIT is not needed, we can skip it and transition directly to CLOSED instead.
*/
const TCP_STATE_CLOSED = "closed";
const TCP_STATE_SYN_RECEIVED = "syn-received";
const TCP_STATE_SYN_SENT = "syn-sent";
const TCP_STATE_SYN_PROBE = "syn-probe";
export const TCP_STATE_CLOSED = "closed";
export const TCP_STATE_SYN_RECEIVED = "syn-received";
export const TCP_STATE_SYN_SENT = "syn-sent";
export const TCP_STATE_SYN_PROBE = "syn-probe";
//const TCP_STATE_LISTEN = "listen";
const TCP_STATE_ESTABLISHED = "established";
const TCP_STATE_FIN_WAIT_1 = "fin-wait-1";
const TCP_STATE_CLOSE_WAIT = "close-wait";
const TCP_STATE_FIN_WAIT_2 = "fin-wait-2";
const TCP_STATE_LAST_ACK = "last-ack";
const TCP_STATE_CLOSING = "closing";
export const TCP_STATE_ESTABLISHED = "established";
export const TCP_STATE_FIN_WAIT_1 = "fin-wait-1";
export const TCP_STATE_CLOSE_WAIT = "close-wait";
export const TCP_STATE_FIN_WAIT_2 = "fin-wait-2";
export const TCP_STATE_LAST_ACK = "last-ack";
export const TCP_STATE_CLOSING = "closing";
//const TCP_STATE_TIME_WAIT = "time-wait";
// source: RFC6335, 6. Port Number Ranges
@ -158,7 +162,7 @@ class GrowableRingbuffer
}
}
function create_eth_encoder_buf()
export function create_eth_encoder_buf()
{
const eth_frame = new Uint8Array(ETH_FRAME_SIZE);
const buffer = eth_frame.buffer;
@ -445,7 +449,7 @@ function handle_fake_dhcp(packet, adapter) {
adapter.receive(make_packet(adapter.eth_encoder_buf, reply));
}
function handle_fake_networking(data, adapter) {
export function handle_fake_networking(data, adapter) {
let packet = {};
parse_eth(data, packet);
@ -974,7 +978,7 @@ function write_tcp(spec, out) {
return total_length;
}
function fake_tcp_connect(dport, adapter)
export function fake_tcp_connect(dport, adapter)
{
const vm_ip_str = adapter.vm_ip.join(".");
const router_ip_str = adapter.router_ip.join(".");
@ -1003,7 +1007,7 @@ function fake_tcp_connect(dport, adapter)
return conn;
}
function fake_tcp_probe(dport, adapter) {
export function fake_tcp_probe(dport, adapter) {
return new Promise((res, rej) => {
let handle = fake_tcp_connect(dport, adapter);
handle.state = TCP_STATE_SYN_PROBE;
@ -1014,7 +1018,7 @@ function fake_tcp_probe(dport, adapter) {
/**
* @constructor
*/
function TCPConnection()
export function TCPConnection()
{
this.state = TCP_STATE_CLOSED;
this.net = null; // The adapter is stored here

View file

@ -1,5 +1,21 @@
"use strict";
import { LOG_FETCH } from "../const.js";
import { h } from "../lib.js";
import { dbg_log } from "../log.js";
import {
create_eth_encoder_buf,
handle_fake_networking,
TCPConnection,
TCP_STATE_SYN_RECEIVED,
fake_tcp_connect,
fake_tcp_probe
} from "./fake_network.js";
// For Types Only
import { BusConnector } from "../bus.js";
/**
* @constructor
*
@ -7,7 +23,7 @@
* @param {*=} config
* @export
*/
function FetchNetworkAdapter(bus, config)
export function FetchNetworkAdapter(bus, config)
{
config = config || {};
this.bus = bus;

View file

@ -1,7 +1,11 @@
"use strict";
import { dbg_assert } from "../log.js";
import { load_file } from "../lib.js";
/** @interface */
function FileStorageInterface() {}
export function FileStorageInterface() {}
/**
* Read a portion of a file.
@ -31,7 +35,7 @@ FileStorageInterface.prototype.uncache = function(sha256sum) {};
* @constructor
* @implements {FileStorageInterface}
*/
function MemoryFileStorage()
export function MemoryFileStorage()
{
/**
* From sha256sum to file data.
@ -83,7 +87,7 @@ MemoryFileStorage.prototype.uncache = function(sha256sum)
* @param {FileStorageInterface} file_storage
* @param {string} baseurl
*/
function ServerFileStorageWrapper(file_storage, baseurl)
export function ServerFileStorageWrapper(file_storage, baseurl)
{
dbg_assert(baseurl, "ServerMemoryFileStorage: baseurl should not be empty");
@ -104,7 +108,7 @@ ServerFileStorageWrapper.prototype.load_from_server = function(sha256sum)
{
return new Promise((resolve, reject) =>
{
v86util.load_file(this.baseurl + sha256sum, { done: async buffer =>
load_file(this.baseurl + sha256sum, { done: async buffer =>
{
const data = new Uint8Array(buffer);
await this.cache(sha256sum, data);

View file

@ -1,5 +1,9 @@
"use strict";
// For Types Only
import { BusConnector } from "../bus.js";
/**
* Network adapter "inbrowser" which connects the emulated NIC
* to a shared in-browser BroadcastChannel.
@ -16,7 +20,7 @@
* @param {BusConnector} bus
* @param {*=} config
*/
function InBrowserNetworkAdapter(bus, config)
export function InBrowserNetworkAdapter(bus, config)
{
const id = config.id || 0;

View file

@ -1,5 +1,8 @@
"use strict";
// For Types Only
import { BusConnector } from "../bus.js";
/** @const */
var SHIFT_SCAN_CODE = 0x2A;
@ -14,7 +17,7 @@ const PLATFOM_WINDOWS = typeof window !== "undefined" && window.navigator.platfo
*
* @param {BusConnector} bus
*/
function KeyboardAdapter(bus)
export function KeyboardAdapter(bus)
{
var
/**

View file

@ -1,7 +1,14 @@
"use strict";
(function()
{
import { V86 } from "./starter.js";
import { LOG_NAMES } from "../const.js";
import { LOG_LEVEL, setLogLevel } from "../config.js";
import { print_stats } from "./print_stats.js";
import { SyncFileBuffer } from "../buffer.js";
import { pad0, pads, hex_dump, dump_file, download, round_up_to_next_power_of_2 } from "../lib.js";
import { log_data } from "../log.js";
const ON_LOCALHOST = !location.hostname.endsWith("copy.sh");
const DEFAULT_NETWORKING_PROXIES = ["wss://relay.widgetry.org/", "ws://localhost:8080/"];
@ -29,13 +36,13 @@
}
else if(time < 3600)
{
return (time / 60 | 0) + "m " + v86util.pad0(time % 60, 2) + "s";
return (time / 60 | 0) + "m " + pad0(time % 60, 2) + "s";
}
else
{
return (time / 3600 | 0) + "h " +
v86util.pad0((time / 60 | 0) % 60, 2) + "m " +
v86util.pad0(time % 60, 2) + "s";
pad0((time / 60 | 0) % 60, 2) + "m " +
pad0(time % 60, 2) + "s";
}
}
@ -1659,7 +1666,7 @@
}
input.mask = mask;
label.append(input, v86util.pads(name, 4) + " ");
label.append(input, pads(name, 4) + " ");
log_levels.appendChild(label);
if(i === Math.floor(LOG_NAMES.length / 2))
@ -1675,11 +1682,11 @@
if(target.checked)
{
LOG_LEVEL |= mask;
setLogLevel(LOG_LEVEL | mask);
}
else
{
LOG_LEVEL &= ~mask;
setLogLevel(LOG_LEVEL & ~mask);
}
target.blur();
@ -1765,7 +1772,7 @@
if(chunk_size >= 0)
{
chunk_size = Math.min(4 * 1024 * 1024, Math.max(512, chunk_size));
chunk_size = v86util.round_up_to_next_power_of_2(chunk_size);
chunk_size = round_up_to_next_power_of_2(chunk_size);
}
else
{
@ -2384,6 +2391,9 @@
// $("memory_dump_dmp").blur();
//};
/**
* @this HTMLElement
*/
$("capture_network_traffic").onclick = function()
{
this.value = "0 packets";
@ -2427,6 +2437,9 @@
$("load_state").blur();
};
/**
* @this HTMLElement
*/
$("load_state_input").onchange = async function()
{
var file = this.files[0];
@ -2501,6 +2514,9 @@
$("alttab").blur();
};
/**
* @this HTMLElement
*/
$("scale").onchange = function()
{
var n = parseFloat(this.value);
@ -2627,11 +2643,14 @@
{
$("filesystem_panel").style.display = "block";
/**
* @this HTMLElement
*/
$("filesystem_send_file").onchange = function()
{
Array.prototype.forEach.call(this.files, function(file)
{
var loader = new v86util.SyncFileBuffer(file);
var loader = new SyncFileBuffer(file);
loader.onload = function()
{
loader.get_buffer(async function(buffer)
@ -2646,6 +2665,9 @@
this.blur();
};
/**
* @this HTMLElement
*/
$("filesystem_get_file").onkeypress = async function(e)
{
if(e.which !== 13)
@ -2731,5 +2753,3 @@
window.history.pushState({ search }, "", search);
}
}
})();

View file

@ -1,11 +1,17 @@
"use strict";
import { dbg_log } from "../log.js";
// For Types Only
import { BusConnector } from "../bus.js";
/**
* @constructor
*
* @param {BusConnector} bus
*/
function MouseAdapter(bus, screen_container)
export function MouseAdapter(bus, screen_container)
{
/** @const */
var SPEED_FACTOR = 0.15;

View file

@ -1,5 +1,8 @@
"use strict";
// For Types Only
import { BusConnector } from "../bus.js";
/**
* An ethernet-through-websocket adapter, to be used with
* https://github.com/benjamincburns/websockproxy
@ -12,7 +15,7 @@
* @param {BusConnector} bus
* @param {number} [id=0] id
*/
function NetworkAdapter(url, bus, id)
export function NetworkAdapter(url, bus, id)
{
this.bus = bus;
this.socket = undefined;

View file

@ -1,9 +1,11 @@
"use strict";
import { pads } from "../lib.js";
/**
* @export
*/
const print_stats = {
export const print_stats = {
stats_to_string: function(cpu)
{
return print_stats.print_misc_stats(cpu) +
@ -251,7 +253,7 @@ const print_stats = {
for(let i = 0; i < 0x100; i++)
{
text += i.toString(16).padStart(2, "0") + ":" + v86util.pads(Math.round(per_opcode[i] / factor), pad_length);
text += i.toString(16).padStart(2, "0") + ":" + pads(Math.round(per_opcode[i] / factor), pad_length);
if(i % 16 === 15)
text += "\n";
@ -264,7 +266,7 @@ const print_stats = {
for(let i = 0; i < 0x100; i++)
{
text += (i & 0xFF).toString(16).padStart(2, "0") + ":" + v86util.pads(Math.round(per_opcode0f[i] / factor), pad_length);
text += (i & 0xFF).toString(16).padStart(2, "0") + ":" + pads(Math.round(per_opcode0f[i] / factor), pad_length);
if(i % 16 === 15)
text += "\n";

View file

@ -1,11 +1,14 @@
"use strict";
import { DEBUG_SCREEN_LAYERS } from "../config.js";
import { dbg_assert } from "../log.js";
/**
* Adapter to use visual screen in browsers (in contrast to node)
* @constructor
* @param {Object} options
*/
function ScreenAdapter(options, screen_fill_buffer)
export function ScreenAdapter(options, screen_fill_buffer)
{
const screen_container = options.container;
this.screen_fill_buffer = screen_fill_buffer;

View file

@ -1,11 +1,16 @@
"use strict";
import { dbg_assert, dbg_log } from "../log.js";
// For Types Only
import { BusConnector } from "../bus.js";
/**
* @constructor
*
* @param {BusConnector} bus
*/
function SerialAdapter(element, bus)
export function SerialAdapter(element, bus)
{
var serial = this;
@ -216,7 +221,7 @@ function SerialRecordingAdapter(bus)
* @constructor
* @param {BusConnector} bus
*/
function SerialAdapterXtermJS(element, bus)
export function SerialAdapterXtermJS(element, bus)
{
this.element = element;

View file

@ -1,5 +1,18 @@
"use strict";
import {
MIXER_CHANNEL_BOTH, MIXER_CHANNEL_LEFT, MIXER_CHANNEL_RIGHT,
MIXER_SRC_PCSPEAKER, MIXER_SRC_DAC, MIXER_SRC_MASTER,
} from "../const.js";
import { dbg_assert, dbg_log } from "../log.js";
import { OSCILLATOR_FREQ } from "../pit.js";
import { dump_file } from "../lib.js";
// For Types Only
import { BusConnector } from "../bus.js";
/* global registerProcessor, sampleRate */
/** @const */
var DAC_QUEUE_RESERVE = 0.2;
@ -10,7 +23,7 @@ var AUDIOBUFFER_MINIMUM_SAMPLING_RATE = 8000;
* @constructor
* @param {!BusConnector} bus
*/
function SpeakerAdapter(bus)
export function SpeakerAdapter(bus)
{
if(typeof window === "undefined")
{

View file

@ -1,5 +1,36 @@
"use strict";
import { v86 } from "../main.js";
import { LOG_CPU, WASM_TABLE_OFFSET, WASM_TABLE_SIZE } from "../const.js";
import { setLogLevel } from "../config.js";
import { get_rand_int, load_file, read_sized_string_from_mem } from "../lib.js";
import { dbg_assert, dbg_trace, dbg_log } from "../log.js";
import { print_stats } from "./print_stats.js";
import { Bus } from "../bus.js";
import { BOOT_ORDER_FD_FIRST, BOOT_ORDER_HD_FIRST, BOOT_ORDER_CD_FIRST } from "../rtc.js";
import { SpeakerAdapter } from "./speaker.js";
import { NetworkAdapter } from "./network.js";
import { FetchNetworkAdapter } from "./fetch_network.js";
import { WispNetworkAdapter } from "./wisp_network.js";
import { KeyboardAdapter } from "./keyboard.js";
import { MouseAdapter } from "./mouse.js";
import { ScreenAdapter } from "./screen.js";
import { DummyScreenAdapter } from "./dummy_screen.js";
import { SerialAdapter, SerialAdapterXtermJS } from "./serial.js";
import { InBrowserNetworkAdapter } from "./inbrowser_network.js";
import { MemoryFileStorage, ServerFileStorageWrapper } from "./filestorage.js";
import { SyncBuffer, buffer_from_object } from "../buffer.js";
import { FS } from "../../lib/filesystem.js";
import { EEXIST, ENOENT } from "../../lib/9p.js";
// Decorates CPU
import "../debug.js";
import "../memory.js";
import "../state.js";
/**
* Constructor for emulator instances.
*
@ -107,12 +138,12 @@
* @constructor
* @export
*/
function V86(options)
export function V86(options)
{
if(typeof options.log_level === "number")
{
// XXX: Shared between all emulator instances
LOG_LEVEL = options.log_level;
setLogLevel(options.log_level);
}
//var worker = new Worker("src/browser/worker.js");
@ -136,7 +167,7 @@ function V86(options)
"cpu_event_halt": () => { this.emulator_bus.send("cpu-event-halt"); },
"abort": function() { dbg_assert(false); },
"microtick": v86.microtick,
"get_rand_int": function() { return v86util.get_rand_int(); },
"get_rand_int": function() { return get_rand_int(); },
"apic_acknowledge_irq": function() { return cpu.devices.apic.acknowledge_irq(); },
"stop_idling": function() { return cpu.stop_idling(); },
@ -159,11 +190,11 @@ function V86(options)
},
"log_from_wasm": function(offset, len) {
const str = v86util.read_sized_string_from_mem(wasm_memory, offset, len);
const str = read_sized_string_from_mem(wasm_memory, offset, len);
dbg_log(str, LOG_CPU);
},
"console_log_from_wasm": function(offset, len) {
const str = v86util.read_sized_string_from_mem(wasm_memory, offset, len);
const str = read_sized_string_from_mem(wasm_memory, offset, len);
console.error(str);
},
"dbg_trace_from_wasm": function() {
@ -185,6 +216,8 @@ function V86(options)
{
wasm_fn = env =>
{
/* global __dirname */
return new Promise(resolve => {
let v86_bin = DEBUG ? "v86-debug.wasm" : "v86.wasm";
let v86_bin_fallback = "v86-fallback.wasm";
@ -207,7 +240,7 @@ function V86(options)
v86_bin_fallback = "build/" + v86_bin_fallback;
}
v86util.load_file(v86_bin, {
load_file(v86_bin, {
done: async bytes =>
{
try
@ -218,7 +251,7 @@ function V86(options)
}
catch(err)
{
v86util.load_file(v86_bin_fallback, {
load_file(v86_bin_fallback, {
done: async bytes => {
const { instance } = await WebAssembly.instantiate(bytes, env);
this.wasm_source = bytes;
@ -471,7 +504,7 @@ V86.prototype.continue_init = async function(emulator, options)
{
files_to_load.push({
name,
loadable: v86util.buffer_from_object(file, this.zstd_decompress_worker.bind(this)),
loadable: buffer_from_object(file, this.zstd_decompress_worker.bind(this)),
});
}
};
@ -552,7 +585,7 @@ V86.prototype.continue_init = async function(emulator, options)
}
else
{
v86util.load_file(f.url, {
load_file(f.url, {
done: function(result)
{
if(f.url.endsWith(".zst") && f.name !== "initial_state")
@ -561,7 +594,7 @@ V86.prototype.continue_init = async function(emulator, options)
result = this.zstd_decompress(f.size, new Uint8Array(result));
}
put_on_settings.call(this, f.name, f.as_json ? result : new v86util.SyncBuffer(result));
put_on_settings.call(this, f.name, f.as_json ? result : new SyncBuffer(result));
cont(index + 1);
}.bind(this),
progress: function progress(e)
@ -618,8 +651,8 @@ V86.prototype.continue_init = async function(emulator, options)
settings.fs9p.read_file(initrd_path),
settings.fs9p.read_file(bzimage_path),
]);
put_on_settings.call(this, "initrd", new v86util.SyncBuffer(initrd.buffer));
put_on_settings.call(this, "bzimage", new v86util.SyncBuffer(bzimage.buffer));
put_on_settings.call(this, "initrd", new SyncBuffer(initrd.buffer));
put_on_settings.call(this, "bzimage", new SyncBuffer(bzimage.buffer));
}
}
else
@ -947,16 +980,16 @@ V86.prototype.set_fda = async function(file)
{
if(file.url && !file.async)
{
v86util.load_file(file.url, {
load_file(file.url, {
done: result =>
{
this.v86.cpu.devices.fdc.set_fda(new v86util.SyncBuffer(result));
this.v86.cpu.devices.fdc.set_fda(new SyncBuffer(result));
},
});
}
else
{
const image = v86util.buffer_from_object(file, this.zstd_decompress_worker.bind(this));
const image = buffer_from_object(file, this.zstd_decompress_worker.bind(this));
image.onload = () =>
{
this.v86.cpu.devices.fdc.set_fda(image);
@ -1470,3 +1503,11 @@ function FileNotFoundError(message)
this.message = message || "File not found";
}
FileNotFoundError.prototype = Error.prototype;
/* global module */
if(typeof module !== "undefined" && typeof module.exports !== "undefined")
{
module.exports["V86"] = V86;
module.exports["print_stats"] = print_stats;
}

View file

@ -1,5 +1,18 @@
"use strict";
import { LOG_NET } from "../const.js";
import { dbg_log } from "../log.js";
import {
create_eth_encoder_buf,
handle_fake_networking,
TCPConnection,
TCP_STATE_SYN_RECEIVED,
} from "./fake_network.js";
// For Types Only
import { BusConnector } from "../bus.js";
/**
* @constructor
*
@ -7,7 +20,7 @@
* @param {BusConnector} bus
* @param {*=} config
*/
function WispNetworkAdapter(wisp_url, bus, config)
export function WispNetworkAdapter(wisp_url, bus, config)
{
this.register_ws(wisp_url);
this.last_stream = 1;

View file

@ -1,9 +1,9 @@
"use strict";
var WorkerBus = {};
import { dbg_assert } from "../log.js";
/** @constructor */
WorkerBus.Connector = function(pair)
export var Connector = function(pair)
{
this.listeners = {};
this.pair = pair;
@ -22,7 +22,7 @@ WorkerBus.Connector = function(pair)
};
WorkerBus.Connector.prototype.register = function(name, fn, this_value)
Connector.prototype.register = function(name, fn, this_value)
{
var listeners = this.listeners[name];
@ -44,7 +44,7 @@ WorkerBus.Connector.prototype.register = function(name, fn, this_value)
* @param {*=} value
* @param {*=} transfer_list
*/
WorkerBus.Connector.prototype.send = function(name, value, transfer_list)
Connector.prototype.send = function(name, value, transfer_list)
{
dbg_assert(arguments.length >= 1);
@ -57,7 +57,7 @@ WorkerBus.Connector.prototype.send = function(name, value, transfer_list)
};
WorkerBus.init = function(worker)
export var init = function(worker)
{
return new WorkerBus.Connector(worker);
return new Connector(worker);
};

View file

@ -1,14 +1,8 @@
"use strict";
(function()
{
v86util.SyncBuffer = SyncBuffer;
v86util.AsyncXHRBuffer = AsyncXHRBuffer;
v86util.AsyncXHRPartfileBuffer = AsyncXHRPartfileBuffer;
v86util.AsyncFileBuffer = AsyncFileBuffer;
v86util.SyncFileBuffer = SyncFileBuffer;
v86util.buffer_from_object = buffer_from_object;
import { CPU } from "./cpu.js";
import { load_file } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
// The smallest size the emulated hardware can emit
const BLOCK_SIZE = 256;
@ -19,7 +13,7 @@
* Synchronous access to ArrayBuffer
* @constructor
*/
function SyncBuffer(buffer)
export function SyncBuffer(buffer)
{
dbg_assert(buffer instanceof ArrayBuffer);
@ -208,7 +202,7 @@
requested_length = Math.ceil((offset - requested_start + len) / this.fixed_chunk_size) * this.fixed_chunk_size;
}
v86util.load_file(this.filename, {
load_file(this.filename, {
done: function done(buffer)
{
var block = new Uint8Array(buffer);
@ -383,7 +377,7 @@
* @param {number|undefined} fixed_chunk_size
* @param {boolean|undefined} partfile_alt_format
*/
function AsyncXHRPartfileBuffer(filename, size, fixed_chunk_size, partfile_alt_format, zstd_decompress)
export function AsyncXHRPartfileBuffer(filename, size, fixed_chunk_size, partfile_alt_format, zstd_decompress)
{
const parts = filename.match(/\.[^\.]+(\.zst)?$/);
@ -484,7 +478,7 @@
}
else
{
v86util.load_file(part_filename, {
load_file(part_filename, {
done: async function done(buffer)
{
let block = new Uint8Array(buffer);
@ -512,7 +506,7 @@
{
const part_filename = this.basename + offset + "-" + (offset + len) + this.extension;
v86util.load_file(part_filename, {
load_file(part_filename, {
done: function done(buffer)
{
dbg_assert(buffer.byteLength === len);
@ -537,7 +531,7 @@
*
* @constructor
*/
function SyncFileBuffer(file)
export function SyncFileBuffer(file)
{
this.file = file;
this.byteLength = file.size;
@ -608,7 +602,7 @@
*
* @constructor
*/
function AsyncFileBuffer(file)
export function AsyncFileBuffer(file)
{
this.file = file;
this.byteLength = file.size;
@ -703,11 +697,12 @@
return file;
};
var determine_size;
if(typeof XMLHttpRequest === "undefined")
{
var determine_size = function(path, cb)
determine_size = function(path, cb)
{
require("fs")["stat"](path, (err, stats) =>
import("node:" + "fs").then(fs => fs["stat"](path, (err, stats) =>
{
if(err)
{
@ -717,14 +712,14 @@
{
cb(null, stats.size);
}
});
}));
};
}
else
{
var determine_size = function(url, cb)
determine_size = function(url, cb)
{
v86util.load_file(url, {
load_file(url, {
done: (buffer, http) =>
{
var header = http.getResponseHeader("Content-Range") || "";
@ -748,13 +743,13 @@
};
}
function buffer_from_object(obj, zstd_decompress_worker)
export function buffer_from_object(obj, zstd_decompress_worker)
{
// TODO: accept Uint8Array, ArrayBuffer, File, url rather than { url }
if(obj.buffer instanceof ArrayBuffer)
{
return new v86util.SyncBuffer(obj.buffer);
return new SyncBuffer(obj.buffer);
}
else if(typeof File !== "undefined" && obj.buffer instanceof File)
{
@ -776,11 +771,11 @@
if(is_async)
{
return new v86util.AsyncFileBuffer(obj.buffer);
return new AsyncFileBuffer(obj.buffer);
}
else
{
return new v86util.SyncFileBuffer(obj.buffer);
return new SyncFileBuffer(obj.buffer);
}
}
else if(obj.url)
@ -789,11 +784,11 @@
if(obj.use_parts)
{
return new v86util.AsyncXHRPartfileBuffer(obj.url, obj.size, obj.fixed_chunk_size, false, zstd_decompress_worker);
return new AsyncXHRPartfileBuffer(obj.url, obj.size, obj.fixed_chunk_size, false, zstd_decompress_worker);
}
else
{
return new v86util.AsyncXHRBuffer(obj.url, obj.size, obj.fixed_chunk_size);
return new AsyncXHRBuffer(obj.url, obj.size, obj.fixed_chunk_size);
}
}
else
@ -801,4 +796,3 @@
dbg_log("Ignored file: url=" + obj.url + " buffer=" + obj.buffer);
}
}
})();

View file

@ -1,9 +1,11 @@
"use strict";
var Bus = {};
import { dbg_assert } from "./log.js";
export var Bus = {};
/** @constructor */
function BusConnector()
export function BusConnector()
{
this.listeners = {};
this.pair = undefined;

27
src/cjs.js Normal file
View file

@ -0,0 +1,27 @@
"use strict";
/* global module, self */
var goog = goog || {};
goog.exportSymbol = function(name, sym) {
if(typeof module !== "undefined" && typeof module.exports !== "undefined")
{
module.exports[name] = sym;
}
else if(typeof window !== "undefined")
{
window[name] = sym;
}
else if(typeof importScripts === "function")
{
// web worker
self[name] = sym;
}
};
goog.exportProperty = function() {};
/**
* @define {boolean}
* Overridden for production by closure compiler
*/
var DEBUG = true;

View file

@ -3,51 +3,54 @@
* Compile time configuration, some only relevant for debug mode
*/
/**
* @define {boolean}
* Overridden for production by closure compiler
*/
var DEBUG = true;
import {
LOG_ALL, LOG_PS2, LOG_PIT, LOG_9P, LOG_PIC, LOG_DMA, LOG_NET, LOG_FLOPPY, LOG_DISK,
LOG_SERIAL, LOG_VGA, LOG_SB16, LOG_VIRTIO
} from "./const.js";
/** @const */
var LOG_TO_FILE = false;
export var LOG_TO_FILE = false;
/**
* @const
* Enables logging all IO port reads and writes. Very verbose
*/
var LOG_ALL_IO = false;
export var LOG_ALL_IO = false;
/**
* @const
*/
var DUMP_GENERATED_WASM = false;
export var DUMP_GENERATED_WASM = false;
/**
* @const
*/
var DUMP_UNCOMPILED_ASSEMBLY = false;
export var DUMP_UNCOMPILED_ASSEMBLY = false;
/**
* @const
* More accurate filenames in 9p debug messages at the cost of performance.
*/
var TRACK_FILENAMES = false;
export var TRACK_FILENAMES = false;
var LOG_LEVEL = LOG_ALL & ~LOG_PS2 & ~LOG_PIT & ~LOG_VIRTIO & ~LOG_9P & ~LOG_PIC &
export var LOG_LEVEL = LOG_ALL & ~LOG_PS2 & ~LOG_PIT & ~LOG_VIRTIO & ~LOG_9P & ~LOG_PIC &
~LOG_DMA & ~LOG_SERIAL & ~LOG_NET & ~LOG_FLOPPY & ~LOG_DISK & ~LOG_VGA & ~LOG_SB16;
export function setLogLevel(level) {
LOG_LEVEL = level;
}
/**
* @const
* Draws entire buffer and visualizes the layers that would be drawn
*/
var DEBUG_SCREEN_LAYERS = DEBUG && false;
export var DEBUG_SCREEN_LAYERS = DEBUG && false;
/**
* @const
* How many ticks the TSC does per millisecond
*/
var TSC_RATE = 1 * 1000 * 1000;
export var TSC_RATE = 1 * 1000 * 1000;
/** @const */
var APIC_TIMER_FREQ = TSC_RATE;
export var APIC_TIMER_FREQ = TSC_RATE;

View file

@ -1,6 +1,6 @@
"use strict";
var
export const
/** @const */ LOG_ALL = -1,
/** @const */ LOG_NONE = 0,
@ -35,7 +35,7 @@ var
* @const
* @type {Array<Array<string|number>>}
*/
var LOG_NAMES = [
export const LOG_NAMES = [
[1, ""],
[LOG_CPU, "CPU"],
[LOG_DISK, "DISK"],
@ -62,7 +62,7 @@ var LOG_NAMES = [
[LOG_FETCH, "FETC"],
];
var
export const
// flags register bitflags
/** @const */ FLAG_CARRY = 1,
@ -108,7 +108,7 @@ FLAGS_DEFAULT = 1 << 1,
/** @const */ REG_LDTR = 7; // local descriptor table register
var
export const
/**
* The minimum number of bytes that can be memory-mapped
* by one device.
@ -122,45 +122,45 @@ var
MMAP_MAX = 0x100000000;
/** @const */
var CR0_PG = 1 << 31;
export const CR0_PG = 1 << 31;
/** @const */
var CR4_PAE = 1 << 5;
export const CR4_PAE = 1 << 5;
// https://github.com/qemu/seabios/blob/14221cd86eadba82255fdc55ed174d401c7a0a04/src/fw/paravirt.c#L205-L219
/** @const */ var FW_CFG_SIGNATURE = 0x00;
/** @const */ var FW_CFG_ID = 0x01;
/** @const */ var FW_CFG_RAM_SIZE = 0x03;
/** @const */ var FW_CFG_NB_CPUS = 0x05;
/** @const */ var FW_CFG_MAX_CPUS = 0x0F;
/** @const */ var FW_CFG_NUMA = 0x0D;
/** @const */ var FW_CFG_FILE_DIR = 0x19;
/** @const */ export const FW_CFG_SIGNATURE = 0x00;
/** @const */ export const FW_CFG_ID = 0x01;
/** @const */ export const FW_CFG_RAM_SIZE = 0x03;
/** @const */ export const FW_CFG_NB_CPUS = 0x05;
/** @const */ export const FW_CFG_MAX_CPUS = 0x0F;
/** @const */ export const FW_CFG_NUMA = 0x0D;
/** @const */ export const FW_CFG_FILE_DIR = 0x19;
/** @const */ var FW_CFG_CUSTOM_START = 0x8000;
/** @const */ export const FW_CFG_CUSTOM_START = 0x8000;
// This value is specific to v86, choosen to hopefully not collide with other indexes
/** @const */ var FW_CFG_FILE_START = 0xC000;
/** @const */ export const FW_CFG_FILE_START = 0xC000;
/** @const */ var FW_CFG_SIGNATURE_QEMU = 0x554D4551;
/** @const */ export const FW_CFG_SIGNATURE_QEMU = 0x554D4551;
// See same constant in jit.rs
/** @const */
var WASM_TABLE_SIZE = 900;
export const WASM_TABLE_SIZE = 900;
/** @const */
var WASM_TABLE_OFFSET = 1024;
export const WASM_TABLE_OFFSET = 1024;
/** @const */
var MIXER_CHANNEL_LEFT = 0;
export const MIXER_CHANNEL_LEFT = 0;
/** @const */
var MIXER_CHANNEL_RIGHT = 1;
export const MIXER_CHANNEL_RIGHT = 1;
/** @const */
var MIXER_CHANNEL_BOTH = 2;
export const MIXER_CHANNEL_BOTH = 2;
/** @const */
var MIXER_SRC_MASTER = 0;
export const MIXER_SRC_MASTER = 0;
/** @const */
var MIXER_SRC_PCSPEAKER = 1;
export const MIXER_SRC_PCSPEAKER = 1;
/** @const */
var MIXER_SRC_DAC = 2;
export const MIXER_SRC_DAC = 2;

View file

@ -1,5 +1,58 @@
"use strict";
import {
LOG_CPU, REG_CS,
FW_CFG_SIGNATURE, FW_CFG_SIGNATURE_QEMU,
WASM_TABLE_SIZE, WASM_TABLE_OFFSET, FW_CFG_ID,
FW_CFG_RAM_SIZE, FW_CFG_NB_CPUS, FW_CFG_MAX_CPUS,
FW_CFG_NUMA, FW_CFG_FILE_DIR, FW_CFG_FILE_START,
FW_CFG_CUSTOM_START, REG_EAX, REG_EBX, FLAGS_DEFAULT,
MMAP_BLOCK_BITS, MMAP_BLOCK_SIZE, MMAP_MAX
} from "./const.js";
import { DUMP_GENERATED_WASM, DUMP_UNCOMPILED_ASSEMBLY } from "./config.js";
import { h, view, Bitmap } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
import { SB16 } from "./sb16.js";
import { IOAPIC } from "./ioapic.js";
import { APIC, APIC_LOG_VERBOSE } from "./apic.js";
import { ACPI } from "./acpi.js";
import { PIT } from "./pit.js";
import { DMA } from "./dma.js";
import { UART } from "./uart.js";
import { Ne2k } from "./ne2k.js";
import { IO } from "./io.js";
import { VirtioConsole } from "./virtio_console.js";
import { PCI } from "./pci.js";
import { PS2 } from "./ps2.js";
import { read_elf } from "./elf.js";
import { FloppyController } from "./floppy.js";
import { IDEDevice } from "./ide.js";
import { VirtioNet } from "./virtio_net.js";
import { VGAScreen } from "./vga.js";
import { VirtioBalloon } from "./virtio_balloon.js";
import { Virtio9p } from "../lib/9p.js";
import { load_kernel } from "./kernel.js";
import {
RTC,
CMOS_EQUIPMENT_INFO, CMOS_BIOS_SMP_COUNT,
CMOS_MEM_HIGHMEM_HIGH, CMOS_MEM_HIGHMEM_MID, CMOS_MEM_HIGHMEM_LOW,
CMOS_DISK_DATA, CMOS_BIOS_DISKTRANSFLAG, CMOS_FLOPPY_DRIVE_TYPE,
BOOT_ORDER_CD_FIRST, CMOS_BIOS_BOOTFLAG1, CMOS_BIOS_BOOTFLAG2,
CMOS_MEM_BASE_LOW, CMOS_MEM_BASE_HIGH,
CMOS_MEM_OLD_EXT_LOW, CMOS_MEM_OLD_EXT_HIGH, CMOS_MEM_EXTMEM_LOW,
CMOS_MEM_EXTMEM_HIGH, CMOS_MEM_EXTMEM2_LOW, CMOS_MEM_EXTMEM2_HIGH
} from "./rtc.js";
// For Types Only
import { BusConnector } from "./bus.js";
// Resources:
// https://pdos.csail.mit.edu/6.828/2006/readings/i386/toc.htm
// https://www-ssl.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html
@ -7,7 +60,7 @@
/** @constructor */
function CPU(bus, wm, stop_idling)
export function CPU(bus, wm, stop_idling)
{
this.stop_idling = stop_idling;
this.wm = wm;
@ -18,91 +71,91 @@ function CPU(bus, wm, stop_idling)
this.wasm_memory = memory;
this.memory_size = v86util.view(Uint32Array, memory, 812, 1);
this.memory_size = view(Uint32Array, memory, 812, 1);
this.mem8 = new Uint8Array(0);
this.mem32s = new Int32Array(this.mem8.buffer);
this.segment_is_null = v86util.view(Uint8Array, memory, 724, 8);
this.segment_offsets = v86util.view(Int32Array, memory, 736, 8);
this.segment_limits = v86util.view(Uint32Array, memory, 768, 8);
this.segment_access_bytes = v86util.view(Uint8Array, memory, 512, 8);
this.segment_is_null = view(Uint8Array, memory, 724, 8);
this.segment_offsets = view(Int32Array, memory, 736, 8);
this.segment_limits = view(Uint32Array, memory, 768, 8);
this.segment_access_bytes = view(Uint8Array, memory, 512, 8);
/**
* Wheter or not in protected mode
*/
this.protected_mode = v86util.view(Int32Array, memory, 800, 1);
this.protected_mode = view(Int32Array, memory, 800, 1);
this.idtr_size = v86util.view(Int32Array, memory, 564, 1);
this.idtr_offset = v86util.view(Int32Array, memory, 568, 1);
this.idtr_size = view(Int32Array, memory, 564, 1);
this.idtr_offset = view(Int32Array, memory, 568, 1);
/**
* global descriptor table register
*/
this.gdtr_size = v86util.view(Int32Array, memory, 572, 1);
this.gdtr_offset = v86util.view(Int32Array, memory, 576, 1);
this.gdtr_size = view(Int32Array, memory, 572, 1);
this.gdtr_offset = view(Int32Array, memory, 576, 1);
this.tss_size_32 = v86util.view(Int32Array, memory, 1128, 1);
this.tss_size_32 = view(Int32Array, memory, 1128, 1);
/*
* whether or not a page fault occured
*/
this.page_fault = v86util.view(Uint32Array, memory, 540, 8);
this.page_fault = view(Uint32Array, memory, 540, 8);
this.cr = v86util.view(Int32Array, memory, 580, 8);
this.cr = view(Int32Array, memory, 580, 8);
// current privilege level
this.cpl = v86util.view(Uint8Array, memory, 612, 1);
this.cpl = view(Uint8Array, memory, 612, 1);
// current operand/address size
this.is_32 = v86util.view(Int32Array, memory, 804, 1);
this.is_32 = view(Int32Array, memory, 804, 1);
this.stack_size_32 = v86util.view(Int32Array, memory, 808, 1);
this.stack_size_32 = view(Int32Array, memory, 808, 1);
/**
* Was the last instruction a hlt?
*/
this.in_hlt = v86util.view(Uint8Array, memory, 616, 1);
this.in_hlt = view(Uint8Array, memory, 616, 1);
this.last_virt_eip = v86util.view(Int32Array, memory, 620, 1);
this.eip_phys = v86util.view(Int32Array, memory, 624, 1);
this.last_virt_eip = view(Int32Array, memory, 620, 1);
this.eip_phys = view(Int32Array, memory, 624, 1);
this.sysenter_cs = v86util.view(Int32Array, memory, 636, 1);
this.sysenter_cs = view(Int32Array, memory, 636, 1);
this.sysenter_esp = v86util.view(Int32Array, memory, 640, 1);
this.sysenter_esp = view(Int32Array, memory, 640, 1);
this.sysenter_eip = v86util.view(Int32Array, memory, 644, 1);
this.sysenter_eip = view(Int32Array, memory, 644, 1);
this.prefixes = v86util.view(Int32Array, memory, 648, 1);
this.prefixes = view(Int32Array, memory, 648, 1);
this.flags = v86util.view(Int32Array, memory, 120, 1);
this.flags = view(Int32Array, memory, 120, 1);
/**
* bitmap of flags which are not updated in the flags variable
* changed by arithmetic instructions, so only relevant to arithmetic flags
*/
this.flags_changed = v86util.view(Int32Array, memory, 100, 1);
this.flags_changed = view(Int32Array, memory, 100, 1);
/**
* enough infos about the last arithmetic operation to compute eflags
*/
this.last_op_size = v86util.view(Int32Array, memory, 96, 1);
this.last_op1 = v86util.view(Int32Array, memory, 104, 1);
this.last_result = v86util.view(Int32Array, memory, 112, 1);
this.last_op_size = view(Int32Array, memory, 96, 1);
this.last_op1 = view(Int32Array, memory, 104, 1);
this.last_result = view(Int32Array, memory, 112, 1);
this.current_tsc = v86util.view(Uint32Array, memory, 960, 2); // 64 bit
this.current_tsc = view(Uint32Array, memory, 960, 2); // 64 bit
/** @type {!Object} */
this.devices = {};
this.instruction_pointer = v86util.view(Int32Array, memory, 556, 1);
this.previous_ip = v86util.view(Int32Array, memory, 560, 1);
this.instruction_pointer = view(Int32Array, memory, 556, 1);
this.previous_ip = view(Int32Array, memory, 560, 1);
// configured by guest
this.apic_enabled = v86util.view(Uint8Array, memory, 548, 1);
this.apic_enabled = view(Uint8Array, memory, 548, 1);
// configured when the emulator starts (changes bios initialisation)
this.acpi_enabled = v86util.view(Uint8Array, memory, 552, 1);
this.acpi_enabled = view(Uint8Array, memory, 552, 1);
// managed in io.js
/** @const */ this.memory_map_read8 = [];
@ -119,47 +172,47 @@ function CPU(bus, wm, stop_idling)
vga: null,
};
this.instruction_counter = v86util.view(Uint32Array, memory, 664, 1);
this.instruction_counter = view(Uint32Array, memory, 664, 1);
// registers
this.reg32 = v86util.view(Int32Array, memory, 64, 8);
this.reg32 = view(Int32Array, memory, 64, 8);
this.fpu_st = v86util.view(Int32Array, memory, 1152, 4 * 8);
this.fpu_st = view(Int32Array, memory, 1152, 4 * 8);
this.fpu_stack_empty = v86util.view(Uint8Array, memory, 816, 1);
this.fpu_stack_empty = view(Uint8Array, memory, 816, 1);
this.fpu_stack_empty[0] = 0xFF;
this.fpu_stack_ptr = v86util.view(Uint8Array, memory, 1032, 1);
this.fpu_stack_ptr = view(Uint8Array, memory, 1032, 1);
this.fpu_stack_ptr[0] = 0;
this.fpu_control_word = v86util.view(Uint16Array, memory, 1036, 1);
this.fpu_control_word = view(Uint16Array, memory, 1036, 1);
this.fpu_control_word[0] = 0x37F;
this.fpu_status_word = v86util.view(Uint16Array, memory, 1040, 1);
this.fpu_status_word = view(Uint16Array, memory, 1040, 1);
this.fpu_status_word[0] = 0;
this.fpu_ip = v86util.view(Int32Array, memory, 1048, 1);
this.fpu_ip = view(Int32Array, memory, 1048, 1);
this.fpu_ip[0] = 0;
this.fpu_ip_selector = v86util.view(Int32Array, memory, 1052, 1);
this.fpu_ip_selector = view(Int32Array, memory, 1052, 1);
this.fpu_ip_selector[0] = 0;
this.fpu_opcode = v86util.view(Int32Array, memory, 1044, 1);
this.fpu_opcode = view(Int32Array, memory, 1044, 1);
this.fpu_opcode[0] = 0;
this.fpu_dp = v86util.view(Int32Array, memory, 1056, 1);
this.fpu_dp = view(Int32Array, memory, 1056, 1);
this.fpu_dp[0] = 0;
this.fpu_dp_selector = v86util.view(Int32Array, memory, 1060, 1);
this.fpu_dp_selector = view(Int32Array, memory, 1060, 1);
this.fpu_dp_selector[0] = 0;
this.reg_xmm32s = v86util.view(Int32Array, memory, 832, 8 * 4);
this.reg_xmm32s = view(Int32Array, memory, 832, 8 * 4);
this.mxcsr = v86util.view(Int32Array, memory, 824, 1);
this.mxcsr = view(Int32Array, memory, 824, 1);
// segment registers, tr and ldtr
this.sreg = v86util.view(Uint16Array, memory, 668, 8);
this.sreg = view(Uint16Array, memory, 668, 8);
// debug registers
this.dreg = v86util.view(Int32Array, memory, 684, 8);
this.dreg = view(Int32Array, memory, 684, 8);
this.reg_pdpte = v86util.view(Int32Array, memory, 968, 8);
this.reg_pdpte = view(Int32Array, memory, 968, 8);
this.svga_dirty_bitmap_min_offset = v86util.view(Uint32Array, memory, 716, 1);
this.svga_dirty_bitmap_max_offset = v86util.view(Uint32Array, memory, 720, 1);
this.svga_dirty_bitmap_min_offset = view(Uint32Array, memory, 716, 1);
this.svga_dirty_bitmap_max_offset = view(Uint32Array, memory, 720, 1);
this.fw_value = [];
this.fw_pointer = 0;
@ -573,7 +626,7 @@ CPU.prototype.set_state = function(state)
this.fpu_dp_selector[0] = state[74];
this.fpu_opcode[0] = state[75];
const bitmap = new v86util.Bitmap(state[78].buffer);
const bitmap = new Bitmap(state[78].buffer);
const packed_memory = state[77];
this.unpack_memory(bitmap, packed_memory);
@ -636,7 +689,7 @@ CPU.prototype.pack_memory = function()
}
}
const bitmap = new v86util.Bitmap(page_count);
const bitmap = new Bitmap(page_count);
const packed_memory = new Uint8Array(nonzero_pages.length << 12);
for(const [i, page] of nonzero_pages.entries())
@ -720,8 +773,8 @@ CPU.prototype.create_memory = function(size, minimum_size)
const memory_offset = this.allocate_memory(size);
this.mem8 = v86util.view(Uint8Array, this.wasm_memory, memory_offset, size);
this.mem32s = v86util.view(Uint32Array, this.wasm_memory, memory_offset, size >> 2);
this.mem8 = view(Uint8Array, this.wasm_memory, memory_offset, size);
this.mem32s = view(Uint32Array, this.wasm_memory, memory_offset, size >> 2);
};
/**

View file

@ -1,5 +1,16 @@
"use strict";
import {
LOG_BIOS, LOG_CPU,
REG_ESP, REG_EBP, REG_ESI, REG_EAX, REG_EBX, REG_ECX, REG_EDX, REG_EDI,
REG_CS, REG_DS, REG_ES, REG_FS, REG_GS, REG_SS, CR0_PG, CR4_PAE, REG_LDTR,
FLAG_VM, FLAG_INTERRUPT, FLAG_CARRY, FLAG_ADJUST, FLAG_ZERO, FLAG_SIGN, FLAG_TRAP,
FLAG_DIRECTION, FLAG_OVERFLOW, FLAG_PARITY
} from "./const.js";
import { h, pads } from "./lib.js";
import { dbg_log } from "./log.js";
import { CPU } from "./cpu.js";
CPU.prototype.debug_init = function()
{
var cpu = this;
@ -560,6 +571,7 @@ CPU.prototype.debug_init = function()
{
if(cs === undefined)
{
/* global require */
if(typeof require === "function")
{
cs = require("./capstone-x86.min.js");
@ -588,7 +600,7 @@ CPU.prototype.debug_init = function()
instructions.forEach(function (instr) {
dbg_log(h(instr.address >>> 0) + ": " +
v86util.pads(instr.bytes.map(x => h(x, 2).slice(-2)).join(" "), 20) + " " +
pads(instr.bytes.map(x => h(x, 2).slice(-2)).join(" "), 20) + " " +
instr.mnemonic + " " + instr.op_str);
});
dbg_log("");
@ -616,11 +628,12 @@ CPU.prototype.debug_init = function()
debug.dump_wasm = function(buffer)
{
/* global require */
if(wabt === undefined)
{
if(typeof require === "function")
{
wabt = require("./libwabt.js");
wabt = require("./libwabt.cjs");
}
else
{

View file

@ -1,10 +1,17 @@
"use strict";
import { LOG_DMA } from "./const.js";
import { h } from "./lib.js";
import { dbg_log } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
/**
* @constructor
* @param {CPU} cpu
*/
function DMA(cpu)
export function DMA(cpu)
{
/** @const @type {CPU} */
this.cpu = cpu;

View file

@ -1,5 +1,8 @@
"use strict";
import { LOG_LEVEL } from "./config.js";
import { dbg_log } from "./log.js";
// A minimal elf parser for loading 32 bit, x86, little endian, executable elf files
const ELF_MAGIC = 0x464C457F;
@ -95,7 +98,7 @@ function create_struct(struct)
}
/** @param {ArrayBuffer} buffer */
function read_elf(buffer)
export function read_elf(buffer)
{
const view = new DataView(buffer);

View file

@ -3,6 +3,18 @@
// https://www.isdaman.com/alsos/hardware/fdc/floppy.htm
// https://wiki.osdev.org/Floppy_Disk_Controller
import { LOG_FLOPPY } from "./const.js";
import { h } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
import { CMOS_FLOPPY_DRIVE_TYPE } from "./rtc.js";
import { SyncBuffer } from "./buffer.js";
// For Types Only
import { CPU } from "./cpu.js";
import { DMA } from "./dma.js";
import { IO } from "./io.js";
const DIR_DOOR = 0x80;
const ST1_NID = 1 << 0;
const ST1_NDAT = 1 << 2;
@ -12,7 +24,7 @@ const ST1_NDAT = 1 << 2;
*
* @param {CPU} cpu
*/
function FloppyController(cpu, fda_image, fdb_image)
export function FloppyController(cpu, fda_image, fdb_image)
{
/** @const @type {IO|undefined} */
this.io = cpu.io;
@ -110,7 +122,7 @@ FloppyController.prototype.set_fda = function(fda_image)
dbg_assert(fda_image.buffer && fda_image.buffer instanceof ArrayBuffer);
const new_image = new Uint8Array(floppy_size);
new_image.set(new Uint8Array(fda_image.buffer));
fda_image = new v86util.SyncBuffer(new_image.buffer);
fda_image = new SyncBuffer(new_image.buffer);
dbg_log("Warning: Unkown floppy size: " + fda_image.byteLength + ", assuming " + floppy_size);
}

View file

@ -1,5 +1,14 @@
"use strict";
import { LOG_DISK } from "./const.js";
import { h } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
import { CMOS_BIOS_DISKTRANSFLAG, CMOS_DISK_DATA, CMOS_DISK_DRIVE1_CYL } from "./rtc.js";
// For Types Only
import { CPU } from "./cpu.js";
import { BusConnector } from "./bus.js";
/** @const */
var CDROM_SECTOR_SIZE = 2048;
/** @const */
@ -12,7 +21,7 @@ var HD_SECTOR_SIZE = 512;
* @param {number} nr
* @param {BusConnector} bus
* */
function IDEDevice(cpu, master_buffer, slave_buffer, is_cd, nr, bus)
export function IDEDevice(cpu, master_buffer, slave_buffer, is_cd, nr, bus)
{
this.master = new IDEInterface(this, cpu, master_buffer, is_cd, nr, 0, bus);
this.slave = new IDEInterface(this, cpu, slave_buffer, false, nr, 1, bus);

View file

@ -1,5 +1,14 @@
"use strict";
import { LOG_IO, MMAP_BLOCK_BITS, MMAP_BLOCK_SIZE, MMAP_MAX } from "./const.js";
import { LOG_ALL_IO } from "./config.js";
import { h } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
/**
* The ISA IO bus
* Devices register their ports here
@ -7,7 +16,7 @@
* @constructor
* @param {CPU} cpu
*/
function IO(cpu)
export function IO(cpu)
{
/** @const */
this.ports = [];
@ -87,9 +96,9 @@ IO.prototype.empty_port_write = function(x)
/**
* @param {number} port_addr
* @param {Object} device
* @param {function():number=} r8
* @param {function():number=} r16
* @param {function():number=} r32
* @param {function(number):number=} r8
* @param {function(number):number=} r16
* @param {function(number):number=} r32
*/
IO.prototype.register_read = function(port_addr, device, r8, r16, r32)
{

View file

@ -2,55 +2,64 @@
// http://download.intel.com/design/chipsets/datashts/29056601.pdf
/** @const */
var IOAPIC_ADDRESS = 0xFEC00000;
import { LOG_APIC, MMAP_BLOCK_SIZE } from "./const.js";
import { h } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
import { DELIVERY_MODES, DESTINATION_MODES, APIC_LOG_VERBOSE } from "./apic.js";
/** @const */
var IOREGSEL = 0;
/** @const */
var IOWIN = 0x10;
/** @const */
var IOAPIC_IRQ_COUNT = 24;
/** @const */
var IOAPIC_ID = 0; // must match value in seabios
// For Types Only
import { CPU } from "./cpu.js";
/** @const */
var IOAPIC_CONFIG_TRIGGER_MODE_LEVEL = 1 << 15;
export const IOAPIC_ADDRESS = 0xFEC00000;
/** @const */
var IOAPIC_CONFIG_MASKED = 1 << 16;
export const IOREGSEL = 0;
/** @const */
var IOAPIC_CONFIG_DELIVS = 1 << 12;
export const IOWIN = 0x10;
/** @const */
var IOAPIC_CONFIG_REMOTE_IRR = 1 << 14;
export const IOAPIC_IRQ_COUNT = 24;
/** @const */
var IOAPIC_CONFIG_READONLY_MASK = IOAPIC_CONFIG_REMOTE_IRR | IOAPIC_CONFIG_DELIVS | 0xFFFE0000;
export const IOAPIC_ID = 0; // must match value in seabios
/** @const */
var IOAPIC_DELIVERY_FIXED = 0;
export const IOAPIC_CONFIG_TRIGGER_MODE_LEVEL = 1 << 15;
/** @const */
var IOAPIC_DELIVERY_LOWEST_PRIORITY = 1;
export const IOAPIC_CONFIG_MASKED = 1 << 16;
/** @const */
var IOAPIC_DELIVERY_NMI = 4;
export const IOAPIC_CONFIG_DELIVS = 1 << 12;
/** @const */
var IOAPIC_DELIVERY_INIT = 5;
export const IOAPIC_CONFIG_REMOTE_IRR = 1 << 14;
/** @const */
export const IOAPIC_CONFIG_READONLY_MASK = IOAPIC_CONFIG_REMOTE_IRR | IOAPIC_CONFIG_DELIVS | 0xFFFE0000;
/** @const */
export const IOAPIC_DELIVERY_FIXED = 0;
/** @const */
export const IOAPIC_DELIVERY_LOWEST_PRIORITY = 1;
/** @const */
export const IOAPIC_DELIVERY_NMI = 4;
/** @const */
export const IOAPIC_DELIVERY_INIT = 5;
/**
* @constructor
* @param {CPU} cpu
*/
function IOAPIC(cpu)
export function IOAPIC(cpu)
{
/** @type {CPU} */
this.cpu = cpu;

View file

@ -1,5 +1,9 @@
"use strict";
import { h } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
// https://www.kernel.org/doc/Documentation/x86/boot.txt
const LINUX_BOOT_HDR_SETUP_SECTS = 0x1F1;
@ -37,7 +41,7 @@ const LINUX_BOOT_HDR_LOADFLAGS_KEEP_SEGMENTS = 1 << 6;
const LINUX_BOOT_HDR_LOADFLAGS_CAN_USE_HEAPS = 1 << 7;
function load_kernel(mem8, bzimage, initrd, cmdline)
export function load_kernel(mem8, bzimage, initrd, cmdline)
{
dbg_log("Trying to load kernel of size " + bzimage.byteLength);

View file

@ -1,52 +1,34 @@
"use strict";
var goog = goog || {};
goog.exportSymbol = function(name, sym) {
if(typeof module !== "undefined" && typeof module.exports !== "undefined")
{
module.exports[name] = sym;
}
else if(typeof window !== "undefined")
{
window[name] = sym;
}
else if(typeof importScripts === "function")
{
// web worker
self[name] = sym;
}
};
goog.exportProperty = function() {};
var v86util = v86util || {};
import { dbg_assert } from "./log.js";
// pad string with spaces on the right
v86util.pads = function(str, len)
export function pads(str, len)
{
str = (str || str === 0) ? str + "" : "";
return str.padEnd(len, " ");
};
}
// pad string with zeros on the left
v86util.pad0 = function(str, len)
export function pad0(str, len)
{
str = (str || str === 0) ? str + "" : "";
return str.padStart(len, "0");
};
}
// generates array given size with zeros
v86util.zeros = function(size)
export function zeros(size)
{
return Array(size).fill(0);
};
}
// generates [0, 1, 2, ..., size-1]
v86util.range = function(size)
export function range(size)
{
return Array.from(Array(size).keys());
};
}
v86util.view = function(constructor, memory, offset, length)
export var view = function(constructor, memory, offset, length)
{
dbg_assert(offset >= 0);
return new Proxy({},
@ -78,7 +60,7 @@ v86util.view = function(constructor, memory, offset, length)
* @param {number=} len
* @return {string}
*/
function h(n, len)
export function h(n, len)
{
if(!n)
{
@ -89,14 +71,14 @@ function h(n, len)
var str = n.toString(16);
}
return "0x" + v86util.pad0(str.toUpperCase(), len || 1);
return "0x" + pad0(str.toUpperCase(), len || 1);
}
function hex_dump(buffer)
export function hex_dump(buffer)
{
function hex(n, len)
{
return v86util.pad0(n.toString(16).toUpperCase(), len);
return pad0(n.toString(16).toUpperCase(), len);
}
const result = [];
@ -144,11 +126,13 @@ function hex_dump(buffer)
return "\n" + result.join("\n") + "\n";
}
/* global require */
export var get_rand_int;
if(typeof crypto !== "undefined" && crypto.getRandomValues)
{
const rand_data = new Int32Array(1);
v86util.get_rand_int = function()
get_rand_int = function()
{
crypto.getRandomValues(rand_data);
return rand_data[0];
@ -159,18 +143,27 @@ else if(typeof require !== "undefined")
/** @type {{ randomBytes: Function }} */
const crypto = require("crypto");
v86util.get_rand_int = function()
get_rand_int = function()
{
return crypto.randomBytes(4)["readInt32LE"](0);
};
}
else if(typeof process !== "undefined")
{
import("node:" + "crypto").then(crypto => {
get_rand_int = function()
{
return crypto["randomBytes"](4)["readInt32LE"](0);
};
});
}
else
{
dbg_assert(false, "Unsupported platform: No cryptographic random values");
}
(function()
{
export var int_log2;
if(typeof Math.clz32 === "function" && Math.clz32(0) === 32 && Math.clz32(0x12345) === 15 && Math.clz32(-1) === 0)
{
/**
@ -178,15 +171,13 @@ else
* @param {number} x
* @return {number}
*/
v86util.int_log2 = function(x)
int_log2 = function(x)
{
dbg_assert(x > 0);
return 31 - Math.clz32(x);
};
return;
}
} else {
var int_log2_table = new Int8Array(256);
@ -203,7 +194,7 @@ else
* @param {number} x
* @return {number}
*/
v86util.int_log2 = function(x)
int_log2 = function(x)
{
x >>>= 0;
dbg_assert(x > 0);
@ -236,28 +227,28 @@ else
}
}
};
})();
}
v86util.round_up_to_next_power_of_2 = function(x)
export const round_up_to_next_power_of_2 = function(x)
{
dbg_assert(x >= 0);
return x <= 1 ? 1 : 1 << 1 + v86util.int_log2(x - 1);
return x <= 1 ? 1 : 1 << 1 + int_log2(x - 1);
};
if(DEBUG)
{
dbg_assert(v86util.int_log2(1) === 0);
dbg_assert(v86util.int_log2(2) === 1);
dbg_assert(v86util.int_log2(7) === 2);
dbg_assert(v86util.int_log2(8) === 3);
dbg_assert(v86util.int_log2(123456789) === 26);
dbg_assert(int_log2(1) === 0);
dbg_assert(int_log2(2) === 1);
dbg_assert(int_log2(7) === 2);
dbg_assert(int_log2(8) === 3);
dbg_assert(int_log2(123456789) === 26);
dbg_assert(v86util.round_up_to_next_power_of_2(0) === 1);
dbg_assert(v86util.round_up_to_next_power_of_2(1) === 1);
dbg_assert(v86util.round_up_to_next_power_of_2(2) === 2);
dbg_assert(v86util.round_up_to_next_power_of_2(7) === 8);
dbg_assert(v86util.round_up_to_next_power_of_2(8) === 8);
dbg_assert(v86util.round_up_to_next_power_of_2(123456789) === 134217728);
dbg_assert(round_up_to_next_power_of_2(0) === 1);
dbg_assert(round_up_to_next_power_of_2(1) === 1);
dbg_assert(round_up_to_next_power_of_2(2) === 2);
dbg_assert(round_up_to_next_power_of_2(7) === 8);
dbg_assert(round_up_to_next_power_of_2(8) === 8);
dbg_assert(round_up_to_next_power_of_2(123456789) === 134217728);
}
/**
@ -266,7 +257,7 @@ if(DEBUG)
* Queue wrapper around Uint8Array
* Used by devices such as the PS2 controller
*/
function ByteQueue(size)
export function ByteQueue(size)
{
var data = new Uint8Array(size),
start,
@ -337,7 +328,7 @@ function ByteQueue(size)
* Queue wrapper around Float32Array
* Used by devices such as the sound blaster sound card
*/
function FloatQueue(size)
export function FloatQueue(size)
{
this.size = size;
this.data = new Float32Array(size);
@ -465,7 +456,7 @@ CircularQueue.prototype.set = function(new_data)
this.index = 0;
};
function dump_file(ab, name)
export function dump_file(ab, name)
{
if(!Array.isArray(ab))
{
@ -476,7 +467,7 @@ function dump_file(ab, name)
download(blob, name);
}
function download(file_or_blob, name)
export function download(file_or_blob, name)
{
var a = document.createElement("a");
a["download"] = name;
@ -502,7 +493,7 @@ function download(file_or_blob, name)
* A simple 1d bitmap
* @constructor
*/
v86util.Bitmap = function(length_or_buffer)
export var Bitmap = function(length_or_buffer)
{
if(typeof length_or_buffer === "number")
{
@ -514,11 +505,11 @@ v86util.Bitmap = function(length_or_buffer)
}
else
{
dbg_assert(false, "v86util.Bitmap: Invalid argument");
dbg_assert(false, "Bitmap: Invalid argument");
}
};
v86util.Bitmap.prototype.set = function(index, value)
Bitmap.prototype.set = function(index, value)
{
const bit_index = index & 7;
const byte_index = index >> 3;
@ -528,7 +519,7 @@ v86util.Bitmap.prototype.set = function(index, value)
value ? this.view[byte_index] | bit_mask : this.view[byte_index] & ~bit_mask;
};
v86util.Bitmap.prototype.get = function(index)
Bitmap.prototype.get = function(index)
{
const bit_index = index & 7;
const byte_index = index >> 3;
@ -536,19 +527,20 @@ v86util.Bitmap.prototype.get = function(index)
return this.view[byte_index] >> bit_index & 1;
};
v86util.Bitmap.prototype.get_buffer = function()
Bitmap.prototype.get_buffer = function()
{
return this.view.buffer;
};
export var load_file;
if(typeof XMLHttpRequest === "undefined")
{
v86util.load_file = load_file_nodejs;
load_file = load_file_nodejs;
}
else
{
v86util.load_file = load_file;
load_file = _load_file;
}
/**
@ -556,7 +548,7 @@ else
* @param {Object} options
* @param {number=} n_tries
*/
function load_file(filename, options, n_tries)
function _load_file(filename, options, n_tries)
{
var http = new XMLHttpRequest();
@ -656,13 +648,11 @@ function load_file(filename, options, n_tries)
function load_file_nodejs(filename, options)
{
const fs = require("fs");
if(options.range)
{
dbg_assert(!options.as_json);
fs["open"](filename, "r", (err, fd) =>
import("node:" + "fs").then(fs => fs["open"](filename, "r", (err, fd) =>
{
if(err) throw err;
@ -680,7 +670,7 @@ function load_file_nodejs(filename, options)
if(err) throw err;
});
});
});
}));
}
else
{
@ -688,7 +678,7 @@ function load_file_nodejs(filename, options)
encoding: options.as_json ? "utf-8" : null,
};
fs["readFile"](filename, o, function(err, data)
import("node:" + "fs").then(fs => fs["readFile"](filename, o, function(err, data)
{
if(err)
{
@ -709,14 +699,14 @@ function load_file_nodejs(filename, options)
options.done(result);
}
});
}));
}
}
// Reads len characters at offset from Memory object mem as a JS string
v86util.read_sized_string_from_mem = function read_sized_string_from_mem(mem, offset, len)
export function read_sized_string_from_mem(mem, offset, len)
{
offset >>>= 0;
len >>>= 0;
return String.fromCharCode(...new Uint8Array(mem.buffer, offset, len));
};
}

View file

@ -1,6 +1,10 @@
"use strict";
var log_data = [];
import { LOG_NAMES } from "./const.js";
import { LOG_TO_FILE, LOG_LEVEL } from "./config.js";
import { pad0, pads } from "./lib.js";
export var log_data = [];
function do_the_log(message)
{
@ -18,7 +22,7 @@ function do_the_log(message)
* @type {function((string|number), number=)}
* @const
*/
var dbg_log = (function()
export var dbg_log = (function()
{
if(!DEBUG)
{
@ -47,7 +51,7 @@ var dbg_log = (function()
if(level & LOG_LEVEL)
{
var level_name = dbg_names[level] || "",
message = "[" + v86util.pads(level_name, 4) + "] " + stuff;
message = "[" + pads(level_name, 4) + "] " + stuff;
if(message === log_last_message)
{
@ -60,10 +64,10 @@ var dbg_log = (function()
}
var now = new Date();
var time_str = v86util.pad0(now.getHours(), 2) + ":" +
v86util.pad0(now.getMinutes(), 2) + ":" +
v86util.pad0(now.getSeconds(), 2) + "+" +
v86util.pad0(now.getMilliseconds(), 3) + " ";
var time_str = pad0(now.getHours(), 2) + ":" +
pad0(now.getMinutes(), 2) + ":" +
pad0(now.getSeconds(), 2) + "+" +
pad0(now.getMilliseconds(), 3) + " ";
if(log_message_repetitions)
{
@ -90,7 +94,7 @@ var dbg_log = (function()
/**
* @param {number=} level
*/
function dbg_trace(level)
export function dbg_trace(level)
{
if(!DEBUG) return;
@ -102,7 +106,7 @@ function dbg_trace(level)
* @param {string=} msg
* @param {number=} level
*/
function dbg_assert(cond, msg, level)
export function dbg_assert(cond, msg, level)
{
if(!DEBUG) return;
@ -113,7 +117,7 @@ function dbg_assert(cond, msg, level)
}
function dbg_assert_failed(msg)
export function dbg_assert_failed(msg)
{
debugger;
console.trace();

View file

@ -1,10 +1,12 @@
"use strict";
import { CPU } from "./cpu.js";
/**
* @constructor
* @param {Object=} wasm
*/
function v86(bus, wasm)
export function v86(bus, wasm)
{
/** @type {boolean} */
this.running = false;
@ -98,6 +100,7 @@ if(typeof process !== "undefined")
{
v86.prototype.yield = function(t, tick)
{
/* global global */
if(t < 1)
{
global.setImmediate(tick => this.yield_callback(tick), tick);
@ -205,7 +208,7 @@ v86.prototype.restore_state = function(state)
return this.cpu.restore_state(state);
};
/* global require */
if(typeof performance === "object" && performance.now)
{
v86.microtick = performance.now.bind(performance);

View file

@ -1,5 +1,9 @@
"use strict";
import { MMAP_BLOCK_BITS } from "./const.js";
import { CPU } from "./cpu.js";
import { dbg_assert } from "./log.js";
CPU.prototype.mmap_read8 = function(addr)
{

View file

@ -1,5 +1,14 @@
"use strict";
import { LOG_NET } from "./const.js";
import { h, hex_dump } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
import { PCI } from "./pci.js";
import { BusConnector } from "./bus.js";
// http://www.ethernut.de/pdf/8019asds.pdf
const NE2K_LOG_VERBOSE = false;
@ -226,7 +235,7 @@ function translate_mac_address(packet, search_mac, replacement_mac)
}
}
function format_mac(mac)
export function format_mac(mac)
{
return [
mac[0].toString(16).padStart(2, "0"),
@ -288,7 +297,7 @@ function dump_packet(packet, prefix)
* @param {Boolean} mac_address_translation
* @param {number} [id=0] id
*/
function Ne2k(cpu, bus, preserve_mac_from_state_image, mac_address_translation, id)
export function Ne2k(cpu, bus, preserve_mac_from_state_image, mac_address_translation, id)
{
/** @const @type {CPU} */
this.cpu = cpu;

View file

@ -1,8 +1,16 @@
"use strict";
import { LOG_PCI } from "./const.js";
import { h } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
// http://wiki.osdev.org/PCI
var
export const
/** @const */ PCI_CONFIG_ADDRESS = 0xCF8,
/** @const */ PCI_CONFIG_DATA = 0xCFC;
@ -10,7 +18,7 @@ var
* @constructor
* @param {CPU} cpu
*/
function PCI(cpu)
export function PCI(cpu)
{
this.pci_addr = new Uint8Array(4);
this.pci_value = new Uint8Array(4);

View file

@ -1,17 +1,26 @@
"use strict";
import { v86 } from "./main.js";
import { LOG_PIT } from "./const.js";
import { h } from "./lib.js";
import { dbg_log } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
/**
* @const
* In kHz
*/
var OSCILLATOR_FREQ = 1193.1816666; // 1.193182 MHz
export const OSCILLATOR_FREQ = 1193.1816666; // 1.193182 MHz
/**
* @constructor
*
* Programmable Interval Timer
*/
function PIT(cpu, bus)
export function PIT(cpu, bus)
{
/** @const @type {CPU} */
this.cpu = cpu;

View file

@ -1,5 +1,14 @@
"use strict";
import { LOG_PS2 } from "./const.js";
import { h } from "./lib.js";
import { dbg_log } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
import { BusConnector } from "./bus.js";
import { ByteQueue } from "./lib.js";
/** @const */
const PS2_LOG_VERBOSE = false;
@ -8,7 +17,7 @@ const PS2_LOG_VERBOSE = false;
* @param {CPU} cpu
* @param {BusConnector} bus
*/
function PS2(cpu, bus)
export function PS2(cpu, bus)
{
/** @const @type {CPU} */
this.cpu = cpu;

View file

@ -1,56 +1,67 @@
"use strict";
/** @const */ var CMOS_RTC_SECONDS = 0x00;
/** @const */ var CMOS_RTC_SECONDS_ALARM = 0x01;
/** @const */ var CMOS_RTC_MINUTES = 0x02;
/** @const */ var CMOS_RTC_MINUTES_ALARM = 0x03;
/** @const */ var CMOS_RTC_HOURS = 0x04;
/** @const */ var CMOS_RTC_HOURS_ALARM = 0x05;
/** @const */ var CMOS_RTC_DAY_WEEK = 0x06;
/** @const */ var CMOS_RTC_DAY_MONTH = 0x07;
/** @const */ var CMOS_RTC_MONTH = 0x08;
/** @const */ var CMOS_RTC_YEAR = 0x09;
/** @const */ var CMOS_STATUS_A = 0x0a;
/** @const */ var CMOS_STATUS_B = 0x0b;
/** @const */ var CMOS_STATUS_C = 0x0c;
/** @const */ var CMOS_STATUS_D = 0x0d;
/** @const */ var CMOS_RESET_CODE = 0x0f;
import { v86 } from "./main.js";
import { LOG_RTC } from "./const.js";
import { h } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
/** @const */ var CMOS_FLOPPY_DRIVE_TYPE = 0x10;
/** @const */ var CMOS_DISK_DATA = 0x12;
/** @const */ var CMOS_EQUIPMENT_INFO = 0x14;
/** @const */ var CMOS_MEM_BASE_LOW = 0x15;
/** @const */ var CMOS_MEM_BASE_HIGH = 0x16;
/** @const */ var CMOS_MEM_OLD_EXT_LOW = 0x17;
/** @const */ var CMOS_MEM_OLD_EXT_HIGH = 0x18;
/** @const */ var CMOS_DISK_DRIVE1_TYPE = 0x19;
/** @const */ var CMOS_DISK_DRIVE2_TYPE = 0x1a;
/** @const */ var CMOS_DISK_DRIVE1_CYL = 0x1b;
/** @const */ var CMOS_DISK_DRIVE2_CYL = 0x24;
/** @const */ var CMOS_MEM_EXTMEM_LOW = 0x30;
/** @const */ var CMOS_MEM_EXTMEM_HIGH = 0x31;
/** @const */ var CMOS_CENTURY = 0x32;
/** @const */ var CMOS_MEM_EXTMEM2_LOW = 0x34;
/** @const */ var CMOS_MEM_EXTMEM2_HIGH = 0x35;
/** @const */ var CMOS_CENTURY2 = 0x37;
/** @const */ var CMOS_BIOS_BOOTFLAG1 = 0x38;
/** @const */ var CMOS_BIOS_DISKTRANSFLAG = 0x39;
/** @const */ var CMOS_BIOS_BOOTFLAG2 = 0x3d;
/** @const */ var CMOS_MEM_HIGHMEM_LOW = 0x5b;
/** @const */ var CMOS_MEM_HIGHMEM_MID = 0x5c;
/** @const */ var CMOS_MEM_HIGHMEM_HIGH = 0x5d;
/** @const */ var CMOS_BIOS_SMP_COUNT = 0x5f;
// For Types Only
import { CPU } from "./cpu.js";
import { DMA } from "./dma.js";
/** @const */ export const CMOS_RTC_SECONDS = 0x00;
/** @const */ export const CMOS_RTC_SECONDS_ALARM = 0x01;
/** @const */ export const CMOS_RTC_MINUTES = 0x02;
/** @const */ export const CMOS_RTC_MINUTES_ALARM = 0x03;
/** @const */ export const CMOS_RTC_HOURS = 0x04;
/** @const */ export const CMOS_RTC_HOURS_ALARM = 0x05;
/** @const */ export const CMOS_RTC_DAY_WEEK = 0x06;
/** @const */ export const CMOS_RTC_DAY_MONTH = 0x07;
/** @const */ export const CMOS_RTC_MONTH = 0x08;
/** @const */ export const CMOS_RTC_YEAR = 0x09;
/** @const */ export const CMOS_STATUS_A = 0x0a;
/** @const */ export const CMOS_STATUS_B = 0x0b;
/** @const */ export const CMOS_STATUS_C = 0x0c;
/** @const */ export const CMOS_STATUS_D = 0x0d;
/** @const */ export const CMOS_RESET_CODE = 0x0f;
/** @const */ export const CMOS_FLOPPY_DRIVE_TYPE = 0x10;
/** @const */ export const CMOS_DISK_DATA = 0x12;
/** @const */ export const CMOS_EQUIPMENT_INFO = 0x14;
/** @const */ export const CMOS_MEM_BASE_LOW = 0x15;
/** @const */ export const CMOS_MEM_BASE_HIGH = 0x16;
/** @const */ export const CMOS_MEM_OLD_EXT_LOW = 0x17;
/** @const */ export const CMOS_MEM_OLD_EXT_HIGH = 0x18;
/** @const */ export const CMOS_DISK_DRIVE1_TYPE = 0x19;
/** @const */ export const CMOS_DISK_DRIVE2_TYPE = 0x1a;
/** @const */ export const CMOS_DISK_DRIVE1_CYL = 0x1b;
/** @const */ export const CMOS_DISK_DRIVE2_CYL = 0x24;
/** @const */ export const CMOS_MEM_EXTMEM_LOW = 0x30;
/** @const */ export const CMOS_MEM_EXTMEM_HIGH = 0x31;
/** @const */ export const CMOS_CENTURY = 0x32;
/** @const */ export const CMOS_MEM_EXTMEM2_LOW = 0x34;
/** @const */ export const CMOS_MEM_EXTMEM2_HIGH = 0x35;
/** @const */ export const CMOS_CENTURY2 = 0x37;
/** @const */ export const CMOS_BIOS_BOOTFLAG1 = 0x38;
/** @const */ export const CMOS_BIOS_DISKTRANSFLAG = 0x39;
/** @const */ export const CMOS_BIOS_BOOTFLAG2 = 0x3d;
/** @const */ export const CMOS_MEM_HIGHMEM_LOW = 0x5b;
/** @const */ export const CMOS_MEM_HIGHMEM_MID = 0x5c;
/** @const */ export const CMOS_MEM_HIGHMEM_HIGH = 0x5d;
/** @const */ export const CMOS_BIOS_SMP_COUNT = 0x5f;
// see CPU.prototype.fill_cmos
const BOOT_ORDER_CD_FIRST = 0x123;
const BOOT_ORDER_HD_FIRST = 0x312;
const BOOT_ORDER_FD_FIRST = 0x321;
export const BOOT_ORDER_CD_FIRST = 0x123;
export const BOOT_ORDER_HD_FIRST = 0x312;
export const BOOT_ORDER_FD_FIRST = 0x321;
/**
* RTC (real time clock) and CMOS
* @constructor
* @param {CPU} cpu
*/
export
function RTC(cpu)
{
/** @const @type {CPU} */

View file

@ -1,5 +1,21 @@
"use strict";
import {
LOG_SB16,
MIXER_CHANNEL_BOTH, MIXER_CHANNEL_LEFT, MIXER_CHANNEL_RIGHT,
MIXER_SRC_PCSPEAKER, MIXER_SRC_DAC, MIXER_SRC_MASTER,
} from "./const.js";
import { h } from "./lib.js";
import { dbg_log } from "./log.js";
import { SyncBuffer } from "./buffer.js";
// For Types Only
import { CPU } from "./cpu.js";
import { DMA } from "./dma.js";
import { IO } from "./io.js";
import { BusConnector } from "./bus.js";
import { ByteQueue, FloatQueue } from "./lib.js";
// Useful documentation, articles, and source codes for reference:
// ===============================================================
//
@ -92,7 +108,7 @@ var FM_HANDLERS = [];
* @param {CPU} cpu
* @param {BusConnector} bus
*/
function SB16(cpu, bus)
export function SB16(cpu, bus)
{
/** @const @type {CPU} */
this.cpu = cpu;
@ -150,7 +166,7 @@ function SB16(cpu, bus)
this.dma_buffer_uint8 = new Uint8Array(this.dma_buffer);
this.dma_buffer_int16 = new Int16Array(this.dma_buffer);
this.dma_buffer_uint16 = new Uint16Array(this.dma_buffer);
this.dma_syncbuffer = new v86util.SyncBuffer(this.dma_buffer);
this.dma_syncbuffer = new SyncBuffer(this.dma_buffer);
this.dma_waiting_transfer = false;
this.dma_paused = false;
this.sampling_rate = 22050;
@ -399,7 +415,7 @@ SB16.prototype.set_state = function(state)
this.dma_buffer_int8 = new Int8Array(this.dma_buffer);
this.dma_buffer_int16 = new Int16Array(this.dma_buffer);
this.dma_buffer_uint16 = new Uint16Array(this.dma_buffer);
this.dma_syncbuffer = new v86util.SyncBuffer(this.dma_buffer);
this.dma_syncbuffer = new SyncBuffer(this.dma_buffer);
if(this.dma_paused)
{

View file

@ -1,5 +1,9 @@
"use strict";
import { h } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
import { CPU } from "./cpu.js";
/** @const */
var STATE_VERSION = 6;

View file

@ -1,5 +1,13 @@
"use strict";
import { LOG_SERIAL } from "./const.js";
import { h } from "./lib.js";
import { dbg_log } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
import { BusConnector } from "./bus.js";
/*
* Serial ports
* http://wiki.osdev.org/UART
@ -44,7 +52,7 @@ var DLAB = 0x80;
* @param {number} port
* @param {BusConnector} bus
*/
function UART(cpu, port, bus)
export function UART(cpu, port, bus)
{
/** @const @type {BusConnector} */
this.bus = bus;

View file

@ -1,5 +1,16 @@
"use strict";
import { LOG_VGA } from "./const.js";
import { h } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
import { ScreenAdapter } from "./browser/screen.js";
import { BusConnector } from "./bus.js";
import { DummyScreenAdapter } from "./browser/dummy_screen.js";
import { round_up_to_next_power_of_2, view } from "./lib.js";
// Always 64k
const VGA_BANK_SIZE = 64 * 1024;
@ -51,7 +62,7 @@ const VGA_HOST_MEMORY_SPACE_SIZE = Uint32Array.from([
* @param {ScreenAdapter|DummyScreenAdapter} screen
* @param {number} vga_memory_size
*/
function VGAScreen(cpu, bus, screen, vga_memory_size)
export function VGAScreen(cpu, bus, screen, vga_memory_size)
{
this.cpu = cpu;
@ -216,7 +227,7 @@ function VGAScreen(cpu, bus, screen, vga_memory_size)
else
{
// required for pci code
this.vga_memory_size = v86util.round_up_to_next_power_of_2(this.vga_memory_size);
this.vga_memory_size = round_up_to_next_power_of_2(this.vga_memory_size);
}
dbg_log("effective vga memory size: " + this.vga_memory_size, LOG_VGA);
@ -356,7 +367,7 @@ function VGAScreen(cpu, bus, screen, vga_memory_size)
const vga_offset = cpu.svga_allocate_memory(this.vga_memory_size) >>> 0;
this.svga_memory = v86util.view(Uint8Array, cpu.wasm_memory, vga_offset, this.vga_memory_size);
this.svga_memory = view(Uint8Array, cpu.wasm_memory, vga_offset, this.vga_memory_size);
this.diff_addr_min = this.vga_memory_size;
this.diff_addr_max = 0;

View file

@ -1,5 +1,13 @@
"use strict";
import { LOG_VIRTIO } from "./const.js";
import { h, zeros, int_log2 } from "./lib.js";
import { dbg_assert, dbg_log } from "./log.js";
// For Types Only
import { CPU } from "./cpu.js";
import { PCI } from "./pci.js";
// http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html
const VIRTIO_PCI_VENDOR_ID = 0x1AF4;
@ -32,9 +40,9 @@ const VIRTIO_ISR_DEVICE_CFG = 2;
// Feature bits (bit positions).
const VIRTIO_F_RING_INDIRECT_DESC = 28;
const VIRTIO_F_RING_EVENT_IDX = 29;
const VIRTIO_F_VERSION_1 = 32;
export const VIRTIO_F_RING_INDIRECT_DESC = 28;
export const VIRTIO_F_RING_EVENT_IDX = 29;
export const VIRTIO_F_VERSION_1 = 32;
// Queue struct sizes.
@ -153,7 +161,7 @@ var VirtIO_Options;
* @param {CPU} cpu
* @param {VirtIO_Options} options
*/
function VirtIO(cpu, options)
export function VirtIO(cpu, options)
{
const io = cpu.io;
@ -224,7 +232,7 @@ function VirtIO(cpu, options)
];
// Prevent sparse arrays by preallocating.
this.pci_space = this.pci_space.concat(v86util.zeros(256 - this.pci_space.length));
this.pci_space = this.pci_space.concat(zeros(256 - this.pci_space.length));
// Remaining PCI space is appended by capabilities further below.
this.pci_id = options.pci_id;
@ -480,7 +488,7 @@ VirtIO.prototype.create_common_capability = function(options)
dbg_log("Warning: dev<" + this.name +"> " +
"Given queue size was not a power of 2. " +
"Rounding up to next power of 2.", LOG_VIRTIO);
data = 1 << (v86util.int_log2(data - 1) + 1);
data = 1 << (int_log2(data - 1) + 1);
}
if(data > this.queue_selected.size_supported)
{
@ -727,7 +735,7 @@ VirtIO.prototype.init_capabilities = function(capabilities)
// Round up to next power of 2,
// Minimum 16 bytes for its size to be detectable in general (esp. mmio).
bar_size = bar_size < 16 ? 16 : 1 << (v86util.int_log2(bar_size - 1) + 1);
bar_size = bar_size < 16 ? 16 : 1 << (int_log2(bar_size - 1) + 1);
dbg_assert((cap.port & (bar_size - 1)) === 0,
"VirtIO device<" + this.name + "> capability port should be aligned to pci bar size");

View file

@ -2,6 +2,15 @@
// https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-2900003
import { LOG_PCI } from "./const.js";
import { dbg_log } from "./log.js";
import { VirtIO, VIRTIO_F_VERSION_1 } from "./virtio.js";
import { marshall } from "../lib/marshall.js";
// For Types Only
import { CPU } from "./cpu.js";
import { BusConnector } from "./bus.js";
const VIRTIO_BALLOON_F_MUST_TELL_HOST = 0;
const VIRTIO_BALLOON_F_STATS_VQ = 1;
const VIRTIO_BALLOON_F_DEFLATE_ON_OOM = 2;
@ -25,7 +34,7 @@ const STAT_NAMES = [
* @param {CPU} cpu
* @param {BusConnector} bus
*/
function VirtioBalloon(cpu, bus)
export function VirtioBalloon(cpu, bus)
{
/** @const @type {BusConnector} */
this.bus = bus;

View file

@ -1,7 +1,16 @@
"use strict";
import { dbg_assert } from "./log.js";
import { VirtIO, VIRTIO_F_VERSION_1 } from "./virtio.js";
import { marshall } from "../lib/marshall.js";
// For Types Only
import { CPU } from "./cpu.js";
import { BusConnector } from "./bus.js";
// https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-2900003
const VIRTIO_CONSOLE_DEVICE_READY = 0;
const VIRTIO_CONSOLE_DEVICE_ADD = 1;
const VIRTIO_CONSOLE_DEVICE_REMOVE = 2;
@ -20,7 +29,7 @@ const VIRTIO_CONSOLE_F_EMERG_WRITE = 2;
*
* @param {CPU} cpu
*/
function VirtioConsole(cpu, bus)
export function VirtioConsole(cpu, bus)
{
/** @const @type {BusConnector} */
this.bus = bus;

View file

@ -2,6 +2,14 @@
// https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-2900003
import { dbg_assert } from "./log.js";
import { VirtIO, VIRTIO_F_VERSION_1 } from "./virtio.js";
import { format_mac } from "./ne2k.js";
import { marshall } from "../lib/marshall.js";
// For Types Only
import { CPU } from "./cpu.js";
import { BusConnector } from "./bus.js";
const VIRTIO_NET_F_MAC = 5;
const VIRTIO_NET_F_CTRL_VQ = 17;
@ -19,7 +27,7 @@ const VIRTIO_NET_CTRL_MAC_ADDR_SET = 1;
* @param {BusConnector} bus
* @param {Boolean} preserve_mac_from_state_image
*/
function VirtioNet(cpu, bus, preserve_mac_from_state_image)
export function VirtioNet(cpu, bus, preserve_mac_from_state_image)
{
/** @const @type {BusConnector} */
this.bus = bus;

View file

@ -1,13 +1,15 @@
#!/usr/bin/env node
"use strict";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
// This test checks that calling emulator.destroy() will remove all event
// listeners, so that the nodejs process cleanly and automatically exits.
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const fs = require("fs");
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
process.on("unhandledRejection", exn => { throw exn; });

View file

@ -1,11 +1,14 @@
#!/usr/bin/env node
"use strict";
import {setTimeout as pause} from "timers/promises";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const pause = require("timers/promises").setTimeout;
const fs = require("fs");
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
process.on("unhandledRejection", exn => { throw exn; });

View file

@ -1,10 +1,12 @@
#!/usr/bin/env node
"use strict";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const fs = require("fs");
const V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
import fs from "node:fs";
const { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
const root_path = __dirname + "/../..";

View file

@ -1,10 +1,13 @@
#!/usr/bin/env node
"use strict";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const fs = require("fs");
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
process.on("unhandledRejection", exn => { throw exn; });
@ -30,7 +33,7 @@ let did_reboot = false;
let serial_text = "";
const timeout = setTimeout(() => {
console.log(serial_data);
console.log(serial_text);
throw new Error("Timeout");
}, 120 * 1000);

View file

@ -1,12 +1,15 @@
#!/usr/bin/env node
"use strict";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
// This test checks that reset works
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const fs = require("fs");
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
process.on("unhandledRejection", exn => { throw exn; });

View file

@ -1,12 +1,15 @@
#!/usr/bin/env node
"use strict";
import url from "node:url";
import assert from "node:assert/strict";
import crypto from "node:crypto";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const assert = require("assert").strict;
const fs = require("fs");
const crypto = require("crypto");
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
process.on("unhandledRejection", exn => { throw exn; });

View file

@ -1,13 +1,15 @@
#!/usr/bin/env node
"use strict";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
process.on("unhandledRejection", exn => { throw exn; });
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
const assert = require("assert").strict;
var fs = require("fs");
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
const config_async_cdrom = {
bios: { url: __dirname + "/../../bios/seabios.bin" },

View file

@ -1,10 +1,12 @@
#!/usr/bin/env node
"use strict";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const fs = require("fs");
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
const { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
process.on("unhandledRejection", exn => { throw exn; });

View file

@ -1,10 +1,13 @@
#!/usr/bin/env node
"use strict";
import path from "node:path";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const BENCH_COLLECT_STATS = +process.env.BENCH_COLLECT_STATS;
const { V86, print_stats } = require(`../../build/${BENCH_COLLECT_STATS ? "libv86-debug" : "libv86"}.js`);
const path = require("path");
const { V86, print_stats } = await import(`../../build/${BENCH_COLLECT_STATS ? "libv86-debug" : "libv86"}.js`);
const V86_ROOT = path.join(__dirname, "../..");

View file

@ -1,10 +1,13 @@
#!/usr/bin/env node
"use strict";
import path from "node:path";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const BENCH_COLLECT_STATS = +process.env.BENCH_COLLECT_STATS;
const { V86, print_stats } = require(`../../build/${BENCH_COLLECT_STATS ? "libv86-debug" : "libv86"}.js`);
const path = require("path");
const { V86, print_stats } = await import(`../../build/${BENCH_COLLECT_STATS ? "libv86-debug" : "libv86"}.js`);
const V86_ROOT = path.join(__dirname, "../..");

View file

@ -1,12 +1,15 @@
#!/usr/bin/env node
"use strict";
const BENCH_COLLECT_STATS = +process.env.BENCH_COLLECT_STATS;
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const BENCH_COLLECT_STATS = +process.env.BENCH_COLLECT_STATS;
const { V86, print_stats } = await import(`../../build/${BENCH_COLLECT_STATS ? "libv86-debug" : "libv86"}.js`).V86;
const V86 = require(`../../build/${BENCH_COLLECT_STATS ? "libv86-debug" : "libv86"}.js`).V86;
const print_stats = require("../../build/libv86.js").print_stats;
const fs = require("fs");
const path = require("path");
const V86_ROOT = path.join(__dirname, "../..");
const LOG_SERIAL = true;

View file

@ -1,12 +1,14 @@
#!/usr/bin/env node
"use strict";
import path from "node:path";
import url from "node:url";
const BENCH_COLLECT_STATS = +process.env.BENCH_COLLECT_STATS;
const V86 = require(`../../build/${BENCH_COLLECT_STATS ? "libv86-debug" : "libv86"}.js`).V86;
const print_stats = require("../../build/libv86.js").print_stats;
const fs = require("fs");
const path = require("path");
let { V86, print_stats } = await import(`../../build/${BENCH_COLLECT_STATS ? "libv86-debug" : "libv86"}.js`);
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const V86_ROOT = path.join(__dirname, "../..");
const LOG_SERIAL = true;

View file

@ -1,14 +1,16 @@
#!/usr/bin/env node
"use strict";
import assert from "assert/strict";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
process.on("unhandledRejection", exn => { throw exn; });
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const USE_VIRTIO = !!process.env.USE_VIRTIO;
const V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
const assert = require("assert").strict;
const { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
const SHOW_LOGS = false;
function wait(time) {

View file

@ -1,14 +1,16 @@
#!/usr/bin/env node
"use strict";
import url from "node:url";
import fs from "node:fs";
process.on("unhandledRejection", exn => { throw exn; });
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
const fs = require("fs");
const testfsjson = require("./testfs.json");
const testfsjson = JSON.parse(fs.readFileSync(__dirname + "/testfs.json", "utf-8"));
const SHOW_LOGS = false;
const STOP_ON_FIRST_FAILURE = false;

View file

@ -1,13 +1,15 @@
#!/usr/bin/env node
"use strict";
import assert from "assert/strict";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
process.on("unhandledRejection", exn => { throw exn; });
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
const { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
const assert = require("assert").strict;
const SHOW_LOGS = false;
function wait(time) {

View file

@ -1,13 +1,17 @@
#!/usr/bin/env node
"use strict";
import assert from "assert/strict";
import fs from "node:fs";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
process.on("unhandledRejection", exn => { throw exn; });
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const SHOW_LOGS = false;
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
const fs = require("fs");
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
const emulator = new V86({
bios: { url: __dirname + "/../../bios/seabios.bin" },

View file

@ -1,13 +1,16 @@
#!/usr/bin/env -S node --experimental-websocket
"use strict";
import assert from "assert/strict";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
process.on("unhandledRejection", exn => { throw exn; });
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
const { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
const assert = require("assert").strict;
const SHOW_LOGS = false;
const tests =

View file

@ -1,17 +1,23 @@
#!/usr/bin/env node
"use strict";
import fs from "node:fs";
import path from "node:path";
import assert from "node:assert/strict";
import url from "node:url";
import wabtfactory from "../../build/libwabt.cjs";
import { spawnSync } from "node:child_process";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const assert = require("assert").strict;
const fs = require("fs");
const path = require("path");
const { spawnSync } = require("child_process");
const libwabt = require("../../build/libwabt.js")();
const libwabt = wabtfactory();
try {
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
}
catch(e) {
console.error(e);

View file

@ -1,6 +1,14 @@
#!/usr/bin/env node
"use strict";
import assert from "node:assert/strict";
import cluster from "node:cluster";
import os from "node:os";
import fs from "node:fs";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
process.on("unhandledRejection", exn => { throw exn; });
var TIMEOUT_EXTRA_FACTOR = +process.env.TIMEOUT_EXTRA_FACTOR || 1;
@ -14,7 +22,7 @@ const LOG_SCREEN = false;
try
{
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
}
catch(e)
{
@ -22,10 +30,6 @@ catch(e)
process.exit(1);
}
const assert = require("assert").strict;
var cluster = require("cluster");
var os = require("os");
var fs = require("fs");
var root_path = __dirname + "/../..";
var SCREEN_WIDTH = 80;
@ -79,7 +83,7 @@ function send_work_to_worker(worker, message)
}
}
if(cluster.isMaster)
if(cluster.isPrimary)
{
var tests = [
{
@ -918,7 +922,6 @@ if(cluster.isMaster)
var worker = cluster.fork();
worker.on("message", send_work_to_worker.bind(null, worker));
worker.on("online", send_work_to_worker.bind(null, worker));
worker.on("exit", function(code, signal)
{
@ -949,6 +952,7 @@ else
process.send("I'm done");
});
});
process.send("up");
}
function bytearray_starts_with(arr, search)

View file

@ -1,12 +1,15 @@
#!/usr/bin/env node
"use strict";
import fs from "node:fs";
import url from "node:url";
process.on("unhandledRejection", exn => { throw exn; });
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var fs = require("fs");
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
var test_executable = new Uint8Array(fs.readFileSync(__dirname + "/test-jit"));

View file

@ -1,12 +1,17 @@
#!/usr/bin/env node
"use strict";
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
process.on("unhandledRejection", exn => { throw exn; });
const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var fs = require("fs");
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
function readfile(path)
{

View file

@ -1,6 +1,20 @@
#!/usr/bin/env node
"use strict";
import fs from "node:fs";
import fse from "node:fs/promises";
import path from "node:path";
import assert from "node:assert/strict";
import util from "node:util";
import url from "node:url";
import { execFile as execFileAsync } from "node:child_process";
import encodings from "../../gen/x86_table.js";
import Rand from "./rand.js";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
// number of tests per instruction
const NUMBER_TESTS = 5;
// arithmetic tests
@ -19,14 +33,7 @@ const OF = 1 << 11;
const BUILD_DIR = __dirname + "/build/";
const LOG_VERBOSE = false;
const assert = require("assert").strict;
const fs = require("fs");
const fse = require("fs/promises");
const path = require("path");
const encodings = require("../../gen/x86_table.js");
const util = require("util");
const execFile = util.promisify(require("child_process").execFile);
const Rand = require("./rand.js");
const execFile = util.promisify(execFileAsync);
const header = fs.readFileSync(path.join(__dirname, "header.inc"));
const footer = fs.readFileSync(path.join(__dirname, "footer.inc"));

View file

@ -1,11 +1,14 @@
#!/usr/bin/env node
"use strict";
const assert = require("assert").strict;
const fs = require("fs");
const os = require("os");
const path = require("path");
const { spawn, spawnSync } = require("child_process");
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import assert from "node:assert/strict";
import os from "node:os";
import { spawn, spawnSync } from "node:child_process";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const DEBUG = process.env.DEBUG || false;
// Maximum number of gdb processes to spawn in parallel

View file

@ -1,5 +1,4 @@
"use strict";
const assert = require("assert");
// From http://baagoe.com/en/RandomMusings/javascript/
// Johannes Baagøe <baagoe@baagoe.com>, 2010
@ -25,7 +24,7 @@ function Mash() {
}
// From http://baagoe.com/en/RandomMusings/javascript/
function KISS07() {
export default function KISS07() {
return (function(args) {
// George Marsaglia, 2007-06-23
//http://groups.google.com/group/comp.lang.fortran/msg/6edb8ad6ec5421a5
@ -100,5 +99,3 @@ function KISS07() {
};
} (Array.prototype.slice.call(arguments)));
}
module.exports = KISS07;

View file

@ -1,6 +1,15 @@
#!/usr/bin/env node
"use strict";
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import assert from "node:assert/strict";
import os from "node:os";
import cluster from "node:cluster";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
process.on("unhandledRejection", exn => { throw exn; });
// Mapping between signals and x86 exceptions:
@ -15,12 +24,6 @@ process.on("unhandledRejection", exn => { throw exn; });
// A #UD might indicate a bug in the test generation
const assert = require("assert").strict;
const fs = require("fs");
const path = require("path");
const os = require("os");
const cluster = require("cluster");
const MAX_PARALLEL_TESTS = +process.env.MAX_PARALLEL_TESTS || 99;
const TEST_NAME = new RegExp(process.env.TEST_NAME || "", "i");
const SINGLE_TEST_TIMEOUT = 10000;
@ -29,6 +32,7 @@ const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
const TEST_DIR = __dirname + "/build/";
const DONE_MSG = "DONE";
const TERMINATE_MSG = "DONE";
const READY_MSG = "READY";
const BSS = 0x100000;
const STACK_TOP = 0x102000;
@ -47,7 +51,7 @@ const FPU_STATUS_MASK = 0xFFFF & ~(1 << 9 | 1 << 5 | 1 << 3 | 1 << 1); // bits t
const FP_COMPARISON_SIGNIFICANT_DIGITS = 7;
try {
var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
var { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
}
catch(e) {
console.error(e);
@ -202,14 +206,12 @@ if(cluster.isMaster)
let worker = cluster.fork();
worker.on("message", function(message) {
if(message !== DONE_MSG) {
if(message !== DONE_MSG && message !== READY_MSG) {
failed_tests.push(message);
}
send_work_to_worker(this);
});
worker.on("online", send_work_to_worker.bind(null, worker));
worker.on("exit", function(code, signal) {
if(code !== 0 && code !== null) {
console.log("Worker error code:", code);
@ -548,4 +550,6 @@ else {
run_test(message);
}
});
process.send(READY_MSG);
}

View file

@ -1,12 +1,15 @@
#!/usr/bin/env node
"use strict";
const QEMU = "qemu-system-x86_64";
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import assert from "node:assert/strict";
import { spawn, spawnSync } from "node:child_process";
const assert = require("assert").strict;
const fs = require("fs");
const { spawn, spawnSync } = require("child_process");
const path = require("path");
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const QEMU = "qemu-system-x86_64";
const share_dir_9p = fs.mkdtempSync("/tmp/v86-test-qemu-9p");

View file

@ -10,7 +10,7 @@ import path from "path";
import fs from "fs";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const { default: { V86 } } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`);
const { V86 } = await import(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.mjs`);
var test_executable = new Uint8Array(fs.readFileSync(__dirname + "/test-i386"));

View file

@ -1,11 +1,15 @@
#!/usr/bin/env node
"use strict";
process.on("unhandledRejection", exn => { throw exn; });
const assert = require("assert").strict;
const fs = require("fs");
const path = require("path");
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import assert from "node:assert/strict";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
process.on("unhandledRejection", exn => { throw exn; });
const DUMMY_MODULE_PATH = path.resolve(__dirname, "../../build/dummy_output.wasm");
const dummy_module = fs.readFileSync(DUMMY_MODULE_PATH);

View file

@ -1,11 +1,14 @@
#!/usr/bin/env node
"use strict";
import path from "node:path";
import fs from "node:fs";
import url from "node:url";
console.log("Don't forget to run `make all` before running this script");
const path = require("path");
const fs = require("fs");
const V86 = require("./../../../build/libv86.js").V86;
const { V86 } = await import("./../../../build/libv86.js");
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const V86_ROOT = path.join(__dirname, "../../..");
const OUTPUT_FILE = path.join(V86_ROOT, "images/alpine-state.bin");