Browse Source

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

Fabian 3 years ago
parent
commit
9853bdb868
9 changed files with 78 additions and 156 deletions
  1. 3 6
      .gitignore
  2. 12 18
      Makefile
  3. 18 39
      gen/generate_analyzer.js
  4. 18 43
      gen/generate_interpreter.js
  5. 18 38
      gen/generate_jit.js
  6. 2 2
      src/rust/analysis.rs
  7. 2 2
      src/rust/cpu2/cpu.rs
  8. 3 6
      src/rust/gen/mod.rs
  9. 2 2
      src/rust/jit_instructions.rs

+ 3 - 6
.gitignore

@@ -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

+ 12 - 18
Makefile

@@ -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/

+ 18 - 39
gen/generate_analyzer.js

@@ -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,
-            "}"
-        ];
-
-        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,
+            "pub fn analyzer(opcode: u32, cpu: &mut ::cpu_context::CpuContext, analysis: &mut ::analysis::Analysis) {",
+            table0f,
             "}"
         ];
 
         finalize_table_rust(
             OUT_DIR,
-            "analyzer0f_32.rs",
+            "analyzer0f.rs",
             rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
         );
     }

+ 18 - 43
gen/generate_interpreter.js

@@ -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 = {
-        type: "switch",
-        condition: "opcode",
-        cases: cases0f_16,
-    };
-    const table0f_32 = {
+    const table0f = {
         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,
-            "}",
-        ];
-
-        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,
+            "pub unsafe fn run(opcode: u32) {",
+            table0f,
             "}",
         ];
 
         finalize_table_rust(
             OUT_DIR,
-            "interpreter0f_32.rs",
+            "interpreter0f.rs",
             rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
         );
     }

+ 18 - 38
gen/generate_jit.js

@@ -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 = {
-        type: "switch",
-        condition: "opcode",
-        cases: cases0f_16,
-    };
-    const table0f_32 = {
+    const table0f = {
         type: "switch",
         condition: "opcode",
-        cases: cases0f_32,
+        cases: cases0f,
+        default_case: {
+            body: ["assert!(false);"]
+        },
     };
 
-    if(to_generate.jit0f_16)
-    {
-        const code = [
-            "#[cfg_attr(rustfmt, rustfmt_skip)]",
-            "pub fn jit(opcode: u8, ctx: &mut ::jit::JitContext, instr_flags: &mut u32) {",
-            table0f_16,
-            "}",
-        ];
-
-        finalize_table_rust(
-            OUT_DIR,
-            "jit0f_16.rs",
-            rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
-        );
-    }
-
-    if(to_generate.jit0f_32)
+    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_32,
+            "pub fn jit(opcode: u32, ctx: &mut ::jit::JitContext, instr_flags: &mut u32) {",
+            table0f,
             "}",
         ];
 
         finalize_table_rust(
             OUT_DIR,
-            "jit0f_32.rs",
+            "jit0f.rs",
             rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n"
         );
     }

+ 2 - 2
src/rust/analysis.rs

@@ -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)

+ 2 - 2
src/rust/cpu2/cpu.rs

@@ -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() {

+ 3 - 6
src/rust/gen/mod.rs

@@ -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;

+ 2 - 2
src/rust/jit_instructions.rs

@@ -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)