Merge 16-bit and 32-bit 0f tables (saves 200kB on v86.wasm)

This commit is contained in:
Fabian 2020-12-31 19:14:31 -06:00
parent c28e3b8978
commit 9853bdb868
9 changed files with 78 additions and 156 deletions

9
.gitignore vendored
View file

@ -22,12 +22,9 @@ profile*.json
Cargo.lock
build-head
src/rust/gen/interpreter.rs
src/rust/gen/interpreter0f_16.rs
src/rust/gen/interpreter0f_32.rs
src/rust/gen/interpreter0f.rs
src/rust/gen/analyzer.rs
src/rust/gen/analyzer0f_16.rs
src/rust/gen/analyzer0f_32.rs
src/rust/gen/analyzer0f.rs
src/rust/gen/jit.rs
src/rust/gen/jit0f_16.rs
src/rust/gen/jit0f_32.rs
src/rust/gen/jit0f.rs
bios/seabios

View file

@ -2,9 +2,9 @@ CLOSURE_DIR=closure-compiler
CLOSURE=$(CLOSURE_DIR)/compiler.jar
NASM_TEST_DIR=./tests/nasm
INSTRUCTION_TABLES=src/rust/gen/jit.rs src/rust/gen/jit0f_16.rs src/rust/gen/jit0f_32.rs \
src/rust/gen/interpreter.rs src/rust/gen/interpreter0f_16.rs src/rust/gen/interpreter0f_32.rs \
src/rust/gen/analyzer.rs src/rust/gen/analyzer0f_16.rs src/rust/gen/analyzer0f_32.rs \
INSTRUCTION_TABLES=src/rust/gen/jit.rs src/rust/gen/jit0f.rs \
src/rust/gen/interpreter.rs src/rust/gen/interpreter0f.rs \
src/rust/gen/analyzer.rs src/rust/gen/analyzer0f.rs \
# Only the dependencies common to both generate_{jit,interpreter}.js
GEN_DEPENDENCIES=$(filter-out gen/generate_interpreter.js gen/generate_jit.js gen/generate_analyzer.js, $(wildcard gen/*.js))
@ -95,9 +95,9 @@ BROWSER_FILES=screen.js \
network.js lib.js starter.js worker_bus.js dummy_screen.js print_stats.js filestorage.js
RUST_FILES=$(shell find src/rust/ -name '*.rs') \
src/rust/gen/interpreter.rs src/rust/gen/interpreter0f_16.rs src/rust/gen/interpreter0f_32.rs \
src/rust/gen/jit.rs src/rust/gen/jit0f_16.rs src/rust/gen/jit0f_32.rs \
src/rust/gen/analyzer.rs src/rust/gen/analyzer0f_16.rs src/rust/gen/analyzer0f_32.rs
src/rust/gen/interpreter.rs src/rust/gen/interpreter0f.rs \
src/rust/gen/jit.rs src/rust/gen/jit0f.rs \
src/rust/gen/analyzer.rs src/rust/gen/analyzer0f.rs
CORE_FILES:=$(addprefix src/,$(CORE_FILES))
LIB_FILES:=$(addprefix lib/,$(LIB_FILES))
@ -155,24 +155,18 @@ instruction_tables: $(INSTRUCTION_TABLES)
src/rust/gen/jit.rs: $(JIT_DEPENDENCIES)
./gen/generate_jit.js --output-dir build/ --table jit
src/rust/gen/jit0f_16.rs: $(JIT_DEPENDENCIES)
./gen/generate_jit.js --output-dir build/ --table jit0f_16
src/rust/gen/jit0f_32.rs: $(JIT_DEPENDENCIES)
./gen/generate_jit.js --output-dir build/ --table jit0f_32
src/rust/gen/jit0f.rs: $(JIT_DEPENDENCIES)
./gen/generate_jit.js --output-dir build/ --table jit0f
src/rust/gen/interpreter.rs: $(INTERPRETER_DEPENDENCIES)
./gen/generate_interpreter.js --output-dir build/ --table interpreter
src/rust/gen/interpreter0f_16.rs: $(INTERPRETER_DEPENDENCIES)
./gen/generate_interpreter.js --output-dir build/ --table interpreter0f_16
src/rust/gen/interpreter0f_32.rs: $(INTERPRETER_DEPENDENCIES)
./gen/generate_interpreter.js --output-dir build/ --table interpreter0f_32
src/rust/gen/interpreter0f.rs: $(INTERPRETER_DEPENDENCIES)
./gen/generate_interpreter.js --output-dir build/ --table interpreter0f
src/rust/gen/analyzer.rs: $(ANALYZER_DEPENDENCIES)
./gen/generate_analyzer.js --output-dir build/ --table analyzer
src/rust/gen/analyzer0f_16.rs: $(ANALYZER_DEPENDENCIES)
./gen/generate_analyzer.js --output-dir build/ --table analyzer0f_16
src/rust/gen/analyzer0f_32.rs: $(ANALYZER_DEPENDENCIES)
./gen/generate_analyzer.js --output-dir build/ --table analyzer0f_32
src/rust/gen/analyzer0f.rs: $(ANALYZER_DEPENDENCIES)
./gen/generate_analyzer.js --output-dir build/ --table analyzer0f
build/v86.wasm: $(RUST_FILES) Cargo.toml
mkdir -p build/

View file

@ -16,13 +16,12 @@ const table_arg = get_switch_value("--table");
const gen_all = get_switch_exist("--all");
const to_generate = {
analyzer: gen_all || table_arg === "analyzer",
analyzer0f_16: gen_all || table_arg === "analyzer0f_16",
analyzer0f_32: gen_all || table_arg === "analyzer0f_32",
analyzer0f: gen_all || table_arg === "analyzer0f",
};
assert(
Object.keys(to_generate).some(k => to_generate[k]),
"Pass --table [analyzer|analyzer0f_16|analyzer0f_32] or --all to pick which tables to generate"
"Pass --table [analyzer|analyzer0f] or --all to pick which tables to generate"
);
gen_table();
@ -424,8 +423,7 @@ function gen_table()
);
}
const cases0f_16 = [];
const cases0f_32 = [];
const cases0f = [];
for(let opcode = 0; opcode < 0x100; opcode++)
{
let encoding = by_opcode0f[opcode];
@ -433,70 +431,51 @@ function gen_table()
assert(encoding && encoding.length);
let opcode_hex = hex(opcode, 2);
let opcode_high_hex = hex(opcode | 0x100, 2);
if(encoding[0].os)
{
cases0f_16.push({
cases0f.push({
conditions: [`0x${opcode_hex}`],
body: gen_instruction_body(encoding, 16),
});
cases0f_32.push({
conditions: [`0x${opcode_hex}`],
cases0f.push({
conditions: [`0x${opcode_high_hex}`],
body: gen_instruction_body(encoding, 32),
});
}
else
{
let block = {
conditions: [`0x${opcode_hex}`],
conditions: [`0x${opcode_hex}`, `0x${opcode_high_hex}`],
body: gen_instruction_body(encoding, undefined),
};
cases0f_16.push(block);
cases0f_32.push(block);
cases0f.push(block);
}
}
const table0f_16 = {
const table0f = {
type: "switch",
condition: "opcode",
cases: cases0f_16,
};
const table0f_32 = {
type: "switch",
condition: "opcode",
cases: cases0f_32,
cases: cases0f,
default_case: {
body: ["dbg_assert!(false);"]
},
};
if(to_generate.analyzer0f_16)
if(to_generate.analyzer0f)
{
const code = [
"#![allow(unused)]",
"#[cfg_attr(rustfmt, rustfmt_skip)]",
"pub fn analyzer(opcode: u8, cpu: &mut ::cpu_context::CpuContext, analysis: &mut ::analysis::Analysis) {",
table0f_16,
"pub fn analyzer(opcode: u32, cpu: &mut ::cpu_context::CpuContext, analysis: &mut ::analysis::Analysis) {",
table0f,
"}"
];
finalize_table_rust(
OUT_DIR,
"analyzer0f_16.rs",
rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
);
}
if(to_generate.analyzer0f_32)
{
const code = [
"#![allow(unused)]",
"#[cfg_attr(rustfmt, rustfmt_skip)]",
"pub fn analyzer(opcode: u8, cpu: &mut ::cpu_context::CpuContext, analysis: &mut ::analysis::Analysis) {",
table0f_32,
"}"
];
finalize_table_rust(
OUT_DIR,
"analyzer0f_32.rs",
"analyzer0f.rs",
rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
);
}

View file

@ -16,13 +16,12 @@ const table_arg = get_switch_value("--table");
const gen_all = get_switch_exist("--all");
const to_generate = {
interpreter: gen_all || table_arg === "interpreter",
interpreter0f_16: gen_all || table_arg === "interpreter0f_16",
interpreter0f_32: gen_all || table_arg === "interpreter0f_32",
interpreter0f: gen_all || table_arg === "interpreter0f",
};
assert(
Object.keys(to_generate).some(k => to_generate[k]),
"Pass --table [interpreter|interpreter0f_16|interpreter0f_32] or --all to pick which tables to generate"
"Pass --table [interpreter|interpreter0f] or --all to pick which tables to generate"
);
gen_table();
@ -424,8 +423,7 @@ function gen_table()
);
}
const cases0f_16 = [];
const cases0f_32 = [];
const cases0f = [];
for(let opcode = 0; opcode < 0x100; opcode++)
{
let encoding = by_opcode0f[opcode];
@ -433,41 +431,39 @@ function gen_table()
assert(encoding && encoding.length);
let opcode_hex = hex(opcode, 2);
let opcode_high_hex = hex(opcode | 0x100, 2);
if(encoding[0].os)
{
cases0f_16.push({
cases0f.push({
conditions: [`0x${opcode_hex}`],
body: gen_instruction_body(encoding, 16),
});
cases0f_32.push({
conditions: [`0x${opcode_hex}`],
cases0f.push({
conditions: [`0x${opcode_high_hex}`],
body: gen_instruction_body(encoding, 32),
});
}
else
{
let block = {
conditions: [`0x${opcode_hex}`],
conditions: [`0x${opcode_hex}`, `0x${opcode_high_hex}`],
body: gen_instruction_body(encoding, undefined),
};
cases0f_16.push(block);
cases0f_32.push(block);
cases0f.push(block);
}
}
const table0f_16 = {
const table0f = {
type: "switch",
condition: "opcode",
cases: cases0f_16,
};
const table0f_32 = {
type: "switch",
condition: "opcode",
cases: cases0f_32,
cases: cases0f,
default_case: {
body: ["assert!(false);"]
},
};
if(to_generate.interpreter0f_16)
if(to_generate.interpreter0f)
{
const code = [
"#![cfg_attr(rustfmt, rustfmt_skip)]",
@ -476,35 +472,14 @@ function gen_table()
"use cpu2::instructions_0f::*;",
"use cpu2::global_pointers::*;",
"pub unsafe fn run(opcode: u8) {",
table0f_16,
"pub unsafe fn run(opcode: u32) {",
table0f,
"}",
];
finalize_table_rust(
OUT_DIR,
"interpreter0f_16.rs",
rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
);
}
if(to_generate.interpreter0f_32)
{
const code = [
"#![cfg_attr(rustfmt, rustfmt_skip)]",
"use cpu2::cpu::*;",
"use cpu2::instructions_0f::*;",
"use cpu2::global_pointers::*;",
"pub unsafe fn run(opcode: u8) {",
table0f_32,
"}",
];
finalize_table_rust(
OUT_DIR,
"interpreter0f_32.rs",
"interpreter0f.rs",
rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
);
}

View file

@ -16,13 +16,12 @@ const table_arg = get_switch_value("--table");
const gen_all = get_switch_exist("--all");
const to_generate = {
jit: gen_all || table_arg === "jit",
jit0f_16: gen_all || table_arg === "jit0f_16",
jit0f_32: gen_all || table_arg === "jit0f_32",
jit0f: gen_all || table_arg === "jit0f",
};
assert(
Object.keys(to_generate).some(k => to_generate[k]),
"Pass --table [jit|jit0f_16|jit0f_32] or --all to pick which tables to generate"
"Pass --table [jit|jit0f] or --all to pick which tables to generate"
);
gen_table();
@ -505,8 +504,7 @@ function gen_table()
);
}
const cases0f_16 = [];
const cases0f_32 = [];
const cases0f = [];
for(let opcode = 0; opcode < 0x100; opcode++)
{
let encoding = by_opcode0f[opcode];
@ -514,68 +512,50 @@ function gen_table()
assert(encoding && encoding.length);
let opcode_hex = hex(opcode, 2);
let opcode_high_hex = hex(opcode | 0x100, 2);
if(encoding[0].os)
{
cases0f_16.push({
cases0f.push({
conditions: [`0x${opcode_hex}`],
body: gen_instruction_body(encoding, 16),
});
cases0f_32.push({
conditions: [`0x${opcode_hex}`],
cases0f.push({
conditions: [`0x${opcode_high_hex}`],
body: gen_instruction_body(encoding, 32),
});
}
else
{
let block = {
conditions: [`0x${opcode_hex}`],
conditions: [`0x${opcode_hex}`, `0x${opcode_high_hex}`],
body: gen_instruction_body(encoding, undefined),
};
cases0f_16.push(block);
cases0f_32.push(block);
cases0f.push(block);
}
}
const table0f_16 = {
const table0f = {
type: "switch",
condition: "opcode",
cases: cases0f_16,
};
const table0f_32 = {
type: "switch",
condition: "opcode",
cases: cases0f_32,
cases: cases0f,
default_case: {
body: ["assert!(false);"]
},
};
if(to_generate.jit0f_16)
if(to_generate.jit0f)
{
const code = [
"#[cfg_attr(rustfmt, rustfmt_skip)]",
"pub fn jit(opcode: u8, ctx: &mut ::jit::JitContext, instr_flags: &mut u32) {",
table0f_16,
"pub fn jit(opcode: u32, ctx: &mut ::jit::JitContext, instr_flags: &mut u32) {",
table0f,
"}",
];
finalize_table_rust(
OUT_DIR,
"jit0f_16.rs",
rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
);
}
if(to_generate.jit0f_32)
{
const code = [
"#[cfg_attr(rustfmt, rustfmt_skip)]",
"pub fn jit(opcode: u8, ctx: &mut ::jit::JitContext, instr_flags: &mut u32) {",
table0f_32,
"}",
];
finalize_table_rust(
OUT_DIR,
"jit0f_32.rs",
"jit0f.rs",
rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
);
}

View file

@ -50,10 +50,10 @@ pub fn analyze_step_handle_segment_prefix(
}
pub fn instr16_0F_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
::gen::analyzer0f_16::analyzer(cpu.read_imm8(), cpu, analysis)
::gen::analyzer0f::analyzer(cpu.read_imm8() as u32, cpu, analysis)
}
pub fn instr32_0F_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
::gen::analyzer0f_32::analyzer(cpu.read_imm8(), cpu, analysis)
::gen::analyzer0f::analyzer(cpu.read_imm8() as u32 | 0x100, cpu, analysis)
}
pub fn instr_26_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) {
analyze_step_handle_segment_prefix(ES, cpu, analysis)

View file

@ -2313,8 +2313,8 @@ pub unsafe fn modrm_resolve(modrm_byte: i32) -> OrPageFault<i32> {
}
pub unsafe fn run_instruction(opcode: i32) { ::gen::interpreter::run(opcode as u32) }
pub unsafe fn run_instruction0f_16(opcode: i32) { ::gen::interpreter0f_16::run(opcode as u8) }
pub unsafe fn run_instruction0f_32(opcode: i32) { ::gen::interpreter0f_32::run(opcode as u8) }
pub unsafe fn run_instruction0f_16(opcode: i32) { ::gen::interpreter0f::run(opcode as u32) }
pub unsafe fn run_instruction0f_32(opcode: i32) { ::gen::interpreter0f::run(opcode as u32 | 0x100) }
#[no_mangle]
pub unsafe fn cycle_internal() {

View file

@ -1,11 +1,8 @@
pub mod interpreter;
pub mod interpreter0f_16;
pub mod interpreter0f_32;
pub mod interpreter0f;
pub mod jit;
pub mod jit0f_16;
pub mod jit0f_32;
pub mod jit0f;
pub mod analyzer;
pub mod analyzer0f_16;
pub mod analyzer0f_32;
pub mod analyzer0f;

View file

@ -57,10 +57,10 @@ pub fn jit_handle_segment_prefix(segment: u32, ctx: &mut JitContext, instr_flags
}
pub fn instr16_0F_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
::gen::jit0f_16::jit(ctx.cpu.read_imm8(), ctx, instr_flags)
::gen::jit0f::jit(ctx.cpu.read_imm8() as u32, ctx, instr_flags)
}
pub fn instr32_0F_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
::gen::jit0f_32::jit(ctx.cpu.read_imm8(), ctx, instr_flags)
::gen::jit0f::jit(ctx.cpu.read_imm8() as u32 | 0x100, ctx, instr_flags)
}
pub fn instr_26_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
jit_handle_segment_prefix(ES, ctx, instr_flags)