diff --git a/.gitignore b/.gitignore
index 8118bc7f..cfd26651 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
deploy.sh
screenshots/
tests/qemu/test-i386
+tests/jit-paging/test-jit
*.map
build/
closure-compiler/
diff --git a/.travis-run-nasm.sh b/.travis-run-nasm.sh
index 37970232..e596f97c 100755
--- a/.travis-run-nasm.sh
+++ b/.travis-run-nasm.sh
@@ -1,3 +1,4 @@
#!/usr/bin/env bash
set -e
-make nasmtests
+./tests/nasm/create_tests.js
+make -j $(nproc --all) nasmtests
diff --git a/Makefile b/Makefile
index 3da75efe..60ce0bef 100644
--- a/Makefile
+++ b/Makefile
@@ -76,7 +76,7 @@ CORE_FILES=const.js config.js io.js main.js lib.js fpu.js ide.js pci.js floppy.j
dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js hpet.js acpi.js apic.js ioapic.js \
state.js ne2k.js virtio.js bus.js log.js \
cpu.js translate.js modrm.js string.js arith.js misc_instr.js instructions.js debug.js \
- elf.js
+ elf.js codegen.js
LIB_FILES=9p.js filesystem.js jor1k.js marshall.js utf8.js
BROWSER_FILES=screen.js \
keyboard.js mouse.js serial.js \
@@ -135,14 +135,15 @@ build/libv86-debug.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js
--js $(BROWSER_FILES)\
--js $(LIB_FILES)
-build/v86.wasm: src/native/*.c src/native/*.h
+build/v86.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/native/codegen/*.h
mkdir -p build
-ls -lh build/v86.wasm
# --llvm-opts 3
# -Wno-extra-semi
# EMCC_DEBUG=1 EMCC_WASM_BACKEND=1
# -fno-inline
- emcc src/native/all.c \
+ emcc src/native/all.c src/native/codegen/api.c \
+ -Isrc/native/ -Isrc/native/profiler/ \
-Wall -Wpedantic -Wextra \
-DDEBUG=false \
-DNDEBUG \
@@ -150,6 +151,7 @@ build/v86.wasm: src/native/*.c src/native/*.h
-fcolor-diagnostics \
-fwrapv \
--llvm-opts 3 \
+ --llvm-lto 3 \
-O3 \
-g4 \
-s LEGALIZE_JS_FFI=0 \
@@ -157,8 +159,9 @@ build/v86.wasm: src/native/*.c src/native/*.h
-s WASM=1 -s SIDE_MODULE=1 -o build/v86.wasm
ls -lh build/v86.wasm
-build/v86-debug.wasm: src/native/*.c src/native/*.h
- emcc src/native/all.c \
+build/v86-debug.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/native/codegen/*.h
+ emcc src/native/all.c src/native/codegen/api.c \
+ -Isrc/native/ -Isrc/native/profiler/ \
-Wall -Wpedantic -Wextra \
-Wno-bitwise-op-parentheses -Wno-gnu-binary-literal \
-fcolor-diagnostics \
@@ -170,12 +173,27 @@ build/v86-debug.wasm: src/native/*.c src/native/*.h
-s WASM=1 -s SIDE_MODULE=1 -o build/v86-debug.wasm
ls -lh build/v86-debug.wasm
+build/codegen-test.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/native/codegen/*.h
+ emcc src/native/codegen/api.c \
+ -Wall -Wpedantic -Wextra \
+ -Wno-bitwise-op-parentheses -Wno-gnu-binary-literal \
+ -fcolor-diagnostics \
+ -fwrapv \
+ -Os \
+ -g4 \
+ -s LEGALIZE_JS_FFI=0 \
+ -s "BINARYEN_TRAP_MODE='allow'" \
+ -s WASM=1 -s SIDE_MODULE=1 -o build/codegen-test.wasm
+ ls -lh build/codegen-test.wasm
+
clean:
-rm build/libv86.js
+ -rm build/libv86-debug.js
-rm build/v86_all.js
- -rm build/libv86.js.map
- -rm build/v86_all.js.map
-rm build/v86.wasm
+ -rm build/v86-debug.wasm
+ -rm build/*.map
+ -rm build/*.wast
$(MAKE) -C $(NASM_TEST_DIR) clean
run:
@@ -202,15 +220,19 @@ $(CLOSURE):
tests: build/libv86.js build/v86.wasm
./tests/full/run.js
-nasmtests: build/libv86.js build/v86.wasm
+nasmtests: build/libv86-debug.js build/v86-debug.wasm
$(MAKE) -C $(NASM_TEST_DIR) all
$(NASM_TEST_DIR)/run.js
+jitpagingtests: build/libv86.js build/v86.wasm
+ $(MAKE) -C tests/jit-paging test-jit
+ ./tests/jit-paging/run.js
+
qemutests: build/libv86.js build/v86.wasm
$(MAKE) -C tests/qemu test-i386
- ./tests/qemu/run.js > result
- ./tests/qemu/test-i386 > reference
- diff result reference
+ ./tests/qemu/run.js > /tmp/v86-test-result
+ ./tests/qemu/test-i386 > /tmp/v86-test-reference
+ diff /tmp/v86-test-result /tmp/v86-test-reference
kvm-unit-test: build/libv86.js build/v86.wasm
(cd tests/kvm-unit-tests && ./configure)
diff --git a/debug.html b/debug.html
index bf536f52..9ac2f467 100644
--- a/debug.html
+++ b/debug.html
@@ -185,9 +185,11 @@
Running:
0s
diff --git a/gen/c_ast.js b/gen/c_ast.js
new file mode 100644
index 00000000..4cdcdded
--- /dev/null
+++ b/gen/c_ast.js
@@ -0,0 +1,97 @@
+"use strict";
+
+function repeat(s, n)
+{
+ let out = "";
+ for(let i = 0; i < n; i++) out += s;
+ return out;
+}
+
+function indent(lines, how_much)
+{
+ return lines.map(line => repeat(" ", how_much) + line);
+}
+
+function print_syntax_tree(statements)
+{
+ let code = [];
+
+ for(let statement of statements)
+ {
+ if(typeof statement === "string")
+ {
+ code.push(statement);
+ }
+ else if(statement.type === "switch")
+ {
+ console.assert(statement.condition);
+
+ const cases = [];
+
+ for(let case_ of statement.cases)
+ {
+ console.assert(case_.conditions.length >= 1);
+
+ for(let condition of case_.conditions)
+ {
+ cases.push(`case ${condition}:`);
+ }
+
+ cases.push(`{`);
+ cases.push.apply(cases, indent(print_syntax_tree(case_.body), 4));
+ cases.push(`}`);
+ cases.push(`break;`);
+ }
+
+ if(statement.default_case)
+ {
+ cases.push(`default:`);
+ cases.push.apply(cases, indent(print_syntax_tree(statement.default_case.body), 4));
+ }
+
+ code.push(`switch(${statement.condition})`);
+ code.push(`{`);
+ code.push.apply(code, indent(cases, 4));
+ code.push(`}`);
+ }
+ else if(statement.type === "if-else")
+ {
+ console.assert(statement.if_blocks.length >= 1);
+
+ let first_if_block = statement.if_blocks[0];
+
+ code.push(`if(${first_if_block.condition})`);
+ code.push(`{`);
+ code.push.apply(code, indent(print_syntax_tree(first_if_block.body), 4));
+ code.push(`}`);
+
+ for(let i = 1; i < statement.if_blocks.length; i++)
+ {
+ let if_block = statement.if_blocks[i];
+
+ code.push(`else if(${if_block.condition})`);
+ code.push(`{`);
+ code.push.apply(code, indent(print_syntax_tree(if_block.body), 4));
+ code.push(`}`);
+ }
+
+ if(statement.else_block)
+ {
+ code.push(`else`);
+ code.push(`{`);
+ code.push.apply(code, indent(print_syntax_tree(statement.else_block.body), 4));
+ code.push(`}`);
+ }
+ }
+ else
+ {
+ console.assert(false, "Unexpected type: " + statement.type);
+ }
+ }
+
+ return code;
+}
+
+module.exports = {
+ print_syntax_tree,
+};
diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js
new file mode 100755
index 00000000..ba6619f3
--- /dev/null
+++ b/gen/generate_interpreter.js
@@ -0,0 +1,439 @@
+#!/usr/bin/env node
+"use strict";
+
+const fs = require("fs");
+const encodings = require("./x86_table");
+const c_ast = require("./c_ast");
+const { hex } = require("./util");
+
+gen_table();
+
+
+function gen_read_imm_call(op, size_variant)
+{
+ let size = (op.os || op.opcode % 2 === 1) ? size_variant : 8;
+
+ if(op.imm8 || op.imm8s || op.imm16 || op.imm1632 || op.imm32 || op.immaddr)
+ {
+ if(op.imm8)
+ {
+ return "read_imm8()";
+ }
+ else if(op.imm8s)
+ {
+ return "read_imm8s()";
+ }
+ else
+ {
+ if(op.immaddr)
+ {
+ // immaddr: depends on address size
+ return "read_moffs()";
+ }
+ else
+ {
+ console.assert(op.imm1632 || op.imm16 || op.imm32);
+
+ if(op.imm1632 && size === 16 || op.imm16)
+ {
+ return "read_imm16()";
+ }
+ else
+ {
+ console.assert(op.imm1632 && size === 32 || op.imm32);
+ return "read_imm32s()";
+ }
+ }
+ }
+ }
+ else
+ {
+ return undefined;
+ }
+}
+
+function gen_call(name, args)
+{
+ args = args || [];
+ return `${name}(${args.join(", ")});`;
+}
+
+function gen_modrm_mem_reg_split(name, mem_args, reg_args)
+{
+ return {
+ type: "if-else",
+ if_blocks: [{
+ condition: "modrm_byte < 0xC0",
+ body: [gen_call(`${name}_mem`, mem_args)],
+ }],
+ else_block: {
+ body: [gen_call(`${name}_reg`, reg_args)],
+ },
+ };
+}
+
+/*
+ * Current naming scheme:
+ * instr(16|32|)_((66|F2|F3)?0F)?[0-9a-f]{2}(_[0-7])?(_mem|_reg|)
+ */
+
+function make_instruction_name(encoding, size, prefix_variant)
+{
+ const suffix = encoding.os ? String(size) : "";
+ const opcode_hex = hex(encoding.opcode & 0xFF, 2);
+ const prefix_0f = (encoding.opcode & 0xFF00) === 0x0F00 ? "0F" : "";
+ const prefix = prefix_variant === undefined ? "" : hex(prefix_variant, 2);
+ const fixed_g_suffix = encoding.fixed_g === undefined ? "" : `_${encoding.fixed_g}`;
+
+ return `instr${suffix}_${prefix}${prefix_0f}${opcode_hex}${fixed_g_suffix}`;
+}
+
+function gen_instruction_body(encodings, size)
+{
+ const encoding = encodings[0];
+
+ let has_66 = false;
+ let has_F2 = false;
+ let has_F3 = false;
+
+ for(let e of encodings)
+ {
+ if((e.opcode >>> 16) === 0x66) has_66 = true;
+ if((e.opcode >>> 16) === 0xF2) has_F2 = true;
+ if((e.opcode >>> 16) === 0xF3) has_F3 = true;
+ }
+
+ if(has_66 || has_F2 || has_F3)
+ {
+ console.assert((encoding.opcode & 0xFF00) === 0x0F00);
+ }
+
+ if(encoding.fixed_g !== undefined)
+ {
+ // instruction with modrm byte where the middle 3 bits encode the instruction
+
+ // group by opcode without prefix plus middle bits of modrm byte
+ let cases = encodings.reduce((cases_by_opcode, case_) => {
+ console.assert(typeof case_.fixed_g === "number");
+ cases_by_opcode[case_.opcode & 0xFFFF | case_.fixed_g << 16] = case_;
+ return cases_by_opcode;
+ }, Object.create(null));
+ cases = Object.values(cases).sort((e1, e2) => e1.fixed_g - e2.fixed_g);
+
+ return [
+ "int32_t modrm_byte = read_imm8();",
+ {
+ type: "switch",
+ condition: "modrm_byte >> 3 & 7",
+ cases: cases.map(case_ => {
+ const fixed_g = case_.fixed_g;
+ const instruction_name = make_instruction_name(case_, size, undefined);
+
+ const modrm_resolve = case_.custom_modrm_resolve ? instruction_name + "_modrm_resolve" : "modrm_resolve";
+ const mem_args = [`${modrm_resolve}(modrm_byte)`];
+ const reg_args = ["modrm_byte & 7"];
+
+ const imm_read = gen_read_imm_call(case_, size);
+ if(imm_read)
+ {
+ mem_args.push(imm_read);
+ reg_args.push(imm_read);
+ }
+
+ if(has_66 || has_F2 || has_F3)
+ {
+ const if_blocks = [];
+
+ if(has_66) {
+ const name = make_instruction_name(case_, size, 0x66);
+ const body = [gen_modrm_mem_reg_split(name, mem_args, reg_args)];
+ if_blocks.push({ condition: "prefixes_ & PREFIX_66", body, });
+ }
+ if(has_F2) {
+ const name = make_instruction_name(case_, size, 0xF2);
+ const body = [gen_modrm_mem_reg_split(name, mem_args, reg_args)];
+ if_blocks.push({ condition: "prefixes_ & PREFIX_F2", body, });
+ }
+ if(has_F3) {
+ const name = make_instruction_name(case_, size, 0xF3);
+ const body = [gen_modrm_mem_reg_split(name, mem_args, reg_args)];
+ if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, });
+ }
+
+ const else_block = {
+ body: [gen_modrm_mem_reg_split(instruction_name, mem_args, reg_args)],
+ };
+
+ return {
+ conditions: [fixed_g],
+ body: [
+ "int32_t prefixes_ = *prefixes;",
+ {
+ type: "if-else",
+ if_blocks,
+ else_block,
+ },
+ ],
+ };
+ }
+ else
+ {
+ const body = [gen_modrm_mem_reg_split(instruction_name, mem_args, reg_args)];
+
+ return {
+ conditions: [fixed_g],
+ body,
+ };
+ }
+ }),
+
+ default_case: {
+ body: [
+ "assert(false);",
+ "trigger_ud();",
+ ],
+ }
+ }
+ ];
+ }
+ else if(has_66 || has_F2 || has_F3)
+ {
+ // instruction withoud modrm byte but with prefix
+
+ console.assert(encoding.e);
+ console.assert(!encoding.ignore_mod);
+ console.assert(!encoding.requires_prefix_call, "Unexpected instruction (66/f2/f3 with prefix call)");
+
+ const imm_read = gen_read_imm_call(encoding, size);
+ const modrm_resolve = encoding.custom_modrm_resolve ? instruction_name + "_modrm_resolve" : "modrm_resolve";
+ const mem_args = [`${modrm_resolve}(modrm_byte)`, "modrm_byte >> 3 & 7"];
+ const reg_args = ["modrm_byte & 7", "modrm_byte >> 3 & 7"];
+
+ if(imm_read)
+ {
+ mem_args.push(imm_read);
+ reg_args.push(imm_read);
+ }
+
+ const if_blocks = [];
+
+ if(has_66) {
+ const name = make_instruction_name(encoding, size, 0x66);
+ const body = [gen_modrm_mem_reg_split(name, mem_args, reg_args)];
+ if_blocks.push({ condition: "prefixes_ & PREFIX_66", body, });
+ }
+ if(has_F2) {
+ const name = make_instruction_name(encoding, size, 0xF2);
+ const body = [gen_modrm_mem_reg_split(name, mem_args, reg_args)];
+ if_blocks.push({ condition: "prefixes_ & PREFIX_F2", body, });
+ }
+ if(has_F3) {
+ const name = make_instruction_name(encoding, size, 0xF3);
+ const body = [gen_modrm_mem_reg_split(name, mem_args, reg_args)];
+ if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, });
+ }
+
+ const else_block = {
+ body: [gen_modrm_mem_reg_split(make_instruction_name(encoding, size), mem_args, reg_args)],
+ };
+
+ return [
+ "int32_t modrm_byte = read_imm8();",
+ "int32_t prefixes_ = *prefixes;",
+ {
+ type: "if-else",
+ if_blocks,
+ else_block,
+ }
+ ];
+ }
+ else if(encoding.fixed_g === undefined && encoding.e)
+ {
+ // instruction with modrm byte where the middle 3 bits encode a register
+
+ console.assert(encodings.length === 1);
+
+ const instruction_name = make_instruction_name(encoding, size);
+ const imm_read = gen_read_imm_call(encoding, size);
+
+ if(encoding.ignore_mod)
+ {
+ console.assert(!imm_read, "Unexpected instruction (ignore mod with immediate value)");
+
+ // Has modrm byte, but the 2 mod bits are ignored and both
+ // operands are always registers (0f20-0f24)
+
+ return [
+ "int32_t modrm_byte = read_imm8();",
+ gen_call(instruction_name, ["modrm_byte & 7", "modrm_byte >> 3 & 7"]),
+ ];
+ }
+ else
+ {
+ const modrm_resolve = encoding.custom_modrm_resolve ? instruction_name + "_modrm_resolve" : "modrm_resolve";
+ const mem_args = [`${modrm_resolve}(modrm_byte)`, "modrm_byte >> 3 & 7"];
+ const reg_args = ["modrm_byte & 7", "modrm_byte >> 3 & 7"];
+
+ if(imm_read)
+ {
+ mem_args.push(imm_read);
+ reg_args.push(imm_read);
+ }
+
+ return [
+ "int32_t modrm_byte = read_imm8();",
+ gen_modrm_mem_reg_split(instruction_name, mem_args, reg_args),
+ ];
+ }
+ }
+ else
+ {
+ // instruction without modrm byte or prefix
+
+ const imm_read = gen_read_imm_call(encoding, size);
+ const instruction_name = make_instruction_name(encoding, size);
+
+ const args = [];
+
+ if(imm_read)
+ {
+ args.push(imm_read);
+ }
+
+ if(encoding.extra_imm16)
+ {
+ console.assert(imm_read);
+ args.push("read_imm16()");
+ }
+ else if(encoding.extra_imm8)
+ {
+ console.assert(imm_read);
+ args.push("read_imm8()");
+ }
+
+ return [gen_call(instruction_name, args)];
+ }
+}
+
+function gen_table()
+{
+ let by_opcode = Object.create(null);
+ let by_opcode0f = Object.create(null);
+
+ for(let o of encodings)
+ {
+ let opcode = o.opcode;
+
+ if(opcode >= 0x100)
+ {
+ if((opcode & 0xFF00) === 0x0F00)
+ {
+ opcode &= 0xFF;
+ by_opcode0f[opcode] = by_opcode0f[opcode] || [];
+ by_opcode0f[opcode].push(o);
+ }
+ }
+ else
+ {
+ by_opcode[opcode] = by_opcode[opcode] || [];
+ by_opcode[opcode].push(o);
+ }
+ }
+
+ let cases = [];
+ for(let opcode = 0; opcode < 0x100; opcode++)
+ {
+ let encoding = by_opcode[opcode];
+ console.assert(encoding && encoding.length);
+
+ let opcode_hex = hex(opcode, 2);
+
+ if(encoding[0].os)
+ {
+ cases.push({
+ conditions: [`0x${opcode_hex}`],
+ body: gen_instruction_body(encoding, 16),
+ });
+ cases.push({
+ conditions: [`0x${opcode_hex}|0x100`],
+ body: gen_instruction_body(encoding, 32),
+ });
+ }
+ else
+ {
+ cases.push({
+ conditions: [`0x${opcode_hex}`, `0x${opcode_hex}|0x100`],
+ body: gen_instruction_body(encoding, undefined),
+ });
+ }
+ }
+ const table = {
+ type: "switch",
+ condition: "opcode",
+ cases,
+ default_case: {
+ body: ["assert(false);"]
+ },
+ };
+ fs.writeFileSync("/tmp/table", c_ast.print_syntax_tree([table]).join("\n") + "\n");
+
+ const cases0f_16 = [];
+ const cases0f_32 = [];
+ for(let opcode = 0; opcode < 0x100; opcode++)
+ {
+ let encoding = by_opcode0f[opcode];
+
+ if(!encoding)
+ {
+ encoding = [
+ {
+ opcode: 0x0F00 | opcode,
+ },
+ ];
+ }
+
+ console.assert(encoding && encoding.length);
+
+ let opcode_hex = hex(opcode, 2);
+
+ if(encoding[0].os)
+ {
+ cases0f_16.push({
+ conditions: [`0x${opcode_hex}`],
+ body: gen_instruction_body(encoding, 16),
+ });
+ cases0f_32.push({
+ conditions: [`0x${opcode_hex}`],
+ body: gen_instruction_body(encoding, 32),
+ });
+ }
+ else
+ {
+ let block = {
+ conditions: [`0x${opcode_hex}`],
+ body: gen_instruction_body(encoding, undefined),
+ };
+ cases0f_16.push(block);
+ cases0f_32.push(block);
+ }
+ }
+
+ const table0f_16 = {
+ type: "switch",
+ condition: "opcode",
+ cases: cases0f_16,
+ default_case: {
+ body: ["assert(false);"]
+ },
+ };
+ const table0f_32 = {
+ type: "switch",
+ condition: "opcode",
+ cases: cases0f_32,
+ default_case: {
+ body: ["assert(false);"]
+ },
+ };
+ fs.writeFileSync("/tmp/table0f_16", c_ast.print_syntax_tree([table0f_16]).join("\n") + "\n");
+ fs.writeFileSync("/tmp/table0f_32", c_ast.print_syntax_tree([table0f_32]).join("\n") + "\n");
+}
diff --git a/gen/util.js b/gen/util.js
new file mode 100644
index 00000000..d0502d9e
--- /dev/null
+++ b/gen/util.js
@@ -0,0 +1,14 @@
+"use strict";
+
+
+function hex(n, pad)
+{
+ pad = pad || 0;
+ let s = n.toString(16).toUpperCase();
+ while(s.length < pad) s = "0" + s;
+ return s;
+}
+
+module.exports = {
+ hex,
+};
diff --git a/gen/x86_table.js b/gen/x86_table.js
new file mode 100644
index 00000000..56110e85
--- /dev/null
+++ b/gen/x86_table.js
@@ -0,0 +1,648 @@
+"use strict";
+
+// http://ref.x86asm.net/coder32.html
+
+const zf = 1 << 6;
+const of = 1 << 11;
+const cf = 1 << 0;
+const af = 1 << 4;
+const pf = 1 << 2;
+const sf = 1 << 7;
+
+// TODO:
+// - describe which registers are written and read
+
+// os: the instruction behaves differently depending on the operand size
+const encodings = [
+ { opcode: 0x06, os: 1, skip: 1, },
+ { opcode: 0x07, os: 1, skip: 1, },
+ { opcode: 0x0E, os: 1, skip: 1, },
+ { opcode: 0x0F, os: 1, prefix: 1, },
+ { opcode: 0x16, os: 1, skip: 1, },
+ { opcode: 0x17, os: 1, skip: 1, },
+ { opcode: 0x1E, os: 1, skip: 1, },
+ { opcode: 0x1F, os: 1, skip: 1, },
+ { opcode: 0x26, prefix: 1, },
+ { opcode: 0x27, mask_flags: of, },
+ { opcode: 0x2E, prefix: 1, },
+ { opcode: 0x2F, mask_flags: of, },
+ { opcode: 0x36, prefix: 1, },
+ { opcode: 0x37, mask_flags: of | sf | pf | zf, },
+ { opcode: 0x3E, prefix: 1, },
+ { opcode: 0x3F, mask_flags: of | sf | pf | zf, },
+
+ { opcode: 0x40, os: 1, },
+ { opcode: 0x41, os: 1, },
+ { opcode: 0x42, os: 1, },
+ { opcode: 0x43, os: 1, },
+ { opcode: 0x44, os: 1, },
+ { opcode: 0x45, os: 1, },
+ { opcode: 0x46, os: 1, },
+ { opcode: 0x47, os: 1, },
+
+ { opcode: 0x48, os: 1, },
+ { opcode: 0x49, os: 1, },
+ { opcode: 0x4A, os: 1, },
+ { opcode: 0x4B, os: 1, },
+ { opcode: 0x4C, os: 1, },
+ { opcode: 0x4D, os: 1, },
+ { opcode: 0x4E, os: 1, },
+ { opcode: 0x4F, os: 1, },
+
+ { opcode: 0x50, os: 1, },
+ { opcode: 0x51, os: 1, },
+ { opcode: 0x52, os: 1, },
+ { opcode: 0x53, os: 1, },
+ { opcode: 0x54, os: 1, },
+ { opcode: 0x55, os: 1, },
+ { opcode: 0x56, os: 1, },
+ { opcode: 0x57, os: 1, },
+
+ { opcode: 0x58, os: 1, },
+ { opcode: 0x59, os: 1, },
+ { opcode: 0x5A, os: 1, },
+ { opcode: 0x5B, os: 1, },
+ { opcode: 0x5C, os: 1, },
+ { opcode: 0x5D, os: 1, },
+ { opcode: 0x5E, os: 1, },
+ { opcode: 0x5F, os: 1, },
+
+ { opcode: 0x60, os: 1, },
+ { opcode: 0x61, os: 1, },
+ { opcode: 0x62, e: 1, skip: 1, },
+ { opcode: 0x63, e: 1, },
+ { opcode: 0x64, prefix: 1, },
+ { opcode: 0x65, prefix: 1, },
+ { opcode: 0x66, prefix: 1, },
+ { opcode: 0x67, prefix: 1, },
+
+ { opcode: 0x68, os: 1, imm1632: 1, },
+ { opcode: 0x69, os: 1, e: 1, imm1632: 1, mask_flags: af, }, // zf?
+ { opcode: 0x6A, os: 1, imm8s: 1, },
+ { opcode: 0x6B, os: 1, e: 1, imm8s: 1, mask_flags: af, }, // zf?
+
+ { opcode: 0x6C, is_string: 1, skip: 1, },
+ { opcode: 0x6D, is_string: 1, os: 1, skip: 1, },
+ { opcode: 0x6E, is_string: 1, skip: 1, },
+ { opcode: 0x6F, is_string: 1, os: 1, skip: 1, },
+
+ { opcode: 0x84, e: 1, },
+ { opcode: 0x85, os: 1, e: 1, },
+ { opcode: 0x86, e: 1, },
+ { opcode: 0x87, os: 1, e: 1, },
+ { opcode: 0x88, e: 1, },
+ { opcode: 0x89, os: 1, e: 1, },
+ { opcode: 0x8A, e: 1, },
+ { opcode: 0x8B, os: 1, e: 1, },
+
+ { opcode: 0x8C, os: 1, e: 1, skip: 1, },
+ { opcode: 0x8D, os: 1, e: 1, only_mem: 1, custom_modrm_resolve: 1, }, // lea
+ { opcode: 0x8E, e: 1, skip: 1, },
+ { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, custom_modrm_resolve: 1, }, // pop r/m
+
+ { opcode: 0x90, },
+ { opcode: 0x91, os: 1, },
+ { opcode: 0x92, os: 1, },
+ { opcode: 0x93, os: 1, },
+ { opcode: 0x94, os: 1, },
+ { opcode: 0x95, os: 1, },
+ { opcode: 0x96, os: 1, },
+ { opcode: 0x97, os: 1, },
+
+ { opcode: 0x98, os: 1, },
+ { opcode: 0x99, os: 1, },
+ { opcode: 0x9A, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, }, // callf
+ { opcode: 0x9B, skip: 1, },
+ { opcode: 0x9C, os: 1, },
+ { opcode: 0x9D, os: 1, skip: 1, }, // popf
+ { opcode: 0x9E, },
+ { opcode: 0x9F, },
+
+ { opcode: 0xA0, immaddr: 1, },
+ { opcode: 0xA1, os: 1, immaddr: 1, },
+ { opcode: 0xA2, immaddr: 1, },
+ { opcode: 0xA3, os: 1, immaddr: 1, },
+
+ { opcode: 0xA4, is_string: 1, },
+ { opcode: 0xA5, is_string: 1, os: 1, },
+ { opcode: 0xA6, is_string: 1, },
+ { opcode: 0xA7, is_string: 1, os: 1, },
+
+ { opcode: 0xA8, imm8: 1, },
+ { opcode: 0xA9, os: 1, imm1632: 1, },
+
+ { opcode: 0xAA, is_string: 1, },
+ { opcode: 0xAB, is_string: 1, os: 1, },
+ { opcode: 0xAC, is_string: 1, },
+ { opcode: 0xAD, is_string: 1, os: 1, },
+ { opcode: 0xAE, is_string: 1, },
+ { opcode: 0xAF, is_string: 1, os: 1, },
+
+ { opcode: 0xC2, os: 1, imm16: 1, skip: 1, },
+ { opcode: 0xC3, os: 1, skip: 1, },
+
+ { opcode: 0xC4, os: 1, e: 1, skip: 1, },
+ { opcode: 0xC5, os: 1, e: 1, skip: 1, },
+
+ { opcode: 0xC6, e: 1, fixed_g: 0, imm8: 1, },
+ { opcode: 0xC7, os: 1, e: 1, fixed_g: 0, imm1632: 1, },
+
+ { opcode: 0xC8, os: 1, imm16: 1, extra_imm8: 1, }, // enter
+ { opcode: 0xC9, os: 1, skip: 1, }, // leave: requires valid ebp
+ { opcode: 0xCA, os: 1, imm16: 1, skip: 1, },
+ { opcode: 0xCB, os: 1, skip: 1, },
+ { opcode: 0xCC, skip: 1, },
+ { opcode: 0xCD, imm8: 1, skip: 1, },
+ { opcode: 0xCE, skip: 1, },
+ { opcode: 0xCF, os: 1, skip: 1, },
+
+ { opcode: 0xD4, imm8: 1, }, // aam, may trigger #de
+ { opcode: 0xD5, imm8: 1, mask_flags: of | cf | af, },
+ { opcode: 0xD6, },
+ { opcode: 0xD7, skip: 1, },
+
+ { opcode: 0xD8, e: 1, skip: 1, },
+ { opcode: 0xD9, e: 1, skip: 1, },
+ { opcode: 0xDA, e: 1, skip: 1, },
+ { opcode: 0xDB, e: 1, skip: 1, },
+ { opcode: 0xDC, e: 1, skip: 1, },
+ { opcode: 0xDD, e: 1, skip: 1, },
+ { opcode: 0xDE, e: 1, skip: 1, },
+ { opcode: 0xDF, e: 1, skip: 1, },
+
+ { opcode: 0xE0, imm8s: 1, skip: 1, },
+ { opcode: 0xE1, imm8s: 1, skip: 1, },
+ { opcode: 0xE2, imm8s: 1, skip: 1, },
+ { opcode: 0xE3, imm8s: 1, skip: 1, },
+
+ { opcode: 0xE4, imm8: 1, skip: 1, },
+ { opcode: 0xE5, os: 1, imm8: 1, skip: 1, },
+ { opcode: 0xE6, imm8: 1, skip: 1, },
+ { opcode: 0xE7, os: 1, imm8: 1, skip: 1, },
+
+ { opcode: 0xE8, os: 1, imm1632: 1, skip: 1, },
+ { opcode: 0xE9, os: 1, imm1632: 1, skip: 1, },
+ { opcode: 0xEA, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, }, // jmpf
+ { opcode: 0xEB, imm8s: 1, skip: 1, },
+
+ { opcode: 0xEC, skip: 1, },
+ { opcode: 0xED, os: 1, skip: 1, },
+ { opcode: 0xEE, skip: 1, },
+ { opcode: 0xEF, os: 1, skip: 1, },
+
+ { opcode: 0xF0, prefix: 1, },
+ { opcode: 0xF1, skip: 1, },
+ { opcode: 0xF2, prefix: 1, },
+ { opcode: 0xF3, prefix: 1, },
+ { opcode: 0xF4, skip: 1, },
+ { opcode: 0xF5, },
+
+ { opcode: 0xF6, fixed_g: 0, imm8: 1, },
+ { opcode: 0xF6, fixed_g: 1, imm8: 1, },
+ { opcode: 0xF6, fixed_g: 2, },
+ { opcode: 0xF6, fixed_g: 3, },
+ { opcode: 0xF6, fixed_g: 4, mask_flags: af | zf, },
+ { opcode: 0xF6, fixed_g: 5, mask_flags: af | zf, },
+ { opcode: 0xF6, fixed_g: 6, },
+ { opcode: 0xF6, fixed_g: 7, },
+
+ { opcode: 0xF7, os: 1, fixed_g: 0, imm1632: 1, },
+ { opcode: 0xF7, os: 1, fixed_g: 1, imm1632: 1, },
+ { opcode: 0xF7, os: 1, fixed_g: 2, },
+ { opcode: 0xF7, os: 1, fixed_g: 3, },
+ { opcode: 0xF7, os: 1, fixed_g: 4, mask_flags: zf | af, },
+ { opcode: 0xF7, os: 1, fixed_g: 5, mask_flags: zf | af, },
+ { opcode: 0xF7, os: 1, fixed_g: 6, },
+ { opcode: 0xF7, os: 1, fixed_g: 7, },
+
+ { opcode: 0xF8, },
+ { opcode: 0xF9, },
+ { opcode: 0xFA, skip: 1, },
+ { opcode: 0xFB, skip: 1, },
+ { opcode: 0xFC, },
+ { opcode: 0xFD, },
+
+ { opcode: 0xFE, e: 1, fixed_g: 0, },
+ { opcode: 0xFE, e: 1, fixed_g: 1, },
+ { opcode: 0xFF, os: 1, e: 1, fixed_g: 0, },
+ { opcode: 0xFF, os: 1, e: 1, fixed_g: 1, },
+ { opcode: 0xFF, os: 1, e: 1, fixed_g: 2, skip: 1, },
+ { opcode: 0xFF, os: 1, e: 1, fixed_g: 3, skip: 1, },
+ { opcode: 0xFF, os: 1, e: 1, fixed_g: 4, skip: 1, },
+ { opcode: 0xFF, os: 1, e: 1, fixed_g: 5, skip: 1, },
+ { opcode: 0xFF, os: 1, e: 1, fixed_g: 6, },
+
+ { opcode: 0x0F00, fixed_g: 0, e: 1, skip: 1 },
+ { opcode: 0x0F00, fixed_g: 1, e: 1, skip: 1 },
+ { opcode: 0x0F00, fixed_g: 2, e: 1, skip: 1 },
+ { opcode: 0x0F00, fixed_g: 3, e: 1, skip: 1 },
+ { opcode: 0x0F00, fixed_g: 4, e: 1, skip: 1 },
+ { opcode: 0x0F00, fixed_g: 5, e: 1, skip: 1 },
+
+ { opcode: 0x0F01, fixed_g: 0, e: 1, skip: 1 },
+ { opcode: 0x0F01, fixed_g: 1, e: 1, skip: 1 },
+ { opcode: 0x0F01, fixed_g: 2, e: 1, skip: 1 },
+ { opcode: 0x0F01, fixed_g: 3, e: 1, skip: 1 },
+ { opcode: 0x0F01, fixed_g: 4, e: 1, skip: 1 },
+ { opcode: 0x0F01, fixed_g: 6, e: 1, skip: 1 },
+ { opcode: 0x0F01, fixed_g: 7, e: 1, skip: 1 },
+
+ { opcode: 0x0F02, os: 1, e: 1, skip: 1 },
+ { opcode: 0x0F03, os: 1, e: 1, skip: 1 },
+ { opcode: 0x0F04, skip: 1 },
+ { opcode: 0x0F05, skip: 1 },
+ { opcode: 0x0F06, skip: 1 },
+ { opcode: 0x0F07, skip: 1 },
+ { opcode: 0x0F08, skip: 1 },
+ { opcode: 0x0F09, skip: 1 },
+ { opcode: 0x0F09, skip: 1 },
+ { opcode: 0x0F0A, skip: 1 },
+ { opcode: 0x0F0B, skip: 1 },
+ { opcode: 0x0F0C, skip: 1 },
+ { opcode: 0x0F0D, skip: 1 },
+ { opcode: 0x0F0E, skip: 1 },
+ { opcode: 0x0F0F, skip: 1 },
+
+ { opcode: 0x0F18, only_mem: 1, e: 1, },
+ { opcode: 0x0F1F, e: 1, },
+
+ { opcode: 0x0F20, ignore_mod: 1, e: 1, skip: 1 },
+ { opcode: 0x0F21, ignore_mod: 1, e: 1, skip: 1 },
+ { opcode: 0x0F22, ignore_mod: 1, e: 1, skip: 1 },
+ { opcode: 0x0F23, ignore_mod: 1, e: 1, skip: 1 },
+
+ { opcode: 0x0F30, skip: 1 },
+ { opcode: 0x0F31, skip: 1 },
+ { opcode: 0x0F32, skip: 1 },
+ { opcode: 0x0F33, skip: 1 },
+ { opcode: 0x0F34, skip: 1 },
+ { opcode: 0x0F35, skip: 1 },
+
+ { opcode: 0x0F40, e: 1, os: 1, },
+ { opcode: 0x0F41, e: 1, os: 1, },
+ { opcode: 0x0F42, e: 1, os: 1, },
+ { opcode: 0x0F43, e: 1, os: 1, },
+ { opcode: 0x0F44, e: 1, os: 1, },
+ { opcode: 0x0F45, e: 1, os: 1, },
+ { opcode: 0x0F46, e: 1, os: 1, },
+ { opcode: 0x0F47, e: 1, os: 1, },
+ { opcode: 0x0F48, e: 1, os: 1, },
+ { opcode: 0x0F49, e: 1, os: 1, },
+ { opcode: 0x0F4A, e: 1, os: 1, },
+ { opcode: 0x0F4B, e: 1, os: 1, },
+ { opcode: 0x0F4C, e: 1, os: 1, },
+ { opcode: 0x0F4D, e: 1, os: 1, },
+ { opcode: 0x0F4E, e: 1, os: 1, },
+ { opcode: 0x0F4F, e: 1, os: 1, },
+
+ { opcode: 0x0F80, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F81, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F82, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F83, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F84, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F85, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F86, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F87, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F88, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F89, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F8A, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F8B, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F8C, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F8D, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F8E, imm1632: 1, os: 1, skip: 1, },
+ { opcode: 0x0F8F, imm1632: 1, os: 1, skip: 1, },
+
+ { opcode: 0x0F90, e: 1, },
+ { opcode: 0x0F91, e: 1, },
+ { opcode: 0x0F92, e: 1, },
+ { opcode: 0x0F93, e: 1, },
+ { opcode: 0x0F94, e: 1, },
+ { opcode: 0x0F95, e: 1, },
+ { opcode: 0x0F96, e: 1, },
+ { opcode: 0x0F97, e: 1, },
+ { opcode: 0x0F98, e: 1, },
+ { opcode: 0x0F99, e: 1, },
+ { opcode: 0x0F9A, e: 1, },
+ { opcode: 0x0F9B, e: 1, },
+ { opcode: 0x0F9C, e: 1, },
+ { opcode: 0x0F9D, e: 1, },
+ { opcode: 0x0F9E, e: 1, },
+ { opcode: 0x0F9F, e: 1, },
+
+ { opcode: 0x0FA0, os: 1, skip: 1, },
+ { opcode: 0x0FA1, os: 1, skip: 1, },
+ { opcode: 0x0FA2, skip: 1, },
+
+ { opcode: 0x0FA8, os: 1, skip: 1, },
+ { opcode: 0x0FA9, os: 1, skip: 1, },
+
+ { opcode: 0x0FA3, os: 1, e: 1, only_reg: 1, }, // bt (can also index memory, but not supported by test right now)
+ { opcode: 0x0FAB, os: 1, e: 1, only_reg: 1, },
+ { opcode: 0x0FB3, os: 1, e: 1, only_reg: 1, },
+ { opcode: 0x0FBB, os: 1, e: 1, only_reg: 1, },
+
+ { opcode: 0x0FBA, os: 1, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, }, // bt
+ { opcode: 0x0FBA, os: 1, e: 1, fixed_g: 5, imm8: 1, only_reg: 1, },
+ { opcode: 0x0FBA, os: 1, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
+ { opcode: 0x0FBA, os: 1, e: 1, fixed_g: 7, imm8: 1, only_reg: 1, },
+
+ { opcode: 0x0FBC, os: 1, e: 1, mask_flags: af, }, // bsf
+ { opcode: 0x0FBD, os: 1, e: 1, mask_flags: af, },
+
+ // note: overflow flag only undefined if shift is > 1
+ { opcode: 0x0FA4, os: 1, e: 1, imm8: 1, mask_flags: af | of, }, // shld
+ { opcode: 0x0FA5, os: 1, e: 1, mask_flags: af | of, },
+ { opcode: 0x0FAC, os: 1, e: 1, imm8: 1, mask_flags: af | of, },
+ { opcode: 0x0FAD, os: 1, e: 1, mask_flags: af | of, },
+
+ { opcode: 0x0FAE, e: 1, fixed_g: 0, only_mem: 1, skip: 1, }, // fxsave, ...
+ { opcode: 0x0FAE, e: 1, fixed_g: 1, only_mem: 1, skip: 1, },
+ { opcode: 0x0FAE, e: 1, fixed_g: 2, only_mem: 1, skip: 1, },
+ { opcode: 0x0FAE, e: 1, fixed_g: 3, only_mem: 1, skip: 1, },
+ { opcode: 0x0FAE, e: 1, fixed_g: 4, only_mem: 1, skip: 1, },
+
+ { opcode: 0x0FAE, e: 1, fixed_g: 5, only_reg: 1, skip: 1, }, // lfence (reg, only 0), xrstor (mem)
+ { opcode: 0x0FAE, e: 1, fixed_g: 6, only_reg: 1, skip: 1, }, // mfence (reg, only 0)
+ { opcode: 0x0FAE, e: 1, fixed_g: 7, only_reg: 1, skip: 1, }, // sfence (reg, only 0), clflush (mem)
+
+ { opcode: 0x0FAF, os: 1, e: 1, mask_flags: af | zf }, // imul
+
+ { opcode: 0x0FB0, e: 1 }, // cmxchg
+ { opcode: 0x0FB1, os: 1, e: 1 },
+ { opcode: 0x0FC7, e: 1, fixed_g: 1, only_mem: 1, }, // cmpxchg8b (memory)
+ { opcode: 0x0FC7, e: 1, fixed_g: 6, only_reg: 1, skip: 1, }, // rdrand
+
+ { opcode: 0x0FB2, os: 1, e: 1, skip: 1, }, // lss, lfs, lgs
+ { opcode: 0x0FB4, os: 1, e: 1, skip: 1, },
+ { opcode: 0x0FB5, os: 1, e: 1, skip: 1, },
+
+ { opcode: 0x0FB6, os: 1, e: 1, }, // movzx
+ { opcode: 0x0FB7, os: 1, e: 1, },
+
+ { opcode: 0xF30FB8, os: 1, e: 1 }, // popcnt
+
+ { opcode: 0x0FBE, os: 1, e: 1, }, // movsx
+ { opcode: 0x0FBF, os: 1, e: 1, },
+
+ { opcode: 0x0FC0, e: 1, }, // xadd
+ { opcode: 0x0FC1, os: 1, e: 1, },
+
+ { opcode: 0x0FC8, }, // bswap
+ { opcode: 0x0FC9, },
+ { opcode: 0x0FCA, },
+ { opcode: 0x0FCB, },
+ { opcode: 0x0FCC, },
+ { opcode: 0x0FCD, },
+ { opcode: 0x0FCE, },
+ { opcode: 0x0FCF, },
+
+
+ // mmx, sse
+ // - Skipped are not implemented
+ // - Missing are sse3+, and floating point
+
+ { opcode: 0x0F12, e: 1, skip: 1, },
+ { opcode: 0x660F12, only_mem: 1, e: 1 },
+ { opcode: 0xF20F12, e: 1, skip: 1, },
+ { opcode: 0xF30F12, e: 1, skip: 1, },
+ { opcode: 0x0F13, only_mem: 1, e: 1 },
+ { opcode: 0x660F13, only_mem: 1, e: 1 },
+ { opcode: 0x0F14, e: 1, skip: 1, },
+ { opcode: 0x660F14, e: 1 },
+
+ { opcode: 0x0F28, e: 1 },
+ { opcode: 0x660F28, e: 1 },
+ { opcode: 0x0F29, e: 1 },
+ { opcode: 0x660F29, e: 1 },
+ { opcode: 0x0F2B, only_mem: 1, e: 1 },
+ { opcode: 0x660F2B, only_mem: 1, e: 1 },
+
+ { opcode: 0xF20F2C, e: 1, },
+ { opcode: 0x0F2C, e: 1, skip: 1, },
+ { opcode: 0xF30F2C, e: 1, skip: 1, },
+ { opcode: 0x660F2C, e: 1, skip: 1, },
+
+ { opcode: 0x0F54, e: 1 },
+ { opcode: 0x660F54, e: 1 },
+ { opcode: 0x0F57, e: 1 },
+ { opcode: 0x660F57, e: 1 },
+
+ { opcode: 0x660F60, e: 1 },
+ { opcode: 0x0F60, e: 1 },
+ { opcode: 0x660F61, e: 1 },
+ { opcode: 0x0F61, e: 1 },
+ { opcode: 0x660F62, e: 1, skip: 1, },
+ { opcode: 0x0F62, e: 1 },
+ { opcode: 0x660F63, e: 1, skip: 1, },
+ { opcode: 0x0F63, e: 1 },
+ { opcode: 0x660F64, e: 1, skip: 1, },
+ { opcode: 0x0F64, e: 1 },
+ { opcode: 0x660F65, e: 1, skip: 1, },
+ { opcode: 0x0F65, e: 1 },
+ { opcode: 0x660F66, e: 1, skip: 1, },
+ { opcode: 0x0F66, e: 1 },
+ { opcode: 0x660F67, e: 1 },
+ { opcode: 0x0F67, e: 1 },
+
+ { opcode: 0x660F68, e: 1 },
+ { opcode: 0x0F68, e: 1 },
+ { opcode: 0x660F69, e: 1, skip: 1, },
+ { opcode: 0x0F69, e: 1 },
+ { opcode: 0x660F6A, e: 1, skip: 1, },
+ { opcode: 0x0F6A, e: 1 },
+ { opcode: 0x660F6B, e: 1, skip: 1, },
+ { opcode: 0x0F6B, e: 1 },
+ { opcode: 0x660F6C, e: 1, skip: 1, },
+ { opcode: 0x660F6D, e: 1, skip: 1, },
+ { opcode: 0x660F6E, e: 1 },
+ { opcode: 0x0F6E, e: 1 },
+ { opcode: 0xF30F6F, e: 1 },
+ { opcode: 0x660F6F, e: 1 },
+ { opcode: 0x0F6F, e: 1 },
+
+ { opcode: 0x0F70, e: 1, imm8: 1, },
+ { opcode: 0x660F70, e: 1, imm8: 1, },
+ { opcode: 0xF20F70, e: 1, imm8: 1, },
+ { opcode: 0xF30F70, e: 1, imm8: 1, },
+
+ { opcode: 0x0F71, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
+ { opcode: 0x660F71, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, skip: 1, },
+ { opcode: 0x0F71, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, },
+ { opcode: 0x660F71, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, skip: 1, },
+ { opcode: 0x0F71, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
+ { opcode: 0x660F71, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, skip: 1, },
+
+ { opcode: 0x0F72, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
+ { opcode: 0x660F72, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, skip: 1, },
+ { opcode: 0x0F72, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, },
+ { opcode: 0x660F72, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, skip: 1, },
+ { opcode: 0x0F72, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
+ { opcode: 0x660F72, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, skip: 1, },
+
+ { opcode: 0x0F73, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
+ { opcode: 0x660F73, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
+ { opcode: 0x660F73, e: 1, fixed_g: 3, imm8: 1, only_reg: 1, skip: 1, },
+ { opcode: 0x0F73, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
+ { opcode: 0x660F73, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, skip: 1, },
+ { opcode: 0x660F73, e: 1, fixed_g: 7, imm8: 1, only_reg: 1, skip: 1, },
+
+ { opcode: 0x0F74, e: 1, },
+ { opcode: 0x660F74, e: 1, },
+ { opcode: 0x0F75, e: 1, },
+ { opcode: 0x660F75, e: 1, },
+ { opcode: 0x0F76, e: 1, },
+ { opcode: 0x660F76, e: 1, },
+ { opcode: 0x0F77 },
+
+ { opcode: 0x0F7E, e: 1 },
+ { opcode: 0x660F7E, e: 1 },
+ { opcode: 0xF30F7E, e: 1 },
+ { opcode: 0x0F7F, e: 1 },
+ { opcode: 0x660F7F, e: 1 },
+ { opcode: 0xF30F7F, e: 1 },
+
+ { opcode: 0x0FC3, e: 1, only_mem: 1, },
+
+ { opcode: 0x0FC5, e: 1, only_reg: 1, imm8: 1, skip: 1, },
+ { opcode: 0x660FC5, e: 1, only_reg: 1, imm8: 1, },
+
+ { opcode: 0x0FD1, e: 1 },
+ { opcode: 0x660FD1, e: 1, skip: 1, },
+ { opcode: 0x0FD2, e: 1 },
+ { opcode: 0x660FD2, e: 1, skip: 1, },
+ { opcode: 0x0FD3, e: 1 },
+ { opcode: 0x660FD3, e: 1 },
+ { opcode: 0x0FD4, e: 1, skip: 1, },
+ { opcode: 0x660FD4, e: 1, skip: 1, },
+ { opcode: 0x0FD5, e: 1 },
+ { opcode: 0x660FD5, e: 1 },
+
+ { opcode: 0x660FD6, e: 1 },
+ { opcode: 0xF20FD6, e: 1, skip: 1, },
+ { opcode: 0xF30FD6, e: 1, skip: 1, },
+ { opcode: 0x0FD7, e: 1, only_reg: 1, skip: 1, },
+ { opcode: 0x660FD7, e: 1, only_reg: 1, },
+
+ { opcode: 0x0FD8, e: 1 },
+ { opcode: 0x660FD8, e: 1, skip: 1, },
+ { opcode: 0x0FD9, e: 1 },
+ { opcode: 0x660FD9, e: 1, skip: 1, },
+ { opcode: 0x0FDA, e: 1, skip: 1, },
+ { opcode: 0x660FDA, e: 1 },
+ { opcode: 0x0FDB, e: 1 },
+ { opcode: 0x660FDB, e: 1, skip: 1, },
+ { opcode: 0x0FDC, e: 1 },
+ { opcode: 0x660FDC, e: 1 },
+ { opcode: 0x0FDD, e: 1 },
+ { opcode: 0x660FDD, e: 1 },
+ { opcode: 0x0FDE, e: 1, skip: 1, },
+ { opcode: 0x660FDE, e: 1 },
+ { opcode: 0x0FDF, e: 1 },
+ { opcode: 0x660FDF, e: 1, skip: 1, },
+
+ { opcode: 0x0FE0, e: 1, skip: 1, },
+ { opcode: 0x660FE0, e: 1, skip: 1, },
+ { opcode: 0x0FE1, e: 1 },
+ { opcode: 0x660FE1, e: 1, skip: 1, },
+ { opcode: 0x0FE2, e: 1 },
+ { opcode: 0x660FE2, e: 1, skip: 1, },
+ { opcode: 0x0FE3, e: 1, skip: 1, },
+ { opcode: 0x660FE3, e: 1, skip: 1, },
+ { opcode: 0x0FE4, e: 1, skip: 1, },
+ { opcode: 0x660FE4, e: 1 },
+ { opcode: 0x0FE5, e: 1 },
+ { opcode: 0x660FE5, e: 1, skip: 1, },
+
+ { opcode: 0x660FE6, e: 1, skip: 1, },
+ { opcode: 0xF20FE6, e: 1, skip: 1, },
+ { opcode: 0xF30FE6, e: 1, skip: 1, },
+ { opcode: 0x0FE7, e: 1, only_mem: 1, skip: 1, },
+ { opcode: 0x660FE7, e: 1, only_mem: 1, },
+
+ { opcode: 0x0FE8, e: 1 },
+ { opcode: 0x660FE8, e: 1, skip: 1, },
+ { opcode: 0x0FE9, e: 1 },
+ { opcode: 0x660FE9, e: 1, skip: 1, },
+ { opcode: 0x0FEA, e: 1, skip: 1, },
+ { opcode: 0x660FEA, e: 1, skip: 1, },
+ { opcode: 0x0FEB, e: 1 },
+ { opcode: 0x660FEB, e: 1 },
+ { opcode: 0x0FEC, e: 1 },
+ { opcode: 0x660FEC, e: 1, skip: 1, },
+ { opcode: 0x0FED, e: 1 },
+ { opcode: 0x660FED, e: 1, skip: 1, },
+ { opcode: 0x0FEE, e: 1, skip: 1, },
+ { opcode: 0x660FEE, e: 1, skip: 1, },
+ { opcode: 0x0FEF, e: 1 },
+ { opcode: 0x660FEF, e: 1 },
+
+ { opcode: 0x0FF1, e: 1 },
+ { opcode: 0x660FF1, e: 1, skip: 1, },
+ { opcode: 0x0FF2, e: 1 },
+ { opcode: 0x660FF2, e: 1, skip: 1, },
+ { opcode: 0x0FF3, e: 1 },
+ { opcode: 0x660FF3, e: 1, },
+ { opcode: 0x0FF4, e: 1, skip: 1, },
+ { opcode: 0x660FF4, e: 1, skip: 1, },
+ { opcode: 0x0FF5, e: 1 },
+ { opcode: 0x660FF5, e: 1, skip: 1, },
+ { opcode: 0x0FF6, e: 1, skip: 1, },
+ { opcode: 0x660FF6, e: 1, skip: 1, },
+ { opcode: 0x0FF7, e: 1, skip: 1, },
+ { opcode: 0x660FF7, e: 1, skip: 1, },
+
+ { opcode: 0x0FF8, e: 1 },
+ { opcode: 0x660FF8, e: 1, skip: 1, },
+ { opcode: 0x0FF9, e: 1 },
+ { opcode: 0x660FF9, e: 1, skip: 1, },
+ { opcode: 0x0FFA, e: 1 },
+ { opcode: 0x660FFA, e: 1 },
+ { opcode: 0x0FFB, e: 1, skip: 1, },
+ { opcode: 0x660FFB, e: 1, skip: 1, },
+ { opcode: 0x0FFC, e: 1 },
+ { opcode: 0x660FFC, e: 1, skip: 1, },
+ { opcode: 0x0FFD, e: 1 },
+ { opcode: 0x660FFD, e: 1, skip: 1, },
+ { opcode: 0x0FFE, e: 1 },
+ { opcode: 0x660FFE, e: 1, skip: 1, },
+];
+
+for(let i = 0; i < 8; i++)
+{
+ encodings.push.apply(encodings, [
+ { opcode: 0x00 | i << 3, e: 1, },
+ { opcode: 0x01 | i << 3, os: 1, e: 1, },
+ { opcode: 0x02 | i << 3, e: 1, },
+ { opcode: 0x03 | i << 3, os: 1, e: 1, },
+ { opcode: 0x04 | i << 3, eax: 1, imm8: 1, },
+ { opcode: 0x05 | i << 3, os: 1, eax: 1, imm1632: 1, },
+
+ { opcode: 0x70 | i, imm8s: 1, skip: 1, },
+ { opcode: 0x78 | i, imm8s: 1, skip: 1, },
+
+ { opcode: 0x80, e: 1, fixed_g: i, imm8: 1, },
+ { opcode: 0x81, os: 1, e: 1, fixed_g: i, imm1632: 1, },
+ { opcode: 0x82, e: 1, fixed_g: i, imm8: 1, },
+ { opcode: 0x83, os: 1, e: 1, fixed_g: i, imm8s: 1, },
+
+ { opcode: 0xB0 | i, imm8: 1, },
+ { opcode: 0xB8 | i, os: 1, imm1632: 1, },
+
+ // note: overflow flag only undefined if shift is > 1
+ // note: the adjust flag is undefined for shifts > 0 and unaffected by rotates
+ { opcode: 0xC0, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, },
+ { opcode: 0xC1, os: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, },
+ { opcode: 0xD0, e: 1, fixed_g: i, mask_flags: af, },
+ { opcode: 0xD1, os: 1, e: 1, fixed_g: i, mask_flags: af, },
+ { opcode: 0xD2, e: 1, fixed_g: i, mask_flags: of | af, },
+ { opcode: 0xD3, os: 1, e: 1, fixed_g: i, mask_flags: of | af, },
+ ]);
+}
+
+encodings.sort((e1, e2) => {
+ let o1 = (e1.opcode & 0xFF00) === 0x0F00 ? e1.opcode & 0xFFFF : e1.opcode & 0xFF;
+ let o2 = (e2.opcode & 0xFF00) === 0x0F00 ? e2.opcode & 0xFFFF : e2.opcode & 0xFF;
+ return o1 - o2 || e1.fixed_g - e2.fixed_g;
+});
+
+module.exports = Object.freeze(encodings);
diff --git a/index.html b/index.html
index cc815caa..c683d2e7 100644
--- a/index.html
+++ b/index.html
@@ -156,11 +156,12 @@
-
-
Running:
0s
Speed:
0kIPS
diff --git a/loader.js b/loader.js
index 9f474a72..7b850bd1 100644
--- a/loader.js
+++ b/loader.js
@@ -5,7 +5,7 @@
"use strict";
var CORE_FILES =
- "const.js config.js log.js cpu.js debug.js translate.js modrm.js string.js arith.js misc_instr.js instructions.js " +
+ "const.js config.js log.js cpu.js debug.js translate.js modrm.js string.js arith.js misc_instr.js instructions.js codegen.js " +
"io.js main.js lib.js ide.js fpu.js pci.js floppy.js " +
"memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js acpi.js apic.js ioapic.js hpet.js " +
"ne2k.js state.js virtio.js bus.js elf.js";
diff --git a/src/browser/lib.js b/src/browser/lib.js
index 6a368a73..6ec5f7d3 100644
--- a/src/browser/lib.js
+++ b/src/browser/lib.js
@@ -58,6 +58,50 @@ var ASYNC_SAFE = false;
});
};
+ v86util.add_download_button = function(data, filename)
+ {
+ let b = document.createElement("button");
+ b.textContent = "download";
+ document.body.appendChild(b);
+ b.onclick = function()
+ {
+ dump_file(data, filename);
+ };
+ };
+
+ function dump_file(ab, name)
+ {
+ if(!(ab instanceof Array))
+ {
+ ab = [ab];
+ }
+
+ var blob = new Blob(ab);
+ download(blob, name);
+ }
+
+ function download(file_or_blob, name)
+ {
+ var a = document.createElement("a");
+ a["download"] = name;
+ a.href = window.URL.createObjectURL(file_or_blob);
+ a.dataset["downloadurl"] = ["application/octet-stream", a["download"], a.href].join(":");
+
+ if(document.createEvent)
+ {
+ var ev = document.createEvent("MouseEvent");
+ ev.initMouseEvent("click", true, true, window,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ a.dispatchEvent(ev);
+ }
+ else
+ {
+ a.click();
+ }
+
+ window.URL.revokeObjectURL(a.href);
+ }
+
/**
* @param {string} filename
* @param {Object} options
diff --git a/src/browser/main.js b/src/browser/main.js
index 17ed37da..3c336e11 100644
--- a/src/browser/main.js
+++ b/src/browser/main.js
@@ -787,8 +787,6 @@
$("runtime_infos").style.display = "block";
$("screen_container").style.display = "block";
- document.getElementsByClassName("phone_keyboard")[0].style.display = "block";
-
if(settings.filesystem)
{
init_filesystem_panel(emulator);
@@ -1197,6 +1195,19 @@
}
};
+ const phone_keyboard = document.getElementsByClassName("phone_keyboard")[0];
+
+ phone_keyboard.setAttribute("autocorrect", "off");
+ phone_keyboard.setAttribute("autocapitalize", "off");
+ phone_keyboard.setAttribute("spellcheck", "false");
+ phone_keyboard.tabIndex = 0;
+
+ $("screen_container").addEventListener("mousedown", (e) =>
+ {
+ e.preventDefault();
+ phone_keyboard.focus();
+ }, false);
+
$("take_screenshot").onclick = function()
{
emulator.screen_make_screenshot();
diff --git a/src/browser/screen.js b/src/browser/screen.js
index d62a42b2..4ef27a44 100644
--- a/src/browser/screen.js
+++ b/src/browser/screen.js
@@ -22,7 +22,7 @@ function ScreenAdapter(screen_container, bus)
graphic_screen = screen_container.getElementsByTagName("canvas")[0],
graphic_context = graphic_screen.getContext("2d"),
- text_screen = graphic_screen.nextElementSibling || graphic_screen.previousElementSibling,
+ text_screen = screen_container.getElementsByTagName("div")[0],
cursor_element = document.createElement("div");
var
diff --git a/src/browser/starter.js b/src/browser/starter.js
index 777c57be..8bb2fdd7 100644
--- a/src/browser/starter.js
+++ b/src/browser/starter.js
@@ -97,18 +97,28 @@ function V86Starter(options)
var mem;
var mem8;
var wasm_shared_funcs = {
- "_throw_cpu_exception": () => { throw MAGIC_CPU_EXCEPTION; },
+ "_throw_cpu_exception": () => {
+ throw MAGIC_CPU_EXCEPTION;
+ },
+ "_cpu_exception_hook": (n) => {
+ return this["cpu_exception_hook"] && this["cpu_exception_hook"](n);
+ },
"_hlt_op": function() { return cpu.hlt_op(); },
"abort": function() { dbg_assert(false); },
"_dbg_assert": function() { return cpu.dbg_assert.apply(cpu, arguments); },
"_dbg_log": function() { return cpu.dbg_log.apply(cpu, arguments); },
+ "_dbg_trace": function() { return dbg_trace(); },
+ "_logop": function(eip, op) { return cpu.debug.logop(eip, op); },
"_todo": function() { return cpu.todo.apply(cpu, arguments); },
"_undefined_instruction": function() { return cpu.undefined_instruction.apply(cpu, arguments); },
- "_unimplemented_sse": function() { return cpu.unimplemented_sse_wasm(); },
+ "_unimplemented_sse": function() { return cpu.unimplemented_sse(); },
"_microtick": function() { return v86.microtick(); },
"_get_rand_int": function() { return v86util.get_rand_int(); },
"_has_rand_int": function() { return v86util.has_rand_int(); },
- "_printf": function(offset) { dbg_log_wasm(mem, offset, [].slice.call(arguments, 1)); },
+ "_printf": function(format_string_offset, stack_top) {
+ dbg_assert(arguments.length === 2);
+ dbg_log_wasm(mem, format_string_offset, stack_top);
+ },
"_memcpy_large": function(dest, source, length) {
mem8.set(mem8.subarray(source, source + length), dest);
return dest;
@@ -122,6 +132,11 @@ function V86Starter(options)
"_switch_seg": function(reg, selector) { cpu.switch_seg(reg, selector); },
"_iret16": function() { return cpu.iret16(); },
"_iret32": function() { return cpu.iret32(); },
+ "_handle_irqs": function() { return cpu.handle_irqs(); },
+
+ //XXX: These are temporary for as long as we are testing the JIT
+ "_resolve_modrm16": function(modrm_byte) { return cpu.resolve_modrm16(modrm_byte); },
+ "_resolve_modrm32": function(modrm_byte) { return cpu.resolve_modrm32(modrm_byte); },
"_io_port_read8": function(addr) { return cpu.io.port_read8(addr); },
"_io_port_read16": function(addr) { return cpu.io.port_read16(addr); },
@@ -160,22 +175,12 @@ function V86Starter(options)
"_math_pow": function(x, y) { return Math.pow(x, y); },
"_do_page_translation": function() { return cpu.do_page_translation.apply(cpu, arguments); },
- "_read_reg_e16": function() { return cpu.read_reg_e16.apply(cpu, arguments); },
- "_read_reg_e32s": function() { return cpu.read_reg_e32s.apply(cpu, arguments); },
- "_write_reg_e16": function() { return cpu.write_reg_e16.apply(cpu, arguments); },
- "_write_reg_e32": function() { return cpu.write_reg_e32.apply(cpu, arguments); },
"_popa16": function() { return cpu.popa16.apply(cpu, arguments); },
"_popa32": function() { return cpu.popa32.apply(cpu, arguments); },
"_arpl": function() { return cpu.arpl.apply(cpu, arguments); },
- "_trigger_ud": function() { return cpu.trigger_ud.apply(cpu, arguments); },
- "_trigger_nm": function() { return cpu.trigger_nm.apply(cpu, arguments); },
- "_virt_boundary_read16": function() { return cpu.virt_boundary_read16.apply(cpu, arguments); },
- "_virt_boundary_read32s": function() { return cpu.virt_boundary_read32s.apply(cpu, arguments); },
- "_virt_boundary_write16": function() { return cpu.virt_boundary_write16.apply(cpu, arguments); },
- "_virt_boundary_write32": function() { return cpu.virt_boundary_write32.apply(cpu, arguments); },
"_getiopl": function() { return cpu.getiopl.apply(cpu, arguments); },
"_vm86_mode": function() { return cpu.vm86_mode.apply(cpu, arguments); },
-
+
"_bswap": function() { return cpu.bswap.apply(cpu, arguments); },
"_lar": function() { return cpu.lar.apply(cpu, arguments); },
@@ -200,12 +205,6 @@ function V86Starter(options)
"_enter16": function() { return cpu.enter16.apply(cpu, arguments); },
"_enter32": function() { return cpu.enter32.apply(cpu, arguments); },
"_update_eflags": function() { return cpu.update_eflags.apply(cpu, arguments); },
- "_handle_irqs": function() { return cpu.handle_irqs.apply(cpu, arguments); },
- "_xchg8": function() { return cpu.xchg8.apply(cpu, arguments); },
- "_xchg16": function() { return cpu.xchg16.apply(cpu, arguments); },
- "_xchg16r": function() { return cpu.xchg16r.apply(cpu, arguments); },
- "_xchg32": function() { return cpu.xchg32.apply(cpu, arguments); },
- "_xchg32r": function() { return cpu.xchg32r.apply(cpu, arguments); },
"_loop": function() { return cpu.loop.apply(cpu, arguments); },
"_loope": function() { return cpu.loope.apply(cpu, arguments); },
"_loopne": function() { return cpu.loopne.apply(cpu, arguments); },
@@ -214,6 +213,20 @@ function V86Starter(options)
"_jcxz": function() { return cpu.jcxz.apply(cpu, arguments); },
"_test_privileges_for_io": function() { return cpu.test_privileges_for_io.apply(cpu, arguments); },
+ "_convert_f64_to_i32": function(f) {
+ // implemented here due to emscripten bug
+ if(!(f <= 0x7FFFFFFF && f >= -0x80000000))
+ {
+ f = 0x80000000 | 0;
+ }
+
+ return f | 0;
+ },
+ "_get_time": () => Date.now(),
+ // XXX: Closure compiler hack; these functions are actually wasm exports
+ "_jit_empty_cache": () => {},
+ "_jit_dirty_cache": () => {},
+ "_after_jump": () => {},
};
let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm";
@@ -229,7 +242,7 @@ function V86Starter(options)
v86util.load_wasm(wasm_file, { 'env': wasm_shared_funcs }, wm => {
wm.instance.exports["__post_instantiate"]();
- emulator = this.v86 = new v86(this.emulator_bus, wm);
+ emulator = this.v86 = new v86(this.emulator_bus, wm, new Codegen(wm));
cpu = emulator.cpu;
mem = wm.mem.buffer;
mem8 = new Uint8Array(mem);
@@ -255,6 +268,7 @@ function V86Starter(options)
};
settings.load_devices = true;
+ settings.log_level = options["log_level"];
settings.memory_size = options["memory_size"] || 64 * 1024 * 1024;
settings.vga_memory_size = options["vga_memory_size"] || 8 * 1024 * 1024;
settings.boot_order = options["boot_order"] || 0x213;
diff --git a/src/codegen.js b/src/codegen.js
new file mode 100644
index 00000000..1a3b0900
--- /dev/null
+++ b/src/codegen.js
@@ -0,0 +1,91 @@
+/** @constructor */
+function Codegen(wm)
+{
+ this.wm = wm;
+ this.wm.funcs['_gen_init']();
+}
+
+Codegen.prototype.reset = function()
+{
+ this.wm.funcs['_gen_reset']();
+}
+
+Codegen.OUTPUT_OFFSET = 2048 + 0x100000 * 6;
+Codegen.STR_INPUT_OFFSET = Codegen.OUTPUT_OFFSET + 1024 - 32;
+
+Codegen.prototype.str_input = function(str)
+{
+ if (str.length > 32) {
+ throw new Error('Max string length for crossing boundary is 32');
+ }
+ const view = new Uint8Array(this.wm.mem.buffer, Codegen.STR_INPUT_OFFSET, 32);
+ for (let i = 0; i < str.length; i++)
+ {
+ view[i] = str.charCodeAt(i);
+ }
+};
+
+Codegen.prototype.fn0 = function(fn)
+{
+ this.str_input(fn);
+ this.wm.funcs['_gen_fn0'](Codegen.STR_INPUT_OFFSET, fn.length);
+};
+
+Codegen.prototype.fn1 = function(fn, arg0)
+{
+ this.str_input(fn);
+ this.wm.funcs['_gen_fn1'](Codegen.STR_INPUT_OFFSET, fn.length, arg0);
+};
+
+Codegen.prototype.fn2 = function(fn, arg0, arg1)
+{
+ this.str_input(fn);
+ this.wm.funcs['_gen_fn2'](Codegen.STR_INPUT_OFFSET, fn.length, arg0, arg1);
+};
+
+Codegen.prototype.modrm_fn0 = function(fn, modrm_byte, arg)
+{
+ this.str_input(fn);
+ this.wm.funcs['_gen_modrm_fn0'](Codegen.STR_INPUT_OFFSET, fn.length, modrm_byte, arg);
+};
+
+Codegen.prototype.modrm_fn1 = function(fn, modrm_byte)
+{
+ this.str_input(fn);
+ this.wm.funcs['_gen_modrm_fn1'](Codegen.STR_INPUT_OFFSET, fn.length, modrm_byte);
+};
+
+Codegen.prototype.jit_resolve_modrm16 = function(modrm_byte)
+{
+ this.wm.funcs['_gen_resolve_modrm16'](modrm_byte);
+};
+
+Codegen.prototype.jit_resolve_modrm32 = function(modrm_byte)
+{
+ this.wm.funcs['_gen_resolve_modrm32'](modrm_byte);
+};
+
+Codegen.prototype.increment_instruction_pointer = function(n)
+{
+ this.wm.funcs['_gen_increment_instruction_pointer'](n);
+};
+
+Codegen.prototype.set_previous_eip = function()
+{
+ this.wm.funcs['_gen_set_previous_eip']();
+};
+
+Codegen.prototype.finish = function()
+{
+ return this.wm.funcs['_gen_finish']();
+};
+
+Codegen.prototype.get_module_code = function()
+{
+ const final_offset = this.wm.funcs['_gen_get_final_offset']();
+
+ // extract wasm module
+ const output_buffer_view = new Uint8Array(this.wm.mem.buffer, Codegen.OUTPUT_OFFSET, final_offset - Codegen.OUTPUT_OFFSET);
+ return output_buffer_view;
+};
+
diff --git a/src/const.js b/src/const.js
index 5d3f5642..e2693491 100644
--- a/src/const.js
+++ b/src/const.js
@@ -349,3 +349,8 @@ var PREFIX_66 = PREFIX_MASK_OPSIZE; // alias
/** @const */
var MXCSR_MASK = (0xFFFF & ~(1 << 6));
+
+/** @const */
+const P_IDLE = 0;
+/** @const */
+const P_DO_MANY_CYCLES = 2;
diff --git a/src/cpu.js b/src/cpu.js
index 351e3ead..e97a8c41 100644
--- a/src/cpu.js
+++ b/src/cpu.js
@@ -11,9 +11,10 @@ var CPU_LOG_VERBOSE = false;
/** @constructor */
-function CPU(bus, wm)
+function CPU(bus, wm, codegen)
{
this.wm = wm;
+ this.codegen = codegen;
this.wasm_patch(wm);
this.memory_size = new Uint32Array(wm.mem.buffer, 812, 1);
@@ -182,7 +183,7 @@ function CPU(bus, wm)
vga: null,
};
- this.timestamp_counter = new Int32Array(wm.mem.buffer, 664, 1);
+ this.timestamp_counter = new Uint32Array(wm.mem.buffer, 664, 1);
// registers
this.reg32s = new Int32Array(wm.mem.buffer, 4, 8);
@@ -198,6 +199,9 @@ function CPU(bus, wm)
this.reg_mmx8s = new Int8Array(this.reg_mmxs.buffer, 1064, 64);
this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer, 1064, 64);
+ this.cache_hit = new Uint32Array(wm.mem.buffer, 1280, 1);
+ this.cache_compile = new Uint32Array(wm.mem.buffer, 1284, 1);
+
this.reg_xmm32s = new Int32Array(wm.mem.buffer, 828, 8 * 4);
this.mxcsr = new Int32Array(wm.mem.buffer, 824, 1);
@@ -373,6 +377,88 @@ CPU.prototype.wasm_patch = function(wm)
this.fxrstor = this.wm.funcs['_fxrstor'];
};
+//*
+CPU.prototype.resolve_modrm16 = function(modrm_byte)
+{
+ dbg_log("resolve_modrm16, modrm_byte=" + h(modrm_byte));
+
+ let buf;
+ const RESULT_LOC = 1600;
+
+ try {
+ const gen = this.codegen;
+ gen.reset();
+ gen.jit_resolve_modrm16(modrm_byte);
+ gen.finish();
+ buf = gen.get_module_code();
+
+ //XXX: move the following logic to a separate function
+ const module = new WebAssembly.Module(buf);
+ const imports = { "e": {
+ "get_seg": v => this.get_seg(v),
+ "get_reg": v => v, //XXX: no get_reg on CPU :|
+ "get_seg_prefix_ds": v => this.get_seg_prefix_ds(v),
+ "get_seg_prefix_ss": v => this.get_seg_prefix_ss(v),
+ "get_seg_prefix": v => this.get_seg_prefix(v),
+ "m": this.wm.mem,
+ } };
+ const o = new WebAssembly.Instance(module, imports);
+ o.exports["f"]();
+ const view = new Int32Array(this.wm.mem.buffer, RESULT_LOC, 4);
+ return view[0];
+ }
+ catch(err)
+ {
+ if (typeof buf !== "undefined")
+ {
+ v86util.add_download_button(buf, "myjit.wasm");
+ }
+ throw err;
+ }
+};
+//*/
+
+//*
+CPU.prototype.resolve_modrm32 = function(modrm_byte)
+{
+ dbg_log("resolve_modrm32, modrm_byte=" + h(modrm_byte));
+
+ let buf;
+ const RESULT_LOC = 1600;
+
+ try {
+ const gen = this.codegen;
+ gen.reset();
+ gen.jit_resolve_modrm32(modrm_byte);
+ gen.finish();
+ buf = gen.get_module_code();
+
+ //XXX: move the following logic to a separate function
+ const module = new WebAssembly.Module(buf);
+ const imports = { "e": {
+ "get_seg": v => this.get_seg(v),
+ "get_reg": v => v, //XXX: no get_reg on CPU :|
+ "get_seg_prefix_ds": v => this.get_seg_prefix_ds(v),
+ "get_seg_prefix_ss": v => this.get_seg_prefix_ss(v),
+ "get_seg_prefix": v => this.get_seg_prefix(v),
+ "m": this.wm.mem,
+ } };
+ const o = new WebAssembly.Instance(module, imports);
+ o.exports["f"]();
+ const view = new Int32Array(this.wm.mem.buffer, RESULT_LOC, 4);
+ return view[0];
+ }
+ catch(err)
+ {
+ if (typeof buf !== "undefined")
+ {
+ v86util.add_download_button(buf, "myjit.wasm");
+ }
+ throw err;
+ }
+};
+//*/
+
CPU.prototype.get_state = function()
{
var state = [];
@@ -701,9 +787,9 @@ CPU.prototype.create_memory = function(size)
var buffer = this.wm.mem.buffer;
- this.mem8 = new Uint8Array(buffer, 2048 + 0x100000 * 6, size);
- this.mem16 = new Uint16Array(buffer, 2048 + 0x100000 * 6, size >> 1);
- this.mem32s = new Int32Array(buffer, 2048 + 0x100000 * 6, size >> 2);
+ this.mem8 = new Uint8Array(buffer, 2048 + 0x100000 * 6 + 2048, size);
+ this.mem16 = new Uint16Array(buffer, 2048 + 0x100000 * 6 + 2048, size >> 1);
+ this.mem32s = new Int32Array(buffer, 2048 + 0x100000 * 6 + 2048, size >> 2);
};
CPU.prototype.init = function(settings, device_bus)
@@ -713,6 +799,12 @@ CPU.prototype.init = function(settings, device_bus)
this.reset();
+ if(typeof settings.log_level === "number")
+ {
+ // XXX: Shared between all emulator instances
+ LOG_LEVEL = settings.log_level;
+ }
+
var io = new IO(this);
this.io = io;
@@ -857,6 +949,8 @@ CPU.prototype.init = function(settings, device_bus)
{
this.debug.init();
}
+
+ this.wm.funcs["_profiler_init"]();
};
CPU.prototype.load_multiboot = function(buffer)
@@ -1161,6 +1255,9 @@ CPU.prototype.load_bios = function()
CPU.prototype.do_run = function()
{
+ // Idle time is when no instructions are being executed
+ this.wm.funcs["_profiler_end"](P_IDLE);
+
/** @type {number} */
var start = v86.microtick();
@@ -1183,10 +1280,15 @@ CPU.prototype.do_run = function()
now = v86.microtick();
}
+
+ this.wm.funcs["_profiler_start"](P_IDLE);
};
CPU.prototype.do_many_cycles = function()
{
+ // Capture the total time we were executing instructions
+ this.wm.funcs["_profiler_start"](P_DO_MANY_CYCLES);
+
try {
this.do_many_cycles_unsafe();
}
@@ -1194,6 +1296,8 @@ CPU.prototype.do_many_cycles = function()
{
this.exception_cleanup(e);
}
+
+ this.wm.funcs["_profiler_end"](P_DO_MANY_CYCLES);
};
CPU.prototype.do_many_cycles_unsafe = function()
@@ -1419,12 +1523,15 @@ CPU.prototype.set_cr0 = function(cr0)
}
this.protected_mode[0] = +((this.cr[0] & CR0_PE) === CR0_PE);
+
+ this.wm.funcs._jit_empty_cache();
};
CPU.prototype.set_cr4 = function(cr4)
{
if(cr4 & (1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19 | 0xFFC00000))
{
+ dbg_log("trigger_gp: Invalid cr4 bit", LOG_CPU);
this.trigger_gp(0);
}
@@ -1553,9 +1660,20 @@ CPU.prototype.read_disp16 = CPU.prototype.read_imm16;
CPU.prototype.read_disp32s = CPU.prototype.read_imm32s;
CPU.prototype.init2 = function () {};
-CPU.prototype.branch_taken = function () {};
-CPU.prototype.branch_not_taken = function () {};
-CPU.prototype.diverged = function () {};
+
+CPU.prototype.after_jump = function () {
+ // May be called through JS imports in the WASM module, such as loop or handle_irqs (through popf, sti)
+ this.wm.funcs._after_jump();
+};
+CPU.prototype.branch_taken = function () {
+ this.after_jump();
+};
+CPU.prototype.branch_not_taken = function () {
+ this.after_jump();
+};
+CPU.prototype.diverged = function () {
+ this.after_jump();
+};
CPU.prototype.modrm_resolve = function(modrm_byte)
{
@@ -3240,6 +3358,7 @@ CPU.prototype.hlt_op = function()
{
if(this.cpl[0])
{
+ dbg_log("#gp hlt with cpl != 0", LOG_CPU);
this.trigger_gp(0);
}
@@ -3389,13 +3508,6 @@ CPU.prototype.unimplemented_sse = function()
this.trigger_ud();
};
-CPU.prototype.unimplemented_sse_wasm = function()
-{
- this.instruction_pointer[0] -= 1;
-
- this.table0F_32[this.read_op0F()](this);
-};
-
CPU.prototype.get_seg_prefix_ds = function(offset)
{
offset = offset || 0;
@@ -3930,9 +4042,10 @@ CPU.prototype.cpuid = function()
var edx = 0;
var ebx = 0;
- var winnt_fix = false;
+ const winnt_fix = false;
+ const level = this.reg32s[reg_eax];
- switch(this.reg32s[reg_eax])
+ switch(level)
{
case 0:
// maximum supported level
@@ -4029,7 +4142,14 @@ CPU.prototype.cpuid = function()
dbg_log("cpuid: unimplemented eax: " + h(this.reg32[reg_eax]), LOG_CPU);
}
- dbg_log("cpuid: eax=" + h(this.reg32[reg_eax], 8) + " cl=" + h(this.reg8[reg_cl], 2), LOG_CPU);
+ if(level === 4)
+ {
+ dbg_log("cpuid: eax=" + h(this.reg32[reg_eax], 8) + " cl=" + h(this.reg8[reg_cl], 2), LOG_CPU);
+ }
+ else
+ {
+ dbg_log("cpuid: eax=" + h(this.reg32[reg_eax], 8), LOG_CPU);
+ }
this.reg32s[reg_eax] = eax;
this.reg32s[reg_ecx] = ecx;
@@ -4403,6 +4523,12 @@ CPU.prototype.lar = function(selector, original)
{
dbg_log("lar sel=" + h(selector, 4), LOG_CPU);
+ if(!this.protected_mode[0] || this.vm86_mode())
+ {
+ dbg_log("lar #ud");
+ this.trigger_ud();
+ }
+
/** @const */
var LAR_INVALID_TYPE = 1 << 0 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 0xA |
1 << 0xD | 1 << 0xE | 1 << 0xF;
@@ -4431,6 +4557,12 @@ CPU.prototype.lsl = function(selector, original)
{
dbg_log("lsl sel=" + h(selector, 4), LOG_CPU);
+ if(!this.protected_mode[0] || this.vm86_mode())
+ {
+ dbg_log("lsl #ud");
+ this.trigger_ud();
+ }
+
/** @const */
var LSL_INVALID_TYPE = 1 << 0 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 |
1 << 0xA | 1 << 0xC | 1 << 0xD | 1 << 0xE | 1 << 0xF;
diff --git a/src/debug.js b/src/debug.js
index 21d5cbab..e2c02f49 100644
--- a/src/debug.js
+++ b/src/debug.js
@@ -177,6 +177,8 @@ CPU.prototype.debug_init = function()
return;
}
+ _ip = _ip >>> 0;
+
if(debug.trace_all && debug.all_ops)
{
debug.all_ops.push(_ip, op);
diff --git a/src/elf.js b/src/elf.js
index a303d0fa..d3b2bcdc 100644
--- a/src/elf.js
+++ b/src/elf.js
@@ -106,9 +106,9 @@ function read_elf(buffer)
{
for(let key in header)
{
- console.log(key + ": 0x" + header[key].toString(16));
+ dbg_log(key + ": 0x" + header[key].toString(16));
}
- console.log(header);
+ dbg_log(header);
}
console.assert(header.magic === ELF_MAGIC, "Bad magic");
@@ -137,7 +137,7 @@ function read_elf(buffer)
SectionHeader,
header.shnum);
- if(DEBUG)
+ if(DEBUG && LOG_LEVEL)
{
console.log("%d program headers:", program_headers.length);
for(let program of program_headers)
diff --git a/src/externs.js b/src/externs.js
index cd914398..b055dc45 100644
--- a/src/externs.js
+++ b/src/externs.js
@@ -14,4 +14,4 @@ var exports = {};
var define = {};
var module = {};
-var WebAssembly = { Memory() {}, Table() {}, instantiate() {}, compile() {} };
+var WebAssembly = { Memory() {}, Table() {}, instantiate() {}, compile() {}, Instance() {}, Module() {} };
diff --git a/src/ide.js b/src/ide.js
index 22471a59..d6a6a14f 100644
--- a/src/ide.js
+++ b/src/ide.js
@@ -151,7 +151,7 @@ function IDEDevice(cpu, buffer, is_cd, nr, bus)
{
dbg_log("Read error: " + h(this.current_interface.error & 0xFF) +
" slave=" + (this.current_interface === this.slave), LOG_DISK);
- return this.current_interface.error;
+ return this.current_interface.error & 0xFF;
});
cpu.io.register_read(this.ata_port | 2, this, function()
{
@@ -177,7 +177,7 @@ function IDEDevice(cpu, buffer, is_cd, nr, bus)
cpu.io.register_read(this.ata_port | 6, this, function()
{
dbg_log("Read 1F6", LOG_DISK);
- return this.current_interface.drive_head;
+ return this.current_interface.drive_head & 0xFF;
});
cpu.io.register_write(this.ata_port | 0, this, function(data)
diff --git a/src/log.js b/src/log.js
index 881b095f..951824e0 100644
--- a/src/log.js
+++ b/src/log.js
@@ -87,25 +87,50 @@ var dbg_log = (function()
return dbg_log_;
})();
-function dbg_log_wasm(memory, offset, args)
+function dbg_log_wasm(memory, format_string_offset, stack)
{
- if(!(LOG_LEVEL & LOG_CPU))
+ if(!DEBUG || !(LOG_LEVEL & LOG_CPU))
{
return;
}
- let s = new Uint8Array(memory, offset);
- let length = s.indexOf(0);
+ let s = new Uint8Array(memory, format_string_offset);
+
+ const length = s.indexOf(0);
if(length !== -1)
{
- s = new Uint8Array(memory, offset, length);
+ s = new Uint8Array(memory, format_string_offset, length);
}
- let format_string = "[CPU ] " + String.fromCharCode.apply(String, s);
- let format_args = [format_string];
- format_args.push.apply(format_args, args);
+ function pop_arg()
+ {
+ const arg = new Int32Array(memory, stack, 1)[0];
+ stack += 4;
+ return arg;
+ }
- console.log.apply(console, format_args);
+ let format_string = String.fromCharCode.apply(String, s);
+ format_string = format_string.replace(/%([xd%])/g, function(full_match, identifier)
+ {
+ if(identifier === "x")
+ {
+ return (pop_arg() >>> 0).toString(16);
+ }
+ else if(identifier === "d")
+ {
+ return pop_arg().toString(10);
+ }
+ else if(identifier === "%")
+ {
+ return "%";
+ }
+ else
+ {
+ console.assert(false);
+ }
+ });
+
+ dbg_log(format_string, LOG_CPU);
}
/**
diff --git a/src/main.js b/src/main.js
index b8efd8cb..f4c1de0d 100644
--- a/src/main.js
+++ b/src/main.js
@@ -3,8 +3,9 @@
/**
* @constructor
* @param {Object=} wm
+ * @param {Object=} codegen
*/
-function v86(bus, wm)
+function v86(bus, wm, codegen)
{
/** @type {boolean} */
this.running = false;
@@ -13,7 +14,7 @@ function v86(bus, wm)
this.stopped = false;
/** @type {CPU} */
- this.cpu = new CPU(bus, wm);
+ this.cpu = new CPU(bus, wm, codegen);
this.bus = bus;
bus.register("cpu-init", this.init, this);
diff --git a/src/memory.js b/src/memory.js
index 3f4ca06d..226ef06a 100644
--- a/src/memory.js
+++ b/src/memory.js
@@ -70,14 +70,14 @@ CPU.prototype.mmap_read32 = function(addr)
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
return this.memory_map_read32[aligned_addr](addr);
-}
+};
CPU.prototype.mmap_write32 = function(addr, value)
{
var aligned_addr = addr >>> MMAP_BLOCK_BITS;
this.memory_map_write32[aligned_addr](addr, value);
-}
+};
CPU.prototype.in_mapped_range = function(addr)
{
@@ -223,12 +223,14 @@ CPU.prototype.write16 = function(addr, value)
CPU.prototype.write_aligned16 = function(addr, value)
{
dbg_assert(addr >= 0 && addr < 0x80000000);
- this.debug_write(addr << 1, 2, value);
+
+ let phys_addr = addr << 1;
+ this.debug_write(phys_addr, 2, value);
if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK16;
- if(this.in_mapped_range(addr << 1))
+ if(this.in_mapped_range(phys_addr))
{
- this.mmap_write16(addr << 1, value);
+ this.mmap_write16(phys_addr, value);
}
else
{
@@ -261,12 +263,14 @@ CPU.prototype.write32 = function(addr, value)
CPU.prototype.write_aligned32 = function(addr, value)
{
dbg_assert(addr >= 0 && addr < 0x40000000);
- this.debug_write(addr << 2, 4, value);
+
+ let phys_addr = addr << 2;
+ this.debug_write(phys_addr, 4, value);
if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK32;
- if(this.in_mapped_range(addr << 2))
+ if(this.in_mapped_range(phys_addr))
{
- this.mmap_write32(addr << 2, value);
+ this.mmap_write32(phys_addr, value);
}
else
{
@@ -280,7 +284,9 @@ CPU.prototype.write_aligned32 = function(addr, value)
*/
CPU.prototype.write_blob = function(blob, offset)
{
- this.debug_write(offset, blob.length, 0)
+ this.debug_write(offset, blob.length, 0);
+ this.wm.funcs._jit_dirty_cache(offset, offset + blob.length);
+
dbg_assert(blob && blob.length >= 0);
this.mem8.set(blob, offset);
@@ -293,6 +299,9 @@ CPU.prototype.write_blob = function(blob, offset)
CPU.prototype.write_blob32 = function(blob, offset)
{
dbg_assert(blob && blob.length);
+ let phys_addr = offset << 2;
+ this.wm.funcs._jit_dirty_cache(phys_addr, phys_addr + blob.length);
+
this.debug_write(offset, blob.length << 2, 0);
this.mem32s.set(blob, offset);
};
diff --git a/src/native/all.c b/src/native/all.c
index 14a70831..896c70fe 100644
--- a/src/native/all.c
+++ b/src/native/all.c
@@ -1,6 +1,5 @@
#include
#include
-#include
#include
extern void call_interrupt_vector(int32_t interrupt_nr, bool is_software_int, bool has_error_code, int32_t error_code);
@@ -11,6 +10,7 @@ extern double_t math_pow(double_t, double_t);
#include "global_pointers.h"
#include "log.c"
#include "cpu.c"
+#include "profiler.c"
#include "memory.c"
#include "modrm.c"
#include "misc_instr.c"
@@ -19,3 +19,7 @@ extern double_t math_pow(double_t, double_t);
#include "instructions.c"
#include "instructions_0f.c"
#include "string.c"
+
+extern void jit_resolve_modrm16(int32_t);
+extern void jit_resolve_modrm32(int32_t);
+
diff --git a/src/native/arith.c b/src/native/arith.c
index 1b066740..2c45339a 100644
--- a/src/native/arith.c
+++ b/src/native/arith.c
@@ -249,51 +249,21 @@ int32_t imul_reg16(int32_t operand1, int32_t operand2)
return result;
}
-void do_mul32(uint32_t a, uint32_t b)
-{
- uint32_t a00 = a & 0xFFFF;
- uint32_t a16 = a >> 16;
- uint32_t b00 = b & 0xFFFF;
- int32_t b16 = b >> 16;
- uint32_t low_result = a00 * b00;
- uint32_t mid = (low_result >> 16) + (a16 * b00);
- uint32_t high_result = mid >> 16;
- mid = (mid & 0xFFFF) + (a00 * b16);
- mul32_result[0] = (mid << 16) | low_result & 0xFFFF;
- mul32_result[1] = ((mid >> 16) + (a16 * b16)) + high_result;
-}
-
-void do_imul32(int32_t a, int32_t b)
-{
- bool is_neg = false;
- if(a < 0) {
- is_neg = true;
- a = -a;
- }
- if(b < 0) {
- is_neg = !is_neg;
- b = -b;
- }
- do_mul32(a, b);
- if(is_neg) {
- mul32_result[0] = -mul32_result[0];
- mul32_result[1] = ~mul32_result[1] + !mul32_result[0];
- }
-}
-
void mul32(int32_t source_operand)
{
int32_t dest_operand = reg32s[EAX];
- do_mul32(dest_operand, source_operand);
+ uint64_t result = (uint64_t)(uint32_t)dest_operand * (uint32_t)source_operand;
+ int32_t result_low = result;
+ int32_t result_high = result >> 32;
- reg32s[EAX] = mul32_result[0];
- reg32s[EDX] = mul32_result[1];
+ reg32s[EAX] = result_low;
+ reg32s[EDX] = result_high;
- *last_result = mul32_result[0];
+ *last_result = result_low;
*last_op_size = OPSIZE_32;
- if(mul32_result[1] == 0)
+ if(result_high == 0)
{
*flags &= ~1 & ~FLAG_OVERFLOW;
}
@@ -307,16 +277,17 @@ void mul32(int32_t source_operand)
void imul32(int32_t source_operand)
{
int32_t dest_operand = reg32s[EAX];
+ int64_t result = (int64_t)dest_operand * (int64_t)source_operand;
+ int32_t result_low = result;
+ int32_t result_high = result >> 32;
- do_imul32(dest_operand, source_operand);
+ reg32s[EAX] = result_low;
+ reg32s[EDX] = result_high;
- reg32s[EAX] = mul32_result[0];
- reg32s[EDX] = mul32_result[1];
-
- *last_result = mul32_result[0];
+ *last_result = result_low;
*last_op_size = OPSIZE_32;
- if(mul32_result[1] == (mul32_result[0] >> 31))
+ if(result_high == (result_low >> 31))
{
*flags &= ~1 & ~FLAG_OVERFLOW;
}
@@ -329,12 +300,14 @@ void imul32(int32_t source_operand)
int32_t imul_reg32(int32_t operand1, int32_t operand2)
{
- do_imul32(operand1, operand2);
+ int64_t result = (int64_t)operand1 * (int64_t)operand2;
+ int32_t result_low = result;
+ int32_t result_high = result >> 32;
- *last_result = mul32_result[0];
+ *last_result = result_low;
*last_op_size = OPSIZE_32;
- if(mul32_result[1] == (mul32_result[0] >> 31))
+ if(result_high == (result_low >> 31))
{
*flags &= ~1 & ~FLAG_OVERFLOW;
}
@@ -344,7 +317,7 @@ int32_t imul_reg32(int32_t operand1, int32_t operand2)
}
*flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW;
- return mul32_result[0];
+ return result_low;
}
int32_t xadd8(int32_t source_operand, int32_t reg)
@@ -1011,7 +984,7 @@ int32_t sar8(int32_t dest_operand, int32_t count)
if(count < 8)
{
- *last_result = dest_operand << 24 >> count + 24;
+ *last_result = dest_operand << 24 >> (count + 24);
// of is zero
*flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (count - 1) & 1);
}
@@ -1036,7 +1009,7 @@ int32_t sar16(int32_t dest_operand, int32_t count)
if(count < 16)
{
- *last_result = dest_operand << 16 >> count + 16;
+ *last_result = dest_operand << 16 >> (count + 16);
*flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (count - 1) & 1);
}
else
@@ -1193,7 +1166,7 @@ int32_t btr_reg(int32_t bit_base, int32_t bit_offset)
void bt_mem(int32_t virt_addr, int32_t bit_offset)
{
- int32_t bit_base = safe_read8(virt_addr + (bit_offset >> 3) | 0);
+ int32_t bit_base = safe_read8(virt_addr + (bit_offset >> 3));
bit_offset &= 7;
*flags = (*flags & ~1) | (bit_base >> bit_offset & 1);
@@ -1202,7 +1175,7 @@ void bt_mem(int32_t virt_addr, int32_t bit_offset)
void btc_mem(int32_t virt_addr, int32_t bit_offset)
{
- int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3) | 0);
+ int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3));
int32_t bit_base = read8(phys_addr);
bit_offset &= 7;
@@ -1215,7 +1188,7 @@ void btc_mem(int32_t virt_addr, int32_t bit_offset)
void btr_mem(int32_t virt_addr, int32_t bit_offset)
{
- int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3) | 0);
+ int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3));
int32_t bit_base = read8(phys_addr);
bit_offset &= 7;
@@ -1228,7 +1201,7 @@ void btr_mem(int32_t virt_addr, int32_t bit_offset)
void bts_mem(int32_t virt_addr, int32_t bit_offset)
{
- int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3) | 0);
+ int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3));
int32_t bit_base = read8(phys_addr);
bit_offset &= 7;
@@ -1277,7 +1250,7 @@ int32_t bsf32(int32_t old, int32_t bit_base)
{
*flags &= ~FLAG_ZERO;
- return *last_result = int_log2(((uint32_t) (-bit_base & bit_base)) >> 0);
+ return *last_result = int_log2(((uint32_t) (-bit_base & bit_base)));
}
}
@@ -1316,7 +1289,7 @@ int32_t bsr32(int32_t old, int32_t bit_base)
else
{
*flags &= ~FLAG_ZERO;
- return *last_result = int_log2(((uint32_t) bit_base) >> 0);
+ return *last_result = int_log2(((uint32_t) bit_base));
}
}
@@ -1343,7 +1316,7 @@ uint32_t saturate_sw_to_ub(uint32_t v)
{
dbg_assert((v & 0xFFFF0000) == 0);
- uint32_t ret = v >> 0;
+ uint32_t ret = v;
if (ret >= 0x8000) {
ret = 0;
}
@@ -1377,7 +1350,7 @@ int32_t saturate_sw_to_sb(int32_t v)
uint32_t saturate_sd_to_sw(uint32_t v)
{
- uint32_t ret = v >> 0;
+ uint32_t ret = v;
if (ret > 0xFFFF8000) {
ret = ret & 0xFFFF;
@@ -1395,7 +1368,7 @@ uint32_t saturate_sd_to_sw(uint32_t v)
uint32_t saturate_sd_to_sb(uint32_t v)
{
- uint32_t ret = v >> 0;
+ uint32_t ret = v;
if (ret > 0xFFFFFF80) {
ret = ret & 0xFF;
@@ -1413,7 +1386,7 @@ uint32_t saturate_sd_to_sb(uint32_t v)
int32_t saturate_sd_to_ub(int32_t v)
{
- int32_t ret = v | 0;
+ int32_t ret = v;
if (ret < 0) {
ret = 0;
@@ -1425,7 +1398,7 @@ int32_t saturate_sd_to_ub(int32_t v)
uint32_t saturate_ud_to_ub(uint32_t v)
{
- uint32_t ret = v >> 0;
+ uint32_t ret = v;
if (ret > 0xFF) {
ret = 0xFF;
diff --git a/src/native/codegen/api.c b/src/native/codegen/api.c
new file mode 100644
index 00000000..89da8a11
--- /dev/null
+++ b/src/native/codegen/api.c
@@ -0,0 +1,332 @@
+#include
+#include
+#include
+#include
+
+#include "cstring.h"
+#include "../const.h"
+#include "wasm_opcodes.h"
+#include "util.h"
+#include "codegen.h"
+
+// location in memory where we store the result of the computation for testing
+#define RESULT_LOC 1600
+
+extern bool is_asize_32(void);
+extern int32_t read_imm8();
+extern int32_t read_imm8s();
+extern int32_t read_imm16();
+extern int32_t read_imm32s();
+
+extern int32_t* const instruction_pointer;
+extern int32_t* const previous_ip;
+extern uint8_t* const reg8;
+extern uint16_t* const reg16;
+extern int8_t* const reg8s;
+extern int16_t* const reg16s;
+extern int32_t* const reg32s;
+
+static void jit_resolve_modrm32_(int32_t);
+static void jit_resolve_modrm16_(int32_t);
+
+void gen_increment_instruction_pointer(int32_t n)
+{
+ push_i32((int32_t)instruction_pointer); // store address of ip
+
+ load_i32((int32_t)instruction_pointer); // load ip
+ push_i32(n); // load value to add to it
+ add_i32();
+
+ store_i32(); // store it back in
+}
+
+void gen_set_previous_eip()
+{
+ push_i32((int32_t)previous_ip); // store address of previous ip
+ load_i32((int32_t)instruction_pointer); // load ip
+ store_i32(); // store it as previous ip
+}
+
+void gen_fn0(char* fn, uint8_t fn_len)
+{
+ int32_t fn_idx = get_fn_index(fn, fn_len, FN0_TYPE_INDEX);
+ call_fn(fn_idx);
+}
+
+void gen_fn1(char* fn, uint8_t fn_len, int32_t arg0)
+{
+ int32_t fn_idx = get_fn_index(fn, fn_len, FN1_TYPE_INDEX);
+ push_i32(arg0);
+ call_fn(fn_idx);
+}
+
+void gen_fn2(char* fn, uint8_t fn_len, int32_t arg0, int32_t arg1)
+{
+ int32_t fn_idx = get_fn_index(fn, fn_len, FN2_TYPE_INDEX);
+ push_i32(arg0);
+ push_i32(arg1);
+ call_fn(fn_idx);
+}
+
+#define MODRM_ENTRY(n, work)\
+ case (n) | 0 << 3:\
+ case (n) | 1 << 3:\
+ case (n) | 2 << 3:\
+ case (n) | 3 << 3:\
+ case (n) | 4 << 3:\
+ case (n) | 5 << 3:\
+ case (n) | 6 << 3:\
+ case (n) | 7 << 3:\
+ work; break;
+
+#define MODRM_ENTRY16_0(row, seg, reg1, reg2)\
+ MODRM_ENTRY(0x00 | row, gen_modrm_entry_0(seg, reg1, reg2, 0))\
+ MODRM_ENTRY(0x40 | row, gen_modrm_entry_0(seg, reg1, reg2, read_imm8s()))\
+ MODRM_ENTRY(0x80 | row, gen_modrm_entry_0(seg, reg1, reg2, read_imm16()))\
+
+#define MODRM_ENTRY16_1(row, seg, reg)\
+ MODRM_ENTRY(0x00 | row, gen_modrm_entry_1(seg, reg, 0))\
+ MODRM_ENTRY(0x40 | row, gen_modrm_entry_1(seg, reg, read_imm8s()))\
+ MODRM_ENTRY(0x80 | row, gen_modrm_entry_1(seg, reg, read_imm16()))\
+
+static void inline gen_modrm_entry_0(int32_t fn_idx, int32_t reg16_idx_1, int32_t reg16_idx_2, int32_t imm)
+{
+ // generates: fn( ( reg1 + reg2 + imm ) & 0xFFFF )
+ load_u16(reg16_idx_1);
+ load_u16(reg16_idx_2);
+ add_i32();
+
+ push_i32(imm);
+ add_i32();
+
+ push_i32(0xFFFF);
+ and_i32();
+
+ call_fn(fn_idx);
+}
+
+static void gen_modrm_entry_1(int32_t fn_idx, int32_t reg16_idx, int32_t imm)
+{
+ // generates: fn ( ( reg + imm ) & 0xFFFF )
+ load_u16(reg16_idx);
+ push_i32(imm);
+ add_i32();
+
+ push_i32(0xFFFF);
+ and_i32();
+
+ call_fn(fn_idx);
+}
+
+static void jit_resolve_modrm16_(int32_t modrm_byte)
+{
+ int32_t const ds = fn_get_seg_prefix_ds_idx;
+ int32_t const ss = fn_get_seg_prefix_ss_idx;
+
+ switch(modrm_byte)
+ {
+ // The following casts cause some weird issue with emscripten and cause
+ // a performance hit. XXX: look into this later.
+ MODRM_ENTRY16_0(0, ds, (int32_t)(reg16 + BX), (int32_t)(reg16 + SI))
+ MODRM_ENTRY16_0(1, ds, (int32_t)(reg16 + BX), (int32_t)(reg16 + DI))
+ MODRM_ENTRY16_0(2, ss, (int32_t)(reg16 + BP), (int32_t)(reg16 + SI))
+ MODRM_ENTRY16_0(3, ss, (int32_t)(reg16 + BP), (int32_t)(reg16 + DI))
+ MODRM_ENTRY16_1(4, ds, (int32_t)(reg16 + SI))
+ MODRM_ENTRY16_1(5, ds, (int32_t)(reg16 + DI))
+
+ // special case
+ MODRM_ENTRY(0x00 | 6, call_fn_with_arg(ds, read_imm16()))
+ MODRM_ENTRY(0x40 | 6, gen_modrm_entry_1(ss, (int32_t)(reg16 + BP), read_imm8s()))
+ MODRM_ENTRY(0x80 | 6, gen_modrm_entry_1(ss, (int32_t)(reg16 + BP), read_imm16()))
+
+ MODRM_ENTRY16_1(7, ds, (int32_t)(reg16 + BX))
+
+ default:
+ assert(false);
+ }
+}
+
+void gen_resolve_modrm16(int32_t modrm_byte)
+{
+ push_u32(RESULT_LOC);
+ jit_resolve_modrm16_(modrm_byte);
+ store_i32();
+}
+
+#define MODRM_ENTRY32_0(row, seg, reg)\
+ MODRM_ENTRY(0x00 | row, gen_modrm32_entry(seg, reg, 0))\
+ MODRM_ENTRY(0x40 | row, gen_modrm32_entry(seg, reg, read_imm8s()))\
+ MODRM_ENTRY(0x80 | row, gen_modrm32_entry(seg, reg, read_imm32s()))\
+
+static void gen_modrm32_entry(int32_t fn_idx, int32_t reg32s_idx, int32_t imm)
+{
+ // generates: fn ( reg + imm )
+ load_i32(reg32s_idx);
+ push_i32(imm);
+ add_i32();
+
+ call_fn(fn_idx);
+}
+
+static void jit_resolve_sib(bool mod)
+{
+ uint8_t sib_byte = read_imm8();
+ uint8_t r = sib_byte & 7;
+ uint8_t m = sib_byte >> 3 & 7;
+
+ int32_t base_addr;
+ int32_t base;
+ uint8_t seg;
+ bool base_is_mem_access = true;
+
+ if(r == 4)
+ {
+ base_addr = (int32_t)(reg32s + ESP);
+ seg = SS;
+ }
+ else if(r == 5)
+ {
+ if(mod)
+ {
+ base_addr = (int32_t)(reg32s + EBP);
+ seg = SS;
+ }
+ else
+ {
+ base = read_imm32s();
+ seg = DS;
+ base_is_mem_access = false;
+ }
+ }
+ else
+ {
+ base_addr = (int32_t)(reg32s + r);
+ seg = DS;
+ }
+
+ // generate: get_seg_prefix(seg) + base
+ // Where base is accessed from memory if base_is_mem_access or written as a constant otherwise
+
+ // We don't use push_i32 here since we know seg will fit in 1 byte anyways so no need to loop
+ cs_write_u8(OP_I32CONST);
+ cs_write_u8(seg);
+
+ call_fn(fn_get_seg_prefix_idx);
+
+ if(base_is_mem_access)
+ {
+ load_i32(base_addr);
+ }
+ else
+ {
+ push_i32(base);
+ }
+
+ add_i32();
+
+ // We now have to generate an offset value to add
+
+ if(m == 4)
+ {
+ // offset is 0, we don't need to add anything
+ return;
+ }
+
+ // Offset is reg32s[m] << s, where s is:
+
+ uint8_t s = sib_byte >> 6 & 3;
+
+ load_i32((int32_t)(reg32s + m));
+ // We don't use push_u32 here either since s will fit in 1 byte
+ cs_write_u8(OP_I32CONST);
+ cs_write_u8(s);
+ shl_i32();
+
+ add_i32();
+}
+
+static void modrm32_special_case_1()
+{
+ jit_resolve_sib(true);
+ push_i32(read_imm8s());
+ add_i32();
+}
+
+static void modrm32_special_case_2()
+{
+ jit_resolve_sib(true);
+ push_i32(read_imm32s());
+ add_i32();
+}
+
+static void jit_resolve_modrm32_(int32_t modrm_byte)
+{
+ int32_t const ds = fn_get_seg_prefix_ds_idx;
+ int32_t const ss = fn_get_seg_prefix_ss_idx;
+
+ switch(modrm_byte)
+ {
+ MODRM_ENTRY32_0(0, ds, (int32_t)(reg32s + EAX))
+ MODRM_ENTRY32_0(1, ds, (int32_t)(reg32s + ECX))
+ MODRM_ENTRY32_0(2, ds, (int32_t)(reg32s + EDX))
+ MODRM_ENTRY32_0(3, ds, (int32_t)(reg32s + EBX))
+
+ // special cases
+ MODRM_ENTRY(0x00 | 4, jit_resolve_sib(false))
+ MODRM_ENTRY(0x40 | 4, modrm32_special_case_1())
+ MODRM_ENTRY(0x80 | 4, modrm32_special_case_2())
+ MODRM_ENTRY(0x00 | 5, call_fn_with_arg(ds, read_imm32s()))
+ MODRM_ENTRY(0x40 | 5, gen_modrm32_entry(ss, (int32_t)(reg32s + EBP), read_imm8s()))
+ MODRM_ENTRY(0x80 | 5, gen_modrm32_entry(ss, (int32_t)(reg32s + EBP), read_imm32s()))
+
+ MODRM_ENTRY32_0(6, ds, (int32_t)(reg32s + ESI))
+ MODRM_ENTRY32_0(7, ds, (int32_t)(reg32s + EDI))
+
+ default:
+ assert(false);
+ }
+}
+
+void gen_resolve_modrm32(int32_t modrm_byte)
+{
+ push_i32(RESULT_LOC);
+ jit_resolve_modrm32_(modrm_byte);
+ store_i32();
+}
+
+#undef MODRM_ENTRY
+
+void gen_modrm_fn1(char* fn, uint8_t fn_len, int32_t modrm_byte, int32_t arg0)
+{
+ // generates: fn( modrm_resolve( modrm_byte ), arg0 )
+ if(is_asize_32())
+ {
+ jit_resolve_modrm32_(modrm_byte);
+ }
+ else
+ {
+ jit_resolve_modrm16_(modrm_byte);
+ }
+
+ push_i32(arg0);
+
+ int32_t fn_idx = get_fn_index(fn, fn_len, FN2_RET_TYPE_INDEX);
+ call_fn(fn_idx);
+}
+
+void gen_modrm_fn0(char* fn, uint8_t fn_len, int32_t modrm_byte)
+{
+ // generates: fn( modrm_resolve( modrm_byte ) )
+ if(is_asize_32())
+ {
+ jit_resolve_modrm32_(modrm_byte);
+ }
+ else
+ {
+ jit_resolve_modrm16_(modrm_byte);
+ }
+
+ int32_t fn_idx = get_fn_index(fn, fn_len, FN1_RET_TYPE_INDEX);
+ call_fn(fn_idx);
+}
+
diff --git a/src/native/codegen/codegen.h b/src/native/codegen/codegen.h
new file mode 100644
index 00000000..6ff9a3aa
--- /dev/null
+++ b/src/native/codegen/codegen.h
@@ -0,0 +1,331 @@
+#include
+#include
+#include
+#include
+
+#include "cstring.h"
+#include "../const.h"
+#include "wasm_opcodes.h"
+#include "util.h"
+
+// taken from chrome's buffer size limit on synchronous compilation
+#define TOTAL_SIZE_LIMIT (4 * 1024)
+
+// Memory layout
+// - First 1024 bytes (except for the nullptr) are for storing all sections except for the code
+// section
+// - Followed by that, upto TOTAL_SIZE_LIMIT bytes could be used for storing the code section
+
+static uint8_t* const output = (uint8_t* const) 2048 + 0x100000 * 6;
+
+// pointer to next free byte slot in output buffer, incremented as we write along in the buffer
+static uint8_t* op_ptr = output;
+
+static uint8_t* const code_section = output + 1024;
+static uint8_t* cs_ptr = code_section;
+
+// JS can keep strings at this location for passing them to wasm
+//XXX: figure out a better location for this
+static uint8_t* const str_input = code_section - 32;
+
+static void inline write_u8(uint8_t x)
+{
+ *op_ptr++ = x;
+}
+
+static void inline cs_write_u8(uint8_t x)
+{
+ *cs_ptr++ = x;
+}
+
+static void inline write_i32(int32_t x)
+{
+ op_ptr = _write_leb_i32(op_ptr, x);
+}
+
+static void inline cs_write_i32(int32_t x)
+{
+ cs_ptr = _write_leb_i32(cs_ptr, x);
+}
+
+static void inline write_u32(uint32_t x)
+{
+ op_ptr = _write_leb_u32(op_ptr, x);
+}
+
+static void inline cs_write_u32(uint32_t x)
+{
+ cs_ptr = _write_leb_u32(cs_ptr, x);
+}
+
+#define FN0_TYPE_INDEX 0
+#define FN1_TYPE_INDEX 1
+#define FN2_TYPE_INDEX 2
+#define FN0_RET_TYPE_INDEX 3
+#define FN1_RET_TYPE_INDEX 4
+#define FN2_RET_TYPE_INDEX 5
+
+static void write_type_section()
+{
+ write_u8(SC_TYPE);
+
+ uint8_t* ptr_section_size = op_ptr;
+ write_u8(0);
+
+ write_u8(6); // number of type descriptors
+
+ // FN0
+ write_u8(TYPE_FUNC);
+ write_u8(0); // no args
+ write_u8(0); // no return val
+
+ // FN1
+ write_u8(TYPE_FUNC);
+ write_u8(1);
+ write_u8(TYPE_I32);
+ write_u8(0);
+
+ // FN2
+ write_u8(TYPE_FUNC);
+ write_u8(2);
+ write_u8(TYPE_I32);
+ write_u8(TYPE_I32);
+ write_u8(0);
+
+ // FN0_RET
+ write_u8(TYPE_FUNC);
+ write_u8(0);
+ write_u8(1);
+ write_u8(TYPE_I32);
+
+ // FN1_RET
+ write_u8(TYPE_FUNC);
+ write_u8(1);
+ write_u8(TYPE_I32);
+ write_u8(1);
+ write_u8(TYPE_I32);
+
+ // FN2_RET
+ write_u8(TYPE_FUNC);
+ write_u8(2);
+ write_u8(TYPE_I32);
+ write_u8(TYPE_I32);
+ write_u8(1);
+ write_u8(TYPE_I32);
+
+ *ptr_section_size = (op_ptr - 1) - ptr_section_size;
+}
+
+// Import table
+
+static uint8_t* ptr_import_count = (uint8_t*) 0;
+static uint8_t* ptr_import_entries = (uint8_t*) 0;
+static uint8_t* ptr_import_table_size = (uint8_t*) 0;
+
+// The import table size is written in leb encoding, which we can't read by simple dereferencing so
+// we store the actual value separately. This is needed since we reserve two bytes for the import
+// table size as it can exceed 127
+// Default value is one as the section starts with containing one byte for the import count
+static uint32_t import_table_size = 1;
+
+// Goes over the import block to find index of an import entry by function name
+// Returns -1 if not found
+static int32_t get_import_index(char* fn, uint8_t fn_len)
+{
+ uint8_t* offset = ptr_import_entries;
+ for(int32_t i = 0; i < *ptr_import_count; i++)
+ {
+ offset += 1; // skip length of module name
+ offset += 1; // skip module name itself
+ uint8_t len = *offset++;
+ char* name = (char*) offset;
+ if (len == fn_len && strncmp(name, fn, fn_len) == 0)
+ {
+ return i;
+ }
+ offset += len; // skip the string
+ offset += 1; // skip import kind
+ offset += 1; // skip type index
+ }
+ return -1;
+}
+
+static void set_import_table_size(uint16_t size)
+{
+ import_table_size = size;
+ write_fixed_leb16_to_ptr(ptr_import_table_size, size);
+}
+
+static void write_import_section_preamble()
+{
+ write_u8(SC_IMPORT);
+
+ ptr_import_table_size = op_ptr; // store current pointer location to write into later on
+ write_u8(1 | 0b10000000); write_u8(0); // 1 in 2 byte leb
+
+ // same as above but for count of entries
+ ptr_import_count = op_ptr;
+ write_u8(0);
+
+ // here after starts the actual list of imports
+ ptr_import_entries = op_ptr;
+}
+
+static void write_memory_import()
+{
+ write_u8(1);
+ write_u8('e');
+ write_u8(1);
+ write_u8('m');
+
+ write_u8(EXT_MEMORY);
+
+ write_u8(0); // memory flag, 0 for no maximum memory limit present
+ write_u32(256); // initial memory length of 256 pages, takes 2 bytes in leb128
+
+ *ptr_import_count += 1;
+ set_import_table_size(import_table_size + 1 + 1 + 1 + 1 + 1 + 1 + 2);
+}
+
+static uint8_t write_import_entry(char* fn_name, uint8_t fn_name_len, uint8_t type_index)
+{
+ write_u8(1); // length of module name
+ write_u8('e'); // module name
+ write_u8(fn_name_len);
+ for (uint8_t i = 0; i < fn_name_len; i++)
+ {
+ write_u8(fn_name[i]);
+ }
+ write_u8(EXT_FUNCTION);
+ write_u8(type_index);
+ *ptr_import_count += 1;
+
+ set_import_table_size(import_table_size + 1 + 1 + 1 + fn_name_len + 1 + 1);
+
+ return *ptr_import_count - 1;
+}
+
+static void write_function_section()
+{
+ write_u8(SC_FUNCTION);
+ write_u8(2); // length of this section
+ write_u8(1); // count of signature indices
+ write_u8(FN0_TYPE_INDEX); // we export one function which is nullary
+}
+
+static void write_export_section()
+{
+ write_u8(SC_EXPORT);
+ write_u8(1 + 1 + 1 + 1 + 1); // size of this section
+ write_u8(1); // count of table: just one function exported
+
+ write_u8(1); // length of exported function name
+ write_u8('f'); // function name
+ write_u8(EXT_FUNCTION);
+
+ // index of the exported function
+ // function space starts with imports. index of last import is import count - 1
+ // the last import however is a memory, so we subtract one from that
+ write_u8(*ptr_import_count - 1);
+}
+
+static int32_t get_fn_index(char* fn, uint8_t fn_len, uint8_t type_index)
+{
+ int32_t fn_idx = get_import_index(fn, fn_len);
+ if (fn_idx == -1)
+ {
+ return write_import_entry(fn, fn_len, type_index);
+ }
+ return fn_idx;
+}
+
+static uint8_t const fn_get_seg_prefix_ds_idx = 0;
+static uint8_t const fn_get_seg_prefix_ss_idx = 1;
+static uint8_t const fn_get_seg_prefix_idx = 2;
+
+static uint8_t* op_ptr_reset_location;
+static uint32_t import_table_size_reset_value;
+static uint32_t initial_import_count;
+
+void gen_init()
+{
+ // wasm magic header
+ write_u8(0); write_u8('a'); write_u8('s'); write_u8('m');
+
+ // wasm version in leb128, 4 bytes
+ write_u8(WASM_VERSION); write_u8(0); write_u8(0); write_u8(0);
+
+ write_type_section();
+ write_import_section_preamble();
+
+ // add initial imports
+ uint8_t _fn_get_seg_prefix_ds_idx = write_import_entry("get_seg_prefix_ds", 17, FN1_RET_TYPE_INDEX);
+ assert(_fn_get_seg_prefix_ds_idx == fn_get_seg_prefix_ds_idx);
+ uint8_t _fn_get_seg_prefix_ss_idx = write_import_entry("get_seg_prefix_ss", 17, FN1_RET_TYPE_INDEX);
+ assert(_fn_get_seg_prefix_ss_idx == fn_get_seg_prefix_ss_idx);
+ uint8_t _fn_get_seg_prefix_idx = write_import_entry("get_seg_prefix", 14, FN1_RET_TYPE_INDEX);
+ assert(_fn_get_seg_prefix_idx == fn_get_seg_prefix_idx);
+
+ // store state of current pointers etc. so we can reset them later
+ op_ptr_reset_location = op_ptr;
+ initial_import_count = *ptr_import_count;
+ import_table_size_reset_value = import_table_size;
+}
+
+void gen_reset()
+{
+ op_ptr = op_ptr_reset_location;
+ cs_ptr = code_section;
+ *ptr_import_count = initial_import_count;
+ import_table_size = import_table_size_reset_value;
+}
+
+static void copy_code_section()
+{
+ uint8_t* offset = code_section;
+ while (offset < cs_ptr)
+ {
+ write_u8(*offset++);
+ }
+}
+
+uintptr_t gen_finish()
+{
+ write_memory_import();
+ write_function_section();
+ write_export_section();
+
+ uint8_t* ptr_code_section_size = (uint8_t*) 0; // initialized below
+ uint8_t* ptr_fn_body_size = (uint8_t*) 0; // this as well
+
+ // write code section preamble
+ write_u8(SC_CODE);
+ ptr_code_section_size = op_ptr; // we will write to this location later
+ write_u8(0); write_u8(0); // write temp val for now using 2 bytes
+
+ write_u8(1); // number of function bodies: just 1
+
+ // same as above but for body size of the function
+ ptr_fn_body_size = op_ptr;
+ write_u8(0); write_u8(0);
+
+ write_u8(0); // count of locals, none
+
+ copy_code_section();
+
+ // write code section epilogue
+ write_u8(OP_END);
+
+ // write the actual sizes to the pointer locations stored above. We subtract 1 from the actual
+ // value because the ptr itself points to two bytes
+ write_fixed_leb16_to_ptr(ptr_fn_body_size, ((op_ptr - 1) - ptr_fn_body_size) - 1);
+ write_fixed_leb16_to_ptr(ptr_code_section_size, ((op_ptr - 1) - ptr_code_section_size) - 1);
+
+ return (uintptr_t) op_ptr;
+}
+
+uintptr_t gen_get_final_offset()
+{
+ return (uintptr_t) op_ptr;
+}
+
diff --git a/src/native/codegen/cstring.h b/src/native/codegen/cstring.h
new file mode 100644
index 00000000..64308e6d
--- /dev/null
+++ b/src/native/codegen/cstring.h
@@ -0,0 +1,132 @@
+// everything here is copied from musl
+
+#ifndef _CSTRING_H
+#define _CSTRING_H
+
+#include
+#include
+
+// from strncmp.c
+
+static int strncmp(const char *_l, const char *_r, size_t n)
+{
+ const unsigned char *l=(void *)_l, *r=(void *)_r;
+ if (!n--) return 0;
+ for (; *l && *r && n && *l == *r ; l++, r++, n--);
+ return *l - *r;
+}
+
+// from memset.c
+
+static void *memset(void *dest, int c, size_t n)
+{
+ unsigned char *s = dest;
+ size_t k;
+
+ /* Fill head and tail with minimal branching. Each
+ * conditional ensures that all the subsequently used
+ * offsets are well-defined and in the dest region. */
+
+ if (!n) return dest;
+ s[0] = s[n-1] = c;
+ if (n <= 2) return dest;
+ s[1] = s[n-2] = c;
+ s[2] = s[n-3] = c;
+ if (n <= 6) return dest;
+ s[3] = s[n-4] = c;
+ if (n <= 8) return dest;
+
+ /* Advance pointer to align it at a 4-byte boundary,
+ * and truncate n to a multiple of 4. The previous code
+ * already took care of any head/tail that get cut off
+ * by the alignment. */
+
+ k = -(uintptr_t)s & 3;
+ s += k;
+ n -= k;
+ n &= -4;
+
+#ifdef __GNUC__
+ typedef uint32_t __attribute__((__may_alias__)) u32;
+ typedef uint64_t __attribute__((__may_alias__)) u64;
+
+ u32 c32 = ((u32)-1)/255 * (unsigned char)c;
+
+ /* In preparation to copy 32 bytes at a time, aligned on
+ * an 8-byte bounary, fill head/tail up to 28 bytes each.
+ * As in the initial byte-based head/tail fill, each
+ * conditional below ensures that the subsequent offsets
+ * are valid (e.g. !(n<=24) implies n>=28). */
+
+ *(u32 *)(s+0) = c32;
+ *(u32 *)(s+n-4) = c32;
+ if (n <= 8) return dest;
+ *(u32 *)(s+4) = c32;
+ *(u32 *)(s+8) = c32;
+ *(u32 *)(s+n-12) = c32;
+ *(u32 *)(s+n-8) = c32;
+ if (n <= 24) return dest;
+ *(u32 *)(s+12) = c32;
+ *(u32 *)(s+16) = c32;
+ *(u32 *)(s+20) = c32;
+ *(u32 *)(s+24) = c32;
+ *(u32 *)(s+n-28) = c32;
+ *(u32 *)(s+n-24) = c32;
+ *(u32 *)(s+n-20) = c32;
+ *(u32 *)(s+n-16) = c32;
+
+ /* Align to a multiple of 8 so we can fill 64 bits at a time,
+ * and avoid writing the same bytes twice as much as is
+ * practical without introducing additional branching. */
+
+ k = 24 + ((uintptr_t)s & 4);
+ s += k;
+ n -= k;
+
+ /* If this loop is reached, 28 tail bytes have already been
+ * filled, so any remainder when n drops below 32 can be
+ * safely ignored. */
+
+ u64 c64 = c32 | ((u64)c32 << 32);
+ for (; n >= 32; n-=32, s+=32) {
+ *(u64 *)(s+0) = c64;
+ *(u64 *)(s+8) = c64;
+ *(u64 *)(s+16) = c64;
+ *(u64 *)(s+24) = c64;
+ }
+#else
+ /* Pure C fallback with no aliasing violations. */
+ for (; n; n--, s++) *s = c;
+#endif
+
+ return dest;
+}
+
+// from stpncpy.c, function renamed from __stpncpy to strncpy
+// strncpy was assigned simply as an alias to that function
+
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+static char *strncpy(char *restrict d, const char *restrict s, size_t n)
+{
+ size_t *wd;
+ const size_t *ws;
+
+ if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
+ for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
+ if (!n || !*s) goto tail;
+ wd=(void *)d; ws=(const void *)s;
+ for (; n>=sizeof(size_t) && !HASZERO(*ws);
+ n-=sizeof(size_t), ws++, wd++) *wd = *ws;
+ d=(void *)wd; s=(const void *)ws;
+ }
+ for (; n && (*d=*s); n--, s++, d++);
+tail:
+ memset(d, 0, n);
+ return d;
+}
+
+#endif
diff --git a/src/native/codegen/util.h b/src/native/codegen/util.h
new file mode 100644
index 00000000..27de869f
--- /dev/null
+++ b/src/native/codegen/util.h
@@ -0,0 +1,135 @@
+#ifndef _WASM_UTIL_H
+#define _WASM_UTIL_H
+
+#include
+
+static uint8_t* _write_leb_u32(uint8_t* ptr, uint32_t v)
+{
+ uint8_t byte;
+ do {
+ byte = v & 0b1111111; // get last 7 bits
+ v >>= 7; // shift them away from the value
+ if (v != 0)
+ {
+ byte |= 0b10000000; // turn on MSB
+ }
+ *ptr++ = byte;
+ } while (v != 0);
+ return ptr;
+}
+
+static uint8_t* _write_leb_i32(uint8_t* ptr, int32_t v)
+{
+ // Super complex stuff. See the following:
+ // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer
+ // http://llvm.org/doxygen/LEB128_8h_source.html#l00048
+
+ bool more = true;
+ bool negative = v < 0;
+ uint32_t size = 32;
+ uint8_t byte;
+ while (more)
+ {
+ byte = v & 0b1111111; // get last 7 bits
+ v >>= 7; // shift them away from the value
+ if (negative)
+ {
+ v |= (~0 << (size - 7)); // extend sign
+ }
+ uint8_t sign_bit = byte & (1 << 6);
+ if ((v == 0 && sign_bit == 0) || (v == -1 && sign_bit != 0))
+ {
+ more = false;
+ }
+ else
+ {
+ byte |= 0b10000000; // turn on MSB
+ }
+ *ptr++ = byte;
+ }
+ return ptr;
+}
+
+static void inline write_fixed_leb16_to_ptr(uint8_t* ptr, uint16_t x)
+{
+ if (x < 128)
+ {
+ *ptr = x | 0b10000000;
+ *(ptr + 1) = 0;
+ }
+ else
+ {
+ *ptr = (x & 0b1111111) | 0b10000000;
+ *(ptr + 1) = x >> 7;
+ }
+}
+
+static void cs_write_u8(uint8_t);
+static void cs_write_u32(uint32_t);
+static void cs_write_i32(int32_t);
+
+static void inline push_i32(int32_t v)
+{
+ cs_write_u8(OP_I32CONST);
+ cs_write_i32(v);
+}
+
+static void inline push_u32(uint32_t v)
+{
+ cs_write_u8(OP_I32CONST);
+ cs_write_u32(v);
+}
+
+static void inline load_u16(uint32_t addr)
+{
+ cs_write_u8(OP_I32CONST);
+ cs_write_u32(addr);
+ cs_write_u8(OP_I32LOAD16U);
+ cs_write_u8(MEM_IMM_ALIGNMENT);
+ cs_write_u8(MEM_IMM_OFFSET);
+}
+
+static void inline load_i32(uint32_t addr)
+{
+ cs_write_u8(OP_I32CONST);
+ cs_write_u32(addr);
+ cs_write_u8(OP_I32LOAD);
+ cs_write_u8(MEM_IMM_ALIGNMENT);
+ cs_write_u8(MEM_IMM_OFFSET);
+}
+
+static void inline store_i32()
+{
+ cs_write_u8(OP_I32STORE);
+ cs_write_u8(MEM_IMM_ALIGNMENT);
+ cs_write_u8(MEM_IMM_OFFSET);
+}
+
+static void inline add_i32()
+{
+ cs_write_u8(OP_I32ADD);
+}
+
+static void inline and_i32()
+{
+ cs_write_u8(OP_I32AND);
+}
+
+static void inline shl_i32()
+{
+ cs_write_u8(OP_I32SHL);
+}
+
+static void inline call_fn(uint8_t fn_idx)
+{
+ cs_write_u8(OP_CALL);
+ cs_write_u8(fn_idx);
+}
+
+static void inline call_fn_with_arg(uint8_t fn_idx, int32_t arg0)
+{
+ push_i32(arg0);
+ call_fn(fn_idx);
+}
+
+#endif
diff --git a/src/native/codegen/wasm_opcodes.h b/src/native/codegen/wasm_opcodes.h
new file mode 100644
index 00000000..38260151
--- /dev/null
+++ b/src/native/codegen/wasm_opcodes.h
@@ -0,0 +1,212 @@
+// https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#high-level-structure
+#define WASM_VERSION 0x1
+
+// Section codes
+#define SC_TYPE 1
+#define SC_IMPORT 2
+#define SC_FUNCTION 3
+#define SC_TABLE 4
+#define SC_MEMORY 5
+#define SC_GLOBAL 6
+#define SC_EXPORT 7
+#define SC_START 8
+#define SC_ELEMENT 9
+#define SC_CODE 10
+#define SC_DATA 11
+
+// https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#language-types
+#define TYPE_I32 0x7f
+#define TYPE_I64 0x7e
+#define TYPE_F32 0x7d
+#define TYPE_F64 0x7c
+#define TYPE_ANYFUNC 0x70
+#define TYPE_FUNC 0x60
+#define TYPE_BLOCK_TYPE 0x40
+
+// https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#external_kind
+#define EXT_FUNCTION 0
+#define EXT_TABLE 1
+#define EXT_MEMORY 2
+#define EXT_GLOBAL 3
+
+// Taken from wasm2ast's source code and modified with vim magic
+#define OP_UNREACHABLE 0x00
+#define OP_NOP 0x01
+#define OP_BLOCK 0x02
+#define OP_LOOP 0x03
+#define OP_IF 0x04
+#define OP_ELSE 0x05
+#define OP_TRY 0x06
+#define OP_CATCH 0x07
+#define OP_THROW 0x08
+#define OP_RETHROW 0x09
+#define OP_CATCHALL 0x0a
+#define OP_END 0x0b
+#define OP_BR 0x0c
+#define OP_BRIF 0x0d
+#define OP_BRTABLE 0x0e
+#define OP_RETURN 0x0f
+#define OP_CALL 0x10
+#define OP_CALLINDIRECT 0x11
+#define OP_DROP 0x1a
+#define OP_SELECT 0x1b
+#define OP_GETLOCAL 0x20
+#define OP_SETLOCAL 0x21
+#define OP_TEELOCAL 0x22
+#define OP_GETGLOBAL 0x23
+#define OP_SETGLOBAL 0x24
+#define OP_I32LOAD 0x28
+#define OP_I64LOAD 0x29
+#define OP_F32LOAD 0x2a
+#define OP_F64LOAD 0x2b
+#define OP_I32LOAD8S 0x2c
+#define OP_I32LOAD8U 0x2d
+#define OP_I32LOAD16S 0x2e
+#define OP_I32LOAD16U 0x2f
+#define OP_I64LOAD8S 0x30
+#define OP_I64LOAD8U 0x31
+#define OP_I64LOAD16S 0x32
+#define OP_I64LOAD16U 0x33
+#define OP_I64LOAD32S 0x34
+#define OP_I64LOAD32U 0x35
+#define OP_I32STORE 0x36
+#define OP_I64STORE 0x37
+#define OP_F32STORE 0x38
+#define OP_F64STORE 0x39
+#define OP_I32STORE8 0x3a
+#define OP_I32STORE16 0x3b
+#define OP_I64STORE8 0x3c
+#define OP_I64STORE16 0x3d
+#define OP_I64STORE32 0x3e
+#define OP_CURRENTMEMORY 0x3f
+#define OP_GROWMEMORY 0x40
+#define OP_I32CONST 0x41
+#define OP_I64CONST 0x42
+#define OP_F32CONST 0x43
+#define OP_F64CONST 0x44
+#define OP_I32EQZ 0x45
+#define OP_I32EQ 0x46
+#define OP_I32NE 0x47
+#define OP_I32LTS 0x48
+#define OP_I32LTU 0x49
+#define OP_I32GTS 0x4a
+#define OP_I32GTU 0x4b
+#define OP_I32LES 0x4c
+#define OP_I32LEU 0x4d
+#define OP_I32GES 0x4e
+#define OP_I32GEU 0x4f
+#define OP_I64EQZ 0x50
+#define OP_I64EQ 0x51
+#define OP_I64NE 0x52
+#define OP_I64LTS 0x53
+#define OP_I64LTU 0x54
+#define OP_I64GTS 0x55
+#define OP_I64GTU 0x56
+#define OP_I64LES 0x57
+#define OP_I64LEU 0x58
+#define OP_I64GES 0x59
+#define OP_I64GEU 0x5a
+#define OP_F32EQ 0x5b
+#define OP_F32NE 0x5c
+#define OP_F32LT 0x5d
+#define OP_F32GT 0x5e
+#define OP_F32LE 0x5f
+#define OP_F32GE 0x60
+#define OP_F64EQ 0x61
+#define OP_F64NE 0x62
+#define OP_F64LT 0x63
+#define OP_F64GT 0x64
+#define OP_F64LE 0x65
+#define OP_F64GE 0x66
+#define OP_I32CLZ 0x67
+#define OP_I32CTZ 0x68
+#define OP_I32POPCNT 0x69
+#define OP_I32ADD 0x6a
+#define OP_I32SUB 0x6b
+#define OP_I32MUL 0x6c
+#define OP_I32DIVS 0x6d
+#define OP_I32DIVU 0x6e
+#define OP_I32REMS 0x6f
+#define OP_I32REMU 0x70
+#define OP_I32AND 0x71
+#define OP_I32OR 0x72
+#define OP_I32XOR 0x73
+#define OP_I32SHL 0x74
+#define OP_I32SHRS 0x75
+#define OP_I32SHRU 0x76
+#define OP_I32ROTL 0x77
+#define OP_I32ROTR 0x78
+#define OP_I64CLZ 0x79
+#define OP_I64CTZ 0x7a
+#define OP_I64POPCNT 0x7b
+#define OP_I64ADD 0x7c
+#define OP_I64SUB 0x7d
+#define OP_I64MUL 0x7e
+#define OP_I64DIVS 0x7f
+#define OP_I64DIVU 0x80
+#define OP_I64REMS 0x81
+#define OP_I64REMU 0x82
+#define OP_I64AND 0x83
+#define OP_I64OR 0x84
+#define OP_I64XOR 0x85
+#define OP_I64SHL 0x86
+#define OP_I64SHRS 0x87
+#define OP_I64SHRU 0x88
+#define OP_I64ROTL 0x89
+#define OP_I64ROTR 0x8a
+#define OP_F32ABS 0x8b
+#define OP_F32NEG 0x8c
+#define OP_F32CEIL 0x8d
+#define OP_F32FLOOR 0x8e
+#define OP_F32TRUNC 0x8f
+#define OP_F32NEAREST 0x90
+#define OP_F32SQRT 0x91
+#define OP_F32ADD 0x92
+#define OP_F32SUB 0x93
+#define OP_F32MUL 0x94
+#define OP_F32DIV 0x95
+#define OP_F32MIN 0x96
+#define OP_F32MAX 0x97
+#define OP_F32COPYSIGN 0x98
+#define OP_F64ABS 0x99
+#define OP_F64NEG 0x9a
+#define OP_F64CEIL 0x9b
+#define OP_F64FLOOR 0x9c
+#define OP_F64TRUNC 0x9d
+#define OP_F64NEAREST 0x9e
+#define OP_F64SQRT 0x9f
+#define OP_F64ADD 0xa0
+#define OP_F64SUB 0xa1
+#define OP_F64MUL 0xa2
+#define OP_F64DIV 0xa3
+#define OP_F64MIN 0xa4
+#define OP_F64MAX 0xa5
+#define OP_F64COPYSIGN 0xa6
+#define OP_I32WRAPI64 0xa7
+#define OP_I32TRUNCSF32 0xa8
+#define OP_I32TRUNCUF32 0xa9
+#define OP_I32TRUNCSF64 0xaa
+#define OP_I32TRUNCUF64 0xab
+#define OP_I64EXTENDSI32 0xac
+#define OP_I64EXTENDUI32 0xad
+#define OP_I64TRUNCSF32 0xae
+#define OP_I64TRUNCUF32 0xaf
+#define OP_I64TRUNCSF64 0xb0
+#define OP_I64TRUNCUF64 0xb1
+#define OP_F32CONVERTSI32 0xb2
+#define OP_F32CONVERTUI32 0xb3
+#define OP_F32CONVERTSI64 0xb4
+#define OP_F32CONVERTUI64 0xb5
+#define OP_F32DEMOTEF64 0xb6
+#define OP_F64CONVERTSI32 0xb7
+#define OP_F64CONVERTUI32 0xb8
+#define OP_F64CONVERTSI64 0xb9
+#define OP_F64CONVERTUI64 0xba
+#define OP_F64PROMOTEF32 0xbb
+#define OP_I32REINTERPRETF32 0xbc
+#define OP_I64REINTERPRETF64 0xbd
+#define OP_F32REINTERPRETI32 0xbe
+#define OP_F64REINTERPRETI64 0xbf
+
+#define MEM_IMM_ALIGNMENT 0
+#define MEM_IMM_OFFSET 0
diff --git a/src/native/const.h b/src/native/const.h
index 97dbd3bc..1d411b53 100644
--- a/src/native/const.h
+++ b/src/native/const.h
@@ -161,3 +161,17 @@
#define USE_A20 false
#define MXCSR_MASK (0xFFFF & ~(1 << 6))
+
+// Mask used to map physical address to index in cache array
+#define JIT_PHYS_MASK 0xFFFF
+
+#define CACHE_LEN 0x10000
+#define HASH_PRIME 6151
+#define JIT_THRESHOLD 10000
+// XXX: Consider making this the same as page size (12) during perf testing
+#define DIRTY_ARR_SHIFT 16
+#define MAX_INSTR_LEN 15
+#define MAX_BLOCK_LENGTH ((1 << DIRTY_ARR_SHIFT) - MAX_INSTR_LEN)
+
+#define ENABLE_JIT 0
+#define ENABLE_PROFILER 0
diff --git a/src/native/cpu.c b/src/native/cpu.c
index 16009e26..a59c14e9 100644
--- a/src/native/cpu.c
+++ b/src/native/cpu.c
@@ -6,10 +6,7 @@
#include "const.h"
#include "global_pointers.h"
-
-int32_t read_e8_partial_branch() {
- return reg8[*modrm_byte << 2 & 0xC | *modrm_byte >> 2 & 1];
-}
+#include "profiler.h"
// like memcpy, but only efficient for large (approximately 10k) sizes
// See memcpy in https://github.com/kripken/emscripten/blob/master/src/library.js
@@ -21,14 +18,19 @@ int32_t translate_address_write(int32_t);
int32_t read8(uint32_t);
int32_t read16(uint32_t);
int32_t read32s(uint32_t);
+int64_t read64s(uint32_t);
+int32_t read_aligned16(uint32_t addr);
int32_t virt_boundary_read16(int32_t, int32_t);
int32_t virt_boundary_read32s(int32_t, int32_t);
-void write8(uint32_t, uint8_t);
-void write16(uint32_t, uint16_t);
+void write8(uint32_t, int32_t);
+void write16(uint32_t, int32_t);
void write32(uint32_t, int32_t);
+void write64(uint32_t, int64_t);
void virt_boundary_write16(int32_t, int32_t, int32_t);
void virt_boundary_write32(int32_t, int32_t, int32_t);
+bool cpu_exception_hook(int32_t);
+
bool in_mapped_range(uint32_t);
void trigger_gp(int32_t);
@@ -48,9 +50,25 @@ void fxrstor(uint32_t);
int32_t do_page_translation(int32_t, bool, bool);
-void diverged() {}
-void branch_taken() {}
-void branch_not_taken() {}
+void after_jump()
+{
+ jit_jump = 1;
+}
+
+void diverged() {
+ after_jump();
+}
+
+void branch_taken()
+{
+ after_jump();
+}
+
+void branch_not_taken()
+{
+ after_jump();
+}
+
int32_t getcf(void);
int32_t getpf(void);
@@ -60,6 +78,9 @@ int32_t getsf(void);
int32_t getof(void);
+double_t microtick();
+
+
int32_t get_eflags()
{
return (*flags & ~FLAGS_ALL) | !!getcf() | !!getpf() << 2 | !!getaf() << 4 |
@@ -148,17 +169,6 @@ int32_t read_imm32s()
return data32;
}
-int32_t read_op0F() { return read_imm8(); }
-int32_t read_sib() { return read_imm8(); }
-int32_t read_op8() { return read_imm8(); }
-int32_t read_op8s() { return read_imm8s(); }
-int32_t read_op16() { return read_imm16(); }
-int32_t read_op32s() { return read_imm32s(); }
-int32_t read_disp8() { return read_imm8(); }
-int32_t read_disp8s() { return read_imm8s(); }
-int32_t read_disp16() { return read_imm16(); }
-int32_t read_disp32s() { return read_imm32s(); }
-
bool is_osize_32()
{
return *is_32 != ((*prefixes & PREFIX_MASK_OPSIZE) == PREFIX_MASK_OPSIZE);
@@ -169,11 +179,6 @@ bool is_asize_32()
return *is_32 != ((*prefixes & PREFIX_MASK_ADDRSIZE) == PREFIX_MASK_ADDRSIZE);
}
-void read_modrm_byte()
-{
- *modrm_byte = read_imm8();
-}
-
int32_t get_seg(int32_t segment)
{
assert(segment >= 0 && segment < 8);
@@ -184,6 +189,7 @@ int32_t get_seg(int32_t segment)
if(segment_is_null[segment])
{
assert(segment != CS && segment != SS);
+ dbg_log("#gp: Access null segment");
trigger_gp(0);
}
}
@@ -232,129 +238,117 @@ static int32_t modrm_resolve(int32_t modrm_byte)
}
}
-void set_e8(int32_t value)
+uint32_t jit_hot_hash(uint32_t addr)
{
- int32_t modrm_byte_ = *modrm_byte;
- if(modrm_byte_ < 0xC0) {
- int32_t addr = modrm_resolve(modrm_byte_);
- safe_write8(addr, value);
- } else {
- reg8[modrm_byte_ << 2 & 0xC | modrm_byte_ >> 2 & 1] = value;
- }
-}
-
-void set_e16(int32_t value)
-{
- int32_t modrm_byte_ = *modrm_byte;
- if(modrm_byte_ < 0xC0) {
- int32_t addr = modrm_resolve(modrm_byte_);
- safe_write16(addr, value);
- } else {
- reg16[modrm_byte_ << 1 & 14] = value;
- }
-}
-
-void set_e32(int32_t value)
-{
- int32_t modrm_byte_ = *modrm_byte;
- if(modrm_byte_ < 0xC0) {
- int32_t addr = modrm_resolve(modrm_byte_);
- safe_write32(addr, value);
- } else {
- reg32s[modrm_byte_ & 7] = value;
- }
-}
-
-int32_t read_g8()
-{
- return reg8[*modrm_byte >> 1 & 0xC | *modrm_byte >> 5 & 1];
-}
-
-int32_t read_g16()
-{
- return reg16[*modrm_byte >> 2 & 14];
-}
-
-int32_t read_g16s()
-{
- return reg16s[*modrm_byte >> 2 & 14];
-}
-
-int32_t read_g32s()
-{
- return reg32s[*modrm_byte >> 3 & 7];
-}
-
-void write_g8(int32_t value)
-{
- reg8[*modrm_byte >> 1 & 0xC | *modrm_byte >> 5 & 1] = value;
-}
-
-void write_g16(int32_t value)
-{
- reg16[*modrm_byte >> 2 & 14] = value;
-}
-
-void write_g32(int32_t value)
-{
- reg32s[*modrm_byte >> 3 & 7] = value;
-}
-
-int32_t read_e8()
-{
- if(*modrm_byte < 0xC0)
- {
- return safe_read8(modrm_resolve(*modrm_byte));
- }
- else
- {
- return reg8[*modrm_byte << 2 & 0xC | *modrm_byte >> 2 & 1];
- }
-}
-
-int32_t read_e8s()
-{
- return read_e8() << 24 >> 24;
-}
-
-int32_t read_e16()
-{
- if(*modrm_byte < 0xC0)
- {
- return safe_read16(modrm_resolve(*modrm_byte));
- }
- else
- {
- return reg16[*modrm_byte << 1 & 14];
- }
-}
-
-int32_t read_e16s()
-{
- return read_e16() << 16 >> 16;
-}
-
-int32_t read_e32s()
-{
- if(*modrm_byte < 0xC0)
- {
- return safe_read32s(modrm_resolve(*modrm_byte));
- }
- else
- {
- return reg32s[*modrm_byte & 7];
- }
+ return addr % HASH_PRIME;
}
void cycle_internal()
{
+#if ENABLE_JIT
+/* Use JIT mode */
+ int32_t eip = *instruction_pointer;
+ // Save previous_ip now since translate_address_read might trigger a page-fault
+ *previous_ip = *instruction_pointer;
+
+ if((eip & ~0xFFF) ^ *last_virt_eip)
+ {
+ *eip_phys = translate_address_read(eip) ^ eip;
+ *last_virt_eip = eip & ~0xFFF;
+ }
+
+ uint32_t phys_addr = *eip_phys ^ eip;
+ assert(!in_mapped_range(phys_addr));
+
+ struct code_cache *entry = &jit_cache_arr[phys_addr & JIT_PHYS_MASK];
+
+ if(entry->group_status == group_dirtiness[phys_addr >> DIRTY_ARR_SHIFT] &&
+ entry->start_addr == phys_addr)
+ {
+ // XXX: With the code-generation, we need to figure out how we
+ // would call the function from the other module here; likely
+ // through a handler in JS. For now:
+
+ // Confirm that cache is not dirtied (through page-writes,
+ // mode switch, or just cache eviction)
+ for(int32_t i = 0; i < entry->len; i++)
+ {
+ *previous_ip = *instruction_pointer;
+ int32_t opcode = read_imm8();
+ phys_addr = *eip_phys ^ (*instruction_pointer - 1);
+ assert(opcode == entry->opcode[i]);
+ run_instruction(entry->opcode[i] | !!*is_32 << 8);
+ (*timestamp_counter)++;
+ }
+ // XXX: Try to find an assert to detect self-modifying code
+ // JIT compiled self-modifying basic blocks may trigger this assert
+ // assert(entry->group_status != group_dirtiness[entry->start_addr >> DIRTY_ARR_SHIFT]);
+ *cache_hit = *cache_hit + 1;
+ }
+ // A jump just occured indicating the start of a basic block + the
+ // address is hot; let's JIT compile it
+ else if(jit_jump == 1 && ++hot_code_addresses[jit_hot_hash(phys_addr)] > JIT_THRESHOLD)
+ {
+ // Minimize collision based thrashing
+ hot_code_addresses[jit_hot_hash(phys_addr)] = 0;
+ jit_jump = 0;
+ entry->len = 0;
+ entry->start_addr = phys_addr;
+ entry->end_addr = phys_addr + 1;
+ jit_cache_arr[phys_addr & JIT_PHYS_MASK] = *entry;
+
+ *cache_compile = *cache_compile + 1;
+
+ // XXX: Artificial limit allows jit_dirty_cache to be
+ // simplified by only dirtying 2 entries based on a mask
+ // (instead of all possible entries)
+ while(jit_jump == 0 && entry->len < 100 &&
+ (entry->end_addr - entry->start_addr) < MAX_BLOCK_LENGTH)
+ {
+ *previous_ip = *instruction_pointer;
+ int32_t opcode = read_imm8();
+ // XXX: Currently only includes opcode of final jmp, not operands
+ entry->end_addr = *eip_phys ^ *instruction_pointer;
+ entry->opcode[entry->len] = opcode;
+ entry->len++;
+
+ // XXX: Generate the instruction instead of running it
+ // XXX: If it's a jmp instruction, make sure
+ // generate_instruction sets jit_jump=1 and end_addr is set correctly
+ run_instruction(opcode | !!*is_32 << 8);
+ (*timestamp_counter)++;
+ }
+ jit_jump = 0;
+ // When the hot instruction is a jmp (backwards),
+ // leave its group_status unupdated, thereby invalidating it
+ if (entry->end_addr > entry->start_addr)
+ {
+ entry->group_status = group_dirtiness[phys_addr >> DIRTY_ARR_SHIFT];
+ }
+ }
+ // Regular un-hot code execution
+ else
+ {
+ jit_jump = 0;
+ int32_t opcode = read_imm8();
+ run_instruction(opcode | !!*is_32 << 8);
+ (*timestamp_counter)++;
+ }
+
+#else
+/* Use non-JIT mode */
previous_ip[0] = instruction_pointer[0];
(*timestamp_counter)++;
int32_t opcode = read_imm8();
+#if DEBUG
+ logop(previous_ip[0], opcode);
+#endif
+
run_instruction(opcode | !!*is_32 << 8);
+#endif
}
static void run_prefix_instruction()
@@ -385,12 +379,26 @@ void do_many_cycles_unsafe()
void raise_exception(int32_t interrupt_nr)
{
+#if DEBUG
+ if(cpu_exception_hook(interrupt_nr))
+ {
+ throw_cpu_exception();
+ return;
+ }
+#endif
call_interrupt_vector(interrupt_nr, false, false, 0);
throw_cpu_exception();
}
void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code)
{
+#if DEBUG
+ if(cpu_exception_hook(interrupt_nr))
+ {
+ throw_cpu_exception();
+ return;
+ }
+#endif
call_interrupt_vector(interrupt_nr, false, true, error_code);
throw_cpu_exception();
}
@@ -401,12 +409,104 @@ void trigger_de()
raise_exception(0);
}
+void trigger_ud()
+{
+ dbg_log("#ud");
+ dbg_trace();
+ *instruction_pointer = *previous_ip;
+ raise_exception(6);
+}
+
+void trigger_nm()
+{
+ *instruction_pointer = *previous_ip;
+ raise_exception(7);
+}
+
void trigger_gp(int32_t code)
{
*instruction_pointer = *previous_ip;
raise_exception_with_code(13, code);
}
+int32_t virt_boundary_read16(int32_t low, int32_t high)
+{
+ dbg_assert((low & 0xFFF) == 0xFFF);
+ dbg_assert((high & 0xFFF) == 0);
+
+ return read8(low) | read8(high) << 8;
+}
+
+int32_t virt_boundary_read32s(int32_t low, int32_t high)
+{
+ dbg_assert((low & 0xFFF) >= 0xFFD);
+ dbg_assert((high - 3 & 0xFFF) == (low & 0xFFF));
+
+ int32_t mid = 0;
+
+ if(low & 1)
+ {
+ if(low & 2)
+ {
+ // 0xFFF
+ mid = read_aligned16((high - 2) >> 1);
+ }
+ else
+ {
+ // 0xFFD
+ mid = read_aligned16((low + 1) >> 1);
+ }
+ }
+ else
+ {
+ // 0xFFE
+ mid = virt_boundary_read16(low + 1, high - 1);
+ }
+
+ return read8(low) | mid << 8 | read8(high) << 24;
+}
+
+void virt_boundary_write16(int32_t low, int32_t high, int32_t value)
+{
+ dbg_assert((low & 0xFFF) == 0xFFF);
+ dbg_assert((high & 0xFFF) == 0);
+
+ write8(low, value);
+ write8(high, value >> 8);
+}
+
+void virt_boundary_write32(int32_t low, int32_t high, int32_t value)
+{
+ dbg_assert((low & 0xFFF) >= 0xFFD);
+ dbg_assert((high - 3 & 0xFFF) == (low & 0xFFF));
+
+ write8(low, value);
+
+ if(low & 1)
+ {
+ if(low & 2)
+ {
+ // 0xFFF
+ write8(high - 2, value >> 8);
+ write8(high - 1, value >> 16);
+ }
+ else
+ {
+ // 0xFFD
+ write8(low + 1, value >> 8);
+ write8(low + 2, value >> 16);
+ }
+ }
+ else
+ {
+ // 0xFFE
+ write8(low + 1, value >> 8);
+ write8(high - 1, value >> 16);
+ }
+
+ write8(high, value >> 24);
+}
+
int32_t safe_read8(int32_t addr)
{
return read8(translate_address_read(addr));
@@ -439,7 +539,7 @@ int32_t safe_read32s(int32_t addr)
union reg64 safe_read64s(int32_t addr)
{
union reg64 x;
- if((addr & 0xFFF) >= 0xFF9)
+ if((addr & 0xFFF) > (0x1000 - 8))
{
x.u32[0] = safe_read32s(addr);
x.u32[1] = safe_read32s(addr + 4);
@@ -447,8 +547,7 @@ union reg64 safe_read64s(int32_t addr)
else
{
int32_t addr_phys = translate_address_read(addr);
- x.u32[0] = read32s(addr_phys);
- x.u32[1] = read32s(addr_phys + 4);
+ x.u64[0] = read64s(addr_phys);
}
return x;
}
@@ -456,7 +555,7 @@ union reg64 safe_read64s(int32_t addr)
union reg128 safe_read128s(int32_t addr)
{
union reg128 x;
- if((addr & 0xFFF) >= 0xFF1)
+ if((addr & 0xFFF) > (0x1000 - 16))
{
x.u32[0] = safe_read32s(addr);
x.u32[1] = safe_read32s(addr + 4);
@@ -466,32 +565,12 @@ union reg128 safe_read128s(int32_t addr)
else
{
int32_t addr_phys = translate_address_read(addr);
- x.u32[0] = read32s(addr_phys);
- x.u32[1] = read32s(addr_phys + 4);
- x.u32[2] = read32s(addr_phys + 8);
- x.u32[3] = read32s(addr_phys + 12);
+ x.u64[0] = read64s(addr_phys);
+ x.u64[1] = read64s(addr_phys + 8);
}
return x;
}
-void safe_write64(int32_t addr, int32_t low, int32_t high)
-{
- // TODO: Optimize
- writable_or_pagefault(addr, 8);
- safe_write32(addr, low);
- safe_write32(addr + 4, high);
-}
-
-void safe_write128(int32_t addr, union reg128 value)
-{
- // TODO: Optimize
- writable_or_pagefault(addr, 16);
- safe_write32(addr, value.u32[0]);
- safe_write32(addr + 4, value.u32[1]);
- safe_write32(addr + 8, value.u32[2]);
- safe_write32(addr + 12, value.u32[3]);
-}
-
void safe_write8(int32_t addr, int32_t value)
{
write8(translate_address_write(addr), value);
@@ -515,7 +594,7 @@ void safe_write32(int32_t addr, int32_t value)
{
int32_t phys_low = translate_address_write(addr);
- if((addr & 0xFFF) >= 0xFFD)
+ if((addr & 0xFFF) > (0x1000 - 4))
{
virt_boundary_write32(phys_low, translate_address_write(addr + 3 & ~3) | (addr + 3) & 3, value);
}
@@ -525,245 +604,127 @@ void safe_write32(int32_t addr, int32_t value)
}
}
-int32_t read_write_e8()
+void safe_write64(int32_t addr, int64_t value)
{
- if(*modrm_byte < 0xC0)
+ if((addr & 0xFFF) > (0x1000 - 8))
{
- int32_t virt_addr = modrm_resolve(*modrm_byte);
- *phys_addr = translate_address_write(virt_addr);
- return read8(*phys_addr);
+ safe_write32(addr, value);
+ safe_write32(addr + 4, value >> 32);
}
else
{
- return reg8[*modrm_byte << 2 & 0xC | *modrm_byte >> 2 & 1];
+ int32_t phys = translate_address_write(addr);
+ write64(phys, value);
}
}
-void write_e8(int32_t value)
+void safe_write128(int32_t addr, union reg128 value)
{
- if(*modrm_byte < 0xC0)
+ if((addr & 0xFFF) > (0x1000 - 16))
{
- write8(*phys_addr, value);
+ safe_write64(addr, value.u64[0]);
+ safe_write64(addr + 8, value.u64[1]);
}
else
{
- reg8[*modrm_byte << 2 & 0xC | *modrm_byte >> 2 & 1] = value;
+ int32_t phys = translate_address_write(addr);
+ write64(phys, value.u64[0]);
+ write64(phys + 8, value.u64[1]);
}
}
-int32_t read_write_e16()
+static int32_t get_reg8_index(int32_t index) { return index << 2 & 0xC | index >> 2 & 1; }
+
+static int32_t read_reg8(int32_t index)
{
- if(*modrm_byte < 0xC0)
+ return reg8[get_reg8_index(index)];
+}
+
+static void write_reg8(int32_t index, int32_t value)
+{
+ reg8[get_reg8_index(index)] = value;
+}
+
+static int32_t get_reg16_index(int32_t index) { return index << 1; }
+
+static int32_t read_reg16(int32_t index)
+{
+ return reg16[get_reg16_index(index)];
+}
+
+static void write_reg16(int32_t index, int32_t value)
+{
+ reg16[get_reg16_index(index)] = value;
+}
+
+
+static int32_t read_reg32(int32_t index)
+{
+ return reg32s[index];
+}
+
+static void write_reg32(int32_t index, int32_t value)
+{
+ reg32s[index] = value;
+}
+
+static void write_reg_osize(int32_t index, int32_t value)
+{
+ assert(index >= 0 && index < 8);
+
+ if(is_osize_32())
{
- int32_t virt_addr = modrm_resolve(*modrm_byte);
- *phys_addr = translate_address_write(virt_addr);
- if((virt_addr & 0xFFF) == 0xFFF)
- {
- *phys_addr_high = translate_address_write(virt_addr + 1);
- dbg_assert(*phys_addr_high);
- return virt_boundary_read16(*phys_addr, *phys_addr_high);
- }
- else
- {
- *phys_addr_high = 0;
- return read16(*phys_addr);
- }
+ write_reg32(index, value);
}
else
{
- return reg16[*modrm_byte << 1 & 14];
+ write_reg16(index, value & 0xFFFF);
}
}
-void write_e16(int32_t value)
+int32_t read_mmx32s(int32_t r)
{
- if(*modrm_byte < 0xC0)
- {
- if(*phys_addr_high)
- {
- virt_boundary_write16(*phys_addr, *phys_addr_high, value);
- }
- else
- {
- write16(*phys_addr, value);
- }
- }
- else
- {
- reg16[*modrm_byte << 1 & 14] = value;
- }
+ return reg_mmx[r].u32[0];
}
-int32_t read_write_e32()
+union reg64 read_mmx64s(int32_t r)
{
- if(*modrm_byte < 0xC0)
- {
- int32_t virt_addr = modrm_resolve(*modrm_byte);
- *phys_addr = translate_address_write(virt_addr);
- if((virt_addr & 0xFFF) >= 0xFFD)
- {
- *phys_addr_high = translate_address_write(virt_addr + 3 & ~3) | (virt_addr + 3) & 3;
- dbg_assert(*phys_addr_high);
- return virt_boundary_read32s(*phys_addr, *phys_addr_high);
- }
- else
- {
- *phys_addr_high = 0;
- return read32s(*phys_addr);
- }
- }
- else
- {
- return reg32s[*modrm_byte & 7];
- }
+ return reg_mmx[r];
}
-void write_e32(int32_t value)
+void write_mmx64(int32_t r, int32_t low, int32_t high)
{
- if(*modrm_byte < 0xC0)
- {
- if(*phys_addr_high)
- {
- virt_boundary_write32(*phys_addr, *phys_addr_high, value);
- }
- else
- {
- write32(*phys_addr, value);
- }
- }
- else
- {
- reg32s[*modrm_byte & 7] = value;
- }
+ reg_mmx[r].u32[0] = low;
+ reg_mmx[r].u32[1] = high;
}
-union reg64 read_mmx64s()
+union reg64 read_xmm64s(int32_t r)
{
union reg64 x;
- int32_t i = (*modrm_byte >> 3 & 7) << 1;
- x.u32[0] = reg_mmx32s[i];
- x.u32[1] = reg_mmx32s[i | 1];
+ x.u64[0] = reg_xmm[r].u64[0];
return x;
}
-
-int32_t read_mmx_mem32s()
+union reg128 read_xmm128s(int32_t r)
{
- if(*modrm_byte < 0xC0)
- {
- return safe_read32s(modrm_resolve(*modrm_byte));
- }
- else
- {
- // Returning lower dword of qword
- return reg_mmx32s[(*modrm_byte & 7) << 1];
- }
+ return reg_xmm[r];
}
-union reg64 read_mmx_mem64s()
+void write_xmm64(int32_t r, union reg64 data)
{
- if(*modrm_byte < 0xC0)
- {
- return safe_read64s(modrm_resolve(*modrm_byte));
- }
- else
- {
- union reg64 x;
- int32_t i = (*modrm_byte & 7) << 1;
- x.u32[0] = reg_mmx32s[i];
- x.u32[1] = reg_mmx32s[i | 1];
-
- return x;
- }
+ reg_xmm[r].u64[0] = data.u64[0];
}
-void write_mmx64s(int32_t low, int32_t high)
+void write_xmm128(int32_t r, int32_t i0, int32_t i1, int32_t i2, int32_t i3)
{
- int32_t offset = (*modrm_byte >> 3 & 7) << 1;
- reg_mmx32s[offset] = low;
- reg_mmx32s[offset | 1] = high;
+ union reg128 x = { .u32 = { i0, i1, i2, i3 } };
+ reg_xmm[r] = x;
}
-void write_mmx_mem64s(int32_t low, int32_t high)
+void write_xmm_reg128(int32_t r, union reg128 data)
{
- if(*modrm_byte < 0xC0) {
- int32_t addr = modrm_resolve(*modrm_byte);
- safe_write64(addr, low, high);
- } else {
- int32_t offset = (*modrm_byte & 7) << 1;
- reg_mmx32s[offset] = low;
- reg_mmx32s[offset | 1] = high;
- }
-}
-
-union reg64 read_xmm64s()
-{
- union reg64 x;
- int32_t i = (*modrm_byte >> 3 & 7) << 2;
- x.u32[0] = reg_xmm32s[i];
- x.u32[1] = reg_xmm32s[i | 1];
- return x;
-}
-
-union reg128 read_xmm128s()
-{
- union reg128 x;
- int32_t i = (*modrm_byte >> 3 & 7) << 2;
- x.u32[0] = reg_xmm32s[i];
- x.u32[1] = reg_xmm32s[i | 1];
- x.u32[2] = reg_xmm32s[i | 2];
- x.u32[3] = reg_xmm32s[i | 3];
- return x;
-}
-
-union reg64 read_xmm_mem64s()
-{
- if(*modrm_byte < 0xC0)
- {
- return safe_read64s(modrm_resolve(*modrm_byte));
- }
- else
- {
- union reg64 x;
- int32_t i = (*modrm_byte & 7) << 2;
- x.u32[0] = reg_xmm32s[i];
- x.u32[1] = reg_xmm32s[i | 1];
- return x;
- }
-}
-
-union reg128 read_xmm_mem128s()
-{
- if(*modrm_byte < 0xC0)
- {
- return safe_read128s(modrm_resolve(*modrm_byte));
- }
- else
- {
- union reg128 x;
- int32_t i = (*modrm_byte & 7) << 2;
- x.u32[0] = reg_xmm32s[i];
- x.u32[1] = reg_xmm32s[i | 1];
- x.u32[2] = reg_xmm32s[i | 2];
- x.u32[3] = reg_xmm32s[i | 3];
- return x;
- }
-}
-
-void write_xmm64(int32_t d0, int32_t d1)
-{
- int32_t i = (*modrm_byte >> 3 & 7) << 2;
- reg_xmm32s[i] = d0;
- reg_xmm32s[i | 1] = d1;
-}
-
-void write_xmm128s(int32_t d0, int32_t d1, int32_t d2, int32_t d3)
-{
- int32_t i = (*modrm_byte >> 3 & 7) << 2;
- reg_xmm32s[i] = d0;
- reg_xmm32s[i | 1] = d1;
- reg_xmm32s[i | 2] = d2;
- reg_xmm32s[i | 3] = d3;
+ reg_xmm[r].u64[0] = data.u64[0];
+ reg_xmm[r].u64[1] = data.u64[1];
}
void clear_tlb()
@@ -791,11 +752,11 @@ int32_t read_moffs()
{
if(is_asize_32())
{
- return get_seg_prefix(DS) + read_op32s();
+ return read_imm32s();
}
else
{
- return get_seg_prefix(DS) + read_op16();
+ return read_imm16();
}
}
@@ -874,3 +835,9 @@ int32_t decr_ecx_asize()
return is_asize_32() ? --reg32s[ECX] : --reg16[CX];
}
+uint64_t read_tsc()
+{
+ double_t n = microtick() - tsc_offset[0]; // XXX: float
+ n = n * TSC_RATE;
+ return n;
+}
diff --git a/src/native/fpu.c b/src/native/fpu.c
index 12f1824b..ff59d2e6 100644
--- a/src/native/fpu.c
+++ b/src/native/fpu.c
@@ -94,8 +94,8 @@ void fpu_store_m80(uint32_t addr, double_t n)
double_t fpu_load_m80(uint32_t addr)
{
int32_t exponent = safe_read16(addr + 8);
- uint32_t low = ((uint32_t)(safe_read32s(addr))) >> 0;
- uint32_t high = ((uint32_t)(safe_read32s(addr + 4))) >> 0;
+ uint32_t low = ((uint32_t)(safe_read32s(addr)));
+ uint32_t high = ((uint32_t)(safe_read32s(addr + 4)));
int32_t sign = exponent >> 15;
exponent &= ~0x8000;
diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h
index 731f21da..bd5108e8 100644
--- a/src/native/global_pointers.h
+++ b/src/native/global_pointers.h
@@ -1,6 +1,12 @@
#ifndef _GLOBAL_POINTERS_H
#define _GLOBAL_POINTERS_H
+#include
+#include
+#include
+#include "const.h"
+#include "shared.h"
+
uint8_t* const reg8 = (uint8_t* const) 4;
uint16_t* const reg16 = (uint16_t* const) 4;
int8_t* const reg8s = (int8_t* const) 4;
@@ -14,8 +20,7 @@ int32_t* const last_add_result = (int32_t* const) 524;
int32_t* const last_result = (int32_t* const) 528;
int32_t* const flags_changed = (int32_t* const) 532;
int32_t* const flags = (int32_t* const) 536;
-int32_t* const modrm_byte = (int32_t* const) 540;
-int32_t* const mul32_result = (int32_t* const) 544; // length 8
+// gap 16
bool* const a20_enabled = (bool* const) 552;
int32_t* const instruction_pointer = (int32_t* const) 556;
@@ -40,7 +45,7 @@ uint8_t* const prefixes = (uint8_t* const) 648;
int32_t* const tsc_offset = (int32_t* const) 652;
int32_t* const phys_addr = (int32_t* const) 656;
int32_t* const phys_addr_high = (int32_t* const) 660;
-int32_t* const timestamp_counter = (int32_t* const) 664;
+uint32_t* const timestamp_counter = (uint32_t* const) 664;
uint16_t* const sreg = (uint16_t* const) 668;
int32_t* const dreg = (int32_t* const) 684; // length 32
@@ -59,32 +64,17 @@ bool* const paging = (bool* const) 820;
int32_t* const mxcsr = (int32_t* const) 824;
-union reg128 {
- uint8_t u8[16];
- uint16_t u16[8];
- uint32_t u32[4];
-};
-
-union reg64 {
- int8_t s8[8];
- int16_t s16[4];
- int32_t s32[2];
- uint8_t u8[8];
- uint16_t u16[4];
- uint32_t u32[2];
- double f64[1];
-};
-
-int32_t* const reg_xmm32s = (int32_t* const) 828; // length 128
union reg128* const reg_xmm = (union reg128* const) 828; // length 128
uint8_t* const tlb_info = (uint8_t* const) 2048; // length 0x100000
uint8_t* const tlb_info_global = (uint8_t* const) (2048 + 0x100000); // length 0x100000
int32_t* const tlb_data = (int32_t* const) (2048 + 0x100000 + 0x100000); // length 0x100000*4
-uint8_t* const mem8 = (uint8_t* const) (2048 + 0x100000 * 6);
-uint16_t* const mem16 = (uint16_t* const) (2048 + 0x100000 * 6);
-int32_t* const mem32s = (int32_t* const) (2048 + 0x100000 * 6);
+uint8_t* const codegen_buffers = (uint8_t* const) (2048 + 0x100000 * 6); // length 2048
+
+uint8_t* const mem8 = (uint8_t* const) (2048 + 0x100000 * 6 + 2048);
+uint16_t* const mem16 = (uint16_t* const) (2048 + 0x100000 * 6 + 2048);
+int32_t* const mem32s = (int32_t* const) (2048 + 0x100000 * 6 + 2048);
float_t* const fpu_float32 = (float_t* const) 956;
uint8_t* const fpu_float32_byte = (uint8_t* const) 956;
@@ -107,7 +97,8 @@ double_t* const fpu_st = (double_t* const) 968;
uint8_t* const fpu_st8 = (uint8_t* const) 968;
int32_t* const fpu_st32 = (int32_t* const) 968;
-int32_t* const reg_mmx32s = (int32_t* const) 1064; // length 64
union reg64* const reg_mmx = (union reg64* const) 1064; // length 64
+uint32_t* const cache_hit = (uint32_t* const) 1280;
+uint32_t* const cache_compile = (uint32_t* const) 1284;
#endif
diff --git a/src/native/instructions.c b/src/native/instructions.c
index 7a7be636..6af7dc3b 100644
--- a/src/native/instructions.c
+++ b/src/native/instructions.c
@@ -8,6 +8,9 @@
#include "const.h"
#include "global_pointers.h"
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+
int32_t translate_address_write(int32_t);
int32_t resolve_modrm(int32_t);
@@ -45,81 +48,7 @@ int32_t resolve_modrm(int32_t);
write32(phys_addr, fun); \
}
-static int32_t get_reg8_index(int32_t index) { return index << 2 & 0xC | index >> 2 & 1; }
-
-static int32_t read_reg8(int32_t index)
-{
- return reg8[get_reg8_index(index)];
-}
-
-static void write_reg8(int32_t index, int32_t value)
-{
- reg8[get_reg8_index(index)] = value;
-}
-
-static int32_t get_reg16_index(int32_t index) { return index << 1; }
-
-static int32_t read_reg16(int32_t index)
-{
- return reg16[get_reg16_index(index)];
-}
-
-static void write_reg16(int32_t index, int32_t value)
-{
- reg16[get_reg16_index(index)] = value;
-}
-
-
-static int32_t read_reg32(int32_t index)
-{
- return reg32s[index];
-}
-
-static void write_reg32(int32_t index, int32_t value)
-{
- reg32s[index] = value;
-}
-
-
// XXX: Remove these declarations when they are implemented in C
-int32_t read_write_e8(void);
-int32_t read_write_e16(void);
-int32_t read_write_e32(void);
-int32_t read_g8(void);
-int32_t read_g16(void);
-int32_t read_g32s(void);
-
-int32_t read_e8(void);
-int32_t read_e8s(void);
-int32_t read_e16(void);
-int32_t read_e16s(void);
-int32_t read_e32s(void);
-
-void write_e8(int32_t);
-void write_e16(int32_t);
-void write_e32(int32_t);
-
-void write_reg_e16(int32_t);
-void write_reg_e32(int32_t);
-
-void set_e8(int32_t);
-void set_e16(int32_t);
-void set_e32(int32_t);
-
-void write_g8(int32_t);
-void write_g16(int32_t);
-void write_g32(int32_t);
-
-int32_t read_op8(void);
-int32_t read_op8s(void);
-int32_t read_op16(void);
-int32_t read_op32s(void);
-
-int32_t read_disp8(void);
-int32_t read_disp16(void);
-
-int32_t read_moffs(void);
-
void push16(int32_t);
void push32(int32_t);
@@ -235,7 +164,7 @@ int32_t test_be(void);
int32_t test_l(void);
int32_t test_le(void);
-void jmpcc8(bool);
+void jmpcc8(bool, int32_t);
void far_jump(int32_t, int32_t, int32_t);
void far_return(int32_t, int32_t, int32_t);
@@ -258,9 +187,9 @@ void diverged(void);
int32_t xchg8(int32_t, int32_t);
int32_t xchg16(int32_t, int32_t);
-int32_t xchg16r(int32_t);
+void xchg16r(int32_t);
int32_t xchg32(int32_t, int32_t);
-int32_t xchg32r(int32_t);
+void xchg32r(int32_t);
int32_t loop(int32_t);
int32_t loope(int32_t);
@@ -304,6 +233,19 @@ void fwait(void);
static void name ## _reg(int32_t r1) { int32_t ___ = read_reg32(r1); write_reg32(r1, fun); }
+#define DEFINE_MODRM_INSTR2_READ_WRITE_8(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE8(addr, fun) } \
+ static void name ## _reg(int32_t r1, int32_t imm) { int32_t ___ = read_reg8(r1); write_reg8(r1, fun); }
+
+#define DEFINE_MODRM_INSTR2_READ_WRITE_16(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE16(addr, fun) } \
+ static void name ## _reg(int32_t r1, int32_t imm) { int32_t ___ = read_reg16(r1); write_reg16(r1, fun); }
+
+#define DEFINE_MODRM_INSTR2_READ_WRITE_32(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE32(addr, fun) } \
+ static void name ## _reg(int32_t r1, int32_t imm) { int32_t ___ = read_reg32(r1); write_reg32(r1, fun); }
+
+
#define DEFINE_MODRM_INSTR_READ_WRITE_8(name, fun) \
static void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE8(addr, fun) } \
static void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg8(r1); write_reg8(r1, fun); }
@@ -330,6 +272,19 @@ void fwait(void);
static void name ## _reg(int32_t r1) { int32_t ___ = read_reg32(r1); fun; }
+#define DEFINE_MODRM_INSTR2_READ8(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t imm) { int32_t ___ = safe_read8(addr); fun; } \
+ static void name ## _reg(int32_t r1, int32_t imm) { int32_t ___ = read_reg8(r1); fun; }
+
+#define DEFINE_MODRM_INSTR2_READ16(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t imm) { int32_t ___ = safe_read16(addr); fun; } \
+ static void name ## _reg(int32_t r1, int32_t imm) { int32_t ___ = read_reg16(r1); fun; }
+
+#define DEFINE_MODRM_INSTR2_READ32(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t imm) { int32_t ___ = safe_read32s(addr); fun; } \
+ static void name ## _reg(int32_t r1, int32_t imm) { int32_t ___ = read_reg32(r1); fun; }
+
+
#define DEFINE_MODRM_INSTR_READ8(name, fun) \
static void name ## _mem(int32_t addr, int32_t r) { int32_t ___ = safe_read8(addr); fun; } \
static void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg8(r1); fun; }
@@ -349,9 +304,9 @@ DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_01, add32(___, read_reg32(r)))
DEFINE_MODRM_INSTR_READ8(instr_02, write_reg8(r, add8(read_reg8(r), ___)))
DEFINE_MODRM_INSTR_READ16(instr16_03, write_reg16(r, add16(read_reg16(r), ___)))
DEFINE_MODRM_INSTR_READ32(instr32_03, write_reg32(r, add32(read_reg32(r), ___)))
-static void instr_04() { reg8[AL] = add8(reg8[AL], read_op8()); }
-static void instr16_05() { reg16[AX] = add16(reg16[AX], read_op16()); }
-static void instr32_05() { reg32s[EAX] = add32(reg32s[EAX], read_op32s()); }
+static void instr_04(int32_t imm8) { reg8[AL] = add8(reg8[AL], imm8); }
+static void instr16_05(int32_t imm16) { reg16[AX] = add16(reg16[AX], imm16); }
+static void instr32_05(int32_t imm32) { reg32s[EAX] = add32(reg32s[EAX], imm32); }
static void instr16_06() { push16(sreg[ES]); }
static void instr32_06() { push32(sreg[ES]); }
@@ -370,9 +325,9 @@ DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_09, or32(___, read_reg32(r)))
DEFINE_MODRM_INSTR_READ8(instr_0A, write_reg8(r, or8(read_reg8(r), ___)))
DEFINE_MODRM_INSTR_READ16(instr16_0B, write_reg16(r, or16(read_reg16(r), ___)))
DEFINE_MODRM_INSTR_READ32(instr32_0B, write_reg32(r, or32(read_reg32(r), ___)))
-static void instr_0C() { reg8[AL] = or8(reg8[AL], read_op8()); }
-static void instr16_0D() { reg16[AX] = or16(reg16[AX], read_op16()); }
-static void instr32_0D() { reg32s[EAX] = or32(reg32s[EAX], read_op32s()); }
+static void instr_0C(int32_t imm8) { reg8[AL] = or8(reg8[AL], imm8); }
+static void instr16_0D(int32_t imm16) { reg16[AX] = or16(reg16[AX], imm16); }
+static void instr32_0D(int32_t imm32) { reg32s[EAX] = or32(reg32s[EAX], imm32); }
static void instr16_0E() { push16(sreg[CS]); }
@@ -391,9 +346,9 @@ DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_11, adc32(___, read_reg32(r)))
DEFINE_MODRM_INSTR_READ8(instr_12, write_reg8(r, adc8(read_reg8(r), ___)))
DEFINE_MODRM_INSTR_READ16(instr16_13, write_reg16(r, adc16(read_reg16(r), ___)))
DEFINE_MODRM_INSTR_READ32(instr32_13, write_reg32(r, adc32(read_reg32(r), ___)))
-static void instr_14() { reg8[AL] = adc8(reg8[AL], read_op8()); }
-static void instr16_15() { reg16[AX] = adc16(reg16[AX], read_op16()); }
-static void instr32_15() { reg32s[EAX] = adc32(reg32s[EAX], read_op32s()); }
+static void instr_14(int32_t imm8) { reg8[AL] = adc8(reg8[AL], imm8); }
+static void instr16_15(int32_t imm16) { reg16[AX] = adc16(reg16[AX], imm16); }
+static void instr32_15(int32_t imm32) { reg32s[EAX] = adc32(reg32s[EAX], imm32); }
static void instr16_16() { push16(sreg[SS]); }
static void instr32_16() { push32(sreg[SS]); }
@@ -401,13 +356,13 @@ static void instr16_17() {
switch_seg(SS, safe_read16(get_stack_pointer(0)));
adjust_stack_reg(2);
clear_prefixes();
- cycle_internal();
+ //cycle_internal();
}
static void instr32_17() {
switch_seg(SS, safe_read32s(get_stack_pointer(0)) & 0xFFFF);
adjust_stack_reg(4);
clear_prefixes();
- cycle_internal();
+ //cycle_internal();
}
DEFINE_MODRM_INSTR_READ_WRITE_8(instr_18, sbb8(___, read_reg8(r)))
@@ -416,9 +371,9 @@ DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_19, sbb32(___, read_reg32(r)))
DEFINE_MODRM_INSTR_READ8(instr_1A, write_reg8(r, sbb8(read_reg8(r), ___)))
DEFINE_MODRM_INSTR_READ16(instr16_1B, write_reg16(r, sbb16(read_reg16(r), ___)))
DEFINE_MODRM_INSTR_READ32(instr32_1B, write_reg32(r, sbb32(read_reg32(r), ___)))
-static void instr_1C() { reg8[AL] = sbb8(reg8[AL], read_op8()); }
-static void instr16_1D() { reg16[AX] = sbb16(reg16[AX], read_op16()); }
-static void instr32_1D() { reg32s[EAX] = sbb32(reg32s[EAX], read_op32s()); }
+static void instr_1C(int32_t imm8) { reg8[AL] = sbb8(reg8[AL], imm8); }
+static void instr16_1D(int32_t imm16) { reg16[AX] = sbb16(reg16[AX], imm16); }
+static void instr32_1D(int32_t imm32) { reg32s[EAX] = sbb32(reg32s[EAX], imm32); }
static void instr16_1E() { push16(sreg[DS]); }
@@ -438,9 +393,9 @@ DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_21, and32(___, read_reg32(r)))
DEFINE_MODRM_INSTR_READ8(instr_22, write_reg8(r, and8(read_reg8(r), ___)))
DEFINE_MODRM_INSTR_READ16(instr16_23, write_reg16(r, and16(read_reg16(r), ___)))
DEFINE_MODRM_INSTR_READ32(instr32_23, write_reg32(r, and32(read_reg32(r), ___)))
-static void instr_24() { reg8[AL] = and8(reg8[AL], read_op8()); }
-static void instr16_25() { reg16[AX] = and16(reg16[AX], read_op16()); }
-static void instr32_25() { reg32s[EAX] = and32(reg32s[EAX], read_op32s()); }
+static void instr_24(int32_t imm8) { reg8[AL] = and8(reg8[AL], imm8); }
+static void instr16_25(int32_t imm16) { reg16[AX] = and16(reg16[AX], imm16); }
+static void instr32_25(int32_t imm32) { reg32s[EAX] = and32(reg32s[EAX], imm32); }
static void instr_26() { segment_prefix_op(ES); }
@@ -452,9 +407,9 @@ DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_29, sub32(___, read_reg32(r)))
DEFINE_MODRM_INSTR_READ8(instr_2A, write_reg8(r, sub8(read_reg8(r), ___)))
DEFINE_MODRM_INSTR_READ16(instr16_2B, write_reg16(r, sub16(read_reg16(r), ___)))
DEFINE_MODRM_INSTR_READ32(instr32_2B, write_reg32(r, sub32(read_reg32(r), ___)))
-static void instr_2C() { reg8[AL] = sub8(reg8[AL], read_op8()); }
-static void instr16_2D() { reg16[AX] = sub16(reg16[AX], read_op16()); }
-static void instr32_2D() { reg32s[EAX] = sub32(reg32s[EAX], read_op32s()); }
+static void instr_2C(int32_t imm8) { reg8[AL] = sub8(reg8[AL], imm8); }
+static void instr16_2D(int32_t imm16) { reg16[AX] = sub16(reg16[AX], imm16); }
+static void instr32_2D(int32_t imm32) { reg32s[EAX] = sub32(reg32s[EAX], imm32); }
static void instr_2E() { segment_prefix_op(CS); }
static void instr_2F() { bcd_das(); }
@@ -465,9 +420,9 @@ DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_31, xor32(___, read_reg32(r)))
DEFINE_MODRM_INSTR_READ8(instr_32, write_reg8(r, xor8(read_reg8(r), ___)))
DEFINE_MODRM_INSTR_READ16(instr16_33, write_reg16(r, xor16(read_reg16(r), ___)))
DEFINE_MODRM_INSTR_READ32(instr32_33, write_reg32(r, xor32(read_reg32(r), ___)))
-static void instr_34() { reg8[AL] = xor8(reg8[AL], read_op8()); }
-static void instr16_35() { reg16[AX] = xor16(reg16[AX], read_op16()); }
-static void instr32_35() { reg32s[EAX] = xor32(reg32s[EAX], read_op32s()); }
+static void instr_34(int32_t imm8) { reg8[AL] = xor8(reg8[AL], imm8); }
+static void instr16_35(int32_t imm16) { reg16[AX] = xor16(reg16[AX], imm16); }
+static void instr32_35(int32_t imm32) { reg32s[EAX] = xor32(reg32s[EAX], imm32); }
static void instr_36() { segment_prefix_op(SS); }
static void instr_37() { bcd_aaa(); }
@@ -478,9 +433,9 @@ DEFINE_MODRM_INSTR_READ32(instr32_39, cmp32(___, read_reg32(r)))
DEFINE_MODRM_INSTR_READ8(instr_3A, cmp8(read_reg8(r), ___))
DEFINE_MODRM_INSTR_READ16(instr16_3B, cmp16(read_reg16(r), ___))
DEFINE_MODRM_INSTR_READ32(instr32_3B, cmp32(read_reg32(r), ___))
-static void instr_3C() { cmp8(reg8[AL], read_op8()); }
-static void instr16_3D() { cmp16(reg16[AX], read_op16()); }
-static void instr32_3D() { cmp32(reg32s[EAX], read_op32s()); }
+static void instr_3C(int32_t imm8) { cmp8(reg8[AL], imm8); }
+static void instr16_3D(int32_t imm16) { cmp16(reg16[AX], imm16); }
+static void instr32_3D(int32_t imm32) { cmp32(reg32s[EAX], imm32); }
static void instr_3E() { segment_prefix_op(DS); }
static void instr_3F() { bcd_aas(); }
@@ -593,17 +548,21 @@ static void instr_67() {
*prefixes = 0;
}
-static void instr16_68() { push16(read_op16()); }
-static void instr32_68() { push32(read_op32s()); }
+static void instr16_68(int32_t imm16) { push16(imm16); }
+static void instr32_68(int32_t imm32) { push32(imm32); }
-DEFINE_MODRM_INSTR_READ16(instr16_69, write_reg16(r, imul_reg16(___ << 16 >> 16, read_op16() << 16 >> 16)))
-DEFINE_MODRM_INSTR_READ32(instr32_69, write_reg32(r, imul_reg32(___, read_op32s())))
+static void instr16_69_mem(int32_t addr, int32_t r, int32_t imm) { write_reg16(r, imul_reg16(safe_read16(addr) << 16 >> 16, imm << 16 >> 16)); }
+static void instr16_69_reg(int32_t r1, int32_t r, int32_t imm) { write_reg16(r, imul_reg16(read_reg16(r1) << 16 >> 16, imm << 16 >> 16)); }
+static void instr32_69_mem(int32_t addr, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(safe_read32s(addr), imm)); }
+static void instr32_69_reg(int32_t r1, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(read_reg32(r1), imm)); }
-static void instr16_6A() { push16(read_op8s()); }
-static void instr32_6A() { push32(read_op8s()); }
+static void instr16_6A(int32_t imm8) { push16(imm8); }
+static void instr32_6A(int32_t imm8) { push32(imm8); }
-DEFINE_MODRM_INSTR_READ16(instr16_6B, write_reg16(r, imul_reg16(___ << 16 >> 16, read_op8s())))
-DEFINE_MODRM_INSTR_READ32(instr32_6B, write_reg32(r, imul_reg32(___, read_op8s())))
+static void instr16_6B_mem(int32_t addr, int32_t r, int32_t imm) { write_reg16(r, imul_reg16(safe_read16(addr) << 16 >> 16, imm)); }
+static void instr16_6B_reg(int32_t r1, int32_t r, int32_t imm) { write_reg16(r, imul_reg16(read_reg16(r1) << 16 >> 16, imm)); }
+static void instr32_6B_mem(int32_t addr, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(safe_read32s(addr), imm)); }
+static void instr32_6B_reg(int32_t r1, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(read_reg32(r1), imm)); }
static void instr_6C() { insb(); }
static void instr16_6D() { insw(); }
@@ -612,82 +571,82 @@ static void instr_6E() { outsb(); }
static void instr16_6F() { outsw(); }
static void instr32_6F() { outsd(); }
-static void instr_70() { jmpcc8( test_o()); }
-static void instr_71() { jmpcc8(!test_o()); }
-static void instr_72() { jmpcc8( test_b()); }
-static void instr_73() { jmpcc8(!test_b()); }
-static void instr_74() { jmpcc8( test_z()); }
-static void instr_75() { jmpcc8(!test_z()); }
-static void instr_76() { jmpcc8( test_be()); }
-static void instr_77() { jmpcc8(!test_be()); }
-static void instr_78() { jmpcc8( test_s()); }
-static void instr_79() { jmpcc8(!test_s()); }
-static void instr_7A() { jmpcc8( test_p()); }
-static void instr_7B() { jmpcc8(!test_p()); }
-static void instr_7C() { jmpcc8( test_l()); }
-static void instr_7D() { jmpcc8(!test_l()); }
-static void instr_7E() { jmpcc8( test_le()); }
-static void instr_7F() { jmpcc8(!test_le()); }
+static void instr_70(int32_t imm8) { jmpcc8( test_o(), imm8); }
+static void instr_71(int32_t imm8) { jmpcc8(!test_o(), imm8); }
+static void instr_72(int32_t imm8) { jmpcc8( test_b(), imm8); }
+static void instr_73(int32_t imm8) { jmpcc8(!test_b(), imm8); }
+static void instr_74(int32_t imm8) { jmpcc8( test_z(), imm8); }
+static void instr_75(int32_t imm8) { jmpcc8(!test_z(), imm8); }
+static void instr_76(int32_t imm8) { jmpcc8( test_be(), imm8); }
+static void instr_77(int32_t imm8) { jmpcc8(!test_be(), imm8); }
+static void instr_78(int32_t imm8) { jmpcc8( test_s(), imm8); }
+static void instr_79(int32_t imm8) { jmpcc8(!test_s(), imm8); }
+static void instr_7A(int32_t imm8) { jmpcc8( test_p(), imm8); }
+static void instr_7B(int32_t imm8) { jmpcc8(!test_p(), imm8); }
+static void instr_7C(int32_t imm8) { jmpcc8( test_l(), imm8); }
+static void instr_7D(int32_t imm8) { jmpcc8(!test_l(), imm8); }
+static void instr_7E(int32_t imm8) { jmpcc8( test_le(), imm8); }
+static void instr_7F(int32_t imm8) { jmpcc8(!test_le(), imm8); }
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_80_0, add8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_80_1, or8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_80_2, adc8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_80_3, sbb8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_80_4, and8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_80_5, sub8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_80_6, xor8(___, read_op8()))
-static void instr_80_7_reg(int32_t r) { cmp8(read_reg8(r), read_op8()); }
-static void instr_80_7_mem(int32_t addr) { cmp8(safe_read8(addr), read_op8()); }
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_0, add8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_1, or8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_2, adc8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_3, sbb8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_4, and8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_5, sub8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_6, xor8(___, imm))
+static void instr_80_7_reg(int32_t r, int32_t imm) { cmp8(read_reg8(r), imm); }
+static void instr_80_7_mem(int32_t addr, int32_t imm) { cmp8(safe_read8(addr), imm); }
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_81_0, add16(___, read_op16()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_81_1, or16(___, read_op16()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_81_2, adc16(___, read_op16()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_81_3, sbb16(___, read_op16()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_81_4, and16(___, read_op16()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_81_5, sub16(___, read_op16()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_81_6, xor16(___, read_op16()))
-static void instr16_81_7_reg(int32_t r) { cmp16(read_reg16(r), read_op16()); }
-static void instr16_81_7_mem(int32_t addr) { cmp16(safe_read16(addr), read_op16()); }
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_81_0, add16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_81_1, or16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_81_2, adc16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_81_3, sbb16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_81_4, and16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_81_5, sub16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_81_6, xor16(___, imm))
+static void instr16_81_7_reg(int32_t r, int32_t imm) { cmp16(read_reg16(r), imm); }
+static void instr16_81_7_mem(int32_t addr, int32_t imm) { cmp16(safe_read16(addr), imm); }
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_81_0, add32(___, read_op32s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_81_1, or32(___, read_op32s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_81_2, adc32(___, read_op32s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_81_3, sbb32(___, read_op32s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_81_4, and32(___, read_op32s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_81_5, sub32(___, read_op32s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_81_6, xor32(___, read_op32s()))
-static void instr32_81_7_reg(int32_t r) { cmp32(read_reg32(r), read_op32s()); }
-static void instr32_81_7_mem(int32_t addr) { cmp32(safe_read32s(addr), read_op32s()); }
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_81_0, add32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_81_1, or32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_81_2, adc32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_81_3, sbb32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_81_4, and32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_81_5, sub32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_81_6, xor32(___, imm))
+static void instr32_81_7_reg(int32_t r, int32_t imm) { cmp32(read_reg32(r), imm); }
+static void instr32_81_7_mem(int32_t addr, int32_t imm) { cmp32(safe_read32s(addr), imm); }
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_82_0, add8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_82_1, or8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_82_2, adc8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_82_3, sbb8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_82_4, and8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_82_5, sub8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_82_6, xor8(___, read_op8()))
-static void instr_82_7_reg(int32_t r) { cmp8(read_reg8(r), read_op8()); }
-static void instr_82_7_mem(int32_t addr) { cmp8(safe_read8(addr), read_op8()); }
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_82_0, add8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_82_1, or8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_82_2, adc8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_82_3, sbb8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_82_4, and8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_82_5, sub8(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_82_6, xor8(___, imm))
+static void instr_82_7_reg(int32_t r, int32_t imm) { cmp8(read_reg8(r), imm); }
+static void instr_82_7_mem(int32_t addr, int32_t imm) { cmp8(safe_read8(addr), imm); }
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_83_0, add16(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_83_1, or16(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_83_2, adc16(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_83_3, sbb16(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_83_4, and16(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_83_5, sub16(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_83_6, xor16(___, read_op8s()))
-static void instr16_83_7_reg(int32_t r) { cmp16(read_reg16(r), read_op8s()); }
-static void instr16_83_7_mem(int32_t addr) { cmp16(safe_read16(addr), read_op8s()); }
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_83_0, add16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_83_1, or16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_83_2, adc16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_83_3, sbb16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_83_4, and16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_83_5, sub16(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_83_6, xor16(___, imm))
+static void instr16_83_7_reg(int32_t r, int32_t imm) { cmp16(read_reg16(r), imm); }
+static void instr16_83_7_mem(int32_t addr, int32_t imm) { cmp16(safe_read16(addr), imm); }
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_83_0, add32(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_83_1, or32(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_83_2, adc32(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_83_3, sbb32(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_83_4, and32(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_83_5, sub32(___, read_op8s()))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_83_6, xor32(___, read_op8s()))
-static void instr32_83_7_reg(int32_t r) { cmp32(read_reg32(r), read_op8s()); }
-static void instr32_83_7_mem(int32_t addr) { cmp32(safe_read32s(addr), read_op8s()); }
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_83_0, add32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_83_1, or32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_83_2, adc32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_83_3, sbb32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_83_4, and32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_83_5, sub32(___, imm))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_83_6, xor32(___, imm))
+static void instr32_83_7_reg(int32_t r, int32_t imm) { cmp32(read_reg32(r), imm); }
+static void instr32_83_7_mem(int32_t addr, int32_t imm) { cmp32(safe_read32s(addr), imm); }
DEFINE_MODRM_INSTR_READ8(instr_84, test8(___, read_reg8(r)))
DEFINE_MODRM_INSTR_READ16(instr16_85, test16(___, read_reg16(r)))
@@ -708,20 +667,30 @@ DEFINE_MODRM_INSTR_READ8(instr_8A, write_reg8(r, ___))
DEFINE_MODRM_INSTR_READ16(instr16_8B, write_reg16(r, ___))
DEFINE_MODRM_INSTR_READ32(instr32_8B, write_reg32(r, ___))
-static void instr16_8C_reg(int32_t r, int32_t seg) { write_reg16(r, sreg[seg]); }
-static void instr16_8C_mem(int32_t addr, int32_t seg) { safe_write16(addr, sreg[seg]); }
-static void instr32_8C_reg(int32_t r, int32_t seg) { write_reg32(r, sreg[seg]); }
-static void instr32_8C_mem(int32_t addr, int32_t seg) { safe_write32(addr, sreg[seg]); }
+void instr_8C_check_sreg(int32_t sreg) {
+ if(sreg >= 6)
+ {
+ dbg_log("mov sreg #ud");
+ trigger_ud();
+ }
+}
+static void instr16_8C_reg(int32_t r, int32_t seg) { instr_8C_check_sreg(seg); write_reg16(r, sreg[seg]); }
+static void instr16_8C_mem(int32_t addr, int32_t seg) { instr_8C_check_sreg(seg); safe_write16(addr, sreg[seg]); }
+static void instr32_8C_reg(int32_t r, int32_t seg) { instr_8C_check_sreg(seg); write_reg32(r, sreg[seg]); }
+static void instr32_8C_mem(int32_t addr, int32_t seg) { instr_8C_check_sreg(seg); safe_write32(addr, sreg[seg]); }
static void instr16_8D_reg(int32_t r, int32_t r2)
{
dbg_log("lea #ud");
trigger_ud();
}
-static void instr16_8D_mem_pre()
+static int32_t instr16_8D_modrm_resolve(int32_t modrm_byte)
{
// override prefix, so modrm_resolve does not return the segment part
*prefixes |= SEG_PREFIX_ZERO;
+ int32_t result = modrm_resolve(modrm_byte);
+ *prefixes = 0;
+ return result;
}
static void instr16_8D_mem(int32_t addr, int32_t mod)
{
@@ -734,39 +703,50 @@ static void instr32_8D_reg(int32_t r, int32_t r2)
dbg_log("lea #ud");
trigger_ud();
}
-static void instr32_8D_mem_pre()
+static int32_t instr32_8D_modrm_resolve(int32_t modrm_byte)
{
// override prefix, so modrm_resolve does not return the segment part
*prefixes |= SEG_PREFIX_ZERO;
+ int32_t result = modrm_resolve(modrm_byte);
+ *prefixes = 0;
+ return result;
}
static void instr32_8D_mem(int32_t addr, int32_t mod) {
// lea
reg32s[mod] = addr;
- *prefixes = 0;
}
static void instr_8E_helper(int32_t data, int32_t mod)
{
- switch_seg(mod, data);
-
- if(mod == SS)
+ if(mod == ES || mod == SS || mod == DS || mod == FS || mod == GS)
{
- // run next instruction, so no interrupts are handled
- clear_prefixes();
- cycle_internal();
+ switch_seg(mod, data);
+
+ if(mod == SS)
+ {
+ // run next instruction, so no interrupts are handled
+ clear_prefixes();
+ //cycle_internal();
+ }
+ }
+ else
+ {
+ dbg_log("mov sreg #ud");
}
}
DEFINE_MODRM_INSTR_READ16(instr_8E, instr_8E_helper(___, r))
-static void instr16_8F_0_mem_pre()
+static int32_t instr16_8F_0_modrm_resolve(int32_t modrm_byte)
{
for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; // XXX
adjust_stack_reg(2);
+ int32_t result = modrm_resolve(modrm_byte);
+ adjust_stack_reg(-2);
+ return result;
}
static void instr16_8F_0_mem(int32_t addr)
{
// pop
- adjust_stack_reg(-2);
int32_t sp = safe_read16(get_stack_pointer(0));
safe_write16(addr, sp);
adjust_stack_reg(2);
@@ -775,18 +755,22 @@ static void instr16_8F_0_reg(int32_t r)
{
write_reg16(r, pop16());
}
-static void instr32_8F_0_mem_pre()
+static int32_t instr32_8F_0_modrm_resolve(int32_t modrm_byte)
{
+ // prevent page faults during modrm_resolve
for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; // XXX
+
+ // esp must be adjusted before calling modrm_resolved
+ // The order of calls is: instr32_8F_0_mem_pre -> modrm_resolve -> instr32_8F_0_mem
adjust_stack_reg(4);
+
+ int32_t result = modrm_resolve(modrm_byte);
+ adjust_stack_reg(-4);
+ return result;
}
static void instr32_8F_0_mem(int32_t addr)
{
- // Before attempting a write that might cause a page fault,
- // we must set esp to the old value. Fuck Intel.
- adjust_stack_reg(-4);
int32_t sp = safe_read32s(get_stack_pointer(0));
-
safe_write32(addr, sp);
adjust_stack_reg(4);
}
@@ -931,30 +915,30 @@ static void instr_9F() {
reg8[AH] = get_eflags();
}
-static void instr_A0() {
+static void instr_A0(int32_t moffs) {
// mov
- int32_t data = safe_read8(read_moffs());
+ int32_t data = safe_read8(get_seg_prefix_ds(moffs));
reg8[AL] = data;
}
-static void instr16_A1() {
+static void instr16_A1(int32_t moffs) {
// mov
- int32_t data = safe_read16(read_moffs());
+ int32_t data = safe_read16(get_seg_prefix_ds(moffs));
reg16[AX] = data;
}
-static void instr32_A1() {
- int32_t data = safe_read32s(read_moffs());
+static void instr32_A1(int32_t moffs) {
+ int32_t data = safe_read32s(get_seg_prefix_ds(moffs));
reg32s[EAX] = data;
}
-static void instr_A2() {
+static void instr_A2(int32_t moffs) {
// mov
- safe_write8(read_moffs(), reg8[AL]);
+ safe_write8(get_seg_prefix_ds(moffs), reg8[AL]);
}
-static void instr16_A3() {
+static void instr16_A3(int32_t moffs) {
// mov
- safe_write16(read_moffs(), reg16[AX]);
+ safe_write16(get_seg_prefix_ds(moffs), reg16[AX]);
}
-static void instr32_A3() {
- safe_write32(read_moffs(), reg32s[EAX]);
+static void instr32_A3(int32_t moffs) {
+ safe_write32(get_seg_prefix_ds(moffs), reg32s[EAX]);
}
static void instr_A4() { movsb(); }
@@ -964,14 +948,14 @@ static void instr_A6() { cmpsb(); }
static void instr16_A7() { cmpsw(); }
static void instr32_A7() { cmpsd(); }
-static void instr_A8() {
- test8(reg8[AL], read_op8());
+static void instr_A8(int32_t imm8) {
+ test8(reg8[AL], imm8);
}
-static void instr16_A9() {
- test16(reg16[AX], read_op16());
+static void instr16_A9(int32_t imm16) {
+ test16(reg16[AX], imm16);
}
-static void instr32_A9() {
- test32(reg32s[EAX], read_op32s());
+static void instr32_A9(int32_t imm32) {
+ test32(reg32s[EAX], imm32);
}
static void instr_AA() { stosb(); }
@@ -985,62 +969,61 @@ static void instr16_AF() { scasw(); }
static void instr32_AF() { scasd(); }
-static void instr_B0() { reg8[AL] = read_op8(); }
-static void instr_B1() { reg8[CL] = read_op8(); }
-static void instr_B2() { reg8[DL] = read_op8(); }
-static void instr_B3() { reg8[BL] = read_op8(); }
-static void instr_B4() { reg8[AH] = read_op8(); }
-static void instr_B5() { reg8[CH] = read_op8(); }
-static void instr_B6() { reg8[DH] = read_op8(); }
-static void instr_B7() { reg8[BH] = read_op8(); }
+static void instr_B0(int32_t imm8) { reg8[AL] = imm8; }
+static void instr_B1(int32_t imm8) { reg8[CL] = imm8; }
+static void instr_B2(int32_t imm8) { reg8[DL] = imm8; }
+static void instr_B3(int32_t imm8) { reg8[BL] = imm8; }
+static void instr_B4(int32_t imm8) { reg8[AH] = imm8; }
+static void instr_B5(int32_t imm8) { reg8[CH] = imm8; }
+static void instr_B6(int32_t imm8) { reg8[DH] = imm8; }
+static void instr_B7(int32_t imm8) { reg8[BH] = imm8; }
-static void instr16_B8() { reg16[AX] = read_op16(); }
-static void instr32_B8() { reg32s[EAX] = read_op32s(); }
-static void instr16_B9() { reg16[CX] = read_op16(); }
-static void instr32_B9() { reg32s[ECX] = read_op32s(); }
-static void instr16_BA() { reg16[DX] = read_op16(); }
-static void instr32_BA() { reg32s[EDX] = read_op32s(); }
-static void instr16_BB() { reg16[BX] = read_op16(); }
-static void instr32_BB() { reg32s[EBX] = read_op32s(); }
-static void instr16_BC() { reg16[SP] = read_op16(); }
-static void instr32_BC() { reg32s[ESP] = read_op32s(); }
-static void instr16_BD() { reg16[BP] = read_op16(); }
-static void instr32_BD() { reg32s[EBP] = read_op32s(); }
-static void instr16_BE() { reg16[SI] = read_op16(); }
-static void instr32_BE() { reg32s[ESI] = read_op32s(); }
-static void instr16_BF() { reg16[DI] = read_op16(); }
-static void instr32_BF() { reg32s[EDI] = read_op32s(); }
+static void instr16_B8(int32_t imm) { reg16[AX] = imm; }
+static void instr32_B8(int32_t imm) { reg32s[EAX] = imm; }
+static void instr16_B9(int32_t imm) { reg16[CX] = imm; }
+static void instr32_B9(int32_t imm) { reg32s[ECX] = imm; }
+static void instr16_BA(int32_t imm) { reg16[DX] = imm; }
+static void instr32_BA(int32_t imm) { reg32s[EDX] = imm; }
+static void instr16_BB(int32_t imm) { reg16[BX] = imm; }
+static void instr32_BB(int32_t imm) { reg32s[EBX] = imm; }
+static void instr16_BC(int32_t imm) { reg16[SP] = imm; }
+static void instr32_BC(int32_t imm) { reg32s[ESP] = imm; }
+static void instr16_BD(int32_t imm) { reg16[BP] = imm; }
+static void instr32_BD(int32_t imm) { reg32s[EBP] = imm; }
+static void instr16_BE(int32_t imm) { reg16[SI] = imm; }
+static void instr32_BE(int32_t imm) { reg32s[ESI] = imm; }
+static void instr16_BF(int32_t imm) { reg16[DI] = imm; }
+static void instr32_BF(int32_t imm) { reg32s[EDI] = imm; }
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_C0_0, rol8(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_C0_1, ror8(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_C0_2, rcl8(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_C0_3, rcr8(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_C0_4, shl8(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_C0_5, shr8(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_C0_6, shl8(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_C0_7, sar8(___, read_op8() & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_C0_0, rol8(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_C0_1, ror8(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_C0_2, rcl8(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_C0_3, rcr8(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_C0_4, shl8(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_C0_5, shr8(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_C0_6, shl8(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_C0_7, sar8(___, imm & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_C1_0, rol16(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_C1_1, ror16(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_C1_2, rcl16(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_C1_3, rcr16(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_C1_4, shl16(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_C1_5, shr16(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_C1_6, shl16(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_C1_7, sar16(___, read_op8() & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_C1_0, rol16(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_C1_1, ror16(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_C1_2, rcl16(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_C1_3, rcr16(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_C1_4, shl16(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_C1_5, shr16(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_C1_6, shl16(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_16(instr16_C1_7, sar16(___, imm & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_C1_0, rol32(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_C1_1, ror32(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_C1_2, rcl32(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_C1_3, rcr32(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_C1_4, shl32(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_C1_5, shr32(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_C1_6, shl32(___, read_op8() & 31))
-DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_C1_7, sar32(___, read_op8() & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_0, rol32(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_1, ror32(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_2, rcl32(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_3, rcr32(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_4, shl32(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_5, shr32(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_6, shl32(___, imm & 31))
+DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_7, sar32(___, imm & 31))
-static void instr16_C2() {
+static void instr16_C2(int32_t imm16) {
// retn
- int32_t imm16 = read_op16();
int32_t cs = get_seg(CS);
instruction_pointer[0] = cs + pop16();
@@ -1048,9 +1031,8 @@ static void instr16_C2() {
adjust_stack_reg(imm16);
diverged();
}
-static void instr32_C2() {
+static void instr32_C2(int32_t imm16) {
// retn
- int32_t imm16 = read_op16();
int32_t cs = get_seg(CS);
int32_t ip = pop32s();
@@ -1091,12 +1073,12 @@ static void instr32_C5_mem(int32_t addr, int32_t r) {
lss32(addr, r, DS);
}
-static void instr_C6_0_reg(int32_t r) { write_reg8(r, read_op8()); }
-static void instr_C6_0_mem(int32_t addr) { safe_write8(addr, read_op8()); }
-static void instr16_C7_0_reg(int32_t r) { write_reg16(r, read_op16()); }
-static void instr16_C7_0_mem(int32_t addr) { safe_write16(addr, read_op16()); }
-static void instr32_C7_0_reg(int32_t r) { write_reg32(r, read_op32s()); }
-static void instr32_C7_0_mem(int32_t addr) { safe_write32(addr, read_op32s()); }
+static void instr_C6_0_reg(int32_t r, int32_t imm) { write_reg8(r, imm); }
+static void instr_C6_0_mem(int32_t addr, int32_t imm) { safe_write8(addr, imm); }
+static void instr16_C7_0_reg(int32_t r, int32_t imm) { write_reg16(r, imm); }
+static void instr16_C7_0_mem(int32_t addr, int32_t imm) { safe_write16(addr, imm); }
+static void instr32_C7_0_reg(int32_t r, int32_t imm) { write_reg32(r, imm); }
+static void instr32_C7_0_mem(int32_t addr, int32_t imm) { safe_write32(addr, imm); }
static void instr16_C8(int32_t size, int32_t nesting) { enter16(size, nesting); }
static void instr32_C8(int32_t size, int32_t nesting) { enter32(size, nesting); }
@@ -1113,18 +1095,16 @@ static void instr32_C9() {
set_stack_reg(old_vbp + 4);
reg32s[EBP] = new_ebp;
}
-static void instr16_CA() {
+static void instr16_CA(int32_t imm16) {
// retf
- int32_t imm16 = read_op16();
int32_t ip = safe_read16(get_stack_pointer(0));
int32_t cs = safe_read16(get_stack_pointer(2));
far_return(ip, cs, imm16);
diverged();
}
-static void instr32_CA() {
+static void instr32_CA(int32_t imm16) {
// retf
- int32_t imm16 = read_op16();
int32_t ip = safe_read32s(get_stack_pointer(0));
int32_t cs = safe_read32s(get_stack_pointer(4)) & 0xFFFF;
@@ -1158,9 +1138,8 @@ static void instr_CC() {
call_interrupt_vector(3, true, false, 0);
diverged();
}
-static void instr_CD() {
+static void instr_CD(int32_t imm8) {
// INT
- int32_t imm8 = read_op8();
call_interrupt_vector(imm8, true, false, 0);
diverged();
}
@@ -1239,11 +1218,11 @@ DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_5, shr32(___, reg8[CL] & 31))
DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_6, shl32(___, reg8[CL] & 31))
DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_7, sar32(___, reg8[CL] & 31))
-static void instr_D4() {
- bcd_aam(read_op8());
+static void instr_D4(int32_t arg) {
+ bcd_aam(arg);
}
-static void instr_D5() {
- bcd_aad(read_op8());
+static void instr_D5(int32_t arg) {
+ bcd_aad(arg);
}
static void instr_D6() {
@@ -1280,74 +1259,64 @@ static void instr_DF_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_D
static void instr_DF_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_DF_reg(0xC0 | r2 | r << 3); }
-static void instr_E0() { loopne(read_op8s()); }
-static void instr_E1() { loope(read_op8s()); }
-static void instr_E2() { loop(read_op8s()); }
-static void instr_E3() { jcxz(read_op8s()); }
+static void instr_E0(int32_t off) { loopne(off); }
+static void instr_E1(int32_t off) { loope(off); }
+static void instr_E2(int32_t off) { loop(off); }
+static void instr_E3(int32_t off) { jcxz(off); }
-static void instr_E4() {
- int32_t port = read_op8();
+static void instr_E4(int32_t port) {
test_privileges_for_io(port, 1);
reg8[AL] = io_port_read8(port);
diverged();
}
-static void instr16_E5() {
- int32_t port = read_op8();
+static void instr16_E5(int32_t port) {
test_privileges_for_io(port, 2);
reg16[AX] = io_port_read16(port);
diverged();
}
-static void instr32_E5() {
- int32_t port = read_op8();
+static void instr32_E5(int32_t port) {
test_privileges_for_io(port, 4);
reg32s[EAX] = io_port_read32(port);
diverged();
}
-static void instr_E6() {
- int32_t port = read_op8();
+static void instr_E6(int32_t port) {
test_privileges_for_io(port, 1);
io_port_write8(port, reg8[AL]);
diverged();
}
-static void instr16_E7() {
- int32_t port = read_op8();
+static void instr16_E7(int32_t port) {
test_privileges_for_io(port, 2);
io_port_write16(port, reg16[AX]);
diverged();
}
-static void instr32_E7() {
- int32_t port = read_op8();
+static void instr32_E7(int32_t port) {
test_privileges_for_io(port, 4);
io_port_write32(port, reg32s[EAX]);
diverged();
}
-static void instr16_E8() {
+static void instr16_E8(int32_t imm16) {
// call
- int32_t imm16 = read_op16();
push16(get_real_eip());
jmp_rel16(imm16);
diverged();
}
-static void instr32_E8() {
+static void instr32_E8(int32_t imm32s) {
// call
- int32_t imm32s = read_op32s();
push32(get_real_eip());
instruction_pointer[0] = instruction_pointer[0] + imm32s;
dbg_assert(is_asize_32() || get_real_eip() < 0x10000);
diverged();
}
-static void instr16_E9() {
+static void instr16_E9(int32_t imm16) {
// jmp
- int32_t imm16 = read_op16();
jmp_rel16(imm16);
diverged();
}
-static void instr32_E9() {
+static void instr32_E9(int32_t imm32s) {
// jmp
- int32_t imm32s = read_op32s();
instruction_pointer[0] = instruction_pointer[0] + imm32s;
dbg_assert(is_asize_32() || get_real_eip() < 0x10000);
diverged();
@@ -1364,9 +1333,8 @@ static void instr32_EA(int32_t new_ip, int32_t cs) {
dbg_assert(is_asize_32() || get_real_eip() < 0x10000);
diverged();
}
-static void instr_EB() {
+static void instr_EB(int32_t imm8) {
// jmp near
- int32_t imm8 = read_op8s();
instruction_pointer[0] = instruction_pointer[0] + imm8;
dbg_assert(is_asize_32() || get_real_eip() < 0x10000);
diverged();
@@ -1450,8 +1418,8 @@ static void instr_F5() {
flags_changed[0] &= ~1;
}
-DEFINE_MODRM_INSTR1_READ8(instr_F6_0, test8(___, read_op8()))
-DEFINE_MODRM_INSTR1_READ8(instr_F6_1, test8(___, read_op8()))
+DEFINE_MODRM_INSTR2_READ8(instr_F6_0, test8(___, imm))
+DEFINE_MODRM_INSTR2_READ8(instr_F6_1, test8(___, imm))
DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_F6_2, ~___)
DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_F6_3, neg8(___))
DEFINE_MODRM_INSTR1_READ8(instr_F6_4, mul8(___))
@@ -1459,8 +1427,8 @@ DEFINE_MODRM_INSTR1_READ8(instr_F6_5, imul8(___ << 24 >> 24))
DEFINE_MODRM_INSTR1_READ8(instr_F6_6, div8(___))
DEFINE_MODRM_INSTR1_READ8(instr_F6_7, idiv8(___ << 24 >> 24))
-DEFINE_MODRM_INSTR1_READ16(instr16_F7_0, test16(___, read_op16()))
-DEFINE_MODRM_INSTR1_READ16(instr16_F7_1, test16(___, read_op16()))
+DEFINE_MODRM_INSTR2_READ16(instr16_F7_0, test16(___, imm))
+DEFINE_MODRM_INSTR2_READ16(instr16_F7_1, test16(___, imm))
DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_F7_2, ~___)
DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_F7_3, neg16(___))
DEFINE_MODRM_INSTR1_READ16(instr16_F7_4, mul16(___))
@@ -1468,8 +1436,8 @@ DEFINE_MODRM_INSTR1_READ16(instr16_F7_5, imul16(___ << 16 >> 16))
DEFINE_MODRM_INSTR1_READ16(instr16_F7_6, div16(___))
DEFINE_MODRM_INSTR1_READ16(instr16_F7_7, idiv16(___ << 16 >> 16))
-DEFINE_MODRM_INSTR1_READ32(instr32_F7_0, test32(___, read_op32s()))
-DEFINE_MODRM_INSTR1_READ32(instr32_F7_1, test32(___, read_op32s()))
+DEFINE_MODRM_INSTR2_READ32(instr32_F7_0, test32(___, imm))
+DEFINE_MODRM_INSTR2_READ32(instr32_F7_1, test32(___, imm))
DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_F7_2, ~___)
DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_F7_3, neg32(___))
DEFINE_MODRM_INSTR1_READ32(instr32_F7_4, mul32(___))
@@ -1516,15 +1484,20 @@ static void instr_FB() {
// sti
//dbg_log("interrupts on");
+ int32_t old_if = flags[0] & FLAG_INTERRUPT;
+
if(!*protected_mode || ((flags[0] & FLAG_VM) ?
getiopl() == 3 : getiopl() >= *cpl))
{
flags[0] |= FLAG_INTERRUPT;
- clear_prefixes();
- cycle_internal();
+ if(old_if == 0)
+ {
+ clear_prefixes();
+ //cycle_internal();
- handle_irqs();
+ handle_irqs();
+ }
}
else
{
@@ -1682,3609 +1655,4872 @@ DEFINE_MODRM_INSTR1_READ32(instr32_FF_6, push32(___))
static void run_instruction(int32_t opcode)
{
- //dbg_log(opcode);
// XXX: This table is generated. Don't modify
- switch(opcode)
+switch(opcode)
+{
+ case 0x00:
+ case 0x00|0x100:
{
-case 0x00:
-case 0x00|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_00_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_00_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x01:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_01_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_01_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x01|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_01_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_01_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x02:
-case 0x02|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_02_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_02_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x03:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_03_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_03_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x03|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_03_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_03_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x04:
-case 0x04|0x100:
-{
- instr_04();
-}
-break;
-case 0x05:
-{
- instr16_05();
-}
-break;
-case 0x05|0x100:
-{
- instr32_05();
-}
-break;
-case 0x06:
-{
- instr16_06();
-}
-break;
-case 0x06|0x100:
-{
- instr32_06();
-}
-break;
-case 0x07:
-{
- instr16_07();
-}
-break;
-case 0x07|0x100:
-{
- instr32_07();
-}
-break;
-case 0x08:
-case 0x08|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_08_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_08_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x09:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_09_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_09_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x09|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_09_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_09_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x0A:
-case 0x0A|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_0A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_0A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x0B:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_0B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_0B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x0B|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_0B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_0B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x0C:
-case 0x0C|0x100:
-{
- instr_0C();
-}
-break;
-case 0x0D:
-{
- instr16_0D();
-}
-break;
-case 0x0D|0x100:
-{
- instr32_0D();
-}
-break;
-case 0x0E:
-{
- instr16_0E();
-}
-break;
-case 0x0E|0x100:
-{
- instr32_0E();
-}
-break;
-case 0x0F:
-{
- instr16_0F();
-}
-break;
-case 0x0F|0x100:
-{
- instr32_0F();
-}
-break;
-case 0x10:
-case 0x10|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_10_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_10_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x11:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_11_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_11_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x11|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_11_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_11_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x12:
-case 0x12|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x13:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_13_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_13_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x13|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_13_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_13_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x14:
-case 0x14|0x100:
-{
- instr_14();
-}
-break;
-case 0x15:
-{
- instr16_15();
-}
-break;
-case 0x15|0x100:
-{
- instr32_15();
-}
-break;
-case 0x16:
-{
- instr16_16();
-}
-break;
-case 0x16|0x100:
-{
- instr32_16();
-}
-break;
-case 0x17:
-{
- instr16_17();
-}
-break;
-case 0x17|0x100:
-{
- instr32_17();
-}
-break;
-case 0x18:
-case 0x18|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_18_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_18_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x19:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_19_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_19_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x19|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_19_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_19_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x1A:
-case 0x1A|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_1A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_1A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x1B:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_1B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_1B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x1B|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_1B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_1B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x1C:
-case 0x1C|0x100:
-{
- instr_1C();
-}
-break;
-case 0x1D:
-{
- instr16_1D();
-}
-break;
-case 0x1D|0x100:
-{
- instr32_1D();
-}
-break;
-case 0x1E:
-{
- instr16_1E();
-}
-break;
-case 0x1E|0x100:
-{
- instr32_1E();
-}
-break;
-case 0x1F:
-{
- instr16_1F();
-}
-break;
-case 0x1F|0x100:
-{
- instr32_1F();
-}
-break;
-case 0x20:
-case 0x20|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_20_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_20_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x21:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_21_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_21_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x21|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_21_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_21_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x22:
-case 0x22|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_22_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_22_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x23:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_23_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_23_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x23|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_23_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_23_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x24:
-case 0x24|0x100:
-{
- instr_24();
-}
-break;
-case 0x25:
-{
- instr16_25();
-}
-break;
-case 0x25|0x100:
-{
- instr32_25();
-}
-break;
-case 0x26:
-case 0x26|0x100:
-{
- instr_26();
-}
-break;
-case 0x27:
-case 0x27|0x100:
-{
- instr_27();
-}
-break;
-case 0x28:
-case 0x28|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_28_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_28_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x29:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_29_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_29_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x29|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_29_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_29_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x2A:
-case 0x2A|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_2A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_2A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x2B:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_2B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_2B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x2B|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_2B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_2B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x2C:
-case 0x2C|0x100:
-{
- instr_2C();
-}
-break;
-case 0x2D:
-{
- instr16_2D();
-}
-break;
-case 0x2D|0x100:
-{
- instr32_2D();
-}
-break;
-case 0x2E:
-case 0x2E|0x100:
-{
- instr_2E();
-}
-break;
-case 0x2F:
-case 0x2F|0x100:
-{
- instr_2F();
-}
-break;
-case 0x30:
-case 0x30|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_30_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_30_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x31:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_31_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_31_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x31|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_31_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_31_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x32:
-case 0x32|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_32_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_32_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x33:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_33_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_33_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x33|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_33_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_33_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x34:
-case 0x34|0x100:
-{
- instr_34();
-}
-break;
-case 0x35:
-{
- instr16_35();
-}
-break;
-case 0x35|0x100:
-{
- instr32_35();
-}
-break;
-case 0x36:
-case 0x36|0x100:
-{
- instr_36();
-}
-break;
-case 0x37:
-case 0x37|0x100:
-{
- instr_37();
-}
-break;
-case 0x38:
-case 0x38|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_38_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_38_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x39:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_39_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_39_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x39|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_39_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_39_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x3A:
-case 0x3A|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_3A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_3A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x3B:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_3B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_3B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x3B|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_3B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_3B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x3C:
-case 0x3C|0x100:
-{
- instr_3C();
-}
-break;
-case 0x3D:
-{
- instr16_3D();
-}
-break;
-case 0x3D|0x100:
-{
- instr32_3D();
-}
-break;
-case 0x3E:
-case 0x3E|0x100:
-{
- instr_3E();
-}
-break;
-case 0x3F:
-case 0x3F|0x100:
-{
- instr_3F();
-}
-break;
-case 0x40:
-{
- instr16_40();
-}
-break;
-case 0x40|0x100:
-{
- instr32_40();
-}
-break;
-case 0x41:
-{
- instr16_41();
-}
-break;
-case 0x41|0x100:
-{
- instr32_41();
-}
-break;
-case 0x42:
-{
- instr16_42();
-}
-break;
-case 0x42|0x100:
-{
- instr32_42();
-}
-break;
-case 0x43:
-{
- instr16_43();
-}
-break;
-case 0x43|0x100:
-{
- instr32_43();
-}
-break;
-case 0x44:
-{
- instr16_44();
-}
-break;
-case 0x44|0x100:
-{
- instr32_44();
-}
-break;
-case 0x45:
-{
- instr16_45();
-}
-break;
-case 0x45|0x100:
-{
- instr32_45();
-}
-break;
-case 0x46:
-{
- instr16_46();
-}
-break;
-case 0x46|0x100:
-{
- instr32_46();
-}
-break;
-case 0x47:
-{
- instr16_47();
-}
-break;
-case 0x47|0x100:
-{
- instr32_47();
-}
-break;
-case 0x48:
-{
- instr16_48();
-}
-break;
-case 0x48|0x100:
-{
- instr32_48();
-}
-break;
-case 0x49:
-{
- instr16_49();
-}
-break;
-case 0x49|0x100:
-{
- instr32_49();
-}
-break;
-case 0x4A:
-{
- instr16_4A();
-}
-break;
-case 0x4A|0x100:
-{
- instr32_4A();
-}
-break;
-case 0x4B:
-{
- instr16_4B();
-}
-break;
-case 0x4B|0x100:
-{
- instr32_4B();
-}
-break;
-case 0x4C:
-{
- instr16_4C();
-}
-break;
-case 0x4C|0x100:
-{
- instr32_4C();
-}
-break;
-case 0x4D:
-{
- instr16_4D();
-}
-break;
-case 0x4D|0x100:
-{
- instr32_4D();
-}
-break;
-case 0x4E:
-{
- instr16_4E();
-}
-break;
-case 0x4E|0x100:
-{
- instr32_4E();
-}
-break;
-case 0x4F:
-{
- instr16_4F();
-}
-break;
-case 0x4F|0x100:
-{
- instr32_4F();
-}
-break;
-case 0x50:
-{
- instr16_50();
-}
-break;
-case 0x50|0x100:
-{
- instr32_50();
-}
-break;
-case 0x51:
-{
- instr16_51();
-}
-break;
-case 0x51|0x100:
-{
- instr32_51();
-}
-break;
-case 0x52:
-{
- instr16_52();
-}
-break;
-case 0x52|0x100:
-{
- instr32_52();
-}
-break;
-case 0x53:
-{
- instr16_53();
-}
-break;
-case 0x53|0x100:
-{
- instr32_53();
-}
-break;
-case 0x54:
-{
- instr16_54();
-}
-break;
-case 0x54|0x100:
-{
- instr32_54();
-}
-break;
-case 0x55:
-{
- instr16_55();
-}
-break;
-case 0x55|0x100:
-{
- instr32_55();
-}
-break;
-case 0x56:
-{
- instr16_56();
-}
-break;
-case 0x56|0x100:
-{
- instr32_56();
-}
-break;
-case 0x57:
-{
- instr16_57();
-}
-break;
-case 0x57|0x100:
-{
- instr32_57();
-}
-break;
-case 0x58:
-{
- instr16_58();
-}
-break;
-case 0x58|0x100:
-{
- instr32_58();
-}
-break;
-case 0x59:
-{
- instr16_59();
-}
-break;
-case 0x59|0x100:
-{
- instr32_59();
-}
-break;
-case 0x5A:
-{
- instr16_5A();
-}
-break;
-case 0x5A|0x100:
-{
- instr32_5A();
-}
-break;
-case 0x5B:
-{
- instr16_5B();
-}
-break;
-case 0x5B|0x100:
-{
- instr32_5B();
-}
-break;
-case 0x5C:
-{
- instr16_5C();
-}
-break;
-case 0x5C|0x100:
-{
- instr32_5C();
-}
-break;
-case 0x5D:
-{
- instr16_5D();
-}
-break;
-case 0x5D|0x100:
-{
- instr32_5D();
-}
-break;
-case 0x5E:
-{
- instr16_5E();
-}
-break;
-case 0x5E|0x100:
-{
- instr32_5E();
-}
-break;
-case 0x5F:
-{
- instr16_5F();
-}
-break;
-case 0x5F|0x100:
-{
- instr32_5F();
-}
-break;
-case 0x60:
-{
- instr16_60();
-}
-break;
-case 0x60|0x100:
-{
- instr32_60();
-}
-break;
-case 0x61:
-{
- instr16_61();
-}
-break;
-case 0x61|0x100:
-{
- instr32_61();
-}
-break;
-case 0x62:
-case 0x62|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_62_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_62_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x63:
-case 0x63|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_63_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_63_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x64:
-case 0x64|0x100:
-{
- instr_64();
-}
-break;
-case 0x65:
-case 0x65|0x100:
-{
- instr_65();
-}
-break;
-case 0x66:
-case 0x66|0x100:
-{
- instr_66();
-}
-break;
-case 0x67:
-case 0x67|0x100:
-{
- instr_67();
-}
-break;
-case 0x68:
-{
- instr16_68();
-}
-break;
-case 0x68|0x100:
-{
- instr32_68();
-}
-break;
-case 0x69:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_69_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_69_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x69|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_69_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_69_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x6A:
-{
- instr16_6A();
-}
-break;
-case 0x6A|0x100:
-{
- instr32_6A();
-}
-break;
-case 0x6B:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_6B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_6B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x6B|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_6B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_6B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x6C:
-case 0x6C|0x100:
-{
- instr_6C();
-}
-break;
-case 0x6D:
-{
- instr16_6D();
-}
-break;
-case 0x6D|0x100:
-{
- instr32_6D();
-}
-break;
-case 0x6E:
-case 0x6E|0x100:
-{
- instr_6E();
-}
-break;
-case 0x6F:
-{
- instr16_6F();
-}
-break;
-case 0x6F|0x100:
-{
- instr32_6F();
-}
-break;
-case 0x70:
-case 0x70|0x100:
-{
- instr_70();
-}
-break;
-case 0x71:
-case 0x71|0x100:
-{
- instr_71();
-}
-break;
-case 0x72:
-case 0x72|0x100:
-{
- instr_72();
-}
-break;
-case 0x73:
-case 0x73|0x100:
-{
- instr_73();
-}
-break;
-case 0x74:
-case 0x74|0x100:
-{
- instr_74();
-}
-break;
-case 0x75:
-case 0x75|0x100:
-{
- instr_75();
-}
-break;
-case 0x76:
-case 0x76|0x100:
-{
- instr_76();
-}
-break;
-case 0x77:
-case 0x77|0x100:
-{
- instr_77();
-}
-break;
-case 0x78:
-case 0x78|0x100:
-{
- instr_78();
-}
-break;
-case 0x79:
-case 0x79|0x100:
-{
- instr_79();
-}
-break;
-case 0x7A:
-case 0x7A|0x100:
-{
- instr_7A();
-}
-break;
-case 0x7B:
-case 0x7B|0x100:
-{
- instr_7B();
-}
-break;
-case 0x7C:
-case 0x7C|0x100:
-{
- instr_7C();
-}
-break;
-case 0x7D:
-case 0x7D|0x100:
-{
- instr_7D();
-}
-break;
-case 0x7E:
-case 0x7E|0x100:
-{
- instr_7E();
-}
-break;
-case 0x7F:
-case 0x7F|0x100:
-{
- instr_7F();
-}
-break;
-case 0x80:
-case 0x80|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_00_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_00_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x01:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr_80_0_mem(modrm_resolve(modrm_byte)) :
- instr_80_0_reg(modrm_byte & 7);
+ instr16_01_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr_80_1_mem(modrm_resolve(modrm_byte)) :
- instr_80_1_reg(modrm_byte & 7);
+ instr16_01_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr_80_2_mem(modrm_resolve(modrm_byte)) :
- instr_80_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr_80_3_mem(modrm_resolve(modrm_byte)) :
- instr_80_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr_80_4_mem(modrm_resolve(modrm_byte)) :
- instr_80_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr_80_5_mem(modrm_resolve(modrm_byte)) :
- instr_80_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr_80_6_mem(modrm_resolve(modrm_byte)) :
- instr_80_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr_80_7_mem(modrm_resolve(modrm_byte)) :
- instr_80_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-case 0x81:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x01|0x100:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr16_81_0_mem(modrm_resolve(modrm_byte)) :
- instr16_81_0_reg(modrm_byte & 7);
+ instr32_01_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr16_81_1_mem(modrm_resolve(modrm_byte)) :
- instr16_81_1_reg(modrm_byte & 7);
+ instr32_01_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr16_81_2_mem(modrm_resolve(modrm_byte)) :
- instr16_81_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr16_81_3_mem(modrm_resolve(modrm_byte)) :
- instr16_81_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr16_81_4_mem(modrm_resolve(modrm_byte)) :
- instr16_81_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr16_81_5_mem(modrm_resolve(modrm_byte)) :
- instr16_81_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr16_81_6_mem(modrm_resolve(modrm_byte)) :
- instr16_81_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr16_81_7_mem(modrm_resolve(modrm_byte)) :
- instr16_81_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-case 0x81|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x02:
+ case 0x02|0x100:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr32_81_0_mem(modrm_resolve(modrm_byte)) :
- instr32_81_0_reg(modrm_byte & 7);
+ instr_02_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr32_81_1_mem(modrm_resolve(modrm_byte)) :
- instr32_81_1_reg(modrm_byte & 7);
+ instr_02_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr32_81_2_mem(modrm_resolve(modrm_byte)) :
- instr32_81_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr32_81_3_mem(modrm_resolve(modrm_byte)) :
- instr32_81_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr32_81_4_mem(modrm_resolve(modrm_byte)) :
- instr32_81_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr32_81_5_mem(modrm_resolve(modrm_byte)) :
- instr32_81_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr32_81_6_mem(modrm_resolve(modrm_byte)) :
- instr32_81_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr32_81_7_mem(modrm_resolve(modrm_byte)) :
- instr32_81_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-case 0x82:
-case 0x82|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x03:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr_82_0_mem(modrm_resolve(modrm_byte)) :
- instr_82_0_reg(modrm_byte & 7);
+ instr16_03_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr_82_1_mem(modrm_resolve(modrm_byte)) :
- instr_82_1_reg(modrm_byte & 7);
+ instr16_03_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr_82_2_mem(modrm_resolve(modrm_byte)) :
- instr_82_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr_82_3_mem(modrm_resolve(modrm_byte)) :
- instr_82_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr_82_4_mem(modrm_resolve(modrm_byte)) :
- instr_82_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr_82_5_mem(modrm_resolve(modrm_byte)) :
- instr_82_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr_82_6_mem(modrm_resolve(modrm_byte)) :
- instr_82_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr_82_7_mem(modrm_resolve(modrm_byte)) :
- instr_82_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-case 0x83:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x03|0x100:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr16_83_0_mem(modrm_resolve(modrm_byte)) :
- instr16_83_0_reg(modrm_byte & 7);
+ instr32_03_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr16_83_1_mem(modrm_resolve(modrm_byte)) :
- instr16_83_1_reg(modrm_byte & 7);
+ instr32_03_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr16_83_2_mem(modrm_resolve(modrm_byte)) :
- instr16_83_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr16_83_3_mem(modrm_resolve(modrm_byte)) :
- instr16_83_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr16_83_4_mem(modrm_resolve(modrm_byte)) :
- instr16_83_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr16_83_5_mem(modrm_resolve(modrm_byte)) :
- instr16_83_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr16_83_6_mem(modrm_resolve(modrm_byte)) :
- instr16_83_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr16_83_7_mem(modrm_resolve(modrm_byte)) :
- instr16_83_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-case 0x83|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x04:
+ case 0x04|0x100:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr32_83_0_mem(modrm_resolve(modrm_byte)) :
- instr32_83_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr32_83_1_mem(modrm_resolve(modrm_byte)) :
- instr32_83_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr32_83_2_mem(modrm_resolve(modrm_byte)) :
- instr32_83_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr32_83_3_mem(modrm_resolve(modrm_byte)) :
- instr32_83_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr32_83_4_mem(modrm_resolve(modrm_byte)) :
- instr32_83_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr32_83_5_mem(modrm_resolve(modrm_byte)) :
- instr32_83_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr32_83_6_mem(modrm_resolve(modrm_byte)) :
- instr32_83_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr32_83_7_mem(modrm_resolve(modrm_byte)) :
- instr32_83_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr_04(read_imm8());
}
-}
-break;
-case 0x84:
-case 0x84|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_84_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_84_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x85:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_85_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_85_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x85|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_85_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_85_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x86:
-case 0x86|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_86_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_86_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x87:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_87_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_87_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x87|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_87_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_87_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x88:
-case 0x88|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_88_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_88_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x89:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_89_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_89_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x89|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_89_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_89_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x8A:
-case 0x8A|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_8A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_8A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x8B:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_8B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_8B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x8B|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_8B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_8B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x8C:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_8C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_8C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x8C|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_8C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_8C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x8D:
-{
- int32_t modrm_byte = read_imm8();
- if(modrm_byte < 0xC0) { instr16_8D_mem_pre(); };
- modrm_byte < 0xC0 ?
- instr16_8D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_8D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x8D|0x100:
-{
- int32_t modrm_byte = read_imm8();
- if(modrm_byte < 0xC0) { instr32_8D_mem_pre(); };
- modrm_byte < 0xC0 ?
- instr32_8D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_8D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x8E:
-case 0x8E|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_8E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_8E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0x8F:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x05:
{
- case 0:
- {
- if(modrm_byte < 0xC0) { instr16_8F_0_mem_pre(); };
- modrm_byte < 0xC0 ?
- instr16_8F_0_mem(modrm_resolve(modrm_byte)) :
- instr16_8F_0_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr16_05(read_imm16());
}
-}
-break;
-case 0x8F|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x05|0x100:
{
- case 0:
- {
- if(modrm_byte < 0xC0) { instr32_8F_0_mem_pre(); };
- modrm_byte < 0xC0 ?
- instr32_8F_0_mem(modrm_resolve(modrm_byte)) :
- instr32_8F_0_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr32_05(read_imm32s());
}
-}
-break;
-case 0x90:
-case 0x90|0x100:
-{
- instr_90();
-}
-break;
-case 0x91:
-{
- instr16_91();
-}
-break;
-case 0x91|0x100:
-{
- instr32_91();
-}
-break;
-case 0x92:
-{
- instr16_92();
-}
-break;
-case 0x92|0x100:
-{
- instr32_92();
-}
-break;
-case 0x93:
-{
- instr16_93();
-}
-break;
-case 0x93|0x100:
-{
- instr32_93();
-}
-break;
-case 0x94:
-{
- instr16_94();
-}
-break;
-case 0x94|0x100:
-{
- instr32_94();
-}
-break;
-case 0x95:
-{
- instr16_95();
-}
-break;
-case 0x95|0x100:
-{
- instr32_95();
-}
-break;
-case 0x96:
-{
- instr16_96();
-}
-break;
-case 0x96|0x100:
-{
- instr32_96();
-}
-break;
-case 0x97:
-{
- instr16_97();
-}
-break;
-case 0x97|0x100:
-{
- instr32_97();
-}
-break;
-case 0x98:
-{
- instr16_98();
-}
-break;
-case 0x98|0x100:
-{
- instr32_98();
-}
-break;
-case 0x99:
-{
- instr16_99();
-}
-break;
-case 0x99|0x100:
-{
- instr32_99();
-}
-break;
-case 0x9A:
-{
- instr16_9A(read_imm16(), read_imm16());
-}
-break;
-case 0x9A|0x100:
-{
- instr32_9A(read_imm32s(), read_imm16());
-}
-break;
-case 0x9B:
-case 0x9B|0x100:
-{
- instr_9B();
-}
-break;
-case 0x9C:
-{
- instr16_9C();
-}
-break;
-case 0x9C|0x100:
-{
- instr32_9C();
-}
-break;
-case 0x9D:
-{
- instr16_9D();
-}
-break;
-case 0x9D|0x100:
-{
- instr32_9D();
-}
-break;
-case 0x9E:
-case 0x9E|0x100:
-{
- instr_9E();
-}
-break;
-case 0x9F:
-case 0x9F|0x100:
-{
- instr_9F();
-}
-break;
-case 0xA0:
-case 0xA0|0x100:
-{
- instr_A0();
-}
-break;
-case 0xA1:
-{
- instr16_A1();
-}
-break;
-case 0xA1|0x100:
-{
- instr32_A1();
-}
-break;
-case 0xA2:
-case 0xA2|0x100:
-{
- instr_A2();
-}
-break;
-case 0xA3:
-{
- instr16_A3();
-}
-break;
-case 0xA3|0x100:
-{
- instr32_A3();
-}
-break;
-case 0xA4:
-case 0xA4|0x100:
-{
- instr_A4();
-}
-break;
-case 0xA5:
-{
- instr16_A5();
-}
-break;
-case 0xA5|0x100:
-{
- instr32_A5();
-}
-break;
-case 0xA6:
-case 0xA6|0x100:
-{
- instr_A6();
-}
-break;
-case 0xA7:
-{
- instr16_A7();
-}
-break;
-case 0xA7|0x100:
-{
- instr32_A7();
-}
-break;
-case 0xA8:
-case 0xA8|0x100:
-{
- instr_A8();
-}
-break;
-case 0xA9:
-{
- instr16_A9();
-}
-break;
-case 0xA9|0x100:
-{
- instr32_A9();
-}
-break;
-case 0xAA:
-case 0xAA|0x100:
-{
- instr_AA();
-}
-break;
-case 0xAB:
-{
- instr16_AB();
-}
-break;
-case 0xAB|0x100:
-{
- instr32_AB();
-}
-break;
-case 0xAC:
-case 0xAC|0x100:
-{
- instr_AC();
-}
-break;
-case 0xAD:
-{
- instr16_AD();
-}
-break;
-case 0xAD|0x100:
-{
- instr32_AD();
-}
-break;
-case 0xAE:
-case 0xAE|0x100:
-{
- instr_AE();
-}
-break;
-case 0xAF:
-{
- instr16_AF();
-}
-break;
-case 0xAF|0x100:
-{
- instr32_AF();
-}
-break;
-case 0xB0:
-case 0xB0|0x100:
-{
- instr_B0();
-}
-break;
-case 0xB1:
-case 0xB1|0x100:
-{
- instr_B1();
-}
-break;
-case 0xB2:
-case 0xB2|0x100:
-{
- instr_B2();
-}
-break;
-case 0xB3:
-case 0xB3|0x100:
-{
- instr_B3();
-}
-break;
-case 0xB4:
-case 0xB4|0x100:
-{
- instr_B4();
-}
-break;
-case 0xB5:
-case 0xB5|0x100:
-{
- instr_B5();
-}
-break;
-case 0xB6:
-case 0xB6|0x100:
-{
- instr_B6();
-}
-break;
-case 0xB7:
-case 0xB7|0x100:
-{
- instr_B7();
-}
-break;
-case 0xB8:
-{
- instr16_B8();
-}
-break;
-case 0xB8|0x100:
-{
- instr32_B8();
-}
-break;
-case 0xB9:
-{
- instr16_B9();
-}
-break;
-case 0xB9|0x100:
-{
- instr32_B9();
-}
-break;
-case 0xBA:
-{
- instr16_BA();
-}
-break;
-case 0xBA|0x100:
-{
- instr32_BA();
-}
-break;
-case 0xBB:
-{
- instr16_BB();
-}
-break;
-case 0xBB|0x100:
-{
- instr32_BB();
-}
-break;
-case 0xBC:
-{
- instr16_BC();
-}
-break;
-case 0xBC|0x100:
-{
- instr32_BC();
-}
-break;
-case 0xBD:
-{
- instr16_BD();
-}
-break;
-case 0xBD|0x100:
-{
- instr32_BD();
-}
-break;
-case 0xBE:
-{
- instr16_BE();
-}
-break;
-case 0xBE|0x100:
-{
- instr32_BE();
-}
-break;
-case 0xBF:
-{
- instr16_BF();
-}
-break;
-case 0xBF|0x100:
-{
- instr32_BF();
-}
-break;
-case 0xC0:
-case 0xC0|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x06:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr_C0_0_mem(modrm_resolve(modrm_byte)) :
- instr_C0_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr_C0_1_mem(modrm_resolve(modrm_byte)) :
- instr_C0_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr_C0_2_mem(modrm_resolve(modrm_byte)) :
- instr_C0_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr_C0_3_mem(modrm_resolve(modrm_byte)) :
- instr_C0_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr_C0_4_mem(modrm_resolve(modrm_byte)) :
- instr_C0_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr_C0_5_mem(modrm_resolve(modrm_byte)) :
- instr_C0_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr_C0_6_mem(modrm_resolve(modrm_byte)) :
- instr_C0_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr_C0_7_mem(modrm_resolve(modrm_byte)) :
- instr_C0_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr16_06();
}
-}
-break;
-case 0xC1:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x06|0x100:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr16_C1_0_mem(modrm_resolve(modrm_byte)) :
- instr16_C1_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr16_C1_1_mem(modrm_resolve(modrm_byte)) :
- instr16_C1_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr16_C1_2_mem(modrm_resolve(modrm_byte)) :
- instr16_C1_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr16_C1_3_mem(modrm_resolve(modrm_byte)) :
- instr16_C1_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr16_C1_4_mem(modrm_resolve(modrm_byte)) :
- instr16_C1_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr16_C1_5_mem(modrm_resolve(modrm_byte)) :
- instr16_C1_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr16_C1_6_mem(modrm_resolve(modrm_byte)) :
- instr16_C1_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr16_C1_7_mem(modrm_resolve(modrm_byte)) :
- instr16_C1_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr32_06();
}
-}
-break;
-case 0xC1|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x07:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr32_C1_0_mem(modrm_resolve(modrm_byte)) :
- instr32_C1_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr32_C1_1_mem(modrm_resolve(modrm_byte)) :
- instr32_C1_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr32_C1_2_mem(modrm_resolve(modrm_byte)) :
- instr32_C1_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr32_C1_3_mem(modrm_resolve(modrm_byte)) :
- instr32_C1_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr32_C1_4_mem(modrm_resolve(modrm_byte)) :
- instr32_C1_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr32_C1_5_mem(modrm_resolve(modrm_byte)) :
- instr32_C1_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr32_C1_6_mem(modrm_resolve(modrm_byte)) :
- instr32_C1_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr32_C1_7_mem(modrm_resolve(modrm_byte)) :
- instr32_C1_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr16_07();
}
-}
-break;
-case 0xC2:
-{
- instr16_C2();
-}
-break;
-case 0xC2|0x100:
-{
- instr32_C2();
-}
-break;
-case 0xC3:
-{
- instr16_C3();
-}
-break;
-case 0xC3|0x100:
-{
- instr32_C3();
-}
-break;
-case 0xC4:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_C4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_C4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xC4|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_C4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_C4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xC5:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr16_C5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr16_C5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xC5|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr32_C5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr32_C5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xC6:
-case 0xC6|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x07|0x100:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr_C6_0_mem(modrm_resolve(modrm_byte)) :
- instr_C6_0_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr32_07();
}
-}
-break;
-case 0xC7:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x08:
+ case 0x08|0x100:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr16_C7_0_mem(modrm_resolve(modrm_byte)) :
- instr16_C7_0_reg(modrm_byte & 7);
+ instr_08_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_08_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- default:
- assert(false);
}
-}
-break;
-case 0xC7|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x09:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr32_C7_0_mem(modrm_resolve(modrm_byte)) :
- instr32_C7_0_reg(modrm_byte & 7);
+ instr16_09_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_09_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- default:
- assert(false);
}
-}
-break;
-case 0xC8:
-{
- instr16_C8(read_imm16(), read_imm8());
-}
-break;
-case 0xC8|0x100:
-{
- instr32_C8(read_imm16(), read_imm8());
-}
-break;
-case 0xC9:
-{
- instr16_C9();
-}
-break;
-case 0xC9|0x100:
-{
- instr32_C9();
-}
-break;
-case 0xCA:
-{
- instr16_CA();
-}
-break;
-case 0xCA|0x100:
-{
- instr32_CA();
-}
-break;
-case 0xCB:
-{
- instr16_CB();
-}
-break;
-case 0xCB|0x100:
-{
- instr32_CB();
-}
-break;
-case 0xCC:
-case 0xCC|0x100:
-{
- instr_CC();
-}
-break;
-case 0xCD:
-case 0xCD|0x100:
-{
- instr_CD();
-}
-break;
-case 0xCE:
-case 0xCE|0x100:
-{
- instr_CE();
-}
-break;
-case 0xCF:
-{
- instr16_CF();
-}
-break;
-case 0xCF|0x100:
-{
- instr32_CF();
-}
-break;
-case 0xD0:
-case 0xD0|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x09|0x100:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr_D0_0_mem(modrm_resolve(modrm_byte)) :
- instr_D0_0_reg(modrm_byte & 7);
+ instr32_09_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr_D0_1_mem(modrm_resolve(modrm_byte)) :
- instr_D0_1_reg(modrm_byte & 7);
+ instr32_09_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr_D0_2_mem(modrm_resolve(modrm_byte)) :
- instr_D0_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr_D0_3_mem(modrm_resolve(modrm_byte)) :
- instr_D0_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr_D0_4_mem(modrm_resolve(modrm_byte)) :
- instr_D0_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr_D0_5_mem(modrm_resolve(modrm_byte)) :
- instr_D0_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr_D0_6_mem(modrm_resolve(modrm_byte)) :
- instr_D0_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr_D0_7_mem(modrm_resolve(modrm_byte)) :
- instr_D0_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-case 0xD1:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0A:
+ case 0x0A|0x100:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr16_D1_0_mem(modrm_resolve(modrm_byte)) :
- instr16_D1_0_reg(modrm_byte & 7);
+ instr_0A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr16_D1_1_mem(modrm_resolve(modrm_byte)) :
- instr16_D1_1_reg(modrm_byte & 7);
+ instr_0A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr16_D1_2_mem(modrm_resolve(modrm_byte)) :
- instr16_D1_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr16_D1_3_mem(modrm_resolve(modrm_byte)) :
- instr16_D1_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr16_D1_4_mem(modrm_resolve(modrm_byte)) :
- instr16_D1_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr16_D1_5_mem(modrm_resolve(modrm_byte)) :
- instr16_D1_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr16_D1_6_mem(modrm_resolve(modrm_byte)) :
- instr16_D1_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr16_D1_7_mem(modrm_resolve(modrm_byte)) :
- instr16_D1_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-case 0xD1|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0B:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr32_D1_0_mem(modrm_resolve(modrm_byte)) :
- instr32_D1_0_reg(modrm_byte & 7);
+ instr16_0B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr32_D1_1_mem(modrm_resolve(modrm_byte)) :
- instr32_D1_1_reg(modrm_byte & 7);
+ instr16_0B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr32_D1_2_mem(modrm_resolve(modrm_byte)) :
- instr32_D1_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr32_D1_3_mem(modrm_resolve(modrm_byte)) :
- instr32_D1_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr32_D1_4_mem(modrm_resolve(modrm_byte)) :
- instr32_D1_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr32_D1_5_mem(modrm_resolve(modrm_byte)) :
- instr32_D1_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr32_D1_6_mem(modrm_resolve(modrm_byte)) :
- instr32_D1_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr32_D1_7_mem(modrm_resolve(modrm_byte)) :
- instr32_D1_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-case 0xD2:
-case 0xD2|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0B|0x100:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr_D2_0_mem(modrm_resolve(modrm_byte)) :
- instr_D2_0_reg(modrm_byte & 7);
+ instr32_0B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr_D2_1_mem(modrm_resolve(modrm_byte)) :
- instr_D2_1_reg(modrm_byte & 7);
+ instr32_0B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr_D2_2_mem(modrm_resolve(modrm_byte)) :
- instr_D2_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr_D2_3_mem(modrm_resolve(modrm_byte)) :
- instr_D2_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr_D2_4_mem(modrm_resolve(modrm_byte)) :
- instr_D2_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr_D2_5_mem(modrm_resolve(modrm_byte)) :
- instr_D2_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr_D2_6_mem(modrm_resolve(modrm_byte)) :
- instr_D2_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr_D2_7_mem(modrm_resolve(modrm_byte)) :
- instr_D2_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-case 0xD3:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0C:
+ case 0x0C|0x100:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr16_D3_0_mem(modrm_resolve(modrm_byte)) :
- instr16_D3_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr16_D3_1_mem(modrm_resolve(modrm_byte)) :
- instr16_D3_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr16_D3_2_mem(modrm_resolve(modrm_byte)) :
- instr16_D3_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr16_D3_3_mem(modrm_resolve(modrm_byte)) :
- instr16_D3_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr16_D3_4_mem(modrm_resolve(modrm_byte)) :
- instr16_D3_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr16_D3_5_mem(modrm_resolve(modrm_byte)) :
- instr16_D3_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr16_D3_6_mem(modrm_resolve(modrm_byte)) :
- instr16_D3_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr16_D3_7_mem(modrm_resolve(modrm_byte)) :
- instr16_D3_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr_0C(read_imm8());
}
-}
-break;
-case 0xD3|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0D:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr32_D3_0_mem(modrm_resolve(modrm_byte)) :
- instr32_D3_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr32_D3_1_mem(modrm_resolve(modrm_byte)) :
- instr32_D3_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr32_D3_2_mem(modrm_resolve(modrm_byte)) :
- instr32_D3_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr32_D3_3_mem(modrm_resolve(modrm_byte)) :
- instr32_D3_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr32_D3_4_mem(modrm_resolve(modrm_byte)) :
- instr32_D3_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr32_D3_5_mem(modrm_resolve(modrm_byte)) :
- instr32_D3_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr32_D3_6_mem(modrm_resolve(modrm_byte)) :
- instr32_D3_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr32_D3_7_mem(modrm_resolve(modrm_byte)) :
- instr32_D3_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr16_0D(read_imm16());
}
-}
-break;
-case 0xD4:
-case 0xD4|0x100:
-{
- instr_D4();
-}
-break;
-case 0xD5:
-case 0xD5|0x100:
-{
- instr_D5();
-}
-break;
-case 0xD6:
-case 0xD6|0x100:
-{
- instr_D6();
-}
-break;
-case 0xD7:
-case 0xD7|0x100:
-{
- instr_D7();
-}
-break;
-case 0xD8:
-case 0xD8|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_D8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_D8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xD9:
-case 0xD9|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_D9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_D9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xDA:
-case 0xDA|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_DA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_DA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xDB:
-case 0xDB|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_DB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_DB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xDC:
-case 0xDC|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_DC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_DC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xDD:
-case 0xDD|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_DD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_DD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xDE:
-case 0xDE|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_DE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_DE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xDF:
-case 0xDF|0x100:
-{
- int32_t modrm_byte = read_imm8();
- modrm_byte < 0xC0 ?
- instr_DF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :
- instr_DF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
-}
-break;
-case 0xE0:
-case 0xE0|0x100:
-{
- instr_E0();
-}
-break;
-case 0xE1:
-case 0xE1|0x100:
-{
- instr_E1();
-}
-break;
-case 0xE2:
-case 0xE2|0x100:
-{
- instr_E2();
-}
-break;
-case 0xE3:
-case 0xE3|0x100:
-{
- instr_E3();
-}
-break;
-case 0xE4:
-case 0xE4|0x100:
-{
- instr_E4();
-}
-break;
-case 0xE5:
-{
- instr16_E5();
-}
-break;
-case 0xE5|0x100:
-{
- instr32_E5();
-}
-break;
-case 0xE6:
-case 0xE6|0x100:
-{
- instr_E6();
-}
-break;
-case 0xE7:
-{
- instr16_E7();
-}
-break;
-case 0xE7|0x100:
-{
- instr32_E7();
-}
-break;
-case 0xE8:
-{
- instr16_E8();
-}
-break;
-case 0xE8|0x100:
-{
- instr32_E8();
-}
-break;
-case 0xE9:
-{
- instr16_E9();
-}
-break;
-case 0xE9|0x100:
-{
- instr32_E9();
-}
-break;
-case 0xEA:
-{
- instr16_EA(read_imm16(), read_imm16());
-}
-break;
-case 0xEA|0x100:
-{
- instr32_EA(read_imm32s(), read_imm16());
-}
-break;
-case 0xEB:
-case 0xEB|0x100:
-{
- instr_EB();
-}
-break;
-case 0xEC:
-case 0xEC|0x100:
-{
- instr_EC();
-}
-break;
-case 0xED:
-{
- instr16_ED();
-}
-break;
-case 0xED|0x100:
-{
- instr32_ED();
-}
-break;
-case 0xEE:
-case 0xEE|0x100:
-{
- instr_EE();
-}
-break;
-case 0xEF:
-{
- instr16_EF();
-}
-break;
-case 0xEF|0x100:
-{
- instr32_EF();
-}
-break;
-case 0xF0:
-case 0xF0|0x100:
-{
- instr_F0();
-}
-break;
-case 0xF1:
-case 0xF1|0x100:
-{
- instr_F1();
-}
-break;
-case 0xF2:
-case 0xF2|0x100:
-{
- instr_F2();
-}
-break;
-case 0xF3:
-case 0xF3|0x100:
-{
- instr_F3();
-}
-break;
-case 0xF4:
-case 0xF4|0x100:
-{
- instr_F4();
-}
-break;
-case 0xF5:
-case 0xF5|0x100:
-{
- instr_F5();
-}
-break;
-case 0xF6:
-case 0xF6|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0D|0x100:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr_F6_0_mem(modrm_resolve(modrm_byte)) :
- instr_F6_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr_F6_1_mem(modrm_resolve(modrm_byte)) :
- instr_F6_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr_F6_2_mem(modrm_resolve(modrm_byte)) :
- instr_F6_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr_F6_3_mem(modrm_resolve(modrm_byte)) :
- instr_F6_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr_F6_4_mem(modrm_resolve(modrm_byte)) :
- instr_F6_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr_F6_5_mem(modrm_resolve(modrm_byte)) :
- instr_F6_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr_F6_6_mem(modrm_resolve(modrm_byte)) :
- instr_F6_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr_F6_7_mem(modrm_resolve(modrm_byte)) :
- instr_F6_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr32_0D(read_imm32s());
}
-}
-break;
-case 0xF7:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0E:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr16_F7_0_mem(modrm_resolve(modrm_byte)) :
- instr16_F7_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr16_F7_1_mem(modrm_resolve(modrm_byte)) :
- instr16_F7_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr16_F7_2_mem(modrm_resolve(modrm_byte)) :
- instr16_F7_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr16_F7_3_mem(modrm_resolve(modrm_byte)) :
- instr16_F7_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr16_F7_4_mem(modrm_resolve(modrm_byte)) :
- instr16_F7_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr16_F7_5_mem(modrm_resolve(modrm_byte)) :
- instr16_F7_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr16_F7_6_mem(modrm_resolve(modrm_byte)) :
- instr16_F7_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr16_F7_7_mem(modrm_resolve(modrm_byte)) :
- instr16_F7_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr16_0E();
}
-}
-break;
-case 0xF7|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0E|0x100:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr32_F7_0_mem(modrm_resolve(modrm_byte)) :
- instr32_F7_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr32_F7_1_mem(modrm_resolve(modrm_byte)) :
- instr32_F7_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr32_F7_2_mem(modrm_resolve(modrm_byte)) :
- instr32_F7_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr32_F7_3_mem(modrm_resolve(modrm_byte)) :
- instr32_F7_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr32_F7_4_mem(modrm_resolve(modrm_byte)) :
- instr32_F7_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr32_F7_5_mem(modrm_resolve(modrm_byte)) :
- instr32_F7_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr32_F7_6_mem(modrm_resolve(modrm_byte)) :
- instr32_F7_6_reg(modrm_byte & 7);
- }
- break;
- case 7:
- {
- modrm_byte < 0xC0 ?
- instr32_F7_7_mem(modrm_resolve(modrm_byte)) :
- instr32_F7_7_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr32_0E();
}
-}
-break;
-case 0xF8:
-case 0xF8|0x100:
-{
- instr_F8();
-}
-break;
-case 0xF9:
-case 0xF9|0x100:
-{
- instr_F9();
-}
-break;
-case 0xFA:
-case 0xFA|0x100:
-{
- instr_FA();
-}
-break;
-case 0xFB:
-case 0xFB|0x100:
-{
- instr_FB();
-}
-break;
-case 0xFC:
-case 0xFC|0x100:
-{
- instr_FC();
-}
-break;
-case 0xFD:
-case 0xFD|0x100:
-{
- instr_FD();
-}
-break;
-case 0xFE:
-case 0xFE|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0F:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr_FE_0_mem(modrm_resolve(modrm_byte)) :
- instr_FE_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr_FE_1_mem(modrm_resolve(modrm_byte)) :
- instr_FE_1_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr16_0F();
}
-}
-break;
-case 0xFF:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x0F|0x100:
{
- case 0:
- {
- modrm_byte < 0xC0 ?
- instr16_FF_0_mem(modrm_resolve(modrm_byte)) :
- instr16_FF_0_reg(modrm_byte & 7);
- }
- break;
- case 1:
- {
- modrm_byte < 0xC0 ?
- instr16_FF_1_mem(modrm_resolve(modrm_byte)) :
- instr16_FF_1_reg(modrm_byte & 7);
- }
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr16_FF_2_mem(modrm_resolve(modrm_byte)) :
- instr16_FF_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr16_FF_3_mem(modrm_resolve(modrm_byte)) :
- instr16_FF_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr16_FF_4_mem(modrm_resolve(modrm_byte)) :
- instr16_FF_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr16_FF_5_mem(modrm_resolve(modrm_byte)) :
- instr16_FF_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr16_FF_6_mem(modrm_resolve(modrm_byte)) :
- instr16_FF_6_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
+ instr32_0F();
}
-}
-break;
-case 0xFF|0x100:
-{
- int32_t modrm_byte = read_imm8();
- switch(modrm_byte >> 3 & 7)
+ break;
+ case 0x10:
+ case 0x10|0x100:
{
- case 0:
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
{
- modrm_byte < 0xC0 ?
- instr32_FF_0_mem(modrm_resolve(modrm_byte)) :
- instr32_FF_0_reg(modrm_byte & 7);
+ instr_10_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
}
- break;
- case 1:
+ else
{
- modrm_byte < 0xC0 ?
- instr32_FF_1_mem(modrm_resolve(modrm_byte)) :
- instr32_FF_1_reg(modrm_byte & 7);
+ instr_10_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
}
- break;
- case 2:
- {
- modrm_byte < 0xC0 ?
- instr32_FF_2_mem(modrm_resolve(modrm_byte)) :
- instr32_FF_2_reg(modrm_byte & 7);
- }
- break;
- case 3:
- {
- modrm_byte < 0xC0 ?
- instr32_FF_3_mem(modrm_resolve(modrm_byte)) :
- instr32_FF_3_reg(modrm_byte & 7);
- }
- break;
- case 4:
- {
- modrm_byte < 0xC0 ?
- instr32_FF_4_mem(modrm_resolve(modrm_byte)) :
- instr32_FF_4_reg(modrm_byte & 7);
- }
- break;
- case 5:
- {
- modrm_byte < 0xC0 ?
- instr32_FF_5_mem(modrm_resolve(modrm_byte)) :
- instr32_FF_5_reg(modrm_byte & 7);
- }
- break;
- case 6:
- {
- modrm_byte < 0xC0 ?
- instr32_FF_6_mem(modrm_resolve(modrm_byte)) :
- instr32_FF_6_reg(modrm_byte & 7);
- }
- break;
- default:
- assert(false);
}
-}
-break;
-default:
- assert(false);
+ break;
+ case 0x11:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_11_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_11_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
}
+ break;
+ case 0x11|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_11_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_11_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x12:
+ case 0x12|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x13:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_13_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_13_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x13|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_13_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_13_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x14:
+ case 0x14|0x100:
+ {
+ instr_14(read_imm8());
+ }
+ break;
+ case 0x15:
+ {
+ instr16_15(read_imm16());
+ }
+ break;
+ case 0x15|0x100:
+ {
+ instr32_15(read_imm32s());
+ }
+ break;
+ case 0x16:
+ {
+ instr16_16();
+ }
+ break;
+ case 0x16|0x100:
+ {
+ instr32_16();
+ }
+ break;
+ case 0x17:
+ {
+ instr16_17();
+ }
+ break;
+ case 0x17|0x100:
+ {
+ instr32_17();
+ }
+ break;
+ case 0x18:
+ case 0x18|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_18_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_18_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x19:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_19_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_19_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x19|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_19_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_19_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x1A:
+ case 0x1A|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_1A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_1A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x1B:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_1B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_1B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x1B|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_1B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_1B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x1C:
+ case 0x1C|0x100:
+ {
+ instr_1C(read_imm8());
+ }
+ break;
+ case 0x1D:
+ {
+ instr16_1D(read_imm16());
+ }
+ break;
+ case 0x1D|0x100:
+ {
+ instr32_1D(read_imm32s());
+ }
+ break;
+ case 0x1E:
+ {
+ instr16_1E();
+ }
+ break;
+ case 0x1E|0x100:
+ {
+ instr32_1E();
+ }
+ break;
+ case 0x1F:
+ {
+ instr16_1F();
+ }
+ break;
+ case 0x1F|0x100:
+ {
+ instr32_1F();
+ }
+ break;
+ case 0x20:
+ case 0x20|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_20_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_20_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x21:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_21_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_21_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x21|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_21_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_21_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x22:
+ case 0x22|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_22_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_22_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x23:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_23_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_23_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x23|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_23_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_23_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x24:
+ case 0x24|0x100:
+ {
+ instr_24(read_imm8());
+ }
+ break;
+ case 0x25:
+ {
+ instr16_25(read_imm16());
+ }
+ break;
+ case 0x25|0x100:
+ {
+ instr32_25(read_imm32s());
+ }
+ break;
+ case 0x26:
+ case 0x26|0x100:
+ {
+ instr_26();
+ }
+ break;
+ case 0x27:
+ case 0x27|0x100:
+ {
+ instr_27();
+ }
+ break;
+ case 0x28:
+ case 0x28|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_28_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_28_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x29:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_29_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_29_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x29|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_29_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_29_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x2A:
+ case 0x2A|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_2A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_2A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x2B:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_2B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_2B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x2B|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_2B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_2B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x2C:
+ case 0x2C|0x100:
+ {
+ instr_2C(read_imm8());
+ }
+ break;
+ case 0x2D:
+ {
+ instr16_2D(read_imm16());
+ }
+ break;
+ case 0x2D|0x100:
+ {
+ instr32_2D(read_imm32s());
+ }
+ break;
+ case 0x2E:
+ case 0x2E|0x100:
+ {
+ instr_2E();
+ }
+ break;
+ case 0x2F:
+ case 0x2F|0x100:
+ {
+ instr_2F();
+ }
+ break;
+ case 0x30:
+ case 0x30|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_30_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_30_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x31:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_31_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_31_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x31|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_31_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_31_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x32:
+ case 0x32|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_32_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_32_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x33:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_33_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_33_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x33|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_33_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_33_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x34:
+ case 0x34|0x100:
+ {
+ instr_34(read_imm8());
+ }
+ break;
+ case 0x35:
+ {
+ instr16_35(read_imm16());
+ }
+ break;
+ case 0x35|0x100:
+ {
+ instr32_35(read_imm32s());
+ }
+ break;
+ case 0x36:
+ case 0x36|0x100:
+ {
+ instr_36();
+ }
+ break;
+ case 0x37:
+ case 0x37|0x100:
+ {
+ instr_37();
+ }
+ break;
+ case 0x38:
+ case 0x38|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_38_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_38_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x39:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_39_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_39_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x39|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_39_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_39_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x3A:
+ case 0x3A|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_3A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_3A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x3B:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_3B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_3B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x3B|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_3B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_3B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x3C:
+ case 0x3C|0x100:
+ {
+ instr_3C(read_imm8());
+ }
+ break;
+ case 0x3D:
+ {
+ instr16_3D(read_imm16());
+ }
+ break;
+ case 0x3D|0x100:
+ {
+ instr32_3D(read_imm32s());
+ }
+ break;
+ case 0x3E:
+ case 0x3E|0x100:
+ {
+ instr_3E();
+ }
+ break;
+ case 0x3F:
+ case 0x3F|0x100:
+ {
+ instr_3F();
+ }
+ break;
+ case 0x40:
+ {
+ instr16_40();
+ }
+ break;
+ case 0x40|0x100:
+ {
+ instr32_40();
+ }
+ break;
+ case 0x41:
+ {
+ instr16_41();
+ }
+ break;
+ case 0x41|0x100:
+ {
+ instr32_41();
+ }
+ break;
+ case 0x42:
+ {
+ instr16_42();
+ }
+ break;
+ case 0x42|0x100:
+ {
+ instr32_42();
+ }
+ break;
+ case 0x43:
+ {
+ instr16_43();
+ }
+ break;
+ case 0x43|0x100:
+ {
+ instr32_43();
+ }
+ break;
+ case 0x44:
+ {
+ instr16_44();
+ }
+ break;
+ case 0x44|0x100:
+ {
+ instr32_44();
+ }
+ break;
+ case 0x45:
+ {
+ instr16_45();
+ }
+ break;
+ case 0x45|0x100:
+ {
+ instr32_45();
+ }
+ break;
+ case 0x46:
+ {
+ instr16_46();
+ }
+ break;
+ case 0x46|0x100:
+ {
+ instr32_46();
+ }
+ break;
+ case 0x47:
+ {
+ instr16_47();
+ }
+ break;
+ case 0x47|0x100:
+ {
+ instr32_47();
+ }
+ break;
+ case 0x48:
+ {
+ instr16_48();
+ }
+ break;
+ case 0x48|0x100:
+ {
+ instr32_48();
+ }
+ break;
+ case 0x49:
+ {
+ instr16_49();
+ }
+ break;
+ case 0x49|0x100:
+ {
+ instr32_49();
+ }
+ break;
+ case 0x4A:
+ {
+ instr16_4A();
+ }
+ break;
+ case 0x4A|0x100:
+ {
+ instr32_4A();
+ }
+ break;
+ case 0x4B:
+ {
+ instr16_4B();
+ }
+ break;
+ case 0x4B|0x100:
+ {
+ instr32_4B();
+ }
+ break;
+ case 0x4C:
+ {
+ instr16_4C();
+ }
+ break;
+ case 0x4C|0x100:
+ {
+ instr32_4C();
+ }
+ break;
+ case 0x4D:
+ {
+ instr16_4D();
+ }
+ break;
+ case 0x4D|0x100:
+ {
+ instr32_4D();
+ }
+ break;
+ case 0x4E:
+ {
+ instr16_4E();
+ }
+ break;
+ case 0x4E|0x100:
+ {
+ instr32_4E();
+ }
+ break;
+ case 0x4F:
+ {
+ instr16_4F();
+ }
+ break;
+ case 0x4F|0x100:
+ {
+ instr32_4F();
+ }
+ break;
+ case 0x50:
+ {
+ instr16_50();
+ }
+ break;
+ case 0x50|0x100:
+ {
+ instr32_50();
+ }
+ break;
+ case 0x51:
+ {
+ instr16_51();
+ }
+ break;
+ case 0x51|0x100:
+ {
+ instr32_51();
+ }
+ break;
+ case 0x52:
+ {
+ instr16_52();
+ }
+ break;
+ case 0x52|0x100:
+ {
+ instr32_52();
+ }
+ break;
+ case 0x53:
+ {
+ instr16_53();
+ }
+ break;
+ case 0x53|0x100:
+ {
+ instr32_53();
+ }
+ break;
+ case 0x54:
+ {
+ instr16_54();
+ }
+ break;
+ case 0x54|0x100:
+ {
+ instr32_54();
+ }
+ break;
+ case 0x55:
+ {
+ instr16_55();
+ }
+ break;
+ case 0x55|0x100:
+ {
+ instr32_55();
+ }
+ break;
+ case 0x56:
+ {
+ instr16_56();
+ }
+ break;
+ case 0x56|0x100:
+ {
+ instr32_56();
+ }
+ break;
+ case 0x57:
+ {
+ instr16_57();
+ }
+ break;
+ case 0x57|0x100:
+ {
+ instr32_57();
+ }
+ break;
+ case 0x58:
+ {
+ instr16_58();
+ }
+ break;
+ case 0x58|0x100:
+ {
+ instr32_58();
+ }
+ break;
+ case 0x59:
+ {
+ instr16_59();
+ }
+ break;
+ case 0x59|0x100:
+ {
+ instr32_59();
+ }
+ break;
+ case 0x5A:
+ {
+ instr16_5A();
+ }
+ break;
+ case 0x5A|0x100:
+ {
+ instr32_5A();
+ }
+ break;
+ case 0x5B:
+ {
+ instr16_5B();
+ }
+ break;
+ case 0x5B|0x100:
+ {
+ instr32_5B();
+ }
+ break;
+ case 0x5C:
+ {
+ instr16_5C();
+ }
+ break;
+ case 0x5C|0x100:
+ {
+ instr32_5C();
+ }
+ break;
+ case 0x5D:
+ {
+ instr16_5D();
+ }
+ break;
+ case 0x5D|0x100:
+ {
+ instr32_5D();
+ }
+ break;
+ case 0x5E:
+ {
+ instr16_5E();
+ }
+ break;
+ case 0x5E|0x100:
+ {
+ instr32_5E();
+ }
+ break;
+ case 0x5F:
+ {
+ instr16_5F();
+ }
+ break;
+ case 0x5F|0x100:
+ {
+ instr32_5F();
+ }
+ break;
+ case 0x60:
+ {
+ instr16_60();
+ }
+ break;
+ case 0x60|0x100:
+ {
+ instr32_60();
+ }
+ break;
+ case 0x61:
+ {
+ instr16_61();
+ }
+ break;
+ case 0x61|0x100:
+ {
+ instr32_61();
+ }
+ break;
+ case 0x62:
+ case 0x62|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_62_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_62_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x63:
+ case 0x63|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_63_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_63_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x64:
+ case 0x64|0x100:
+ {
+ instr_64();
+ }
+ break;
+ case 0x65:
+ case 0x65|0x100:
+ {
+ instr_65();
+ }
+ break;
+ case 0x66:
+ case 0x66|0x100:
+ {
+ instr_66();
+ }
+ break;
+ case 0x67:
+ case 0x67|0x100:
+ {
+ instr_67();
+ }
+ break;
+ case 0x68:
+ {
+ instr16_68(read_imm16());
+ }
+ break;
+ case 0x68|0x100:
+ {
+ instr32_68(read_imm32s());
+ }
+ break;
+ case 0x69:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_69_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm16());
+ }
+ else
+ {
+ instr16_69_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm16());
+ }
+ }
+ break;
+ case 0x69|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_69_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm32s());
+ }
+ else
+ {
+ instr32_69_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm32s());
+ }
+ }
+ break;
+ case 0x6A:
+ {
+ instr16_6A(read_imm8s());
+ }
+ break;
+ case 0x6A|0x100:
+ {
+ instr32_6A(read_imm8s());
+ }
+ break;
+ case 0x6B:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_6B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8s());
+ }
+ else
+ {
+ instr16_6B_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8s());
+ }
+ }
+ break;
+ case 0x6B|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_6B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8s());
+ }
+ else
+ {
+ instr32_6B_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8s());
+ }
+ }
+ break;
+ case 0x6C:
+ case 0x6C|0x100:
+ {
+ instr_6C();
+ }
+ break;
+ case 0x6D:
+ {
+ instr16_6D();
+ }
+ break;
+ case 0x6D|0x100:
+ {
+ instr32_6D();
+ }
+ break;
+ case 0x6E:
+ case 0x6E|0x100:
+ {
+ instr_6E();
+ }
+ break;
+ case 0x6F:
+ {
+ instr16_6F();
+ }
+ break;
+ case 0x6F|0x100:
+ {
+ instr32_6F();
+ }
+ break;
+ case 0x70:
+ case 0x70|0x100:
+ {
+ instr_70(read_imm8s());
+ }
+ break;
+ case 0x71:
+ case 0x71|0x100:
+ {
+ instr_71(read_imm8s());
+ }
+ break;
+ case 0x72:
+ case 0x72|0x100:
+ {
+ instr_72(read_imm8s());
+ }
+ break;
+ case 0x73:
+ case 0x73|0x100:
+ {
+ instr_73(read_imm8s());
+ }
+ break;
+ case 0x74:
+ case 0x74|0x100:
+ {
+ instr_74(read_imm8s());
+ }
+ break;
+ case 0x75:
+ case 0x75|0x100:
+ {
+ instr_75(read_imm8s());
+ }
+ break;
+ case 0x76:
+ case 0x76|0x100:
+ {
+ instr_76(read_imm8s());
+ }
+ break;
+ case 0x77:
+ case 0x77|0x100:
+ {
+ instr_77(read_imm8s());
+ }
+ break;
+ case 0x78:
+ case 0x78|0x100:
+ {
+ instr_78(read_imm8s());
+ }
+ break;
+ case 0x79:
+ case 0x79|0x100:
+ {
+ instr_79(read_imm8s());
+ }
+ break;
+ case 0x7A:
+ case 0x7A|0x100:
+ {
+ instr_7A(read_imm8s());
+ }
+ break;
+ case 0x7B:
+ case 0x7B|0x100:
+ {
+ instr_7B(read_imm8s());
+ }
+ break;
+ case 0x7C:
+ case 0x7C|0x100:
+ {
+ instr_7C(read_imm8s());
+ }
+ break;
+ case 0x7D:
+ case 0x7D|0x100:
+ {
+ instr_7D(read_imm8s());
+ }
+ break;
+ case 0x7E:
+ case 0x7E|0x100:
+ {
+ instr_7E(read_imm8s());
+ }
+ break;
+ case 0x7F:
+ case 0x7F|0x100:
+ {
+ instr_7F(read_imm8s());
+ }
+ break;
+ case 0x80:
+ case 0x80|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_80_0_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_80_0_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_80_1_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_80_1_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_80_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_80_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_80_3_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_80_3_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_80_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_80_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_80_5_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_80_5_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_80_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_80_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_80_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_80_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x81:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_81_0_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_81_0_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_81_1_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_81_1_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_81_2_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_81_2_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_81_3_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_81_3_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_81_4_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_81_4_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_81_5_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_81_5_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_81_6_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_81_6_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_81_7_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_81_7_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x81|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_81_0_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_81_0_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_81_1_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_81_1_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_81_2_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_81_2_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_81_3_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_81_3_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_81_4_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_81_4_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_81_5_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_81_5_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_81_6_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_81_6_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_81_7_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_81_7_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x82:
+ case 0x82|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_82_0_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_82_0_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_82_1_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_82_1_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_82_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_82_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_82_3_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_82_3_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_82_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_82_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_82_5_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_82_5_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_82_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_82_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_82_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_82_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x83:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_83_0_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr16_83_0_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_83_1_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr16_83_1_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_83_2_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr16_83_2_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_83_3_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr16_83_3_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_83_4_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr16_83_4_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_83_5_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr16_83_5_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_83_6_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr16_83_6_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_83_7_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr16_83_7_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x83|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_83_0_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr32_83_0_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_83_1_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr32_83_1_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_83_2_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr32_83_2_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_83_3_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr32_83_3_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_83_4_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr32_83_4_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_83_5_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr32_83_5_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_83_6_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr32_83_6_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_83_7_mem(modrm_resolve(modrm_byte), read_imm8s());
+ }
+ else
+ {
+ instr32_83_7_reg(modrm_byte & 7, read_imm8s());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x84:
+ case 0x84|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_84_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_84_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x85:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_85_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_85_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x85|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_85_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_85_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x86:
+ case 0x86|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_86_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_86_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x87:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_87_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_87_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x87|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_87_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_87_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x88:
+ case 0x88|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_88_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_88_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x89:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_89_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_89_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x89|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_89_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_89_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x8A:
+ case 0x8A|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_8A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_8A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x8B:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_8B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_8B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x8B|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_8B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_8B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x8C:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_8C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_8C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x8C|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_8C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_8C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x8D:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_8D_mem(instr16_8D_modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_8D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x8D|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_8D_mem(instr32_8D_modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_8D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x8E:
+ case 0x8E|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_8E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_8E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x8F:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_8F_0_mem(instr16_8F_0_modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_8F_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x8F|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_8F_0_mem(instr32_8F_0_modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_8F_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x90:
+ case 0x90|0x100:
+ {
+ instr_90();
+ }
+ break;
+ case 0x91:
+ {
+ instr16_91();
+ }
+ break;
+ case 0x91|0x100:
+ {
+ instr32_91();
+ }
+ break;
+ case 0x92:
+ {
+ instr16_92();
+ }
+ break;
+ case 0x92|0x100:
+ {
+ instr32_92();
+ }
+ break;
+ case 0x93:
+ {
+ instr16_93();
+ }
+ break;
+ case 0x93|0x100:
+ {
+ instr32_93();
+ }
+ break;
+ case 0x94:
+ {
+ instr16_94();
+ }
+ break;
+ case 0x94|0x100:
+ {
+ instr32_94();
+ }
+ break;
+ case 0x95:
+ {
+ instr16_95();
+ }
+ break;
+ case 0x95|0x100:
+ {
+ instr32_95();
+ }
+ break;
+ case 0x96:
+ {
+ instr16_96();
+ }
+ break;
+ case 0x96|0x100:
+ {
+ instr32_96();
+ }
+ break;
+ case 0x97:
+ {
+ instr16_97();
+ }
+ break;
+ case 0x97|0x100:
+ {
+ instr32_97();
+ }
+ break;
+ case 0x98:
+ {
+ instr16_98();
+ }
+ break;
+ case 0x98|0x100:
+ {
+ instr32_98();
+ }
+ break;
+ case 0x99:
+ {
+ instr16_99();
+ }
+ break;
+ case 0x99|0x100:
+ {
+ instr32_99();
+ }
+ break;
+ case 0x9A:
+ {
+ instr16_9A(read_imm16(), read_imm16());
+ }
+ break;
+ case 0x9A|0x100:
+ {
+ instr32_9A(read_imm32s(), read_imm16());
+ }
+ break;
+ case 0x9B:
+ case 0x9B|0x100:
+ {
+ instr_9B();
+ }
+ break;
+ case 0x9C:
+ {
+ instr16_9C();
+ }
+ break;
+ case 0x9C|0x100:
+ {
+ instr32_9C();
+ }
+ break;
+ case 0x9D:
+ {
+ instr16_9D();
+ }
+ break;
+ case 0x9D|0x100:
+ {
+ instr32_9D();
+ }
+ break;
+ case 0x9E:
+ case 0x9E|0x100:
+ {
+ instr_9E();
+ }
+ break;
+ case 0x9F:
+ case 0x9F|0x100:
+ {
+ instr_9F();
+ }
+ break;
+ case 0xA0:
+ case 0xA0|0x100:
+ {
+ instr_A0(read_moffs());
+ }
+ break;
+ case 0xA1:
+ {
+ instr16_A1(read_moffs());
+ }
+ break;
+ case 0xA1|0x100:
+ {
+ instr32_A1(read_moffs());
+ }
+ break;
+ case 0xA2:
+ case 0xA2|0x100:
+ {
+ instr_A2(read_moffs());
+ }
+ break;
+ case 0xA3:
+ {
+ instr16_A3(read_moffs());
+ }
+ break;
+ case 0xA3|0x100:
+ {
+ instr32_A3(read_moffs());
+ }
+ break;
+ case 0xA4:
+ case 0xA4|0x100:
+ {
+ instr_A4();
+ }
+ break;
+ case 0xA5:
+ {
+ instr16_A5();
+ }
+ break;
+ case 0xA5|0x100:
+ {
+ instr32_A5();
+ }
+ break;
+ case 0xA6:
+ case 0xA6|0x100:
+ {
+ instr_A6();
+ }
+ break;
+ case 0xA7:
+ {
+ instr16_A7();
+ }
+ break;
+ case 0xA7|0x100:
+ {
+ instr32_A7();
+ }
+ break;
+ case 0xA8:
+ case 0xA8|0x100:
+ {
+ instr_A8(read_imm8());
+ }
+ break;
+ case 0xA9:
+ {
+ instr16_A9(read_imm16());
+ }
+ break;
+ case 0xA9|0x100:
+ {
+ instr32_A9(read_imm32s());
+ }
+ break;
+ case 0xAA:
+ case 0xAA|0x100:
+ {
+ instr_AA();
+ }
+ break;
+ case 0xAB:
+ {
+ instr16_AB();
+ }
+ break;
+ case 0xAB|0x100:
+ {
+ instr32_AB();
+ }
+ break;
+ case 0xAC:
+ case 0xAC|0x100:
+ {
+ instr_AC();
+ }
+ break;
+ case 0xAD:
+ {
+ instr16_AD();
+ }
+ break;
+ case 0xAD|0x100:
+ {
+ instr32_AD();
+ }
+ break;
+ case 0xAE:
+ case 0xAE|0x100:
+ {
+ instr_AE();
+ }
+ break;
+ case 0xAF:
+ {
+ instr16_AF();
+ }
+ break;
+ case 0xAF|0x100:
+ {
+ instr32_AF();
+ }
+ break;
+ case 0xB0:
+ case 0xB0|0x100:
+ {
+ instr_B0(read_imm8());
+ }
+ break;
+ case 0xB1:
+ case 0xB1|0x100:
+ {
+ instr_B1(read_imm8());
+ }
+ break;
+ case 0xB2:
+ case 0xB2|0x100:
+ {
+ instr_B2(read_imm8());
+ }
+ break;
+ case 0xB3:
+ case 0xB3|0x100:
+ {
+ instr_B3(read_imm8());
+ }
+ break;
+ case 0xB4:
+ case 0xB4|0x100:
+ {
+ instr_B4(read_imm8());
+ }
+ break;
+ case 0xB5:
+ case 0xB5|0x100:
+ {
+ instr_B5(read_imm8());
+ }
+ break;
+ case 0xB6:
+ case 0xB6|0x100:
+ {
+ instr_B6(read_imm8());
+ }
+ break;
+ case 0xB7:
+ case 0xB7|0x100:
+ {
+ instr_B7(read_imm8());
+ }
+ break;
+ case 0xB8:
+ {
+ instr16_B8(read_imm16());
+ }
+ break;
+ case 0xB8|0x100:
+ {
+ instr32_B8(read_imm32s());
+ }
+ break;
+ case 0xB9:
+ {
+ instr16_B9(read_imm16());
+ }
+ break;
+ case 0xB9|0x100:
+ {
+ instr32_B9(read_imm32s());
+ }
+ break;
+ case 0xBA:
+ {
+ instr16_BA(read_imm16());
+ }
+ break;
+ case 0xBA|0x100:
+ {
+ instr32_BA(read_imm32s());
+ }
+ break;
+ case 0xBB:
+ {
+ instr16_BB(read_imm16());
+ }
+ break;
+ case 0xBB|0x100:
+ {
+ instr32_BB(read_imm32s());
+ }
+ break;
+ case 0xBC:
+ {
+ instr16_BC(read_imm16());
+ }
+ break;
+ case 0xBC|0x100:
+ {
+ instr32_BC(read_imm32s());
+ }
+ break;
+ case 0xBD:
+ {
+ instr16_BD(read_imm16());
+ }
+ break;
+ case 0xBD|0x100:
+ {
+ instr32_BD(read_imm32s());
+ }
+ break;
+ case 0xBE:
+ {
+ instr16_BE(read_imm16());
+ }
+ break;
+ case 0xBE|0x100:
+ {
+ instr32_BE(read_imm32s());
+ }
+ break;
+ case 0xBF:
+ {
+ instr16_BF(read_imm16());
+ }
+ break;
+ case 0xBF|0x100:
+ {
+ instr32_BF(read_imm32s());
+ }
+ break;
+ case 0xC0:
+ case 0xC0|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_C0_0_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_C0_0_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_C0_1_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_C0_1_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_C0_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_C0_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_C0_3_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_C0_3_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_C0_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_C0_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_C0_5_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_C0_5_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_C0_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_C0_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_C0_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_C0_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xC1:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C1_0_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_C1_0_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C1_1_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_C1_1_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C1_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_C1_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C1_3_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_C1_3_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C1_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_C1_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C1_5_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_C1_5_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C1_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_C1_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C1_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_C1_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xC1|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C1_0_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_C1_0_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C1_1_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_C1_1_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C1_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_C1_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C1_3_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_C1_3_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C1_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_C1_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C1_5_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_C1_5_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C1_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_C1_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C1_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_C1_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xC2:
+ {
+ instr16_C2(read_imm16());
+ }
+ break;
+ case 0xC2|0x100:
+ {
+ instr32_C2(read_imm16());
+ }
+ break;
+ case 0xC3:
+ {
+ instr16_C3();
+ }
+ break;
+ case 0xC3|0x100:
+ {
+ instr32_C3();
+ }
+ break;
+ case 0xC4:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_C4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC4|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_C4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC5:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_C5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC5|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_C5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC6:
+ case 0xC6|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_C6_0_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_C6_0_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xC7:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_C7_0_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_C7_0_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xC7|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_C7_0_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_C7_0_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xC8:
+ {
+ instr16_C8(read_imm16(), read_imm8());
+ }
+ break;
+ case 0xC8|0x100:
+ {
+ instr32_C8(read_imm16(), read_imm8());
+ }
+ break;
+ case 0xC9:
+ {
+ instr16_C9();
+ }
+ break;
+ case 0xC9|0x100:
+ {
+ instr32_C9();
+ }
+ break;
+ case 0xCA:
+ {
+ instr16_CA(read_imm16());
+ }
+ break;
+ case 0xCA|0x100:
+ {
+ instr32_CA(read_imm16());
+ }
+ break;
+ case 0xCB:
+ {
+ instr16_CB();
+ }
+ break;
+ case 0xCB|0x100:
+ {
+ instr32_CB();
+ }
+ break;
+ case 0xCC:
+ case 0xCC|0x100:
+ {
+ instr_CC();
+ }
+ break;
+ case 0xCD:
+ case 0xCD|0x100:
+ {
+ instr_CD(read_imm8());
+ }
+ break;
+ case 0xCE:
+ case 0xCE|0x100:
+ {
+ instr_CE();
+ }
+ break;
+ case 0xCF:
+ {
+ instr16_CF();
+ }
+ break;
+ case 0xCF|0x100:
+ {
+ instr32_CF();
+ }
+ break;
+ case 0xD0:
+ case 0xD0|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D0_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D0_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D0_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D0_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D0_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D0_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D0_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D0_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D0_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D0_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D0_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D0_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D0_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D0_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D0_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D0_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xD1:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D1_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D1_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D1_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D1_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D1_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D1_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D1_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D1_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D1_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D1_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D1_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D1_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D1_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D1_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D1_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D1_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xD1|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D1_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D1_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D1_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D1_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D1_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D1_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D1_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D1_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D1_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D1_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D1_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D1_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D1_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D1_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D1_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D1_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xD2:
+ case 0xD2|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D2_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D2_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D2_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D2_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D2_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D2_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D2_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D2_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D2_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D2_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D2_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D2_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D2_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D2_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_D2_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_D2_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xD3:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D3_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D3_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D3_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D3_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D3_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D3_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D3_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D3_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D3_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D3_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D3_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D3_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D3_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D3_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_D3_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_D3_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xD3|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D3_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D3_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D3_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D3_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D3_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D3_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D3_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D3_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D3_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D3_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D3_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D3_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D3_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D3_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_D3_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_D3_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xD4:
+ case 0xD4|0x100:
+ {
+ instr_D4(read_imm8());
+ }
+ break;
+ case 0xD5:
+ case 0xD5|0x100:
+ {
+ instr_D5(read_imm8());
+ }
+ break;
+ case 0xD6:
+ case 0xD6|0x100:
+ {
+ instr_D6();
+ }
+ break;
+ case 0xD7:
+ case 0xD7|0x100:
+ {
+ instr_D7();
+ }
+ break;
+ case 0xD8:
+ case 0xD8|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_D8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_D8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xD9:
+ case 0xD9|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_D9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_D9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xDA:
+ case 0xDA|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_DA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_DA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xDB:
+ case 0xDB|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_DB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_DB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xDC:
+ case 0xDC|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_DC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_DC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xDD:
+ case 0xDD|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_DD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_DD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xDE:
+ case 0xDE|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_DE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_DE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xDF:
+ case 0xDF|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_DF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_DF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xE0:
+ case 0xE0|0x100:
+ {
+ instr_E0(read_imm8s());
+ }
+ break;
+ case 0xE1:
+ case 0xE1|0x100:
+ {
+ instr_E1(read_imm8s());
+ }
+ break;
+ case 0xE2:
+ case 0xE2|0x100:
+ {
+ instr_E2(read_imm8s());
+ }
+ break;
+ case 0xE3:
+ case 0xE3|0x100:
+ {
+ instr_E3(read_imm8s());
+ }
+ break;
+ case 0xE4:
+ case 0xE4|0x100:
+ {
+ instr_E4(read_imm8());
+ }
+ break;
+ case 0xE5:
+ {
+ instr16_E5(read_imm8());
+ }
+ break;
+ case 0xE5|0x100:
+ {
+ instr32_E5(read_imm8());
+ }
+ break;
+ case 0xE6:
+ case 0xE6|0x100:
+ {
+ instr_E6(read_imm8());
+ }
+ break;
+ case 0xE7:
+ {
+ instr16_E7(read_imm8());
+ }
+ break;
+ case 0xE7|0x100:
+ {
+ instr32_E7(read_imm8());
+ }
+ break;
+ case 0xE8:
+ {
+ instr16_E8(read_imm16());
+ }
+ break;
+ case 0xE8|0x100:
+ {
+ instr32_E8(read_imm32s());
+ }
+ break;
+ case 0xE9:
+ {
+ instr16_E9(read_imm16());
+ }
+ break;
+ case 0xE9|0x100:
+ {
+ instr32_E9(read_imm32s());
+ }
+ break;
+ case 0xEA:
+ {
+ instr16_EA(read_imm16(), read_imm16());
+ }
+ break;
+ case 0xEA|0x100:
+ {
+ instr32_EA(read_imm32s(), read_imm16());
+ }
+ break;
+ case 0xEB:
+ case 0xEB|0x100:
+ {
+ instr_EB(read_imm8s());
+ }
+ break;
+ case 0xEC:
+ case 0xEC|0x100:
+ {
+ instr_EC();
+ }
+ break;
+ case 0xED:
+ {
+ instr16_ED();
+ }
+ break;
+ case 0xED|0x100:
+ {
+ instr32_ED();
+ }
+ break;
+ case 0xEE:
+ case 0xEE|0x100:
+ {
+ instr_EE();
+ }
+ break;
+ case 0xEF:
+ {
+ instr16_EF();
+ }
+ break;
+ case 0xEF|0x100:
+ {
+ instr32_EF();
+ }
+ break;
+ case 0xF0:
+ case 0xF0|0x100:
+ {
+ instr_F0();
+ }
+ break;
+ case 0xF1:
+ case 0xF1|0x100:
+ {
+ instr_F1();
+ }
+ break;
+ case 0xF2:
+ case 0xF2|0x100:
+ {
+ instr_F2();
+ }
+ break;
+ case 0xF3:
+ case 0xF3|0x100:
+ {
+ instr_F3();
+ }
+ break;
+ case 0xF4:
+ case 0xF4|0x100:
+ {
+ instr_F4();
+ }
+ break;
+ case 0xF5:
+ case 0xF5|0x100:
+ {
+ instr_F5();
+ }
+ break;
+ case 0xF6:
+ case 0xF6|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F6_0_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_F6_0_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F6_1_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_F6_1_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F6_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_F6_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F6_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_F6_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F6_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_F6_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F6_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_F6_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F6_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_F6_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F6_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_F6_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xF7:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_F7_0_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_F7_0_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_F7_1_mem(modrm_resolve(modrm_byte), read_imm16());
+ }
+ else
+ {
+ instr16_F7_1_reg(modrm_byte & 7, read_imm16());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_F7_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_F7_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_F7_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_F7_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_F7_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_F7_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_F7_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_F7_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_F7_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_F7_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_F7_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_F7_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xF7|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_F7_0_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_F7_0_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_F7_1_mem(modrm_resolve(modrm_byte), read_imm32s());
+ }
+ else
+ {
+ instr32_F7_1_reg(modrm_byte & 7, read_imm32s());
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_F7_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_F7_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_F7_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_F7_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_F7_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_F7_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_F7_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_F7_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_F7_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_F7_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_F7_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_F7_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xF8:
+ case 0xF8|0x100:
+ {
+ instr_F8();
+ }
+ break;
+ case 0xF9:
+ case 0xF9|0x100:
+ {
+ instr_F9();
+ }
+ break;
+ case 0xFA:
+ case 0xFA|0x100:
+ {
+ instr_FA();
+ }
+ break;
+ case 0xFB:
+ case 0xFB|0x100:
+ {
+ instr_FB();
+ }
+ break;
+ case 0xFC:
+ case 0xFC|0x100:
+ {
+ instr_FC();
+ }
+ break;
+ case 0xFD:
+ case 0xFD|0x100:
+ {
+ instr_FD();
+ }
+ break;
+ case 0xFE:
+ case 0xFE|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_FE_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_FE_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_FE_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_FE_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xFF:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_FF_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_FF_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_FF_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_FF_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_FF_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_FF_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_FF_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_FF_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_FF_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_FF_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_FF_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_FF_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_FF_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr16_FF_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xFF|0x100:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_FF_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_FF_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_FF_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_FF_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_FF_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_FF_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_FF_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_FF_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_FF_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_FF_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_FF_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_FF_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_FF_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr32_FF_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ default:
+ assert(false);
}
+}
+
+#pragma clang diagnostic pop
diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c
index 72b4168b..77a776e7 100644
--- a/src/native/instructions_0f.c
+++ b/src/native/instructions_0f.c
@@ -6,11 +6,14 @@
#include "const.h"
#include "global_pointers.h"
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+
// XXX: Remove these declarations when they are implemented in C
-static void cmovcc16(bool);
-static void cmovcc32(bool);
-void jmpcc16(bool);
-void jmpcc32(bool);
+static void cmovcc16(bool, int32_t, int32_t);
+static void cmovcc32(bool, int32_t, int32_t);
+void jmpcc16(bool, int32_t);
+void jmpcc32(bool, int32_t);
void setcc(bool);
void cpuid();
@@ -30,10 +33,6 @@ int32_t bsr32(int32_t, int32_t);
int32_t popcnt(int32_t);
int32_t bswap(int32_t);
-int32_t read_g16s(void);
-int32_t read_reg_e16(void);
-int32_t read_reg_e32s(void);
-
void cpl_changed(void);
void update_cs_size(int32_t);
void unimplemented_sse(void);
@@ -52,7 +51,7 @@ void undefined_instruction();
void clear_tlb();
void full_clear_tlb();
-int32_t microtick();
+double_t microtick();
int32_t lsl(int32_t, int32_t);
int32_t lar(int32_t, int32_t);
@@ -69,236 +68,192 @@ void writable_or_pagefault(int32_t, int32_t);
bool* const apic_enabled;
-static void instr_0F00() { read_modrm_byte();
- if(!protected_mode[0] || vm86_mode())
- {
- // No GP, UD is correct here
- dbg_log("0f 00 #ud");
- trigger_ud();
- }
+static void write_reg8(int32_t index, int32_t value);
+static int32_t read_reg16(int32_t index);
+static void write_reg16(int32_t index, int32_t value);
+static int32_t read_reg32(int32_t index);
+static void write_reg32(int32_t index, int32_t value);
- switch(modrm_byte[0] >> 3 & 7)
- {
- case 0:
- // sldt
- set_e16(sreg[LDTR]);
- if(is_osize_32() && modrm_byte[0] >= 0xC0)
- {
- reg32s[modrm_byte[0] & 7] &= 0xFFFF;
- }
- break;
- case 1:
- // str
- set_e16(sreg[LDTR]);
- if(is_osize_32() && modrm_byte[0] >= 0xC0)
- {
- reg32s[modrm_byte[0] & 7] &= 0xFFFF;
- }
- break;
- case 2:
- // lldt
- if(cpl[0])
- {
- trigger_gp(0);
- }
- {
- int32_t data = read_e16();
- load_ldt(data);
- }
- break;
- case 3:
- // ltr
- if(cpl[0])
- {
- trigger_gp(0);
- }
+#define DEFINE_MODRM_INSTR_READ16(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t r) { int32_t ___ = safe_read16(addr); fun; } \
+ static void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg16(r1); fun; }
- int32_t data = read_e16();
- load_tr(data);
- break;
- case 4:
- verr(read_e16());
- break;
- case 5:
- verw(read_e16());
- break;
+#define DEFINE_MODRM_INSTR_READ32(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t r) { int32_t ___ = safe_read32s(addr); fun; } \
+ static void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg32(r1); fun; }
- default:
- dbg_log("%d", modrm_byte[0] >> 3 & 7);
- todo();
- }
+
+#define DEFINE_MODRM_INSTR_IMM_READ_WRITE_16(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t r, int32_t imm) { SAFE_READ_WRITE16(addr, fun) } \
+ static void name ## _reg(int32_t r1, int32_t r, int32_t imm) { int32_t ___ = read_reg16(r1); write_reg16(r1, fun); }
+
+#define DEFINE_MODRM_INSTR_IMM_READ_WRITE_32(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t r, int32_t imm) { SAFE_READ_WRITE32(addr, fun) } \
+ static void name ## _reg(int32_t r1, int32_t r, int32_t imm) { int32_t ___ = read_reg32(r1); write_reg32(r1, fun); }
+
+
+#define DEFINE_MODRM_INSTR_READ_WRITE_8(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE8(addr, fun) } \
+ static void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg8(r1); write_reg8(r1, fun); }
+
+#define DEFINE_MODRM_INSTR_READ_WRITE_16(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE16(addr, fun) } \
+ static void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg16(r1); write_reg16(r1, fun); }
+
+#define DEFINE_MODRM_INSTR_READ_WRITE_32(name, fun) \
+ static void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE32(addr, fun) } \
+ static void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg32(r1); write_reg32(r1, fun); }
+
+
+#define DEFINE_SSE_SPLIT(name, mem_fn, reg_fn) \
+ static void name ## _reg(int32_t r1, int32_t r2) { name(reg_fn(r1), r2); } \
+ static void name ## _mem(int32_t addr, int32_t r) { name(mem_fn(addr), r); } \
+
+#define DEFINE_SSE_SPLIT_IMM(name, mem_fn, reg_fn) \
+ static void name ## _reg(int32_t r1, int32_t r2, int32_t imm) { name(reg_fn(r1), r2, imm); } \
+ static void name ## _mem(int32_t addr, int32_t r, int32_t imm) { name(mem_fn(addr), r, imm); } \
+
+#define DEFINE_SSE_SPLIT_WRITE(name, mem_fn, reg_fn) \
+ static void name ## _reg(int32_t r1, int32_t r2) { reg_fn(r1, name(r2)); } \
+ static void name ## _mem(int32_t addr, int32_t r) { mem_fn(addr, name(r)); } \
+
+
+static void instr_0F00_0_mem(int32_t addr) {
+ // sldt
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ safe_write16(addr, sreg[LDTR]);
+}
+static void instr_0F00_0_reg(int32_t r) {
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ write_reg_osize(r, sreg[LDTR]);
+}
+static void instr_0F00_1_mem(int32_t addr) {
+ // str
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ safe_write16(addr, sreg[TR]);
+}
+static void instr_0F00_1_reg(int32_t r) {
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ write_reg_osize(r, sreg[TR]);
+}
+static void instr_0F00_2_mem(int32_t addr) {
+ // lldt
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ if(cpl[0]) trigger_gp(0);
+ load_ldt(safe_read16(addr));
+}
+static void instr_0F00_2_reg(int32_t r) {
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ if(cpl[0]) trigger_gp(0);
+ load_ldt(read_reg16(r));
+}
+static void instr_0F00_3_mem(int32_t addr) {
+ // ltr
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ if(cpl[0]) trigger_gp(0);
+ load_tr(safe_read16(addr));
+}
+static void instr_0F00_3_reg(int32_t r) {
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ if(cpl[0]) trigger_gp(0);
+ load_tr(read_reg16(r));
+}
+static void instr_0F00_4_mem(int32_t addr) {
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ verr(safe_read16(addr));
+}
+static void instr_0F00_4_reg(int32_t r) {
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ verr(read_reg16(r));
+}
+static void instr_0F00_5_mem(int32_t addr) {
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ verw(safe_read16(addr));
+}
+static void instr_0F00_5_reg(int32_t r) {
+ if(!protected_mode[0] || vm86_mode()) trigger_ud();
+ verw(read_reg16(r));
}
-static void instr_0F01() { read_modrm_byte();
- int32_t mod = modrm_byte[0] >> 3 & 7;
- if(mod == 4)
- {
- // smsw
- if(modrm_byte[0] >= 0xC0 && is_osize_32())
- {
- set_e32(cr[0]);
- }
- else
- {
- set_e16(cr[0]);
- }
- return;
- }
- else if(mod == 6)
- {
- // lmsw
- if(cpl[0])
- {
- trigger_gp(0);
- }
-
- int32_t cr0 = read_e16();
-
- cr0 = (cr[0] & ~0xF) | (cr0 & 0xF);
-
- if(protected_mode[0])
- {
- // lmsw cannot be used to switch back
- cr0 |= CR0_PE;
- }
-
- set_cr0(cr0);
- return;
- }
-
- if(modrm_byte[0] >= 0xC0)
- {
- // only memory
- dbg_log("0f 01 #ud");
- trigger_ud();
- }
-
- int32_t addr = modrm_resolve(modrm_byte[0]);
-
- switch(mod)
- {
- case 0:
- // sgdt
- writable_or_pagefault(addr, 6);
- safe_write16(addr, gdtr_size[0]);
- {
- int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF;
- safe_write32(addr + 2, gdtr_offset[0] & mask);
- }
- break;
- case 1:
- // sidt
- writable_or_pagefault(addr, 6);
- safe_write16(addr, idtr_size[0]);
- {
- int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF;
- safe_write32(addr + 2, idtr_offset[0] & mask);
- }
- break;
- case 2:
- // lgdt
- if(cpl[0])
- {
- trigger_gp(0);
- }
-
- {
- int32_t size = safe_read16(addr);
- int32_t offset = safe_read32s(addr + 2);
-
- gdtr_size[0] = size;
- gdtr_offset[0] = offset;
-
- if(!is_osize_32())
- {
- gdtr_offset[0] &= 0xFFFFFF;
- }
-
- //dbg_log("gdt at " + h(gdtr_offset[0]) + ", " + gdtr_size[0] + " bytes");
- //debug.dump_state();
- //debug.dump_regs_short();
- //debug.dump_gdt_ldt();
- }
- break;
- case 3:
- // lidt
- if(cpl[0])
- {
- trigger_gp(0);
- }
-
- {
- int32_t size = safe_read16(addr);
- int32_t offset = safe_read32s(addr + 2);
-
- idtr_size[0] = size;
- idtr_offset[0] = offset;
-
- if(!is_osize_32())
- {
- idtr_offset[0] &= 0xFFFFFF;
- }
-
- //dbg_log("[" + h(instruction_pointer) + "] idt at " +
- // h(idtr_offset) + ", " + idtr_size[0] + " bytes " + h(addr));
- }
- break;
- case 7:
- // flush translation lookaside buffer
- if(cpl[0])
- {
- trigger_gp(0);
- }
-
- invlpg(addr);
- break;
- default:
- dbg_log("%d", mod);
- todo();
- }
+static void instr_0F01_0_reg(int32_t r) { trigger_ud(); }
+static void instr_0F01_0_mem(int32_t addr) {
+ // sgdt
+ writable_or_pagefault(addr, 6);
+ int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF;
+ safe_write16(addr, gdtr_size[0]);
+ safe_write32(addr + 2, gdtr_offset[0] & mask);
+}
+static void instr_0F01_1_reg(int32_t r) { trigger_ud(); }
+static void instr_0F01_1_mem(int32_t addr) {
+ // sidt
+ writable_or_pagefault(addr, 6);
+ int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF;
+ safe_write16(addr, idtr_size[0]);
+ safe_write32(addr + 2, idtr_offset[0] & mask);
+}
+static void instr_0F01_2_reg(int32_t r) { trigger_ud(); }
+static void instr_0F01_2_mem(int32_t addr) {
+ // lgdt
+ if(cpl[0]) trigger_gp(0);
+ int32_t size = safe_read16(addr);
+ int32_t offset = safe_read32s(addr + 2);
+ int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF;
+ gdtr_size[0] = size;
+ gdtr_offset[0] = offset & mask;
+}
+static void instr_0F01_3_reg(int32_t r) { trigger_ud(); }
+static void instr_0F01_3_mem(int32_t addr) {
+ // lidt
+ if(cpl[0]) trigger_gp(0);
+ int32_t size = safe_read16(addr);
+ int32_t offset = safe_read32s(addr + 2);
+ int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF;
+ idtr_size[0] = size;
+ idtr_offset[0] = offset & mask;
}
-static void instr16_0F02() { read_modrm_byte();
- // lar
- if(!protected_mode[0] || vm86_mode())
- {
- dbg_log("lar #ud");
- trigger_ud();
- }
- int32_t data = read_e16();
- write_g16(lar(data, read_g16()));
+static void instr_0F01_4_reg(int32_t r) {
+ // smsw
+ write_reg_osize(r, cr[0]);
}
-static void instr32_0F02() { read_modrm_byte();
- if(!protected_mode[0] || vm86_mode())
- {
- dbg_log("lar #ud");
- trigger_ud();
- }
- int32_t data = read_e16();
- write_g32(lar(data, read_g32s()));
+static void instr_0F01_4_mem(int32_t addr) {
+ safe_write16(addr, cr[0] & 0xFFFF);
}
-static void instr16_0F03() { read_modrm_byte();
- // lsl
- if(!protected_mode[0] || vm86_mode())
+static void lmsw(int32_t new_cr0) {
+ new_cr0 = (cr[0] & ~0xF) | (new_cr0 & 0xF);
+
+ if(protected_mode[0])
{
- dbg_log("lsl #ud");
- trigger_ud();
+ // lmsw cannot be used to switch back
+ new_cr0 |= CR0_PE;
}
- int32_t data = read_e16();
- write_g16(lsl(data, read_g16()));
+
+ set_cr0(new_cr0);
}
-static void instr32_0F03() { read_modrm_byte();
- if(!protected_mode[0] || vm86_mode())
- {
- dbg_log("lsl #ud");
- trigger_ud();
- }
- int32_t data = read_e16();
- write_g32(lsl(data, read_g32s()));
+static void instr_0F01_6_reg(int32_t r) {
+ if(cpl[0]) trigger_gp(0);
+ lmsw(read_reg16(r));
}
+static void instr_0F01_6_mem(int32_t addr) {
+ if(cpl[0]) trigger_gp(0);
+ lmsw(safe_read16(addr));
+}
+
+static void instr_0F01_7_reg(int32_t r) { trigger_ud(); }
+static void instr_0F01_7_mem(int32_t addr) {
+ // invlpg
+ if(cpl[0]) trigger_gp(0);
+ invlpg(addr);
+}
+
+DEFINE_MODRM_INSTR_READ16(instr16_0F02, write_reg16(r, lar(___, read_reg16(r))))
+DEFINE_MODRM_INSTR_READ16(instr32_0F02, write_reg32(r, lar(___, read_reg32(r))))
+
+DEFINE_MODRM_INSTR_READ16(instr16_0F03, write_reg16(r, lsl(___, read_reg16(r))))
+DEFINE_MODRM_INSTR_READ16(instr32_0F03, write_reg32(r, lsl(___, read_reg32(r))))
static void instr_0F04() { undefined_instruction(); }
static void instr_0F05() { undefined_instruction(); }
@@ -350,55 +305,64 @@ static void instr_0F0F() { undefined_instruction(); }
static void instr_0F10() { unimplemented_sse(); }
static void instr_0F11() { unimplemented_sse(); }
-static void instr_0F12() { unimplemented_sse(); }
+static void instr_0F12_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0F12_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_660F12() {
- // movlpd xmm, xmm/m64
+static void instr_660F12_reg(int32_t r1, int32_t r) { trigger_ud(); }
+static void instr_660F12_mem(int32_t addr, int32_t r) {
+ // movlpd xmm, m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 data = read_xmm_mem64s();
- write_xmm64(data.u32[0], data.u32[1]);
+ union reg64 data = safe_read64s(addr);
+ write_xmm64(r, data);
+}
+static void instr_F20F12_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_F20F12_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_F30F12_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_F30F12_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0F13_mem(int32_t addr, int32_t r) {
+ // movlps m64, xmm
+ task_switch_test_mmx();
+ union reg64 data = read_xmm64s(r);
+ safe_write64(addr, data.u64[0]);
}
-static void instr_0F13() { unimplemented_sse(); }
+static void instr_0F13_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_660F13()
-{
+static void instr_660F13_reg(int32_t r1, int32_t r) { trigger_ud(); }
+static void instr_660F13_mem(int32_t addr, int32_t r) {
// movlpd xmm/m64, xmm
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 data = read_xmm64s();
- int32_t addr = modrm_resolve(*modrm_byte);
- safe_write64(addr, data.s32[0], data.s32[1]);
+ union reg64 data = read_xmm64s(r);
+ safe_write64(addr, data.u64[0]);
}
-static void instr_0F14() { unimplemented_sse(); }
+static void instr_0F14_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0F14_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_660F14()
-{
+static void instr_660F14(union reg64 source, int32_t r) {
// unpcklpd xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_xmm_mem64s();
- union reg64 destination = read_xmm64s();
+ union reg64 destination = read_xmm64s(r);
- write_xmm128s(
+ write_xmm128(
+ r,
destination.u32[0],
destination.u32[1],
source.u32[0],
source.u32[1]
);
}
+DEFINE_SSE_SPLIT(instr_660F14, safe_read64s, read_xmm64s)
static void instr_0F15() { unimplemented_sse(); }
static void instr_0F16() { unimplemented_sse(); }
static void instr_0F17() { unimplemented_sse(); }
-static void instr_0F18() { read_modrm_byte();
+static void instr_0F18_reg(int32_t r1, int32_t r2) { trigger_ud(); }
+static void instr_0F18_mem(int32_t addr, int32_t r) {
// prefetch
// nop for us
- if(modrm_byte[0] < 0xC0)
- modrm_resolve(modrm_byte[0]);
}
static void instr_0F19() { unimplemented_sse(); }
@@ -407,77 +371,78 @@ static void instr_0F1B() { unimplemented_sse(); }
static void instr_0F1C() { unimplemented_sse(); }
static void instr_0F1D() { unimplemented_sse(); }
static void instr_0F1E() { unimplemented_sse(); }
-static void instr_0F1F() { read_modrm_byte();
+static void instr_0F1F_reg(int32_t r1, int32_t r2) {
+ // multi-byte nop
+}
+static void instr_0F1F_mem(int32_t addr, int32_t r) {
// multi-byte nop
- if(modrm_byte[0] < 0xC0)
- modrm_resolve(modrm_byte[0]);
}
-static void instr_0F20() { read_modrm_byte();
+static void instr_0F20(int32_t r, int32_t creg) {
if(cpl[0])
{
trigger_gp(0);
}
- //dbg_log("cr" + (modrm_byte[0] >> 3 & 7) + " read");
- // mov addr, cr
- // mod = which control register
- switch(modrm_byte[0] >> 3 & 7)
+ switch(creg)
{
case 0:
- write_reg_e32(cr[0]);
+ write_reg32(r, cr[0]);
break;
case 2:
- //dbg_log("read cr2 at " + h(instruction_pointer, 8));
- write_reg_e32(cr[2]);
+ write_reg32(r, cr[2]);
break;
case 3:
- //dbg_log("read cr3 (" + h(cr[3], 8) + ")");
- write_reg_e32(cr[3]);
+ write_reg32(r, cr[3]);
break;
case 4:
- write_reg_e32(cr[4]);
+ write_reg32(r, cr[4]);
break;
default:
- dbg_log("%d", modrm_byte[0] >> 3 & 7);
+ dbg_log("%d", creg);
todo();
+ trigger_ud();
}
}
-static void instr_0F21() { read_modrm_byte();
+static void instr_0F21(int32_t r, int32_t dreg_index) {
if(cpl[0])
{
trigger_gp(0);
}
- int32_t dreg_index = modrm_byte[0] >> 3 & 7;
- if((cr[4] & CR4_DE) && (dreg_index == 4 || dreg_index == 5))
+ if(dreg_index == 4 || dreg_index == 5)
{
- dbg_log("#ud mov dreg 4/5 with cr4.DE set");
- trigger_ud();
+ if(cr[4] & CR4_DE)
+ {
+ dbg_log("#ud mov dreg 4/5 with cr4.DE set");
+ trigger_ud();
+ }
+ else
+ {
+ // DR4 and DR5 refer to DR6 and DR7 respectively
+ dreg_index += 2;
+ }
}
- // high two bits of modrm are ignored
- reg32s[modrm_byte[0] & 7] = dreg[dreg_index];
+ write_reg32(r, dreg[dreg_index]);
- //dbg_log("read dr" + dreg + ": " + h(dreg[dreg_index]));
+ //dbg_log("read dr%d: %x", dreg_index, dreg[dreg_index]);
}
-static void instr_0F22() { read_modrm_byte();
+static void instr_0F22(int32_t r, int32_t creg) {
if(cpl[0])
{
trigger_gp(0);
}
- int32_t data = read_reg_e32s();
- //dbg_log("cr" + (modrm_byte[0] >> 3 & 7) + " written: " + h(data, 8));
+ int32_t data = read_reg32(r);
// mov cr, addr
- // mod = which control register
- switch(modrm_byte[0] >> 3 & 7)
+ switch(creg)
{
case 0:
set_cr0(data);
@@ -534,27 +499,34 @@ static void instr_0F22() { read_modrm_byte();
break;
default:
- dbg_log("%d", modrm_byte[0] >> 3 & 7);
+ dbg_log("%d", creg);
todo();
+ trigger_ud();
}
}
-static void instr_0F23() { read_modrm_byte();
+static void instr_0F23(int32_t r, int32_t dreg_index) {
if(cpl[0])
{
trigger_gp(0);
}
- int32_t dreg_index = modrm_byte[0] >> 3 & 7;
- if((cr[4] & CR4_DE) && (dreg_index == 4 || dreg_index == 5))
+ if(dreg_index == 4 || dreg_index == 5)
{
- dbg_log("#ud mov dreg 4/5 with cr4.DE set");
- trigger_ud();
+ if(cr[4] & CR4_DE)
+ {
+ dbg_log("#ud mov dreg 4/5 with cr4.DE set");
+ trigger_ud();
+ }
+ else
+ {
+ // DR4 and DR5 refer to DR6 and DR7 respectively
+ dreg_index += 2;
+ }
}
- // high two bits of modrm are ignored
- dreg[dreg_index] = read_reg_e32s();
+ dreg[dreg_index] = read_reg32(r);
- //dbg_log("write dr" + dreg + ": " + h(dreg[dreg_index]));
+ //dbg_log("write dr%d: %x", dreg_index, dreg[dreg_index]);
}
static void instr_0F24() { undefined_instruction(); }
@@ -562,92 +534,82 @@ static void instr_0F25() { undefined_instruction(); }
static void instr_0F26() { undefined_instruction(); }
static void instr_0F27() { undefined_instruction(); }
-static void instr_0F28()
-{
+static void instr_0F28(union reg128 source, int32_t r) {
// movaps xmm, xmm/m128
+ // XXX: Aligned read or #gp
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 data = read_xmm_mem128s();
- write_xmm128s(data.u32[0], data.u32[1], data.u32[2], data.u32[3]);
+ write_xmm_reg128(r, source);
}
+DEFINE_SSE_SPLIT(instr_0F28, safe_read128s, read_xmm128s)
-static void instr_660F28() {
+static void instr_660F28(union reg128 source, int32_t r) {
// movapd xmm, xmm/m128
+ // XXX: Aligned read or #gp
+ // Note: Same as movdqa (660F6F)
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 data = read_xmm_mem128s();
- write_xmm128s(data.u32[0], data.u32[1], data.u32[2], data.u32[3]);
+ write_xmm_reg128(r, source);
}
+DEFINE_SSE_SPLIT(instr_660F28, safe_read128s, read_xmm128s)
-static void instr_0F29() {
- // movaps xmm/m128, xmm
+static void instr_0F29_mem(int32_t addr, int32_t r) {
+ // movaps m128, xmm
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg128 data = read_xmm128s();
- assert(*modrm_byte < 0xC0);
- int32_t addr = modrm_resolve(*modrm_byte);
+ union reg128 data = read_xmm128s(r);
+ // XXX: Aligned write or #gp
safe_write128(addr, data);
}
-static void instr_660F29()
-{
- // movapd xmm/m128, xmm
+static void instr_0F29_reg(int32_t r1, int32_t r2) {
+ // movaps xmm, xmm
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg128 data = read_xmm128s();
- assert(*modrm_byte < 0xC0);
- int32_t addr = modrm_resolve(*modrm_byte);
+ union reg128 data = read_xmm128s(r2);
+ write_xmm_reg128(r1, data);
+}
+static void instr_660F29_mem(int32_t addr, int32_t r) {
+ // movapd m128, xmm
+ task_switch_test_mmx();
+ union reg128 data = read_xmm128s(r);
+ // XXX: Aligned write or #gp
safe_write128(addr, data);
}
+static void instr_660F29_reg(int32_t r1, int32_t r2) {
+ // movapd xmm, xmm
+ task_switch_test_mmx();
+ union reg128 data = read_xmm128s(r2);
+ write_xmm_reg128(r1, data);
+}
static void instr_0F2A() { unimplemented_sse(); }
-static void instr_0F2B()
-{
+static void instr_0F2B_reg(int32_t r1, int32_t r2) { trigger_ud(); }
+static void instr_0F2B_mem(int32_t addr, int32_t r) {
// movntps m128, xmm
- // movntpd m128, xmm
+ // XXX: Aligned write or #gp
task_switch_test_mmx();
- read_modrm_byte();
-
- if(*modrm_byte >= 0xC0)
- {
- trigger_ud();
- }
-
- union reg128 data = read_xmm128s();
- int32_t addr = modrm_resolve(*modrm_byte);
+ union reg128 data = read_xmm128s(r);
safe_write128(addr, data);
}
-static void instr_660F2B()
-{
-
- task_switch_test_mmx();
- read_modrm_byte();
-
- if(*modrm_byte >= 0xC0)
- {
- trigger_ud();
- }
-
- // movntps m128, xmm
+static void instr_660F2B_reg(int32_t r1, int32_t r2) { trigger_ud(); }
+static void instr_660F2B_mem(int32_t addr, int32_t r) {
// movntpd m128, xmm
-
- union reg128 data = read_xmm128s();
- int32_t addr = modrm_resolve(*modrm_byte);
+ // XXX: Aligned write or #gp
+ task_switch_test_mmx();
+ union reg128 data = read_xmm128s(r);
safe_write128(addr, data);
}
-static void instr_0F2C() { unimplemented_sse(); }
+static void instr_0F2C_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0F2C_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660F2C_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F2C_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_F20F2C()
-{
+int32_t convert_f64_to_i32(double_t);
+static void instr_F20F2C(union reg64 source, int32_t r) {
// cvttsd2si r32, xmm/m64
// emscripten bug causes this ported instruction to throw "integer result unpresentable"
// https://github.com/kripken/emscripten/issues/5433
task_switch_test_mmx();
- read_modrm_byte();
+#if 0
union reg64 source = read_xmm_mem64s();
double f = source.f64[0];
@@ -660,7 +622,14 @@ static void instr_F20F2C()
{
write_g32(0x80000000);
}
+#else
+ write_reg32(r, convert_f64_to_i32(source.f64[0]));
+#endif
}
+DEFINE_SSE_SPLIT(instr_F20F2C, safe_read64s, read_xmm64s)
+
+static void instr_F30F2C_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_F30F2C_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
static void instr_0F2D() { unimplemented_sse(); }
static void instr_0F2E() { unimplemented_sse(); }
@@ -672,7 +641,6 @@ static void instr_0F30() {
if(cpl[0])
{
- // cpl > 0 or vm86 mode (vm86 mode is always runs with cpl=3)
trigger_gp(0);
}
@@ -712,7 +680,7 @@ static void instr_0F30() {
case IA32_TIME_STAMP_COUNTER:
{
- int32_t new_tick = (low) + 0x100000000 * (high);
+ uint64_t new_tick = (low) + 0x100000000 * (high);
tsc_offset[0] = microtick() - new_tick / TSC_RATE; // XXX: float
}
break;
@@ -743,11 +711,11 @@ static void instr_0F31() {
if(!cpl[0] || !(cr[4] & CR4_TSD))
{
- int32_t n = microtick() - tsc_offset[0]; // XXX: float
//dbg_assert(isFinite(n), "non-finite tsc: " + n);
+ uint64_t tsc = read_tsc();
- reg32s[EAX] = n * TSC_RATE;
- reg32s[EDX] = n * (TSC_RATE / 0x100000000);
+ reg32s[EAX] = tsc;
+ reg32s[EDX] = tsc >> 32;
//dbg_log("rdtsc edx:eax=" + h(reg32[EDX], 8) + ":" + h(reg32[EAX], 8));
}
@@ -787,9 +755,9 @@ static void instr_0F32() {
case IA32_TIME_STAMP_COUNTER:
{
- int32_t n = microtick() - tsc_offset[0]; // XXX: float
- low = n * TSC_RATE;
- high = n * (TSC_RATE / 0x100000000);
+ uint64_t tsc = read_tsc();
+ low = tsc;
+ high = tsc >> 32;
}
break;
@@ -938,38 +906,38 @@ static void instr_0F3F() { unimplemented_sse(); }
// cmov
-static void instr16_0F40() { read_modrm_byte(); cmovcc16( test_o()); }
-static void instr32_0F40() { read_modrm_byte(); cmovcc32( test_o()); }
-static void instr16_0F41() { read_modrm_byte(); cmovcc16(!test_o()); }
-static void instr32_0F41() { read_modrm_byte(); cmovcc32(!test_o()); }
-static void instr16_0F42() { read_modrm_byte(); cmovcc16( test_b()); }
-static void instr32_0F42() { read_modrm_byte(); cmovcc32( test_b()); }
-static void instr16_0F43() { read_modrm_byte(); cmovcc16(!test_b()); }
-static void instr32_0F43() { read_modrm_byte(); cmovcc32(!test_b()); }
-static void instr16_0F44() { read_modrm_byte(); cmovcc16( test_z()); }
-static void instr32_0F44() { read_modrm_byte(); cmovcc32( test_z()); }
-static void instr16_0F45() { read_modrm_byte(); cmovcc16(!test_z()); }
-static void instr32_0F45() { read_modrm_byte(); cmovcc32(!test_z()); }
-static void instr16_0F46() { read_modrm_byte(); cmovcc16( test_be()); }
-static void instr32_0F46() { read_modrm_byte(); cmovcc32( test_be()); }
-static void instr16_0F47() { read_modrm_byte(); cmovcc16(!test_be()); }
-static void instr32_0F47() { read_modrm_byte(); cmovcc32(!test_be()); }
-static void instr16_0F48() { read_modrm_byte(); cmovcc16( test_s()); }
-static void instr32_0F48() { read_modrm_byte(); cmovcc32( test_s()); }
-static void instr16_0F49() { read_modrm_byte(); cmovcc16(!test_s()); }
-static void instr32_0F49() { read_modrm_byte(); cmovcc32(!test_s()); }
-static void instr16_0F4A() { read_modrm_byte(); cmovcc16( test_p()); }
-static void instr32_0F4A() { read_modrm_byte(); cmovcc32( test_p()); }
-static void instr16_0F4B() { read_modrm_byte(); cmovcc16(!test_p()); }
-static void instr32_0F4B() { read_modrm_byte(); cmovcc32(!test_p()); }
-static void instr16_0F4C() { read_modrm_byte(); cmovcc16( test_l()); }
-static void instr32_0F4C() { read_modrm_byte(); cmovcc32( test_l()); }
-static void instr16_0F4D() { read_modrm_byte(); cmovcc16(!test_l()); }
-static void instr32_0F4D() { read_modrm_byte(); cmovcc32(!test_l()); }
-static void instr16_0F4E() { read_modrm_byte(); cmovcc16( test_le()); }
-static void instr32_0F4E() { read_modrm_byte(); cmovcc32( test_le()); }
-static void instr16_0F4F() { read_modrm_byte(); cmovcc16(!test_le()); }
-static void instr32_0F4F() { read_modrm_byte(); cmovcc32(!test_le()); }
+DEFINE_MODRM_INSTR_READ16(instr16_0F40, cmovcc16( test_o(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F40, cmovcc32( test_o(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F41, cmovcc16(!test_o(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F41, cmovcc32(!test_o(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F42, cmovcc16( test_b(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F42, cmovcc32( test_b(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F43, cmovcc16(!test_b(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F43, cmovcc32(!test_b(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F44, cmovcc16( test_z(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F44, cmovcc32( test_z(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F45, cmovcc16(!test_z(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F45, cmovcc32(!test_z(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F46, cmovcc16( test_be(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F46, cmovcc32( test_be(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F47, cmovcc16(!test_be(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F47, cmovcc32(!test_be(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F48, cmovcc16( test_s(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F48, cmovcc32( test_s(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F49, cmovcc16(!test_s(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F49, cmovcc32(!test_s(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F4A, cmovcc16( test_p(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F4A, cmovcc32( test_p(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F4B, cmovcc16(!test_p(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F4B, cmovcc32(!test_p(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F4C, cmovcc16( test_l(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F4C, cmovcc32( test_l(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F4D, cmovcc16(!test_l(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F4D, cmovcc32(!test_l(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F4E, cmovcc16( test_le(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F4E, cmovcc32( test_le(), ___, r))
+DEFINE_MODRM_INSTR_READ16(instr16_0F4F, cmovcc16(!test_le(), ___, r))
+DEFINE_MODRM_INSTR_READ32(instr32_0F4F, cmovcc32(!test_le(), ___, r))
static void instr_0F50() { unimplemented_sse(); }
@@ -977,82 +945,68 @@ static void instr_0F51() { unimplemented_sse(); }
static void instr_0F52() { unimplemented_sse(); }
static void instr_0F53() { unimplemented_sse(); }
-static void instr_0F54()
-{
+static void instr_0F54(union reg128 source, int32_t r) {
// andps xmm, xmm/mem128
- // andpd xmm, xmm/mem128
// Note: Same code as pand
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
-
- write_xmm128s(
+ union reg128 destination = read_xmm128s(r);
+ write_xmm128(
+ r,
source.u32[0] & destination.u32[0],
source.u32[1] & destination.u32[1],
source.u32[2] & destination.u32[2],
source.u32[3] & destination.u32[3]
);
}
+DEFINE_SSE_SPLIT(instr_0F54, safe_read128s, read_xmm128s)
-static void instr_660F54() {
- // andps xmm, xmm/mem128
+static void instr_660F54(union reg128 source, int32_t r) {
// andpd xmm, xmm/mem128
// Note: Same code as pand
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
-
- write_xmm128s(
+ union reg128 destination = read_xmm128s(r);
+ write_xmm128(
+ r,
source.u32[0] & destination.u32[0],
source.u32[1] & destination.u32[1],
source.u32[2] & destination.u32[2],
source.u32[3] & destination.u32[3]
);
}
+DEFINE_SSE_SPLIT(instr_660F54, safe_read128s, read_xmm128s)
static void instr_0F55() { unimplemented_sse(); }
static void instr_0F56() { unimplemented_sse(); }
-static void instr_0F57()
-{
+static void instr_0F57(union reg128 source, int32_t r) {
// xorps xmm, xmm/mem128
- // xorpd xmm, xmm/mem128
// Note: Same code as pxor
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
-
- write_xmm128s(
+ union reg128 destination = read_xmm128s(r);
+ write_xmm128(
+ r,
source.u32[0] ^ destination.u32[0],
source.u32[1] ^ destination.u32[1],
source.u32[2] ^ destination.u32[2],
source.u32[3] ^ destination.u32[3]
);
}
+DEFINE_SSE_SPLIT(instr_0F57, safe_read128s, read_xmm128s)
-static void instr_660F57() {
- // xorps xmm, xmm/mem128
+static void instr_660F57(union reg128 source, int32_t r) {
// xorpd xmm, xmm/mem128
// Note: Same code as pxor
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
-
- write_xmm128s(
+ union reg128 destination = read_xmm128s(r);
+ write_xmm128(
+ r,
source.u32[0] ^ destination.u32[0],
source.u32[1] ^ destination.u32[1],
source.u32[2] ^ destination.u32[2],
source.u32[3] ^ destination.u32[3]
);
}
+DEFINE_SSE_SPLIT(instr_660F57, safe_read128s, read_xmm128s)
static void instr_0F58() { unimplemented_sse(); }
static void instr_0F59() { unimplemented_sse(); }
@@ -1064,210 +1018,186 @@ static void instr_0F5E() { unimplemented_sse(); }
static void instr_0F5F() { unimplemented_sse(); }
-static void instr_0F60()
-{
+static void instr_0F60(int32_t source, int32_t r) {
// punpcklbw mm, mm/m32
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- int32_t source = read_mmx_mem32s();
- union reg64 destination = read_mmx64s();
-
- int32_t byte0 = destination.u32[0] & 0xFF;
+ int32_t byte0 = destination.u8[0];
int32_t byte1 = source & 0xFF;
- int32_t byte2 = (destination.u32[0] >> 8) & 0xFF;
+ int32_t byte2 = destination.u8[1];
int32_t byte3 = (source >> 8) & 0xFF;
- int32_t byte4 = (destination.u32[0] >> 16) & 0xFF;
+ int32_t byte4 = destination.u8[2];
int32_t byte5 = (source >> 16) & 0xFF;
- int32_t byte6 = destination.u32[0] >> 24;
+ int32_t byte6 = destination.u8[3];
int32_t byte7 = source >> 24;
int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F60, safe_read32s, read_mmx32s)
-void instr_660F60() {
+void instr_660F60(union reg64 source, int32_t r) {
// punpcklbw xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_xmm_mem64s();
- union reg64 destination = read_xmm64s();
- write_xmm128s(
+ union reg64 destination = read_xmm64s(r);
+ write_xmm128(
+ r,
destination.u8[0] | source.u8[0] << 8 | destination.u8[1] << 16 | source.u8[1] << 24,
destination.u8[2] | source.u8[2] << 8 | destination.u8[3] << 16 | source.u8[3] << 24,
destination.u8[4] | source.u8[4] << 8 | destination.u8[5] << 16 | source.u8[5] << 24,
destination.u8[6] | source.u8[6] << 8 | destination.u8[7] << 16 | source.u8[7] << 24
);
}
+DEFINE_SSE_SPLIT(instr_660F60, safe_read64s, read_xmm64s)
-static void instr_0F61()
-{
+static void instr_0F61(int32_t source, int32_t r) {
// punpcklwd mm, mm/m32
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- int32_t source = read_mmx_mem32s();
- union reg64 destination = read_mmx64s();
-
- int32_t word0 = destination.u32[0] & 0xFFFF;
+ int32_t word0 = destination.u16[0];
int32_t word1 = source & 0xFFFF;
- int32_t word2 = destination.u32[0] >> 16;
+ int32_t word2 = destination.u16[1];
int32_t word3 = source >> 16;
int32_t low = word0 | word1 << 16;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F61, safe_read32s, read_mmx32s)
-
-static void instr_660F61()
-{
+static void instr_660F61(union reg64 source, int32_t r) {
// punpcklwd xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg64 source = read_xmm_mem64s();
- union reg64 destination = read_xmm64s();
-
- write_xmm128s(
+ union reg64 destination = read_xmm64s(r);
+ write_xmm128(
+ r,
destination.u16[0] | source.u16[0] << 16,
destination.u16[1] | source.u16[1] << 16,
destination.u16[2] | source.u16[2] << 16,
destination.u16[3] | source.u16[3] << 16
);
}
+DEFINE_SSE_SPLIT(instr_660F61, safe_read64s, read_xmm64s)
-static void instr_0F62()
-{
+static void instr_0F62(int32_t source, int32_t r) {
// punpckldq mm, mm/m32
task_switch_test_mmx();
- read_modrm_byte();
-
- int32_t source = read_mmx_mem32s();
- union reg64 destination = read_mmx64s();
-
- write_mmx64s(destination.u32[0], source);
+ union reg64 destination = read_mmx64s(r);
+ write_mmx64(r, destination.u32[0], source);
}
+DEFINE_SSE_SPLIT(instr_0F62, safe_read32s, read_mmx32s)
+static void instr_660F62_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F62_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0F63() {
+static void instr_0F63(union reg64 source, int32_t r) {
// packsswb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t low = 0;
- low |= (saturate_sw_to_sb((destination.u32[0]) & 0xFFFF));
- low |= (saturate_sw_to_sb(destination.u32[0] >> 16)) << 8;
- low |= (saturate_sw_to_sb((destination.u32[1]) & 0xFFFF)) << 16;
- low |= (saturate_sw_to_sb(destination.u32[1] >> 16)) << 24;
+ low |= saturate_sw_to_sb(destination.u16[0]);
+ low |= saturate_sw_to_sb(destination.u16[1]) << 8;
+ low |= saturate_sw_to_sb(destination.u16[2]) << 16;
+ low |= saturate_sw_to_sb(destination.u16[3]) << 24;
int32_t high = 0;
- high |= (saturate_sw_to_sb((source.u32[0]) & 0xFFFF));
- high |= (saturate_sw_to_sb(source.u32[0] >> 16)) << 8;
- high |= (saturate_sw_to_sb((source.u32[1]) & 0xFFFF)) << 16;
- high |= (saturate_sw_to_sb(source.u32[1] >> 16)) << 24;
+ high |= saturate_sw_to_sb(source.u16[0]);
+ high |= saturate_sw_to_sb(source.u16[1]) << 8;
+ high |= saturate_sw_to_sb(source.u16[2]) << 16;
+ high |= saturate_sw_to_sb(source.u16[3]) << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F63, safe_read64s, read_mmx64s)
+static void instr_660F63_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F63_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-
-static void instr_0F64()
-{
+static void instr_0F64(union reg64 source, int32_t r) {
// pcmpgtb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
-
- int32_t byte0 = destination.s8[0] > source.s8[0] ? 0xFF : 0;
- int32_t byte1 = destination.s8[1] > source.s8[1] ? 0xFF : 0;
- int32_t byte2 = destination.s8[2] > source.s8[2] ? 0xFF : 0;
- int32_t byte3 = destination.s8[3] > source.s8[3] ? 0xFF : 0;
- int32_t byte4 = destination.s8[4] > source.s8[4] ? 0xFF : 0;
- int32_t byte5 = destination.s8[5] > source.s8[5] ? 0xFF : 0;
- int32_t byte6 = destination.s8[6] > source.s8[6] ? 0xFF : 0;
- int32_t byte7 = destination.s8[7] > source.s8[7] ? 0xFF : 0;
+ int32_t byte0 = destination.i8[0] > source.i8[0] ? 0xFF : 0;
+ int32_t byte1 = destination.i8[1] > source.i8[1] ? 0xFF : 0;
+ int32_t byte2 = destination.i8[2] > source.i8[2] ? 0xFF : 0;
+ int32_t byte3 = destination.i8[3] > source.i8[3] ? 0xFF : 0;
+ int32_t byte4 = destination.i8[4] > source.i8[4] ? 0xFF : 0;
+ int32_t byte5 = destination.i8[5] > source.i8[5] ? 0xFF : 0;
+ int32_t byte6 = destination.i8[6] > source.i8[6] ? 0xFF : 0;
+ int32_t byte7 = destination.i8[7] > source.i8[7] ? 0xFF : 0;
int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F64, safe_read64s, read_mmx64s)
+static void instr_660F64_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F64_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-
-static void instr_0F65()
-{
+static void instr_0F65(union reg64 source, int32_t r) {
// pcmpgtw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
-
- int32_t word0 = (destination.s16[0]) > (source.s16[0]) ? 0xFFFF : 0;
- int32_t word1 = (destination.s16[1]) > (source.s16[1]) ? 0xFFFF : 0;
- int32_t word2 = (destination.s16[2]) > (source.s16[2]) ? 0xFFFF : 0;
- int32_t word3 = (destination.s16[3]) > (source.s16[3]) ? 0xFFFF : 0;
+ int32_t word0 = destination.i16[0] > source.i16[0] ? 0xFFFF : 0;
+ int32_t word1 = destination.i16[1] > source.i16[1] ? 0xFFFF : 0;
+ int32_t word2 = destination.i16[2] > source.i16[2] ? 0xFFFF : 0;
+ int32_t word3 = destination.i16[3] > source.i16[3] ? 0xFFFF : 0;
int32_t low = word0 | word1 << 16;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F65, safe_read64s, read_mmx64s)
+static void instr_660F65_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F65_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0F66()
-{
+static void instr_0F66(union reg64 source, int32_t r) {
// pcmpgtd mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ int32_t low = destination.i32[0] > source.i32[0] ? -1 : 0;
+ int32_t high = destination.i32[1] > source.i32[1] ? -1 : 0;
- int32_t low = destination.s32[0] > source.s32[0] ? -1 : 0;
- int32_t high = destination.s32[1] > source.s32[1] ? -1 : 0;
-
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F66, safe_read64s, read_mmx64s)
+static void instr_660F66_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F66_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0F67()
-{
+static void instr_0F67(union reg64 source, int32_t r) {
// packuswb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t low = 0;
- low |= (saturate_sw_to_ub((destination.u32[0]) & 0xFFFF));
- low |= (saturate_sw_to_ub(destination.u32[0] >> 16)) << 8;
- low |= (saturate_sw_to_ub((destination.u32[1]) & 0xFFFF)) << 16;
- low |= (saturate_sw_to_ub(destination.u32[1] >> 16)) << 24;
+ low |= saturate_sw_to_ub(destination.u16[0]);
+ low |= saturate_sw_to_ub(destination.u16[1]) << 8;
+ low |= saturate_sw_to_ub(destination.u16[2]) << 16;
+ low |= saturate_sw_to_ub(destination.u16[3]) << 24;
uint32_t high = 0;
- high |= (saturate_sw_to_ub((source.u32[0]) & 0xFFFF));
- high |= (saturate_sw_to_ub(source.u32[0] >> 16)) << 8;
- high |= (saturate_sw_to_ub((source.u32[1]) & 0xFFFF)) << 16;
- high |= (saturate_sw_to_ub(source.u32[1] >> 16)) << 24;
+ high |= saturate_sw_to_ub(source.u16[0]);
+ high |= saturate_sw_to_ub(source.u16[1]) << 8;
+ high |= saturate_sw_to_ub(source.u16[2]) << 16;
+ high |= saturate_sw_to_ub(source.u16[3]) << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F67, safe_read64s, read_mmx64s)
-static void instr_660F67()
-{
+static void instr_660F67(union reg128 source, int32_t r) {
// packuswb xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
union reg128 result;
for(int32_t i = 0; i < 8; i++)
@@ -1276,93 +1206,80 @@ static void instr_660F67()
result.u8[i | 8] = saturate_sw_to_ub(source.u16[i]);
}
- write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]);
+ write_xmm_reg128(r, result);
}
+DEFINE_SSE_SPLIT(instr_660F67, safe_read128s, read_xmm128s)
-static void instr_0F68()
-{
+static void instr_0F68(union reg64 source, int32_t r) {
// punpckhbw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
-
- int32_t byte0 = destination.u32[1] & 0xFF;
- int32_t byte1 = source.u32[1] & 0xFF;
- int32_t byte2 = (destination.u32[1] >> 8) & 0xFF;
- int32_t byte3 = (source.u32[1] >> 8) & 0xFF;
- int32_t byte4 = (destination.u32[1] >> 16) & 0xFF;
- int32_t byte5 = (source.u32[1] >> 16) & 0xFF;
- int32_t byte6 = destination.u32[1] >> 24;
- int32_t byte7 = source.u32[1] >> 24;
+ int32_t byte0 = destination.u8[4];
+ int32_t byte1 = source.u8[4];
+ int32_t byte2 = destination.u8[5];
+ int32_t byte3 = source.u8[5];
+ int32_t byte4 = destination.u8[6];
+ int32_t byte5 = source.u8[6];
+ int32_t byte6 = destination.u8[7];
+ int32_t byte7 = source.u8[7];
int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F68, safe_read64s, read_mmx64s)
-
-static void instr_660F68()
-{
+static void instr_660F68(union reg128 source, int32_t r) {
// punpckhbw xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
+ union reg128 destination = read_xmm128s(r);
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
-
- write_xmm128s(
+ write_xmm128(
+ r,
destination.u8[ 8] | source.u8[ 8] << 8 | destination.u8[ 9] << 16 | source.u8[ 9] << 24,
destination.u8[10] | source.u8[10] << 8 | destination.u8[11] << 16 | source.u8[11] << 24,
destination.u8[12] | source.u8[12] << 8 | destination.u8[13] << 16 | source.u8[13] << 24,
destination.u8[14] | source.u8[14] << 8 | destination.u8[15] << 16 | source.u8[15] << 24
);
}
+DEFINE_SSE_SPLIT(instr_660F68, safe_read128s, read_xmm128s)
-
-static void instr_0F69()
-{
+static void instr_0F69(union reg64 source, int32_t r) {
// punpckhwd mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
-
- int32_t word0 = destination.u32[1] & 0xFFFF;
- int32_t word1 = source.u32[1] & 0xFFFF;
- int32_t word2 = destination.u32[1] >> 16;
- int32_t word3 = source.u32[1] >> 16;
+ int32_t word0 = destination.u16[2];
+ int32_t word1 = source.u16[2];
+ int32_t word2 = destination.u16[3];
+ int32_t word3 = source.u16[3];
int32_t low = word0 | word1 << 16;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F69, safe_read64s, read_mmx64s)
+static void instr_660F69_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F69_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0F6A()
-{
+static void instr_0F6A(union reg64 source, int32_t r) {
// punpckhdq mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
-
- write_mmx64s(destination.u32[1], source.u32[1]);
+ union reg64 destination = read_mmx64s(r);
+ write_mmx64(r, destination.u32[1], source.u32[1]);
}
+DEFINE_SSE_SPLIT(instr_0F6A, safe_read64s, read_mmx64s)
+static void instr_660F6A_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F6A_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0F6B()
-{
+static void instr_0F6B(union reg64 source, int32_t r) {
// packssdw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t low = 0;
low |= saturate_sd_to_sw(destination.u32[0]);
@@ -1372,422 +1289,352 @@ static void instr_0F6B()
high |= saturate_sd_to_sw(source.u32[0]);
high |= saturate_sd_to_sw(source.u32[1]) << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F6B, safe_read64s, read_mmx64s)
+static void instr_660F6B_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F6B_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0F6C() { unimplemented_sse(); }
-static void instr_0F6D() { unimplemented_sse(); }
+static void instr_0F6C_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0F6C_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660F6C_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F6C_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_0F6D_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0F6D_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660F6D_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F6D_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0F6E()
-{
+static void instr_0F6E(int32_t source, int32_t r) {
// movd mm, r/m32
task_switch_test_mmx();
- read_modrm_byte();
- int32_t data = read_e32s();
- write_mmx64s(data, 0);
+ write_mmx64(r, source, 0);
}
+DEFINE_SSE_SPLIT(instr_0F6E, safe_read32s, read_reg32)
-static void instr_660F6E() {
+static void instr_660F6E(int32_t source, int32_t r) {
// movd mm, r/m32
task_switch_test_mmx();
- read_modrm_byte();
- int32_t data = read_e32s();
- write_xmm128s(data, 0, 0, 0);
+ write_xmm128(r, source, 0, 0, 0);
}
+DEFINE_SSE_SPLIT(instr_660F6E, safe_read32s, read_reg32)
-static void instr_0F6F()
-{
+static void instr_0F6F(union reg64 source, int32_t r) {
// movq mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 data = read_mmx_mem64s();
- write_mmx64s(data.u32[0], data.u32[1]);
+ write_mmx64(r, source.u32[0], source.u32[1]);
}
+DEFINE_SSE_SPLIT(instr_0F6F, safe_read64s, read_mmx64s)
-static void instr_660F6F() {
+static void instr_660F6F(union reg128 source, int32_t r) {
// movdqa xmm, xmm/mem128
+ // XXX: Aligned read or #gp
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 data = read_xmm_mem128s();
- write_xmm128s(data.u32[0], data.u32[1], data.u32[2], data.u32[3]);
+ write_xmm_reg128(r, source);
}
-static void instr_F30F6F() {
+DEFINE_SSE_SPLIT(instr_660F6F, safe_read128s, read_xmm128s)
+static void instr_F30F6F(union reg128 source, int32_t r) {
// movdqu xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 data = read_xmm_mem128s();
- write_xmm128s(data.u32[0], data.u32[1], data.u32[2], data.u32[3]);
+ write_xmm_reg128(r, source);
}
+DEFINE_SSE_SPLIT(instr_F30F6F, safe_read128s, read_xmm128s)
-
-static void instr_0F70()
-{
+static void instr_0F70(union reg64 source, int32_t r, int32_t imm8) {
// pshufw mm1, mm2/m64, imm8
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- int32_t order = read_op8();
-
- int32_t word0_shift = order & 0b11;
+ int32_t word0_shift = imm8 & 0b11;
uint32_t word0 = source.u32[word0_shift >> 1] >> ((word0_shift & 1) << 4) & 0xFFFF;
- int32_t word1_shift = (order >> 2) & 0b11;
+ int32_t word1_shift = (imm8 >> 2) & 0b11;
uint32_t word1 = source.u32[word1_shift >> 1] >> ((word1_shift & 1) << 4);
int32_t low = word0 | word1 << 16;
- int32_t word2_shift = (order >> 4) & 0b11;
+ int32_t word2_shift = (imm8 >> 4) & 0b11;
uint32_t word2 = source.u32[word2_shift >> 1] >> ((word2_shift & 1) << 4) & 0xFFFF;
- uint32_t word3_shift = (order >> 6);
+ uint32_t word3_shift = (imm8 >> 6);
uint32_t word3 = source.u32[word3_shift >> 1] >> ((word3_shift & 1) << 4);
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT_IMM(instr_0F70, safe_read64s, read_mmx64s)
-static void instr_660F70() {
+static void instr_660F70(union reg128 source, int32_t r, int32_t imm8) {
// pshufd xmm, xmm/mem128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- int32_t order = read_op8();
-
- write_xmm128s(
- source.u32[order & 3],
- source.u32[order >> 2 & 3],
- source.u32[order >> 4 & 3],
- source.u32[order >> 6 & 3]
+ write_xmm128(
+ r,
+ source.u32[imm8 & 3],
+ source.u32[imm8 >> 2 & 3],
+ source.u32[imm8 >> 4 & 3],
+ source.u32[imm8 >> 6 & 3]
);
}
+DEFINE_SSE_SPLIT_IMM(instr_660F70, safe_read128s, read_xmm128s)
-static void instr_F20F70()
-{
+static void instr_F20F70(union reg128 source, int32_t r, int32_t imm8) {
// pshuflw xmm, xmm/m128, imm8
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- uint32_t order = read_op8();
-
- write_xmm128s(
- source.u16[order & 3] | source.u16[order >> 2 & 3] << 16,
- source.u16[order >> 4 & 3] | source.u16[order >> 6 & 3] << 16,
+ write_xmm128(
+ r,
+ source.u16[imm8 & 3] | source.u16[imm8 >> 2 & 3] << 16,
+ source.u16[imm8 >> 4 & 3] | source.u16[imm8 >> 6 & 3] << 16,
source.u32[2],
source.u32[3]
);
}
+DEFINE_SSE_SPLIT_IMM(instr_F20F70, safe_read128s, read_xmm128s)
-
-static void instr_F30F70()
-{
+static void instr_F30F70(union reg128 source, int32_t r, int32_t imm8) {
// pshufhw xmm, xmm/m128, imm8
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- uint32_t order = read_op8();
-
- write_xmm128s(
+ write_xmm128(
+ r,
source.u32[0],
source.u32[1],
- source.u16[order & 3 | 4] | source.u16[order >> 2 & 3 | 4] << 16,
- source.u16[order >> 4 & 3 | 4] | source.u16[order >> 6 & 3 | 4] << 16
+ source.u16[imm8 & 3 | 4] | source.u16[imm8 >> 2 & 3 | 4] << 16,
+ source.u16[imm8 >> 4 & 3 | 4] | source.u16[imm8 >> 6 & 3 | 4] << 16
);
}
+DEFINE_SSE_SPLIT_IMM(instr_F30F70, safe_read128s, read_xmm128s)
-static void instr_0F71()
-{
- read_modrm_byte();
+static void instr_0F71_2_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_0F71_4_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_0F71_6_mem(int32_t addr, int32_t r) { trigger_ud(); }
+
+static void instr_0F71_2_reg(int32_t r, int32_t imm8) {
+ // psrlw mm, imm8
task_switch_test_mmx();
-
- if(*modrm_byte < 0xC0)
- {
- trigger_ud();
- }
-
- uint32_t shift = read_op8();
- int32_t destination = (*modrm_byte & 7) << 1;
-
- int32_t destination_low = reg_mmx32s[destination];
- int32_t destination_high = reg_mmx32s[destination + 1];
+ union reg64 destination = read_mmx64s(r);
int32_t low = 0;
int32_t high = 0;
- int32_t word0, word1, word2, word3;
-
- // psrlw, psraw, psllw
- // 2, 4, 6
- switch(*modrm_byte >> 3 & 7)
- {
- case 2:
- // psrlw mm, imm8
- if (shift <= 15) {
- word0 = ((uint32_t) destination_low & 0xFFFF) >> shift;
- word1 = ((uint32_t) destination_low >> 16) >> shift;
- low = word0 | word1 << 16;
-
- word2 = ((uint32_t) destination_high & 0xFFFF) >> shift;
- word3 = ((uint32_t) destination_high >> 16) >> shift;
- high = word2 | word3 << 16;
- }
-
- reg_mmx32s[destination] = low;
- reg_mmx32s[destination + 1] = high;
-
- break;
- case 4:
- // psraw mm, imm8
- if (shift > 15) {
- shift = 16;
- }
-
- word0 = ((destination_low << 16 >> 16) >> shift) & 0xFFFF;
- word1 = ((destination_low >> 16) >> shift) & 0xFFFF;
+ if(imm8 <= 15) {
+ int32_t word0 = ((uint32_t) destination.u16[0]) >> imm8;
+ int32_t word1 = ((uint32_t) destination.u16[1]) >> imm8;
low = word0 | word1 << 16;
- word2 = ((destination_high << 16 >> 16) >> shift) & 0xFFFF;
- word3 = ((destination_high >> 16) >> shift) & 0xFFFF;
+ int32_t word2 = ((uint32_t) destination.u16[2]) >> imm8;
+ int32_t word3 = ((uint32_t) destination.u16[3]) >> imm8;
high = word2 | word3 << 16;
-
- reg_mmx32s[destination] = low;
- reg_mmx32s[destination + 1] = high;
-
- break;
- case 6:
- // psllw mm, imm8
- if (shift <= 15) {
- word0 = ((destination_low & 0xFFFF) << shift) & 0xFFFF;
- word1 = ((uint32_t) destination_low >> 16) << shift;
- low = word0 | word1 << 16;
-
- word2 = ((destination_high & 0xFFFF) << shift) & 0xFFFF;
- word3 = ((uint32_t) destination_high >> 16) << shift;
- high = word2 | word3 << 16;
- }
-
- reg_mmx32s[destination] = low;
- reg_mmx32s[destination + 1] = high;
-
- break;
- default:
- unimplemented_sse();
- break;
}
+
+ write_mmx64(r, low, high);
}
-static void instr_0F72()
-{
+static void instr_0F71_4_reg(int32_t r, int32_t imm8) {
+ // psraw mm, imm8
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- if(*modrm_byte < 0xC0)
- {
- trigger_ud();
- }
+ int32_t shift = imm8 > 15 ? 16 : imm8;
- uint32_t source = read_op8();
- uint32_t destination = (*modrm_byte & 7) << 1;
+ int32_t word0 = (destination.i16[0] >> shift) & 0xFFFF;
+ int32_t word1 = (destination.i16[1] >> shift) & 0xFFFF;
+ int32_t low = word0 | word1 << 16;
- uint32_t low = 0;
- uint32_t high = 0;
- int32_t shift = source;
+ int32_t word2 = (destination.i16[2] >> shift) & 0xFFFF;
+ int32_t word3 = (destination.i16[3] >> shift) & 0xFFFF;
+ int32_t high = word2 | word3 << 16;
- int32_t destination_low, destination_high;
-
- // psrld, psrad, pslld
- // 2, 4, 6
- switch(*modrm_byte >> 3 & 7)
- {
- case 2:
- // psrld mm, imm8
- destination_low = reg_mmx32s[destination];
- destination_high = reg_mmx32s[destination + 1];
-
- if (shift <= 31) {
- low = ((uint32_t) destination_low) >> shift;
- high = ((uint32_t) destination_high) >> shift;
- }
-
- reg_mmx32s[destination] = low;
- reg_mmx32s[destination + 1] = high;
-
- break;
- case 4:
- // psrad mm, imm8
- destination_low = reg_mmx32s[destination];
- destination_high = reg_mmx32s[destination + 1];
-
- if (shift > 31) {
- shift = 31;
- }
-
- low = destination_low >> shift;
- high = destination_high >> shift;
-
- reg_mmx32s[destination] = low;
- reg_mmx32s[destination + 1] = high;
-
- break;
- case 6:
- // pslld mm, imm8
- destination_low = reg_mmx32s[destination];
- destination_high = reg_mmx32s[destination + 1];
-
- if (shift <= 31) {
- low = destination_low << shift;
- high = destination_high << shift;
- }
-
- reg_mmx32s[destination] = low;
- reg_mmx32s[destination + 1] = high;
-
- break;
- default:
- unimplemented_sse();
- break;
- }
+ write_mmx64(r, low, high);
}
-
-static void instr_0F73()
-{
- read_modrm_byte();
+static void instr_0F71_6_reg(int32_t r, int32_t imm8) {
+ // psllw mm, imm8
task_switch_test_mmx();
-
- if(*modrm_byte < 0xC0)
- {
- trigger_ud();
- }
-
- uint32_t shift = read_op8();
- int32_t destination = (*modrm_byte & 7) << 1;
-
- int32_t destination_low = reg_mmx32s[destination];
- int32_t destination_high = reg_mmx32s[destination + 1];
+ union reg64 destination = read_mmx64s(r);
int32_t low = 0;
int32_t high = 0;
- // psrlq, psllq
- // 2, 6
- switch(*modrm_byte >> 3 & 7)
- {
- case 2:
- // psrlq mm, imm8
- if (shift <= 31) {
- low = (uint32_t) destination_low >> shift | (destination_high << (32 - shift));
- high = (uint32_t) destination_high >> shift;
- }
- else if (shift <= 63) {
- low = (uint32_t) destination_high >> (shift & 0x1F);
- high = 0;
- }
+ if(imm8 <= 15) {
+ int32_t word0 = (uint32_t)destination.u16[0] << imm8 & 0xFFFF;
+ int32_t word1 = (uint32_t)destination.u16[1] << imm8;
+ low = word0 | word1 << 16;
- reg_mmx32s[destination] = low;
- reg_mmx32s[destination + 1] = high;
- break;
- case 6:
- // psllq mm, imm8
- if (shift <= 31) {
- low = destination_low << shift;
- high = destination_high << shift | ((uint32_t) destination_low >> (32 - shift));
- }
- else if (shift <= 63) {
- high = destination_low << (shift & 0x1F);
- low = 0;
- }
-
- reg_mmx32s[destination] = low;
- reg_mmx32s[destination + 1] = high;
-
- break;
-
- default:
- unimplemented_sse();
- break;
+ int32_t word2 = (uint32_t)destination.u16[2] << imm8 & 0xFFFF;
+ int32_t word3 = (uint32_t)destination.u16[3] << imm8;
+ high = word2 | word3 << 16;
}
+
+ write_mmx64(r, low, high);
}
-static void instr_660F73()
-{
+static void instr_660F71_2_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F71_2_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660F71_4_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F71_4_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660F71_6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F71_6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
- read_modrm_byte();
+static void instr_0F72_2_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_0F72_4_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_0F72_6_mem(int32_t addr, int32_t r) { trigger_ud(); }
+
+static void instr_0F72_2_reg(int32_t r, int32_t imm8) {
+ // psrld mm, imm8
task_switch_test_mmx();
+ union reg64 destination = read_mmx64s(r);
- if(*modrm_byte < 0xC0)
- {
- trigger_ud();
+ int32_t low = 0;
+ int32_t high = 0;
+
+ if(imm8 <= 31) {
+ low = (uint32_t)destination.u32[0] >> imm8;
+ high = (uint32_t)destination.u32[1] >> imm8;
}
- uint32_t shift = read_op8();
-
- union reg128 destination = read_xmm128s();
- union reg128 result;
-
- // psrlq, psllq
- // 2, 6
- switch(*modrm_byte >> 3 & 7)
- {
- case 2:
- // psrlq xmm, imm8
- if(shift == 0)
- {
- return;
- }
-
- if (shift <= 31)
- {
- result.u32[0] = (uint32_t) destination.u32[0] >> shift | destination.u32[1] << (32 - shift);
- result.u32[1] = (uint32_t) destination.u32[1] >> shift;
-
- result.u32[2] = (uint32_t) destination.u32[2] >> shift | destination.u32[3] << (32 - shift);
- result.u32[3] = (uint32_t) destination.u32[3] >> shift;
- }
- else if (shift <= 63)
- {
- result.u32[0] = (uint32_t) destination.u32[1] >> shift;
- result.u32[2] = (uint32_t) destination.u32[3] >> shift;
- }
-
- write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]);
- break;
- default:
- unimplemented_sse();
- break;
- }
+ write_mmx64(r, low, high);
}
-static void instr_0F74()
-{
+static void instr_0F72_4_reg(int32_t r, int32_t imm8) {
+ // psrad mm, imm8
+ task_switch_test_mmx();
+ union reg64 destination = read_mmx64s(r);
+
+ int32_t shift = imm8 > 31 ? 31 : imm8;
+
+ int32_t low = destination.i32[0] >> shift;
+ int32_t high = destination.i32[1] >> shift;
+
+ write_mmx64(r, low, high);
+}
+
+static void instr_0F72_6_reg(int32_t r, int32_t imm8) {
+ // pslld mm, imm8
+ task_switch_test_mmx();
+ union reg64 destination = read_mmx64s(r);
+
+ int32_t low = 0;
+ int32_t high = 0;
+
+ if(imm8 <= 31) {
+ low = destination.i32[0] << imm8;
+ high = destination.i32[1] << imm8;
+ }
+
+ write_mmx64(r, low, high);
+}
+
+static void instr_660F72_2_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F72_2_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660F72_4_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F72_4_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660F72_6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660F72_6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0F73_2_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_0F73_3_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_0F73_3_reg(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_0F73_6_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_0F73_7_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_0F73_7_reg(int32_t addr, int32_t r) { trigger_ud(); }
+
+static void instr_0F73_2_reg(int32_t r, int32_t imm8) {
+ // psrlq mm, imm8
+ task_switch_test_mmx();
+ union reg64 destination = read_mmx64s(r);
+
+ int32_t low = 0;
+ int32_t high = 0;
+
+ if(imm8 <= 31) {
+ low = (uint32_t) destination.u32[0] >> imm8 | (destination.u32[1] << (32 - imm8));
+ high = (uint32_t) destination.u32[1] >> imm8;
+ }
+ else if(imm8 <= 63) {
+ low = (uint32_t) destination.u32[1] >> (imm8 & 0x1F);
+ high = 0;
+ }
+
+ write_mmx64(r, low, high);
+}
+
+static void instr_0F73_6_reg(int32_t r, int32_t imm8) {
+ // psllq mm, imm8
+ task_switch_test_mmx();
+ union reg64 destination = read_mmx64s(r);
+
+ int32_t low = 0;
+ int32_t high = 0;
+
+ if(imm8 <= 31) {
+ low = destination.u32[0] << imm8;
+ high = destination.u32[1] << imm8 | ((uint32_t) destination.u32[0] >> (32 - imm8));
+ }
+ else if(imm8 <= 63) {
+ high = destination.u32[0] << (imm8 & 0x1F);
+ low = 0;
+ }
+
+ write_mmx64(r, low, high);
+}
+
+static void instr_660F73_2_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_660F73_3_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_660F73_6_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_660F73_7_mem(int32_t addr, int32_t r) { trigger_ud(); }
+
+static void instr_660F73_2_reg(int32_t r, int32_t imm8) {
+ // psrlq mm, imm8
+ task_switch_test_mmx();
+ union reg128 destination = read_xmm128s(r);
+
+ if(imm8 == 0)
+ {
+ return;
+ }
+
+ union reg128 result = { { 0 } };
+
+ if(imm8 <= 31)
+ {
+ result.u32[0] = (uint32_t) destination.u32[0] >> imm8 | destination.u32[1] << (32 - imm8);
+ result.u32[1] = (uint32_t) destination.u32[1] >> imm8;
+
+ result.u32[2] = (uint32_t) destination.u32[2] >> imm8 | destination.u32[3] << (32 - imm8);
+ result.u32[3] = (uint32_t) destination.u32[3] >> imm8;
+ }
+ else if(imm8 <= 63)
+ {
+ result.u32[0] = (uint32_t) destination.u32[1] >> imm8;
+ result.u32[2] = (uint32_t) destination.u32[3] >> imm8;
+ }
+
+ write_xmm_reg128(r, result);
+}
+static void instr_660F73_3_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660F73_6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660F73_7_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0F74(union reg64 source, int32_t r) {
// pcmpeqb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- union reg64 source = read_mmx_mem64s();
-
- union reg64 destination = read_mmx64s();
-
- int32_t byte0 = destination.s8[0] == source.s8[0] ? 0xFF : 0;
- int32_t byte1 = destination.s8[1] == source.s8[1] ? 0xFF : 0;
- int32_t byte2 = destination.s8[2] == source.s8[2] ? 0xFF : 0;
- int32_t byte3 = destination.s8[3] == source.s8[3] ? 0xFF : 0;
- int32_t byte4 = destination.s8[4] == source.s8[4] ? 0xFF : 0;
- int32_t byte5 = destination.s8[5] == source.s8[5] ? 0xFF : 0;
- int32_t byte6 = destination.s8[6] == source.s8[6] ? 0xFF : 0;
- int32_t byte7 = destination.s8[7] == source.s8[7] ? 0xFF : 0;
+ int32_t byte0 = destination.i8[0] == source.i8[0] ? 0xFF : 0;
+ int32_t byte1 = destination.i8[1] == source.i8[1] ? 0xFF : 0;
+ int32_t byte2 = destination.i8[2] == source.i8[2] ? 0xFF : 0;
+ int32_t byte3 = destination.i8[3] == source.i8[3] ? 0xFF : 0;
+ int32_t byte4 = destination.i8[4] == source.i8[4] ? 0xFF : 0;
+ int32_t byte5 = destination.i8[5] == source.i8[5] ? 0xFF : 0;
+ int32_t byte6 = destination.i8[6] == source.i8[6] ? 0xFF : 0;
+ int32_t byte7 = destination.i8[7] == source.i8[7] ? 0xFF : 0;
int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F74, safe_read64s, read_mmx64s)
-static void instr_660F74() {
+static void instr_660F74(union reg128 source, int32_t r) {
// pcmpeqb xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
union reg128 result;
for(int32_t i = 0; i < 16; i++)
@@ -1795,36 +1642,31 @@ static void instr_660F74() {
result.u8[i] = source.u8[i] == destination.u8[i] ? 0xFF : 0;
}
- write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]);
+ write_xmm_reg128(r, result);
}
+DEFINE_SSE_SPLIT(instr_660F74, safe_read128s, read_xmm128s)
-static void instr_0F75()
-{
+static void instr_0F75(union reg64 source, int32_t r) {
// pcmpeqw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
+ union reg64 destination = read_mmx64s(r);
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
-
- int32_t word0 = (destination.u32[0] & 0xFFFF) == (source.u32[0] & 0xFFFF) ? 0xFFFF : 0;
- int32_t word1 = (destination.u32[0] & 0xFFFF0000) == (source.u32[0] & 0xFFFF0000) ? 0xFFFF : 0;
- int32_t word2 = (destination.u32[1] & 0xFFFF) == (source.u32[1] & 0xFFFF) ? 0xFFFF : 0;
- int32_t word3 = (destination.u32[1] & 0xFFFF0000) == (source.u32[1] & 0xFFFF0000) ? 0xFFFF : 0;
+ int32_t word0 = destination.u16[0] == source.u16[0] ? 0xFFFF : 0;
+ int32_t word1 = destination.u16[1] == source.u16[1] ? 0xFFFF : 0;
+ int32_t word2 = destination.u16[2] == source.u16[2] ? 0xFFFF : 0;
+ int32_t word3 = destination.u16[3] == source.u16[3] ? 0xFFFF : 0;
int32_t low = word0 | word1 << 16;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F75, safe_read64s, read_mmx64s)
-static void instr_660F75()
-{
+static void instr_660F75(union reg128 source, int32_t r) {
// pcmpeqw xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
union reg128 result;
for(int32_t i = 0; i < 8; i++)
@@ -1832,40 +1674,37 @@ static void instr_660F75()
result.u16[i] = source.u16[i] == destination.u16[i] ? 0xFFFF : 0;
}
- write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]);
+ write_xmm_reg128(r, result);
}
+DEFINE_SSE_SPLIT(instr_660F75, safe_read128s, read_xmm128s)
-static void instr_0F76()
-{
+static void instr_0F76(union reg64 source, int32_t r) {
// pcmpeqd mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t low = destination.u32[0] == source.u32[0] ? -1 : 0;
int32_t high = destination.u32[1] == source.u32[1] ? -1 : 0;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0F76, safe_read64s, read_mmx64s)
-static void instr_660F76()
-{
+static void instr_660F76(union reg128 source, int32_t r) {
// pcmpeqd xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
+ union reg128 destination = read_xmm128s(r);
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
-
- write_xmm128s(
+ write_xmm128(
+ r,
source.u32[0] == destination.u32[0] ? -1 : 0,
source.u32[1] == destination.u32[1] ? -1 : 0,
source.u32[2] == destination.u32[2] ? -1 : 0,
source.u32[3] == destination.u32[3] ? -1 : 0
);
}
+DEFINE_SSE_SPLIT(instr_660F76, safe_read128s, read_xmm128s)
+
static void instr_0F77() {
// emms
@@ -1888,109 +1727,140 @@ static void instr_0F7B() { unimplemented_sse(); }
static void instr_0F7C() { unimplemented_sse(); }
static void instr_0F7D() { unimplemented_sse(); }
-static void instr_0F7E()
-{
+static int32_t instr_0F7E(int32_t r) {
// movd r/m32, mm
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 data = read_mmx64s();
- set_e32(data.u32[0]);
+ union reg64 data = read_mmx64s(r);
+ return data.u32[0];
}
-
-static void instr_660F7E() {
+DEFINE_SSE_SPLIT_WRITE(instr_0F7E, safe_write32, write_reg32)
+static int32_t instr_660F7E(int32_t r) {
// movd r/m32, xmm
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 data = read_xmm64s();
- set_e32(data.u32[0]);
+ union reg64 data = read_xmm64s(r);
+ return data.u32[0];
}
-static void instr_F30F7E() {
+DEFINE_SSE_SPLIT_WRITE(instr_660F7E, safe_write32, write_reg32)
+static void instr_F30F7E_mem(int32_t addr, int32_t r) {
// movq xmm, xmm/mem64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 data = read_xmm_mem64s();
- write_xmm128s(data.u32[0], data.u32[1], 0, 0);
+ union reg64 data = safe_read64s(addr);
+ write_xmm128(r, data.u32[0], data.u32[1], 0, 0);
+}
+static void instr_F30F7E_reg(int32_t r1, int32_t r2) {
+ // movq xmm, xmm/mem64
+ task_switch_test_mmx();
+ union reg64 data = read_xmm64s(r1);
+ write_xmm128(r2, data.u32[0], data.u32[1], 0, 0);
}
-static void instr_0F7F()
-{
+static void instr_0F7F_mem(int32_t addr, int32_t r) {
// movq mm/m64, mm
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 data = read_mmx64s();
- write_mmx_mem64s(data.u32[0], data.u32[1]);
+ union reg64 data = read_mmx64s(r);
+ safe_write64(addr, data.u64[0]);
}
-
-static void instr_660F7F() {
+static void instr_0F7F_reg(int32_t r1, int32_t r2) {
+ // movq mm/m64, mm
+ task_switch_test_mmx();
+ union reg64 data = read_mmx64s(r2);
+ write_mmx64(r1, data.u32[0], data.u32[1]);
+}
+static void instr_660F7F_mem(int32_t addr, int32_t r) {
+ // movdqa xmm/m128, xmm
+ // XXX: Aligned write or #gp
+ task_switch_test_mmx();
+ union reg128 data = read_xmm128s(r);
+ safe_write128(addr, data);
+}
+static void instr_660F7F_reg(int32_t r1, int32_t r2) {
// movdqa xmm/m128, xmm
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 data = read_xmm128s();
- assert(*modrm_byte < 0xC0);
- int32_t addr = modrm_resolve(*modrm_byte);
- safe_write128(addr, data);
+ union reg128 data = read_xmm128s(r2);
+ write_xmm_reg128(r1, data);
}
-static void instr_F30F7F() {
+static void instr_F30F7F_mem(int32_t addr, int32_t r) {
// movdqu xmm/m128, xmm
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 data = read_xmm128s();
- assert(*modrm_byte < 0xC0);
- int32_t addr = modrm_resolve(*modrm_byte);
+ union reg128 data = read_xmm128s(r);
safe_write128(addr, data);
}
+static void instr_F30F7F_reg(int32_t r1, int32_t r2) {
+ // movdqu xmm/m128, xmm
+ task_switch_test_mmx();
+ union reg128 data = read_xmm128s(r2);
+ write_xmm_reg128(r1, data);
+}
// jmpcc
-static void instr16_0F80() { jmpcc16( test_o()); }
-static void instr32_0F80() { jmpcc32( test_o()); }
-static void instr16_0F81() { jmpcc16(!test_o()); }
-static void instr32_0F81() { jmpcc32(!test_o()); }
-static void instr16_0F82() { jmpcc16( test_b()); }
-static void instr32_0F82() { jmpcc32( test_b()); }
-static void instr16_0F83() { jmpcc16(!test_b()); }
-static void instr32_0F83() { jmpcc32(!test_b()); }
-static void instr16_0F84() { jmpcc16( test_z()); }
-static void instr32_0F84() { jmpcc32( test_z()); }
-static void instr16_0F85() { jmpcc16(!test_z()); }
-static void instr32_0F85() { jmpcc32(!test_z()); }
-static void instr16_0F86() { jmpcc16( test_be()); }
-static void instr32_0F86() { jmpcc32( test_be()); }
-static void instr16_0F87() { jmpcc16(!test_be()); }
-static void instr32_0F87() { jmpcc32(!test_be()); }
-static void instr16_0F88() { jmpcc16( test_s()); }
-static void instr32_0F88() { jmpcc32( test_s()); }
-static void instr16_0F89() { jmpcc16(!test_s()); }
-static void instr32_0F89() { jmpcc32(!test_s()); }
-static void instr16_0F8A() { jmpcc16( test_p()); }
-static void instr32_0F8A() { jmpcc32( test_p()); }
-static void instr16_0F8B() { jmpcc16(!test_p()); }
-static void instr32_0F8B() { jmpcc32(!test_p()); }
-static void instr16_0F8C() { jmpcc16( test_l()); }
-static void instr32_0F8C() { jmpcc32( test_l()); }
-static void instr16_0F8D() { jmpcc16(!test_l()); }
-static void instr32_0F8D() { jmpcc32(!test_l()); }
-static void instr16_0F8E() { jmpcc16( test_le()); }
-static void instr32_0F8E() { jmpcc32( test_le()); }
-static void instr16_0F8F() { jmpcc16(!test_le()); }
-static void instr32_0F8F() { jmpcc32(!test_le()); }
+static void instr16_0F80(int32_t imm) { jmpcc16( test_o(), imm); }
+static void instr32_0F80(int32_t imm) { jmpcc32( test_o(), imm); }
+static void instr16_0F81(int32_t imm) { jmpcc16(!test_o(), imm); }
+static void instr32_0F81(int32_t imm) { jmpcc32(!test_o(), imm); }
+static void instr16_0F82(int32_t imm) { jmpcc16( test_b(), imm); }
+static void instr32_0F82(int32_t imm) { jmpcc32( test_b(), imm); }
+static void instr16_0F83(int32_t imm) { jmpcc16(!test_b(), imm); }
+static void instr32_0F83(int32_t imm) { jmpcc32(!test_b(), imm); }
+static void instr16_0F84(int32_t imm) { jmpcc16( test_z(), imm); }
+static void instr32_0F84(int32_t imm) { jmpcc32( test_z(), imm); }
+static void instr16_0F85(int32_t imm) { jmpcc16(!test_z(), imm); }
+static void instr32_0F85(int32_t imm) { jmpcc32(!test_z(), imm); }
+static void instr16_0F86(int32_t imm) { jmpcc16( test_be(), imm); }
+static void instr32_0F86(int32_t imm) { jmpcc32( test_be(), imm); }
+static void instr16_0F87(int32_t imm) { jmpcc16(!test_be(), imm); }
+static void instr32_0F87(int32_t imm) { jmpcc32(!test_be(), imm); }
+static void instr16_0F88(int32_t imm) { jmpcc16( test_s(), imm); }
+static void instr32_0F88(int32_t imm) { jmpcc32( test_s(), imm); }
+static void instr16_0F89(int32_t imm) { jmpcc16(!test_s(), imm); }
+static void instr32_0F89(int32_t imm) { jmpcc32(!test_s(), imm); }
+static void instr16_0F8A(int32_t imm) { jmpcc16( test_p(), imm); }
+static void instr32_0F8A(int32_t imm) { jmpcc32( test_p(), imm); }
+static void instr16_0F8B(int32_t imm) { jmpcc16(!test_p(), imm); }
+static void instr32_0F8B(int32_t imm) { jmpcc32(!test_p(), imm); }
+static void instr16_0F8C(int32_t imm) { jmpcc16( test_l(), imm); }
+static void instr32_0F8C(int32_t imm) { jmpcc32( test_l(), imm); }
+static void instr16_0F8D(int32_t imm) { jmpcc16(!test_l(), imm); }
+static void instr32_0F8D(int32_t imm) { jmpcc32(!test_l(), imm); }
+static void instr16_0F8E(int32_t imm) { jmpcc16( test_le(), imm); }
+static void instr32_0F8E(int32_t imm) { jmpcc32( test_le(), imm); }
+static void instr16_0F8F(int32_t imm) { jmpcc16(!test_le(), imm); }
+static void instr32_0F8F(int32_t imm) { jmpcc32(!test_le(), imm); }
// setcc
-static void instr_0F90() { read_modrm_byte(); setcc( test_o()); }
-static void instr_0F91() { read_modrm_byte(); setcc(!test_o()); }
-static void instr_0F92() { read_modrm_byte(); setcc( test_b()); }
-static void instr_0F93() { read_modrm_byte(); setcc(!test_b()); }
-static void instr_0F94() { read_modrm_byte(); setcc( test_z()); }
-static void instr_0F95() { read_modrm_byte(); setcc(!test_z()); }
-static void instr_0F96() { read_modrm_byte(); setcc( test_be()); }
-static void instr_0F97() { read_modrm_byte(); setcc(!test_be()); }
-static void instr_0F98() { read_modrm_byte(); setcc( test_s()); }
-static void instr_0F99() { read_modrm_byte(); setcc(!test_s()); }
-static void instr_0F9A() { read_modrm_byte(); setcc( test_p()); }
-static void instr_0F9B() { read_modrm_byte(); setcc(!test_p()); }
-static void instr_0F9C() { read_modrm_byte(); setcc( test_l()); }
-static void instr_0F9D() { read_modrm_byte(); setcc(!test_l()); }
-static void instr_0F9E() { read_modrm_byte(); setcc( test_le()); }
-static void instr_0F9F() { read_modrm_byte(); setcc(!test_le()); }
+static void instr_0F90_reg(int32_t r, int32_t unused) { setcc_reg( test_o(), r); }
+static void instr_0F91_reg(int32_t r, int32_t unused) { setcc_reg(!test_o(), r); }
+static void instr_0F92_reg(int32_t r, int32_t unused) { setcc_reg( test_b(), r); }
+static void instr_0F93_reg(int32_t r, int32_t unused) { setcc_reg(!test_b(), r); }
+static void instr_0F94_reg(int32_t r, int32_t unused) { setcc_reg( test_z(), r); }
+static void instr_0F95_reg(int32_t r, int32_t unused) { setcc_reg(!test_z(), r); }
+static void instr_0F96_reg(int32_t r, int32_t unused) { setcc_reg( test_be(), r); }
+static void instr_0F97_reg(int32_t r, int32_t unused) { setcc_reg(!test_be(), r); }
+static void instr_0F98_reg(int32_t r, int32_t unused) { setcc_reg( test_s(), r); }
+static void instr_0F99_reg(int32_t r, int32_t unused) { setcc_reg(!test_s(), r); }
+static void instr_0F9A_reg(int32_t r, int32_t unused) { setcc_reg( test_p(), r); }
+static void instr_0F9B_reg(int32_t r, int32_t unused) { setcc_reg(!test_p(), r); }
+static void instr_0F9C_reg(int32_t r, int32_t unused) { setcc_reg( test_l(), r); }
+static void instr_0F9D_reg(int32_t r, int32_t unused) { setcc_reg(!test_l(), r); }
+static void instr_0F9E_reg(int32_t r, int32_t unused) { setcc_reg( test_le(), r); }
+static void instr_0F9F_reg(int32_t r, int32_t unused) { setcc_reg(!test_le(), r); }
+
+static void instr_0F90_mem(int32_t addr, int32_t unused) { setcc_mem( test_o(), addr); }
+static void instr_0F91_mem(int32_t addr, int32_t unused) { setcc_mem(!test_o(), addr); }
+static void instr_0F92_mem(int32_t addr, int32_t unused) { setcc_mem( test_b(), addr); }
+static void instr_0F93_mem(int32_t addr, int32_t unused) { setcc_mem(!test_b(), addr); }
+static void instr_0F94_mem(int32_t addr, int32_t unused) { setcc_mem( test_z(), addr); }
+static void instr_0F95_mem(int32_t addr, int32_t unused) { setcc_mem(!test_z(), addr); }
+static void instr_0F96_mem(int32_t addr, int32_t unused) { setcc_mem( test_be(), addr); }
+static void instr_0F97_mem(int32_t addr, int32_t unused) { setcc_mem(!test_be(), addr); }
+static void instr_0F98_mem(int32_t addr, int32_t unused) { setcc_mem( test_s(), addr); }
+static void instr_0F99_mem(int32_t addr, int32_t unused) { setcc_mem(!test_s(), addr); }
+static void instr_0F9A_mem(int32_t addr, int32_t unused) { setcc_mem( test_p(), addr); }
+static void instr_0F9B_mem(int32_t addr, int32_t unused) { setcc_mem(!test_p(), addr); }
+static void instr_0F9C_mem(int32_t addr, int32_t unused) { setcc_mem( test_l(), addr); }
+static void instr_0F9D_mem(int32_t addr, int32_t unused) { setcc_mem(!test_l(), addr); }
+static void instr_0F9E_mem(int32_t addr, int32_t unused) { setcc_mem( test_le(), addr); }
+static void instr_0F9F_mem(int32_t addr, int32_t unused) { setcc_mem(!test_le(), addr); }
+
static void instr16_0FA0() { push16(sreg[FS]); }
static void instr32_0FA0() { push32(sreg[FS]); }
@@ -2005,39 +1875,15 @@ static void instr32_0FA1() {
static void instr_0FA2() { cpuid(); }
-static void instr16_0FA3() { read_modrm_byte();
- if(modrm_byte[0] < 0xC0)
- {
- bt_mem(modrm_resolve(modrm_byte[0]), read_g16s());
- }
- else
- {
- bt_reg(read_reg_e16(), read_g16() & 15);
- }
-}
-static void instr32_0FA3() { read_modrm_byte();
- if(modrm_byte[0] < 0xC0)
- {
- bt_mem(modrm_resolve(modrm_byte[0]), read_g32s());
- }
- else
- {
- bt_reg(read_reg_e32s(), read_g32s() & 31);
- }
-}
+static void instr16_0FA3_reg(int32_t r1, int32_t r2) { bt_reg(read_reg16(r1), read_reg16(r2) & 15); }
+static void instr16_0FA3_mem(int32_t addr, int32_t r) { bt_mem(addr, read_reg16(r) << 16 >> 16); }
+static void instr32_0FA3_reg(int32_t r1, int32_t r2) { bt_reg(read_reg32(r1), read_reg32(r2) & 31); }
+static void instr32_0FA3_mem(int32_t addr, int32_t r) { bt_mem(addr, read_reg32(r)); }
-static void instr16_0FA4() { read_modrm_byte();
- int32_t data = read_write_e16(); write_e16(shld16(data, read_g16(), read_op8() & 31));
-}
-static void instr32_0FA4() { read_modrm_byte();
- int32_t data = read_write_e32(); write_e32(shld32(data, read_g32s(), read_op8() & 31));
-}
-static void instr16_0FA5() { read_modrm_byte();
- int32_t data = read_write_e16(); write_e16(shld16(data, read_g16(), reg8[CL] & 31));
-}
-static void instr32_0FA5() { read_modrm_byte();
- int32_t data = read_write_e32(); write_e32(shld32(data, read_g32s(), reg8[CL] & 31));
-}
+DEFINE_MODRM_INSTR_IMM_READ_WRITE_16(instr16_0FA4, shld16(___, read_reg16(r), imm & 31))
+DEFINE_MODRM_INSTR_IMM_READ_WRITE_32(instr32_0FA4, shld32(___, read_reg32(r), imm & 31))
+DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_0FA5, shld16(___, read_reg16(r), reg8[CL] & 31))
+DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_0FA5, shld32(___, read_reg32(r), reg8[CL] & 31))
static void instr_0FA6() {
// obsolete cmpxchg (os/2)
@@ -2062,533 +1908,364 @@ static void instr_0FAA() {
todo();
}
-static void instr16_0FAB() { read_modrm_byte();
- if(modrm_byte[0] < 0xC0) {
- bts_mem(modrm_resolve(modrm_byte[0]), read_g16s());
- } else {
- write_reg_e16(bts_reg(read_reg_e16(), read_g16s() & 15));
- }
-}
-static void instr32_0FAB() { read_modrm_byte();
- if(modrm_byte[0] < 0xC0) {
- bts_mem(modrm_resolve(modrm_byte[0]), read_g32s());
- } else {
- write_reg_e32(bts_reg(read_reg_e32s(), read_g32s() & 31));
- }
-}
+static void instr16_0FAB_reg(int32_t r1, int32_t r2) { write_reg16(r1, bts_reg(read_reg16(r1), read_reg16(r2) & 15)); }
+static void instr16_0FAB_mem(int32_t addr, int32_t r) { bts_mem(addr, read_reg16(r) << 16 >> 16); }
+static void instr32_0FAB_reg(int32_t r1, int32_t r2) { write_reg32(r1, bts_reg(read_reg32(r1), read_reg32(r2) & 31)); }
+static void instr32_0FAB_mem(int32_t addr, int32_t r) { bts_mem(addr, read_reg32(r)); }
+DEFINE_MODRM_INSTR_IMM_READ_WRITE_16(instr16_0FAC, shrd16(___, read_reg16(r), imm & 31))
+DEFINE_MODRM_INSTR_IMM_READ_WRITE_32(instr32_0FAC, shrd32(___, read_reg32(r), imm & 31))
+DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_0FAD, shrd16(___, read_reg16(r), reg8[CL] & 31))
+DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_0FAD, shrd32(___, read_reg32(r), reg8[CL] & 31))
-static void instr16_0FAC() { read_modrm_byte();
- int32_t data = read_write_e16(); write_e16(shrd16(data, read_g16(), read_op8() & 31));
+static void instr_0FAE_0_reg(int32_t r) { trigger_ud(); }
+static void instr_0FAE_0_mem(int32_t addr) {
+ fxsave(addr);
}
-static void instr32_0FAC() { read_modrm_byte();
- int32_t data = read_write_e32(); write_e32(shrd32(data, read_g32s(), read_op8() & 31));
+static void instr_0FAE_1_reg(int32_t r) { trigger_ud(); }
+static void instr_0FAE_1_mem(int32_t addr) {
+ fxrstor(addr);
}
-static void instr16_0FAD() { read_modrm_byte();
- int32_t data = read_write_e16(); write_e16(shrd16(data, read_g16(), reg8[CL] & 31));
-}
-static void instr32_0FAD() { read_modrm_byte();
- int32_t data = read_write_e32(); write_e32(shrd32(data, read_g32s(), reg8[CL] & 31));
-}
-
-static void instr_0FAE() { read_modrm_byte();
- // fxsave, fxrstor, ldmxcsr ...
-
- switch(modrm_byte[0] >> 3 & 7)
+static void instr_0FAE_2_reg(int32_t r) { trigger_ud(); }
+static void instr_0FAE_2_mem(int32_t addr) {
+ // ldmxcsr
+ int32_t new_mxcsr = safe_read32s(addr);
+ if(new_mxcsr & ~MXCSR_MASK)
{
- case 0: // fxsave
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- {
- int32_t addr = modrm_resolve(modrm_byte[0]);
- fxsave(addr);
- }
- break;
-
- case 1: // fxrstor
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- {
- int32_t addr = modrm_resolve(modrm_byte[0]);
- fxrstor(addr);
- }
- break;
-
- case 2: // ldmxcsr
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- {
- int32_t addr = modrm_resolve(modrm_byte[0]);
- int32_t new_mxcsr = safe_read32s(addr);
- if(new_mxcsr & ~MXCSR_MASK)
- {
- //dbg_log("Invalid mxcsr bits: " + h((new_mxcsr & ~MXCSR_MASK), 8));
- assert(false);
- trigger_gp(0);
- }
- *mxcsr = new_mxcsr;
- }
- break;
-
- case 3: // stmxcsr
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- {
- int32_t addr = modrm_resolve(modrm_byte[0]);
- safe_write32(addr, *mxcsr);
- }
- break;
-
- case 5:
- // lfence
- dbg_assert_message(modrm_byte[0] >= 0xC0, "Unexpected mfence encoding");
- if(modrm_byte[0] < 0xC0) trigger_ud();
- break;
-
- case 6:
- // mfence
- dbg_assert_message(modrm_byte[0] >= 0xC0, "Unexpected mfence encoding");
- if(modrm_byte[0] < 0xC0) trigger_ud();
- break;
-
- case 7:
- // sfence or clflush
- dbg_assert_message(modrm_byte[0] >= 0xC0, "Unexpected sfence encoding");
- if(modrm_byte[0] < 0xC0) trigger_ud();
- break;
-
- default:
- //dbg_log("missing " + (modrm_byte[0] >> 3 & 7));
- todo();
+ dbg_log("Invalid mxcsr bits: %x", (new_mxcsr & ~MXCSR_MASK));
+ assert(false);
+ trigger_gp(0);
}
+ *mxcsr = new_mxcsr;
+}
+static void instr_0FAE_3_reg(int32_t r) { trigger_ud(); }
+static void instr_0FAE_3_mem(int32_t addr) {
+ // stmxcsr
+ safe_write32(addr, *mxcsr);
+}
+static void instr_0FAE_4_reg(int32_t r) { trigger_ud(); }
+static void instr_0FAE_4_mem(int32_t addr) {
+ // xsave
+ todo();
+}
+static void instr_0FAE_5_reg(int32_t r) {
+ // lfence
+ dbg_assert_message(r == 0, "Unexpected lfence encoding");
+}
+static void instr_0FAE_5_mem(int32_t addr) {
+ // xrstor
+ todo();
+}
+static void instr_0FAE_6_reg(int32_t r) {
+ // mfence
+ dbg_assert_message(r == 0, "Unexpected mfence encoding");
+}
+static void instr_0FAE_6_mem(int32_t addr) {
+ dbg_assert_message(false, "0fae/5 #ud");
+ trigger_ud();
+}
+static void instr_0FAE_7_reg(int32_t r) {
+ // sfence
+ dbg_assert_message(r == 0, "Unexpected sfence encoding");
+}
+static void instr_0FAE_7_mem(int32_t addr) {
+ // clflush
+ todo();
}
-static void instr16_0FAF() { read_modrm_byte();
- int32_t data = read_e16s();
- write_g16(imul_reg16(read_g16s(), data));
-}
-static void instr32_0FAF() { read_modrm_byte();
- int32_t data = read_e32s();
- write_g32(imul_reg32(read_g32s(), data));
-}
+DEFINE_MODRM_INSTR_READ16(instr16_0FAF, write_reg16(r, imul_reg16(read_reg16(r) << 16 >> 16, ___ << 16 >> 16)))
+DEFINE_MODRM_INSTR_READ32(instr32_0FAF, write_reg32(r, imul_reg32(read_reg32(r), ___)))
-
-static void instr_0FB0() { read_modrm_byte();
+static void instr_0FB0_reg(int32_t r1, int32_t r2) {
// cmpxchg8
- int32_t data = 0;
- int32_t virt_addr = 0;
- if(modrm_byte[0] < 0xC0)
- {
- virt_addr = modrm_resolve(modrm_byte[0]);
- writable_or_pagefault(virt_addr, 1);
-
- data = safe_read8(virt_addr);
- }
- else
- data = reg8[modrm_byte[0] << 2 & 0xC | modrm_byte[0] >> 2 & 1];
-
-
+ int32_t data = read_reg8(r1);
cmp8(reg8[AL], data);
if(getzf())
{
- if(modrm_byte[0] < 0xC0)
- safe_write8(virt_addr, read_g8());
- else
- reg8[modrm_byte[0] << 2 & 0xC | modrm_byte[0] >> 2 & 1] = read_g8();
+ write_reg8(r1, read_reg8(r2));
}
else
{
- if(modrm_byte[0] < 0xC0)
- safe_write8(virt_addr, data);
-
reg8[AL] = data;
}
}
-static void instr16_0FB1() { read_modrm_byte();
- // cmpxchg16/32
- int32_t data = 0;
- int32_t virt_addr = 0;
- if(modrm_byte[0] < 0xC0)
- {
- virt_addr = modrm_resolve(modrm_byte[0]);
- writable_or_pagefault(virt_addr, 2);
+static void instr_0FB0_mem(int32_t addr, int32_t r) {
+ // cmpxchg8
+ writable_or_pagefault(addr, 1);
+ int32_t data = safe_read8(addr);
+ cmp8(reg8[AL], data);
- data = safe_read16(virt_addr);
+ if(getzf())
+ {
+ safe_write8(addr, read_reg8(r));
}
else
- data = read_reg_e16();
+ {
+ safe_write8(addr, data);
+ reg8[AL] = data;
+ }
+}
+static void instr16_0FB1_reg(int32_t r1, int32_t r2) {
+ // cmpxchg16
+ int32_t data = read_reg16(r1);
cmp16(reg16[AX], data);
if(getzf())
{
- if(modrm_byte[0] < 0xC0)
- safe_write16(virt_addr, read_g16());
- else
- write_reg_e16(read_g16());
+ write_reg16(r1, read_reg16(r2));
}
else
{
- if(modrm_byte[0] < 0xC0)
- safe_write16(virt_addr, data);
-
reg16[AX] = data;
}
}
-static void instr32_0FB1() { read_modrm_byte();
- int32_t virt_addr = 0;
- int32_t data = 0;
- if(modrm_byte[0] < 0xC0)
- {
- virt_addr = modrm_resolve(modrm_byte[0]);
- writable_or_pagefault(virt_addr, 4);
+static void instr16_0FB1_mem(int32_t addr, int32_t r) {
+ // cmpxchg16
+ writable_or_pagefault(addr, 2);
+ int32_t data = safe_read16(addr);
+ cmp16(reg16[AX], data);
- data = safe_read32s(virt_addr);
+ if(getzf())
+ {
+ safe_write16(addr, read_reg16(r));
}
else
{
- data = read_reg_e32s();
+ safe_write16(addr, data);
+ reg16[AX] = data;
}
+}
+static void instr32_0FB1_reg(int32_t r1, int32_t r2) {
+ // cmpxchg32
+ int32_t data = read_reg32(r1);
cmp32(reg32s[EAX], data);
if(getzf())
{
- if(modrm_byte[0] < 0xC0)
- safe_write32(virt_addr, read_g32s());
- else
- write_reg_e32(read_g32s());
+ write_reg32(r1, read_reg32(r2));
}
else
{
- if(modrm_byte[0] < 0xC0)
- safe_write32(virt_addr, data);
+ reg32s[EAX] = data;
+ }
+}
+static void instr32_0FB1_mem(int32_t addr, int32_t r) {
+ // cmpxchg32
+ writable_or_pagefault(addr, 4);
+ int32_t data = safe_read32s(addr);
+ cmp32(reg32s[EAX], data);
+ if(getzf())
+ {
+ safe_write32(addr, read_reg32(r));
+ }
+ else
+ {
+ safe_write32(addr, data);
reg32s[EAX] = data;
}
}
// lss
-static void instr16_0FB2() { read_modrm_byte();
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- lss16(modrm_resolve(*modrm_byte), *modrm_byte >> 2 & 14, SS);
+static void instr16_0FB2_reg(int32_t unused, int32_t unused2) { trigger_ud(); }
+static void instr16_0FB2_mem(int32_t addr, int32_t r) {
+ lss16(addr, get_reg16_index(r), SS);
}
-static void instr32_0FB2() { read_modrm_byte();
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- lss32(modrm_resolve(*modrm_byte), *modrm_byte >> 3 & 7, SS);
+static void instr32_0FB2_reg(int32_t unused, int32_t unused2) { trigger_ud(); }
+static void instr32_0FB2_mem(int32_t addr, int32_t r) {
+ lss32(addr, r, SS);
}
-static void instr16_0FB3() { read_modrm_byte();
- if(modrm_byte[0] < 0xC0) {
- btr_mem(modrm_resolve(modrm_byte[0]), read_g16s());
- } else {
- write_reg_e16(btr_reg(read_reg_e16(), read_g16s() & 15));
- }
-}
-static void instr32_0FB3() { read_modrm_byte();
- if(modrm_byte[0] < 0xC0) {
- btr_mem(modrm_resolve(modrm_byte[0]), read_g32s());
- } else {
- write_reg_e32(btr_reg(read_reg_e32s(), read_g32s() & 31));
- }
-}
+static void instr16_0FB3_reg(int32_t r1, int32_t r2) { write_reg16(r1, btr_reg(read_reg16(r1), read_reg16(r2) & 15)); }
+static void instr16_0FB3_mem(int32_t addr, int32_t r) { btr_mem(addr, read_reg16(r) << 16 >> 16); }
+static void instr32_0FB3_reg(int32_t r1, int32_t r2) { write_reg32(r1, btr_reg(read_reg32(r1), read_reg32(r2) & 31)); }
+static void instr32_0FB3_mem(int32_t addr, int32_t r) { btr_mem(addr, read_reg32(r)); }
// lfs, lgs
-static void instr16_0FB4() { read_modrm_byte();
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- lss16(modrm_resolve(*modrm_byte), *modrm_byte >> 2 & 14, FS);
+static void instr16_0FB4_reg(int32_t unused, int32_t unused2) { trigger_ud(); }
+static void instr16_0FB4_mem(int32_t addr, int32_t r) {
+ lss16(addr, get_reg16_index(r), FS);
}
-static void instr32_0FB4() { read_modrm_byte();
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- lss32(modrm_resolve(*modrm_byte), *modrm_byte >> 3 & 7, FS);
+static void instr32_0FB4_reg(int32_t unused, int32_t unused2) { trigger_ud(); }
+static void instr32_0FB4_mem(int32_t addr, int32_t r) {
+ lss32(addr, r, FS);
}
-static void instr16_0FB5() { read_modrm_byte();
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- lss16(modrm_resolve(*modrm_byte), *modrm_byte >> 2 & 14, GS);
+static void instr16_0FB5_reg(int32_t unused, int32_t unused2) { trigger_ud(); }
+static void instr16_0FB5_mem(int32_t addr, int32_t r) {
+ lss16(addr, get_reg16_index(r), GS);
}
-static void instr32_0FB5() { read_modrm_byte();
- if(modrm_byte[0] >= 0xC0) trigger_ud();
- lss32(modrm_resolve(*modrm_byte), *modrm_byte >> 3 & 7, GS);
+static void instr32_0FB5_reg(int32_t unused, int32_t unused2) { trigger_ud(); }
+static void instr32_0FB5_mem(int32_t addr, int32_t r) {
+ lss32(addr, r, GS);
}
-static void instr16_0FB6() { read_modrm_byte();
- // movzx
- int32_t data = read_e8();
- write_g16(data);
-}
-static void instr32_0FB6() { read_modrm_byte();
- int32_t data = read_e8();
- write_g32(data);
-}
+// movzx
+DEFINE_MODRM_INSTR_READ8(instr16_0FB6, write_reg16(r, ___))
+DEFINE_MODRM_INSTR_READ8(instr32_0FB6, write_reg32(r, ___))
+DEFINE_MODRM_INSTR_READ16(instr16_0FB7, write_reg16(r, ___))
+DEFINE_MODRM_INSTR_READ16(instr32_0FB7, write_reg32(r, ___))
-static void instr16_0FB7() { read_modrm_byte();
- // movzx
- int32_t data = read_e16();
- write_g16(data);
-}
-static void instr32_0FB7() { read_modrm_byte();
- int32_t data = read_e16();
- write_g32(data);
-}
+static void instr16_0FB8_reg(int32_t r1, int32_t r2) { trigger_ud(); }
+static void instr16_0FB8_mem(int32_t addr, int32_t r) { trigger_ud(); }
+DEFINE_MODRM_INSTR_READ16(instr16_F30FB8, write_reg16(r, popcnt(___)))
-static void instr16_0FB8() { read_modrm_byte();
- // popcnt
- int32_t data = read_e16();
- write_g16(popcnt(data));
-}
-static void instr32_0FB8() { read_modrm_byte();
- int32_t data = read_e32s();
- write_g32(popcnt(data));
-}
+static void instr32_0FB8_reg(int32_t r1, int32_t r2) { trigger_ud(); }
+static void instr32_0FB8_mem(int32_t addr, int32_t r) { trigger_ud(); }
+DEFINE_MODRM_INSTR_READ32(instr32_F30FB8, write_reg32(r, popcnt(___)))
static void instr_0FB9() {
// UD
todo();
}
-static void instr16_0FBA() { read_modrm_byte();
- switch(modrm_byte[0] >> 3 & 7)
- {
- case 4:
- if(modrm_byte[0] < 0xC0)
- {
- bt_mem(modrm_resolve(modrm_byte[0]), read_op8() & 15);
- }
- else
- {
- bt_reg(read_reg_e16(), read_op8() & 15);
- }
- break;
- case 5:
- if(modrm_byte[0] < 0xC0) {
- bts_mem(modrm_resolve(modrm_byte[0]), read_op8() & 15);
- } else {
- write_reg_e16(bts_reg(read_reg_e16(), read_op8() & 15));
- }
- break;
- case 6:
- if(modrm_byte[0] < 0xC0) {
- btr_mem(modrm_resolve(modrm_byte[0]), read_op8() & 15);
- } else {
- write_reg_e16(btr_reg(read_reg_e16(), read_op8() & 15));
- }
- break;
- case 7:
- if(modrm_byte[0] < 0xC0) {
- btc_mem(modrm_resolve(modrm_byte[0]), read_op8() & 15);
- } else {
- write_reg_e16(btc_reg(read_reg_e16(), read_op8() & 15));
- }
- break;
- default:
- dbg_log("%d", modrm_byte[0] >> 3 & 7);
- todo();
- }
+static void instr16_0FBA_4_reg(int32_t r, int32_t imm) {
+ bt_reg(read_reg16(r), imm & 15);
}
-static void instr32_0FBA() { read_modrm_byte();
- switch(modrm_byte[0] >> 3 & 7)
- {
- case 4:
- if(modrm_byte[0] < 0xC0)
- {
- bt_mem(modrm_resolve(modrm_byte[0]), read_op8() & 31);
- }
- else
- {
- bt_reg(read_reg_e32s(), read_op8() & 31);
- }
- break;
- case 5:
- if(modrm_byte[0] < 0xC0) {
- bts_mem(modrm_resolve(modrm_byte[0]), read_op8() & 31);
- } else {
- write_reg_e32(bts_reg(read_reg_e32s(), read_op8() & 31));
- }
- break;
- case 6:
- if(modrm_byte[0] < 0xC0) {
- btr_mem(modrm_resolve(modrm_byte[0]), read_op8() & 31);
- } else {
- write_reg_e32(btr_reg(read_reg_e32s(), read_op8() & 31));
- }
- break;
- case 7:
- if(modrm_byte[0] < 0xC0) {
- btc_mem(modrm_resolve(modrm_byte[0]), read_op8() & 31);
- } else {
- write_reg_e32(btc_reg(read_reg_e32s(), read_op8() & 31));
- }
- break;
- default:
- dbg_log("%d", modrm_byte[0] >> 3 & 7);
- todo();
- }
+static void instr16_0FBA_4_mem(int32_t addr, int32_t imm) {
+ bt_mem(addr, imm & 15);
+}
+static void instr16_0FBA_5_reg(int32_t r, int32_t imm) {
+ write_reg16(r, bts_reg(read_reg16(r), imm & 15));
+}
+static void instr16_0FBA_5_mem(int32_t addr, int32_t imm) {
+ bts_mem(addr, imm & 15);
+}
+static void instr16_0FBA_6_reg(int32_t r, int32_t imm) {
+ write_reg16(r, btr_reg(read_reg16(r), imm & 15));
+}
+static void instr16_0FBA_6_mem(int32_t addr, int32_t imm) {
+ btr_mem(addr, imm & 15);
+}
+static void instr16_0FBA_7_reg(int32_t r, int32_t imm) {
+ write_reg16(r, btc_reg(read_reg16(r), imm & 15));
+}
+static void instr16_0FBA_7_mem(int32_t addr, int32_t imm) {
+ btc_mem(addr, imm & 15);
}
-static void instr16_0FBB() { read_modrm_byte();
- if(modrm_byte[0] < 0xC0) {
- btc_mem(modrm_resolve(modrm_byte[0]), read_g16s());
- } else {
- write_reg_e16(btc_reg(read_reg_e16(), read_g16s() & 15));
- }
+static void instr32_0FBA_4_reg(int32_t r, int32_t imm) {
+ bt_reg(read_reg32(r), imm & 31);
}
-static void instr32_0FBB() { read_modrm_byte();
- if(modrm_byte[0] < 0xC0) {
- btc_mem(modrm_resolve(modrm_byte[0]), read_g32s());
- } else {
- write_reg_e32(btc_reg(read_reg_e32s(), read_g32s() & 31));
- }
+static void instr32_0FBA_4_mem(int32_t addr, int32_t imm) {
+ bt_mem(addr, imm & 31);
+}
+static void instr32_0FBA_5_reg(int32_t r, int32_t imm) {
+ write_reg32(r, bts_reg(read_reg32(r), imm & 31));
+}
+static void instr32_0FBA_5_mem(int32_t addr, int32_t imm) {
+ bts_mem(addr, imm & 31);
+}
+static void instr32_0FBA_6_reg(int32_t r, int32_t imm) {
+ write_reg32(r, btr_reg(read_reg32(r), imm & 31));
+}
+static void instr32_0FBA_6_mem(int32_t addr, int32_t imm) {
+ btr_mem(addr, imm & 31);
+}
+static void instr32_0FBA_7_reg(int32_t r, int32_t imm) {
+ write_reg32(r, btc_reg(read_reg32(r), imm & 31));
+}
+static void instr32_0FBA_7_mem(int32_t addr, int32_t imm) {
+ btc_mem(addr, imm & 31);
}
-static void instr16_0FBC() { read_modrm_byte();
- int32_t data = read_e16();
- write_g16(bsf16(read_g16(), data));
-}
-static void instr32_0FBC() { read_modrm_byte();
- int32_t data = read_e32s();
- write_g32(bsf32(read_g32s(), data));
-}
+static void instr16_0FBB_reg(int32_t r1, int32_t r2) { write_reg16(r1, btc_reg(read_reg16(r1), read_reg16(r2) & 15)); }
+static void instr16_0FBB_mem(int32_t addr, int32_t r) { btc_mem(addr, read_reg16(r) << 16 >> 16); }
+static void instr32_0FBB_reg(int32_t r1, int32_t r2) { write_reg32(r1, btc_reg(read_reg32(r1), read_reg32(r2) & 31)); }
+static void instr32_0FBB_mem(int32_t addr, int32_t r) { btc_mem(addr, read_reg32(r)); }
-static void instr16_0FBD() { read_modrm_byte();
- int32_t data = read_e16();
- write_g16(bsr16(read_g16(), data));
-}
-static void instr32_0FBD() { read_modrm_byte();
- int32_t data = read_e32s();
- write_g32(bsr32(read_g32s(), data));
-}
+DEFINE_MODRM_INSTR_READ16(instr16_0FBC, write_reg16(r, bsf16(read_reg16(r), ___)))
+DEFINE_MODRM_INSTR_READ32(instr32_0FBC, write_reg32(r, bsf32(read_reg32(r), ___)))
+DEFINE_MODRM_INSTR_READ16(instr16_0FBD, write_reg16(r, bsr16(read_reg16(r), ___)))
+DEFINE_MODRM_INSTR_READ32(instr32_0FBD, write_reg32(r, bsr32(read_reg32(r), ___)))
-static void instr16_0FBE() { read_modrm_byte();
- // movsx
- int32_t data = read_e8s();
- write_g16(data);
-}
-static void instr32_0FBE() { read_modrm_byte();
- int32_t data = read_e8s();
- write_g32(data);
-}
-
-static void instr16_0FBF() { read_modrm_byte();
- // movsx
- int32_t data = read_e16();
- write_g16(data);
-}
-
-static void instr32_0FBF() { read_modrm_byte();
- int32_t data = read_e16s();
- write_g32(data);
-}
-
-static void instr_0FC0() { read_modrm_byte();
- int32_t data = read_write_e8(); write_e8(xadd8(data, modrm_byte[0] >> 1 & 0xC | modrm_byte[0] >> 5 & 1));
-}
-
-static void instr16_0FC1() { read_modrm_byte();
- int32_t data = read_write_e16();
- write_e16(xadd16(data, modrm_byte[0] >> 2 & 14));
-}
-static void instr32_0FC1() { read_modrm_byte();
- int32_t data = read_write_e32();
- write_e32(xadd32(data, modrm_byte[0] >> 3 & 7));
-}
+// movsx
+DEFINE_MODRM_INSTR_READ8(instr16_0FBE, write_reg16(r, ___ << 24 >> 24))
+DEFINE_MODRM_INSTR_READ8(instr32_0FBE, write_reg32(r, ___ << 24 >> 24))
+DEFINE_MODRM_INSTR_READ16(instr16_0FBF, write_reg16(r, ___ << 16 >> 16))
+DEFINE_MODRM_INSTR_READ16(instr32_0FBF, write_reg32(r, ___ << 16 >> 16))
+DEFINE_MODRM_INSTR_READ_WRITE_8(instr_0FC0, xadd8(___, get_reg8_index(r)))
+DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_0FC1, xadd16(___, get_reg16_index(r)))
+DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_0FC1, xadd32(___, r))
static void instr_0FC2() { unimplemented_sse(); }
-static void instr_0FC3()
-{
+static void instr_0FC3_reg(int32_t r1, int32_t r2) { trigger_ud(); }
+static void instr_0FC3_mem(int32_t addr, int32_t r) {
// movnti
- read_modrm_byte();
- if(*modrm_byte >= 0xC0) trigger_ud();
- set_e32(read_g32s());
+ safe_write32(addr, read_reg32(r));
}
static void instr_0FC4() { unimplemented_sse(); }
-static void instr_0FC5() { unimplemented_sse(); }
+static void instr_0FC5_mem(int32_t addr, int32_t r, int32_t imm8) { unimplemented_sse(); }
+static void instr_0FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { unimplemented_sse(); }
-static void instr_660FC5() {
- // pextrw r32/m16, xmm, imm8
+static void instr_660FC5_mem(int32_t addr, int32_t r, int32_t imm8) { trigger_ud(); }
+static void instr_660FC5_reg(int32_t r1, int32_t r2, int32_t imm8) {
+ // pextrw r32, xmm, imm8
task_switch_test_mmx();
- read_modrm_byte();
- if(*modrm_byte < 0xC0) trigger_ud();
-
- union reg128 data = read_xmm_mem128s();
- uint32_t index = read_imm8() & 7;
+ union reg128 data = read_xmm128s(r1);
+ uint32_t index = imm8 & 7;
uint32_t result = data.u16[index];
- write_g32(result);
+ write_reg32(r2, result);
}
static void instr_0FC6() { unimplemented_sse(); }
-static void instr_0FC7() {
- read_modrm_byte();
+static void instr_0FC7_1_reg(int32_t r) { trigger_ud(); }
+static void instr_0FC7_1_mem(int32_t addr) {
+ // cmpxchg8b
+ writable_or_pagefault(addr, 8);
- switch(modrm_byte[0] >> 3 & 7)
+ int32_t m64_low = safe_read32s(addr);
+ int32_t m64_high = safe_read32s(addr + 4);
+
+ if(reg32s[EAX] == m64_low &&
+ reg32s[EDX] == m64_high)
{
- case 1:
- // cmpxchg8b
- if(modrm_byte[0] >= 0xC0)
- {
- trigger_ud();
- }
+ flags[0] |= FLAG_ZERO;
- int32_t addr = modrm_resolve(modrm_byte[0]);
- writable_or_pagefault(addr, 8);
-
- int32_t m64_low = safe_read32s(addr);
- int32_t m64_high = safe_read32s(addr + 4);
-
- if(reg32s[EAX] == m64_low &&
- reg32s[EDX] == m64_high)
- {
- flags[0] |= FLAG_ZERO;
-
- safe_write32(addr, reg32s[EBX]);
- safe_write32(addr + 4, reg32s[ECX]);
- }
- else
- {
- flags[0] &= ~FLAG_ZERO;
-
- reg32s[EAX] = m64_low;
- reg32s[EDX] = m64_high;
-
- safe_write32(addr, m64_low);
- safe_write32(addr + 4, m64_high);
- }
-
- flags_changed[0] &= ~FLAG_ZERO;
- break;
-
- case 6:
- {
- int32_t has_rand = has_rand_int();
-
- int32_t rand = 0;
- if(has_rand)
- {
- rand = get_rand_int();
- }
- //dbg_log("rdrand -> " + h(rand, 8));
-
- if(is_osize_32())
- {
- set_e32(rand);
- }
- else
- {
- set_e16(rand);
- }
-
- flags[0] &= ~FLAGS_ALL;
- flags[0] |= has_rand;
- flags_changed[0] = 0;
- }
- break;
-
- default:
- dbg_log("%d", modrm_byte[0] >> 3 & 7);
- todo();
+ safe_write32(addr, reg32s[EBX]);
+ safe_write32(addr + 4, reg32s[ECX]);
}
+ else
+ {
+ flags[0] &= ~FLAG_ZERO;
+
+ reg32s[EAX] = m64_low;
+ reg32s[EDX] = m64_high;
+
+ safe_write32(addr, m64_low);
+ safe_write32(addr + 4, m64_high);
+ }
+
+ flags_changed[0] &= ~FLAG_ZERO;
+}
+
+static void instr_0FC7_6_reg(int32_t r) {
+ // rdrand
+ int32_t has_rand = has_rand_int();
+
+ int32_t rand = 0;
+ if(has_rand)
+ {
+ rand = get_rand_int();
+ }
+
+ write_reg_osize(r, rand);
+
+ flags[0] &= ~FLAGS_ALL;
+ flags[0] |= has_rand;
+ flags_changed[0] = 0;
+}
+static void instr_0FC7_6_mem(int32_t addr) {
+ todo();
+ trigger_ud();
}
static void instr_0FC8() { bswap(EAX); }
@@ -2602,40 +2279,38 @@ static void instr_0FCF() { bswap(EDI); }
static void instr_0FD0() { unimplemented_sse(); }
-static void instr_0FD1()
-{
+static void instr_0FD1(union reg64 source, int32_t r) {
// psrlw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t shift = source.u32[0];
int32_t low = 0;
int32_t high = 0;
if (shift <= 15) {
- uint32_t word0 = (destination.u32[0] & 0xFFFF) >> shift;
- uint32_t word1 = ((uint32_t) destination.u32[0] >> 16) >> shift;
+ uint32_t word0 = destination.u16[0] >> shift;
+ uint32_t word1 = ((uint32_t) destination.u16[1]) >> shift;
low = word0 | word1 << 16;
- uint32_t word2 = ((uint32_t) destination.u32[1] & 0xFFFF) >> shift;
- uint32_t word3 = ((uint32_t) destination.u32[1] >> 16) >> shift;
+ uint32_t word2 = ((uint32_t) destination.u16[2]) >> shift;
+ uint32_t word3 = ((uint32_t) destination.u16[3]) >> shift;
high = word2 | word3 << 16;
}
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FD1, safe_read64s, read_mmx64s)
-static void instr_0FD2()
-{
+static void instr_660FD1_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FD1_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FD2(union reg64 source, int32_t r) {
// psrld mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t shift = source.u32[0];
int32_t low = 0;
@@ -2646,18 +2321,18 @@ static void instr_0FD2()
high = (uint32_t) destination.u32[1] >> shift;
}
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FD2, safe_read64s, read_mmx64s)
+static void instr_660FD2_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FD2_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FD3()
-{
+static void instr_0FD3(union reg64 source, int32_t r) {
// psrlq mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t shift = source.u32[0];
@@ -2680,16 +2355,14 @@ static void instr_0FD3()
high = 0;
}
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FD3, safe_read64s, read_mmx64s)
-static void instr_660FD3()
-{
+static void instr_660FD3(union reg128 source, int32_t r) {
// psrlq xmm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_xmm_mem64s();
uint32_t shift = source.u32[0];
if(shift == 0)
@@ -2697,8 +2370,8 @@ static void instr_660FD3()
return;
}
- union reg128 destination = read_xmm128s();
- union reg128 result;
+ union reg128 destination = read_xmm128s(r);
+ union reg128 result = { { 0 } };
if (shift <= 31)
{
@@ -2714,84 +2387,88 @@ static void instr_660FD3()
result.u32[2] = destination.u32[3] >> shift;
}
- write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]);
+ write_xmm_reg128(r, result);
}
+DEFINE_SSE_SPLIT(instr_660FD3, safe_read128s, read_xmm128s)
-static void instr_0FD4() { unimplemented_sse(); }
+static void instr_0FD4_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FD4_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FD4_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FD4_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FD5()
-{
+static void instr_0FD5(union reg64 source, int32_t r) {
// pmullw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
- int32_t word0 = ((destination.u16[0]) * (source.u16[0])) & 0xFFFF;
- int32_t word1 = ((destination.u16[1]) * (source.u16[1])) & 0xFFFF;
- int32_t word2 = ((destination.u16[2]) * (source.u16[2])) & 0xFFFF;
- int32_t word3 = ((destination.u16[3]) * (source.u16[3])) & 0xFFFF;
+ int32_t word0 = (destination.u16[0] * source.u16[0]) & 0xFFFF;
+ int32_t word1 = (destination.u16[1] * source.u16[1]) & 0xFFFF;
+ int32_t word2 = (destination.u16[2] * source.u16[2]) & 0xFFFF;
+ int32_t word3 = (destination.u16[3] * source.u16[3]) & 0xFFFF;
int32_t low = word0 | word1 << 16;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FD5, safe_read64s, read_mmx64s)
-
-static void instr_660FD5()
-{
+static void instr_660FD5(union reg128 source, int32_t r) {
// pmullw xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
- write_xmm128s(
+ write_xmm128(
+ r,
source.u16[0] * destination.u16[0] & 0xFFFF | source.u16[1] * destination.u16[1] << 16,
source.u16[2] * destination.u16[2] & 0xFFFF | source.u16[3] * destination.u16[3] << 16,
source.u16[4] * destination.u16[4] & 0xFFFF | source.u16[5] * destination.u16[5] << 16,
source.u16[6] * destination.u16[6] & 0xFFFF | source.u16[7] * destination.u16[7] << 16
);
}
+DEFINE_SSE_SPLIT(instr_660FD5, safe_read128s, read_xmm128s)
-static void instr_0FD6() { unimplemented_sse(); }
-static void instr_660FD6() {
+static void instr_0FD6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FD6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FD6_mem(int32_t addr, int32_t r) {
// movq xmm/m64, xmm
task_switch_test_mmx();
- read_modrm_byte();
- assert(*modrm_byte < 0xC0);
- union reg64 data = read_xmm64s();
- int32_t addr = modrm_resolve(*modrm_byte);
- safe_write64(addr, data.u32[0], data.u32[1]);
+ union reg64 data = read_xmm64s(r);
+ safe_write64(addr, data.u64[0]);
}
-static void instr_0FD7() { unimplemented_sse(); }
-static void instr_660FD7() {
+static void instr_660FD6_reg(int32_t r1, int32_t r2) {
+ // movq xmm/m64, xmm
+ task_switch_test_mmx();
+ union reg64 data = read_xmm64s(r2);
+ write_xmm128(r1, data.u32[0], data.u32[1], 0, 0);
+}
+static void instr_F20FD6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_F20FD6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_F30FD6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_F30FD6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FD7_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FD7_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FD7_mem(int32_t addr, int32_t r) { trigger_ud(); }
+static void instr_660FD7_reg(int32_t r1, int32_t r2) {
// pmovmskb reg, xmm
task_switch_test_mmx();
- read_modrm_byte();
- if(*modrm_byte < 0xC0) trigger_ud();
- union reg128 x = read_xmm_mem128s();
+ union reg128 x = read_xmm128s(r1);
int32_t result =
x.u8[0] >> 7 << 0 | x.u8[1] >> 7 << 1 | x.u8[2] >> 7 << 2 | x.u8[3] >> 7 << 3 |
x.u8[4] >> 7 << 4 | x.u8[5] >> 7 << 5 | x.u8[6] >> 7 << 6 | x.u8[7] >> 7 << 7 |
x.u8[8] >> 7 << 8 | x.u8[9] >> 7 << 9 | x.u8[10] >> 7 << 10 | x.u8[11] >> 7 << 11 |
x.u8[12] >> 7 << 12 | x.u8[13] >> 7 << 13 | x.u8[14] >> 7 << 14 | x.u8[15] >> 7 << 15;
- write_g32(result);
+ write_reg32(r2, result);
}
-
-static void instr_0FD8()
-{
+static void instr_0FD8(union reg64 source, int32_t r) {
// psubusb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
-
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t byte0 = saturate_sd_to_ub(destination.u8[0] - source.u8[0]);
int32_t byte1 = saturate_sd_to_ub(destination.u8[1] - source.u8[1]);
@@ -2805,21 +2482,21 @@ static void instr_0FD8()
int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FD8, safe_read64s, read_mmx64s)
+static void instr_660FD8_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FD8_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FD9()
-{
+static void instr_0FD9(union reg64 source, int32_t r) {
// psubusw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
- int32_t word0 = (destination.u32[0] & 0xFFFF) - (source.u32[0] & 0xFFFF);
- int32_t word1 = ((uint32_t) destination.u32[0] >> 16) - (source.u32[0] >> 16);
+ int32_t word0 = destination.u16[0] - source.u16[0];
+ int32_t word1 = ((uint32_t) destination.u16[1]) - source.u16[1];
if (word0 < 0) {
word0 = 0;
}
@@ -2827,8 +2504,8 @@ static void instr_0FD9()
word1 = 0;
}
- int32_t word2 = (destination.u32[1] & 0xFFFF) - (source.u32[1] & 0xFFFF);
- int32_t word3 = ((uint32_t) destination.u32[1] >> 16) - (source.u32[1] >> 16);
+ int32_t word2 = destination.u16[2] - source.u16[2];
+ int32_t word3 = ((uint32_t) destination.u16[3]) - source.u16[3];
if (word2 < 0) {
word2 = 0;
}
@@ -2839,19 +2516,21 @@ static void instr_0FD9()
int32_t low = word0 | word1 << 16;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FD9, safe_read64s, read_mmx64s)
-static void instr_0FDA() { unimplemented_sse(); }
+static void instr_660FD9_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FD9_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_660FDA()
-{
+static void instr_0FDA_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FDA_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_660FDA(union reg128 source, int32_t r) {
// pminub xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
union reg128 result;
for(uint32_t i = 0; i < 16; i++)
@@ -2859,32 +2538,31 @@ static void instr_660FDA()
result.u8[i] = source.u8[i] < destination.u8[i] ? source.u8[i] : destination.u8[i];
}
- write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]);
+ write_xmm_reg128(r, result);
}
+DEFINE_SSE_SPLIT(instr_660FDA, safe_read128s, read_xmm128s)
-static void instr_0FDB()
-{
+static void instr_0FDB(union reg64 source, int32_t r) {
// pand mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t low = source.u32[0] & destination.u32[0];
int32_t high = source.u32[1] & destination.u32[1];
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FDB, safe_read64s, read_mmx64s)
-static void instr_0FDC()
-{
+static void instr_660FDB_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FDB_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FDC(union reg64 source, int32_t r) {
// paddusb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t byte0 = saturate_ud_to_ub(destination.u8[0] + source.u8[0]);
uint32_t byte1 = saturate_ud_to_ub(destination.u8[1] + source.u8[1]);
@@ -2898,18 +2576,15 @@ static void instr_0FDC()
int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FDC, safe_read64s, read_mmx64s)
-
-static void instr_660FDC()
-{
+static void instr_660FDC(union reg128 source, int32_t r) {
// paddusb xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
union reg128 result;
for(uint32_t i = 0; i < 16; i++)
@@ -2917,57 +2592,52 @@ static void instr_660FDC()
result.u8[i] = saturate_ud_to_ub(source.u8[i] + destination.u8[i]);
}
- write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]);
+ write_xmm_reg128(r, result);
}
+DEFINE_SSE_SPLIT(instr_660FDC, safe_read128s, read_xmm128s)
-static void instr_0FDD()
-{
+static void instr_0FDD(union reg64 source, int32_t r) {
// paddusw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
- int32_t word0 = saturate_uw((destination.u32[0] & 0xFFFF) + (source.u32[0] & 0xFFFF));
- int32_t word1 = saturate_uw((destination.u32[0] >> 16) + (source.u32[0] >> 16));
- int32_t word2 = saturate_uw((destination.u32[1] & 0xFFFF) + (source.u32[1] & 0xFFFF));
- int32_t word3 = saturate_uw((destination.u32[1] >> 16) + (source.u32[1] >> 16));
+ int32_t word0 = saturate_uw(destination.u16[0] + source.u16[0]);
+ int32_t word1 = saturate_uw(destination.u16[1] + source.u16[1]);
+ int32_t word2 = saturate_uw(destination.u16[2] + source.u16[2]);
+ int32_t word3 = saturate_uw(destination.u16[3] + source.u16[3]);
int32_t low = word0 | word1 << 16;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FDD, safe_read64s, read_mmx64s)
-
-static void instr_660FDD()
-{
+static void instr_660FDD(union reg128 source, int32_t r) {
// paddusw xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
- write_xmm128s(
+ write_xmm128(
+ r,
saturate_uw(source.u16[0] + destination.u16[0]) | saturate_uw(source.u16[1] + destination.u16[1]) << 16,
saturate_uw(source.u16[2] + destination.u16[2]) | saturate_uw(source.u16[3] + destination.u16[3]) << 16,
saturate_uw(source.u16[4] + destination.u16[4]) | saturate_uw(source.u16[5] + destination.u16[5]) << 16,
saturate_uw(source.u16[6] + destination.u16[6]) | saturate_uw(source.u16[7] + destination.u16[7]) << 16
);
}
+DEFINE_SSE_SPLIT(instr_660FDD, safe_read128s, read_xmm128s)
-static void instr_0FDE() { unimplemented_sse(); }
+static void instr_0FDE_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FDE_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_660FDE()
-{
+static void instr_660FDE(union reg128 source, int32_t r) {
// pmaxub xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
union reg128 result;
for(uint32_t i = 0; i < 16; i++)
@@ -2975,318 +2645,331 @@ static void instr_660FDE()
result.u8[i] = source.u8[i] > destination.u8[i] ? source.u8[i] : destination.u8[i];
}
- write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]);
+ write_xmm_reg128(r, result);
}
+DEFINE_SSE_SPLIT(instr_660FDE, safe_read128s, read_xmm128s)
-static void instr_0FDF()
-{
+static void instr_0FDF(union reg64 source, int32_t r) {
// pandn mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t low = source.u32[0] & ~destination.u32[0];
int32_t high = source.u32[1] & ~destination.u32[1];
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FDF, safe_read64s, read_mmx64s)
-static void instr_0FE0() { unimplemented_sse(); }
+static void instr_660FDF_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FDF_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FE1()
-{
+static void instr_0FE0_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FE0_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FE0_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FE0_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FE1(union reg64 source, int32_t r) {
// psraw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t shift = source.u32[0];
if (shift > 15) {
shift = 16;
}
- int32_t word0 = (destination.s16[0] >> shift) & 0xFFFF;
- int32_t word1 = (destination.s16[1] >> shift) & 0xFFFF;
+ int32_t word0 = (destination.i16[0] >> shift) & 0xFFFF;
+ int32_t word1 = (destination.i16[1] >> shift) & 0xFFFF;
int32_t low = word0 | word1 << 16;
- int32_t word2 = (destination.s16[2] >> shift) & 0xFFFF;
- int32_t word3 = (destination.s16[3] >> shift) & 0xFFFF;
+ int32_t word2 = (destination.i16[2] >> shift) & 0xFFFF;
+ int32_t word3 = (destination.i16[3] >> shift) & 0xFFFF;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FE1, safe_read64s, read_mmx64s)
-static void instr_0FE2()
-{
+static void instr_660FE1_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FE1_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FE2(union reg64 source, int32_t r) {
// psrad mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t shift = source.u32[0];
if (shift > 31) {
shift = 31;
}
- int32_t low = destination.s32[0] >> shift;
- int32_t high = destination.s32[1] >> shift;
+ int32_t low = destination.i32[0] >> shift;
+ int32_t high = destination.i32[1] >> shift;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FE2, safe_read64s, read_mmx64s)
-static void instr_0FE3() { unimplemented_sse(); }
-static void instr_0FE4() { unimplemented_sse(); }
+static void instr_660FE2_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FE2_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_660FE4()
-{
+static void instr_0FE3_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FE3_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FE3_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FE3_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FE4_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FE4_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_660FE4(union reg128 source, int32_t r) {
// pmulhuw xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
- write_xmm128s(
+ write_xmm128(
+ r,
(source.u16[0] * destination.u16[0] >> 16) & 0xFFFF | source.u16[1] * destination.u16[1] & 0xFFFF0000,
(source.u16[2] * destination.u16[2] >> 16) & 0xFFFF | source.u16[3] * destination.u16[3] & 0xFFFF0000,
(source.u16[4] * destination.u16[4] >> 16) & 0xFFFF | source.u16[5] * destination.u16[5] & 0xFFFF0000,
(source.u16[6] * destination.u16[6] >> 16) & 0xFFFF | source.u16[7] * destination.u16[7] & 0xFFFF0000
);
}
+DEFINE_SSE_SPLIT(instr_660FE4, safe_read128s, read_xmm128s)
-static void instr_0FE5()
-{
+static void instr_0FE5(union reg64 source, int32_t r) {
// pmulhw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
- uint32_t word0 = ((destination.s16[0] * source.s16[0]) >> 16) & 0xFFFF;
- uint32_t word1 = ((destination.s16[1] * source.s16[1]) >> 16) & 0xFFFF;
- uint32_t word2 = ((destination.s16[2] * source.s16[2]) >> 16) & 0xFFFF;
- uint32_t word3 = ((destination.s16[3] * source.s16[3]) >> 16) & 0xFFFF;
+ uint32_t word0 = ((destination.i16[0] * source.i16[0]) >> 16) & 0xFFFF;
+ uint32_t word1 = ((destination.i16[1] * source.i16[1]) >> 16) & 0xFFFF;
+ uint32_t word2 = ((destination.i16[2] * source.i16[2]) >> 16) & 0xFFFF;
+ uint32_t word3 = ((destination.i16[3] * source.i16[3]) >> 16) & 0xFFFF;
int32_t low = word0 | (word1 << 16);
int32_t high = word2 | (word3 << 16);
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FE5, safe_read64s, read_mmx64s)
-static void instr_0FE6() { unimplemented_sse(); }
-static void instr_0FE7() { unimplemented_sse(); }
-static void instr_660FE7() {
+static void instr_660FE5_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FE5_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_F20FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_F20FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_F30FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_F30FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FE7_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FE7_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FE7_reg(int32_t r1, int32_t r2) { trigger_ud(); }
+static void instr_660FE7_mem(int32_t addr, int32_t r) {
// movntdq m128, xmm
task_switch_test_mmx();
- read_modrm_byte();
-
- if(*modrm_byte >= 0xC0) trigger_ud();
-
- union reg128 data = read_xmm128s();
- int32_t addr = modrm_resolve(*modrm_byte);
+ union reg128 data = read_xmm128s(r);
safe_write128(addr, data);
}
-
-static void instr_0FE8()
-{
+static void instr_0FE8(union reg64 source, int32_t r) {
// psubsb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
+ union reg64 destination = read_mmx64s(r);
- union reg64 destination = read_mmx64s();
-
- int32_t byte0 = saturate_sd_to_sb(destination.s8[0] - source.s8[0]);
- int32_t byte1 = saturate_sd_to_sb(destination.s8[1] - source.s8[1]);
- int32_t byte2 = saturate_sd_to_sb(destination.s8[2] - source.s8[2]);
- int32_t byte3 = saturate_sd_to_sb(destination.s8[3] - source.s8[3]);
- int32_t byte4 = saturate_sd_to_sb(destination.s8[4] - source.s8[4]);
- int32_t byte5 = saturate_sd_to_sb(destination.s8[5] - source.s8[5]);
- int32_t byte6 = saturate_sd_to_sb(destination.s8[6] - source.s8[6]);
- int32_t byte7 = saturate_sd_to_sb(destination.s8[7] - source.s8[7]);
+ int32_t byte0 = saturate_sd_to_sb(destination.i8[0] - source.i8[0]);
+ int32_t byte1 = saturate_sd_to_sb(destination.i8[1] - source.i8[1]);
+ int32_t byte2 = saturate_sd_to_sb(destination.i8[2] - source.i8[2]);
+ int32_t byte3 = saturate_sd_to_sb(destination.i8[3] - source.i8[3]);
+ int32_t byte4 = saturate_sd_to_sb(destination.i8[4] - source.i8[4]);
+ int32_t byte5 = saturate_sd_to_sb(destination.i8[5] - source.i8[5]);
+ int32_t byte6 = saturate_sd_to_sb(destination.i8[6] - source.i8[6]);
+ int32_t byte7 = saturate_sd_to_sb(destination.i8[7] - source.i8[7]);
int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FE8, safe_read64s, read_mmx64s)
+static void instr_660FE8_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FE8_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FE9()
-{
+static void instr_0FE9(union reg64 source, int32_t r) {
// psubsw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
- int32_t word0 = saturate_sd_to_sw(destination.s16[0] - source.s16[0]);
- int32_t word1 = saturate_sd_to_sw(destination.s16[1] - source.s16[1]);
- int32_t word2 = saturate_sd_to_sw(destination.s16[2] - source.s16[2]);
- int32_t word3 = saturate_sd_to_sw(destination.s16[3] - source.s16[3]);
+ int32_t word0 = saturate_sd_to_sw(destination.i16[0] - source.i16[0]);
+ int32_t word1 = saturate_sd_to_sw(destination.i16[1] - source.i16[1]);
+ int32_t word2 = saturate_sd_to_sw(destination.i16[2] - source.i16[2]);
+ int32_t word3 = saturate_sd_to_sw(destination.i16[3] - source.i16[3]);
int32_t low = word0 | word1 << 16;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FE9, safe_read64s, read_mmx64s)
-static void instr_0FEA() { unimplemented_sse(); }
+static void instr_660FE9_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FE9_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FEB()
-{
+static void instr_0FEA_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FEA_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FEA_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FEA_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FEB(union reg64 source, int32_t r) {
// por mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t low = source.u32[0] | destination.u32[0];
int32_t high = source.u32[1] | destination.u32[1];
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FEB, safe_read64s, read_mmx64s)
-
-static void instr_660FEB()
-{
+static void instr_660FEB(union reg128 source, int32_t r) {
// por xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
- write_xmm128s(
+ write_xmm128(
+ r,
source.u32[0] | destination.u32[0],
source.u32[1] | destination.u32[1],
source.u32[2] | destination.u32[2],
source.u32[3] | destination.u32[3]
);
}
+DEFINE_SSE_SPLIT(instr_660FEB, safe_read128s, read_xmm128s)
-static void instr_0FEC()
-{
+static void instr_0FEC(union reg64 source, int32_t r) {
// paddsb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
+ union reg64 destination = read_mmx64s(r);
- union reg64 destination = read_mmx64s();
-
- uint32_t byte0 = saturate_sd_to_sb(destination.s8[0] + source.s8[0]);
- uint32_t byte1 = saturate_sd_to_sb(destination.s8[1] + source.s8[1]);
- uint32_t byte2 = saturate_sd_to_sb(destination.s8[2] + source.s8[2]);
- uint32_t byte3 = saturate_sd_to_sb(destination.s8[3] + source.s8[3]);
- uint32_t byte4 = saturate_sd_to_sb(destination.s8[4] + source.s8[4]);
- uint32_t byte5 = saturate_sd_to_sb(destination.s8[5] + source.s8[5]);
- uint32_t byte6 = saturate_sd_to_sb(destination.s8[6] + source.s8[6]);
- uint32_t byte7 = saturate_sd_to_sb(destination.s8[7] + source.s8[7]);
+ uint32_t byte0 = saturate_sd_to_sb(destination.i8[0] + source.i8[0]);
+ uint32_t byte1 = saturate_sd_to_sb(destination.i8[1] + source.i8[1]);
+ uint32_t byte2 = saturate_sd_to_sb(destination.i8[2] + source.i8[2]);
+ uint32_t byte3 = saturate_sd_to_sb(destination.i8[3] + source.i8[3]);
+ uint32_t byte4 = saturate_sd_to_sb(destination.i8[4] + source.i8[4]);
+ uint32_t byte5 = saturate_sd_to_sb(destination.i8[5] + source.i8[5]);
+ uint32_t byte6 = saturate_sd_to_sb(destination.i8[6] + source.i8[6]);
+ uint32_t byte7 = saturate_sd_to_sb(destination.i8[7] + source.i8[7]);
int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FEC, safe_read64s, read_mmx64s)
-static void instr_0FED() {
+static void instr_660FEC_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FEC_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FED(union reg64 source, int32_t r) {
// paddsw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
- int32_t word0 = saturate_sd_to_sw((destination.s16[0]) + (source.s16[0]));
- int32_t word1 = saturate_sd_to_sw((destination.s16[1]) + (source.s16[1]));
- int32_t word2 = saturate_sd_to_sw((destination.s16[2]) + (source.s16[2]));
- int32_t word3 = saturate_sd_to_sw((destination.s16[3]) + (source.s16[3]));
+ int32_t word0 = saturate_sd_to_sw(destination.i16[0] + source.i16[0]);
+ int32_t word1 = saturate_sd_to_sw(destination.i16[1] + source.i16[1]);
+ int32_t word2 = saturate_sd_to_sw(destination.i16[2] + source.i16[2]);
+ int32_t word3 = saturate_sd_to_sw(destination.i16[3] + source.i16[3]);
int32_t low = word0 | word1 << 16;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FED, safe_read64s, read_mmx64s)
-static void instr_0FEE() { unimplemented_sse(); }
+static void instr_660FED_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FED_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FEF()
-{
+static void instr_0FEE_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FEE_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FEE_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FEE_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FEF(union reg64 source, int32_t r) {
// pxor mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
-
- write_mmx64s(source.u32[0] ^ destination.u32[0], source.u32[1] ^ destination.u32[1]);
+ union reg64 destination = read_mmx64s(r);
+ write_mmx64(r, source.u32[0] ^ destination.u32[0], source.u32[1] ^ destination.u32[1]);
}
+DEFINE_SSE_SPLIT(instr_0FEF, safe_read64s, read_mmx64s)
-static void instr_660FEF() {
+static void instr_660FEF(union reg128 source, int32_t r) {
// pxor xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
- write_xmm128s(
+ write_xmm128(
+ r,
source.u32[0] ^ destination.u32[0],
source.u32[1] ^ destination.u32[1],
source.u32[2] ^ destination.u32[2],
source.u32[3] ^ destination.u32[3]
);
}
+DEFINE_SSE_SPLIT(instr_660FEF, safe_read128s, read_xmm128s)
static void instr_0FF0() { unimplemented_sse(); }
-static void instr_0FF1()
-{
+static void instr_0FF1(union reg64 source, int32_t r) {
// psllw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
-
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t shift = source.u32[0];
int32_t low = 0;
int32_t high = 0;
if (shift <= 15) {
- int32_t word0 = ((destination.u32[0] & 0xFFFF) << shift) & 0xFFFF;
+ int32_t word0 = (destination.u16[0] << shift) & 0xFFFF;
int32_t word1 = (((uint32_t) destination.u32[0]) >> 16) << shift;
low = word0 | word1 << 16;
- int32_t word2 = ((destination.u32[1] & 0xFFFF) << shift) & 0xFFFF;
+ int32_t word2 = (destination.u16[2] << shift) & 0xFFFF;
int32_t word3 = (((uint32_t) destination.u32[1]) >> 16) << shift;
high = word2 | word3 << 16;
}
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FF1, safe_read64s, read_mmx64s)
-static void instr_0FF2()
-{
+static void instr_660FF1_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FF1_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FF2(union reg64 source, int32_t r) {
// pslld mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t shift = source.u32[0];
int32_t low = 0;
@@ -3297,18 +2980,18 @@ static void instr_0FF2()
high = destination.u32[1] << shift;
}
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FF2, safe_read64s, read_mmx64s)
+static void instr_660FF2_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FF2_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FF3()
-{
+static void instr_0FF3(union reg64 source, int32_t r) {
// psllq mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint32_t shift = source.u32[0];
@@ -3329,123 +3012,162 @@ static void instr_0FF3()
low = 0;
}
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FF3, safe_read64s, read_mmx64s)
-static void instr_0FF4() { unimplemented_sse(); }
+static void instr_660FF3(union reg128 source, int32_t r) {
+ // psllq xmm, xmm/m128
+ task_switch_test_mmx();
+ union reg128 destination = read_xmm128s(r);
+ uint32_t shift = source.u32[0];
-static void instr_0FF5()
-{
+ if(shift == 0)
+ {
+ return;
+ }
+
+ union reg128 result = { { 0 } };
+
+ if(shift <= 31) {
+ result.u32[0] = destination.u32[0] << shift;
+ result.u32[1] = destination.u32[1] << shift | (((uint32_t) destination.u32[0]) >> (32 - shift));
+ result.u32[2] = destination.u32[2] << shift;
+ result.u32[3] = destination.u32[3] << shift | (((uint32_t) destination.u32[2]) >> (32 - shift));
+ }
+ else if(shift <= 63) {
+ result.u32[0] = 0;
+ result.u32[1] = destination.u32[0] << (shift & 0x1F);
+ result.u32[2] = 0;
+ result.u32[3] = destination.u32[2] << (shift & 0x1F);
+ }
+
+ write_xmm_reg128(r, result);
+}
+DEFINE_SSE_SPLIT(instr_660FF3, safe_read128s, read_xmm128s)
+
+static void instr_0FF4_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FF4_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FF4_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FF4_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FF5(union reg64 source, int32_t r) {
// pmaddwd mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
- int32_t mul0 = (destination.s16[0] * (source.s16[0]));
- int32_t mul1 = (destination.s16[1] * (source.s16[1]));
- int32_t mul2 = (destination.s16[2] * (source.s16[2]));
- int32_t mul3 = (destination.s16[3] * (source.s16[3]));
+ int32_t mul0 = destination.i16[0] * source.i16[0];
+ int32_t mul1 = destination.i16[1] * source.i16[1];
+ int32_t mul2 = destination.i16[2] * source.i16[2];
+ int32_t mul3 = destination.i16[3] * source.i16[3];
int32_t low = mul0 + mul1;
int32_t high = mul2 + mul3;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FF5, safe_read64s, read_mmx64s)
-static void instr_0FF6() { unimplemented_sse(); }
-static void instr_0FF7() { unimplemented_sse(); }
+static void instr_660FF5_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FF5_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_0FF6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FF6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FF6_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FF6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FF8()
-{
+static void instr_0FF7_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FF7_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FF7_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FF7_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FF8(union reg64 source, int32_t r) {
// psubb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
+ union reg64 destination = read_mmx64s(r);
- union reg64 destination = read_mmx64s();
-
- int32_t byte0 = (destination.s8[0] - source.s8[0]) & 0xFF;
- int32_t byte1 = (destination.s8[1] - source.s8[1]) & 0xFF;
- int32_t byte2 = (destination.s8[2] - source.s8[2]) & 0xFF;
- int32_t byte3 = (destination.s8[3] - source.s8[3]) & 0xFF;
- int32_t byte4 = (destination.s8[4] - source.s8[4]) & 0xFF;
- int32_t byte5 = (destination.s8[5] - source.s8[5]) & 0xFF;
- int32_t byte6 = (destination.s8[6] - source.s8[6]) & 0xFF;
- int32_t byte7 = (destination.s8[7] - source.s8[7]) & 0xFF;
+ int32_t byte0 = (destination.i8[0] - source.i8[0]) & 0xFF;
+ int32_t byte1 = (destination.i8[1] - source.i8[1]) & 0xFF;
+ int32_t byte2 = (destination.i8[2] - source.i8[2]) & 0xFF;
+ int32_t byte3 = (destination.i8[3] - source.i8[3]) & 0xFF;
+ int32_t byte4 = (destination.i8[4] - source.i8[4]) & 0xFF;
+ int32_t byte5 = (destination.i8[5] - source.i8[5]) & 0xFF;
+ int32_t byte6 = (destination.i8[6] - source.i8[6]) & 0xFF;
+ int32_t byte7 = (destination.i8[7] - source.i8[7]) & 0xFF;
int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FF8, safe_read64s, read_mmx64s)
+static void instr_660FF8_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FF8_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FF9()
-{
+static void instr_0FF9(union reg64 source, int32_t r) {
// psubw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t word0 = (destination.u32[0] - source.u32[0]) & 0xFFFF;
- int32_t word1 = (((uint32_t) destination.u32[0] >> 16) - (source.u32[0] >> 16)) & 0xFFFF;
+ int32_t word1 = (((uint32_t) destination.u16[1]) - source.u16[1]) & 0xFFFF;
int32_t low = word0 | word1 << 16;
int32_t word2 = (destination.u32[1] - source.u32[1]) & 0xFFFF;
- int32_t word3 = (((uint32_t) destination.u32[1] >> 16) - (source.u32[1] >> 16)) & 0xFFFF;
+ int32_t word3 = (((uint32_t) destination.u16[3]) - source.u16[3]) & 0xFFFF;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FF9, safe_read64s, read_mmx64s)
-static void instr_0FFA()
-{
+static void instr_660FF9_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FF9_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FFA(union reg64 source, int32_t r) {
// psubd mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
- write_mmx64s(
+ write_mmx64(
+ r,
destination.u32[0] - source.u32[0],
destination.u32[1] - source.u32[1]
);
}
+DEFINE_SSE_SPLIT(instr_0FFA, safe_read64s, read_mmx64s)
-static void instr_660FFA()
-{
+static void instr_660FFA(union reg128 source, int32_t r) {
// psubd xmm, xmm/m128
task_switch_test_mmx();
- read_modrm_byte();
- union reg128 source = read_xmm_mem128s();
- union reg128 destination = read_xmm128s();
+ union reg128 destination = read_xmm128s(r);
- write_xmm128s(
+ write_xmm128(
+ r,
destination.u32[0] - source.u32[0],
destination.u32[1] - source.u32[1],
destination.u32[2] - source.u32[2],
destination.u32[3] - source.u32[3]
);
}
+DEFINE_SSE_SPLIT(instr_660FFA, safe_read128s, read_xmm128s)
-static void instr_0FFB() { unimplemented_sse(); }
+static void instr_0FFB_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_0FFB_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+static void instr_660FFB_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FFB_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
-static void instr_0FFC()
-{
+static void instr_0FFC(union reg64 source, int32_t r) {
// paddb mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
uint8_t byte0 = (destination.u8[0] + source.u8[0]) & 0xFF;
uint8_t byte1 = (destination.u8[1] + source.u8[1]) & 0xFF;
@@ -3459,44 +3181,49 @@ static void instr_0FFC()
uint32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
uint32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24;
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FFC, safe_read64s, read_mmx64s)
-static void instr_0FFD()
-{
+static void instr_660FFC_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FFC_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FFD(union reg64 source, int32_t r) {
// paddw mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t word0 = (destination.u32[0] + source.u32[0]) & 0xFFFF;
- int32_t word1 = ((destination.u32[0] >> 16) + (source.u32[0] >> 16)) & 0xFFFF;
+ int32_t word1 = (destination.u16[1] + source.u16[1]) & 0xFFFF;
int32_t low = word0 | word1 << 16;
int32_t word2 = (destination.u32[1] + source.u32[1]) & 0xFFFF;
- int32_t word3 = ((destination.u32[1] >> 16) + (source.u32[1] >> 16)) & 0xFFFF;
+ int32_t word3 = (destination.u16[3] + source.u16[3]) & 0xFFFF;
int32_t high = word2 | word3 << 16;
- write_mmx64s(low, high);
-
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FFD, safe_read64s, read_mmx64s)
-static void instr_0FFE()
-{
+static void instr_660FFD_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FFD_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
+
+static void instr_0FFE(union reg64 source, int32_t r) {
// paddd mm, mm/m64
task_switch_test_mmx();
- read_modrm_byte();
- union reg64 source = read_mmx_mem64s();
- union reg64 destination = read_mmx64s();
+ union reg64 destination = read_mmx64s(r);
int32_t low = destination.u32[0] + source.u32[0];
int32_t high = destination.u32[1] + source.u32[1];
- write_mmx64s(low, high);
+ write_mmx64(r, low, high);
}
+DEFINE_SSE_SPLIT(instr_0FFE, safe_read64s, read_mmx64s)
+
+static void instr_660FFE_mem(int32_t addr, int32_t r) { unimplemented_sse(); }
+static void instr_660FFE_reg(int32_t r1, int32_t r2) { unimplemented_sse(); }
static void instr_0FFF() {
// Windows 98
@@ -3508,1635 +3235,8691 @@ static void instr_0FFF() {
static void run_instruction0f_16(int32_t opcode)
{
// XXX: This table is generated. Don't modify
- switch(opcode)
+switch(opcode)
+{
+ case 0x00:
{
-case 0x00:
- instr_0F00();
- break;
-case 0x01:
- instr_0F01();
- break;
-case 0x02:
- instr16_0F02();
- break;
-case 0x03:
- instr16_0F03();
- break;
-case 0x04:
- instr_0F04();
- break;
-case 0x05:
- instr_0F05();
- break;
-case 0x06:
- instr_0F06();
- break;
-case 0x07:
- instr_0F07();
- break;
-case 0x08:
- instr_0F08();
- break;
-case 0x09:
- instr_0F09();
- break;
-case 0x0A:
- instr_0F0A();
- break;
-case 0x0B:
- instr_0F0B();
- break;
-case 0x0C:
- instr_0F0C();
- break;
-case 0x0D:
- instr_0F0D();
- break;
-case 0x0E:
- instr_0F0E();
- break;
-case 0x0F:
- instr_0F0F();
- break;
-case 0x10:
- instr_0F10();
- break;
-case 0x11:
- instr_0F11();
- break;
-case 0x12:
- (*prefixes & PREFIX_66) ? instr_660F12() :
- instr_0F12();
- break;
-case 0x13:
- (*prefixes & PREFIX_66) ? instr_660F13() :
- instr_0F13();
- break;
-case 0x14:
- (*prefixes & PREFIX_66) ? instr_660F14() :
- instr_0F14();
- break;
-case 0x15:
- instr_0F15();
- break;
-case 0x16:
- instr_0F16();
- break;
-case 0x17:
- instr_0F17();
- break;
-case 0x18:
- instr_0F18();
- break;
-case 0x19:
- instr_0F19();
- break;
-case 0x1A:
- instr_0F1A();
- break;
-case 0x1B:
- instr_0F1B();
- break;
-case 0x1C:
- instr_0F1C();
- break;
-case 0x1D:
- instr_0F1D();
- break;
-case 0x1E:
- instr_0F1E();
- break;
-case 0x1F:
- instr_0F1F();
- break;
-case 0x20:
- instr_0F20();
- break;
-case 0x21:
- instr_0F21();
- break;
-case 0x22:
- instr_0F22();
- break;
-case 0x23:
- instr_0F23();
- break;
-case 0x24:
- instr_0F24();
- break;
-case 0x25:
- instr_0F25();
- break;
-case 0x26:
- instr_0F26();
- break;
-case 0x27:
- instr_0F27();
- break;
-case 0x28:
- (*prefixes & PREFIX_66) ? instr_660F28() :
- instr_0F28();
- break;
-case 0x29:
- (*prefixes & PREFIX_66) ? instr_660F29() :
- instr_0F29();
- break;
-case 0x2A:
- instr_0F2A();
- break;
-case 0x2B:
- (*prefixes & PREFIX_66) ? instr_660F2B() :
- instr_0F2B();
- break;
-case 0x2C:
- (*prefixes & PREFIX_F2) ? instr_F20F2C() :
- instr_0F2C();
- break;
-case 0x2D:
- instr_0F2D();
- break;
-case 0x2E:
- instr_0F2E();
- break;
-case 0x2F:
- instr_0F2F();
- break;
-case 0x30:
- instr_0F30();
- break;
-case 0x31:
- instr_0F31();
- break;
-case 0x32:
- instr_0F32();
- break;
-case 0x33:
- instr_0F33();
- break;
-case 0x34:
- instr_0F34();
- break;
-case 0x35:
- instr_0F35();
- break;
-case 0x36:
- instr_0F36();
- break;
-case 0x37:
- instr_0F37();
- break;
-case 0x38:
- instr_0F38();
- break;
-case 0x39:
- instr_0F39();
- break;
-case 0x3A:
- instr_0F3A();
- break;
-case 0x3B:
- instr_0F3B();
- break;
-case 0x3C:
- instr_0F3C();
- break;
-case 0x3D:
- instr_0F3D();
- break;
-case 0x3E:
- instr_0F3E();
- break;
-case 0x3F:
- instr_0F3F();
- break;
-case 0x40:
- instr16_0F40();
- break;
-case 0x41:
- instr16_0F41();
- break;
-case 0x42:
- instr16_0F42();
- break;
-case 0x43:
- instr16_0F43();
- break;
-case 0x44:
- instr16_0F44();
- break;
-case 0x45:
- instr16_0F45();
- break;
-case 0x46:
- instr16_0F46();
- break;
-case 0x47:
- instr16_0F47();
- break;
-case 0x48:
- instr16_0F48();
- break;
-case 0x49:
- instr16_0F49();
- break;
-case 0x4A:
- instr16_0F4A();
- break;
-case 0x4B:
- instr16_0F4B();
- break;
-case 0x4C:
- instr16_0F4C();
- break;
-case 0x4D:
- instr16_0F4D();
- break;
-case 0x4E:
- instr16_0F4E();
- break;
-case 0x4F:
- instr16_0F4F();
- break;
-case 0x50:
- instr_0F50();
- break;
-case 0x51:
- instr_0F51();
- break;
-case 0x52:
- instr_0F52();
- break;
-case 0x53:
- instr_0F53();
- break;
-case 0x54:
- (*prefixes & PREFIX_66) ? instr_660F54() :
- instr_0F54();
- break;
-case 0x55:
- instr_0F55();
- break;
-case 0x56:
- instr_0F56();
- break;
-case 0x57:
- (*prefixes & PREFIX_66) ? instr_660F57() :
- instr_0F57();
- break;
-case 0x58:
- instr_0F58();
- break;
-case 0x59:
- instr_0F59();
- break;
-case 0x5A:
- instr_0F5A();
- break;
-case 0x5B:
- instr_0F5B();
- break;
-case 0x5C:
- instr_0F5C();
- break;
-case 0x5D:
- instr_0F5D();
- break;
-case 0x5E:
- instr_0F5E();
- break;
-case 0x5F:
- instr_0F5F();
- break;
-case 0x60:
- (*prefixes & PREFIX_66) ? instr_660F60() :
- instr_0F60();
- break;
-case 0x61:
- (*prefixes & PREFIX_66) ? instr_660F61() :
- instr_0F61();
- break;
-case 0x62:
- instr_0F62();
- break;
-case 0x63:
- instr_0F63();
- break;
-case 0x64:
- instr_0F64();
- break;
-case 0x65:
- instr_0F65();
- break;
-case 0x66:
- instr_0F66();
- break;
-case 0x67:
- (*prefixes & PREFIX_66) ? instr_660F67() :
- instr_0F67();
- break;
-case 0x68:
- (*prefixes & PREFIX_66) ? instr_660F68() :
- instr_0F68();
- break;
-case 0x69:
- instr_0F69();
- break;
-case 0x6A:
- instr_0F6A();
- break;
-case 0x6B:
- instr_0F6B();
- break;
-case 0x6C:
- instr_0F6C();
- break;
-case 0x6D:
- instr_0F6D();
- break;
-case 0x6E:
- (*prefixes & PREFIX_66) ? instr_660F6E() :
- instr_0F6E();
- break;
-case 0x6F:
- (*prefixes & PREFIX_66) ? instr_660F6F() :
- (*prefixes & PREFIX_F3) ? instr_F30F6F() :
- instr_0F6F();
- break;
-case 0x70:
- (*prefixes & PREFIX_66) ? instr_660F70() :
- (*prefixes & PREFIX_F2) ? instr_F20F70() :
- (*prefixes & PREFIX_F3) ? instr_F30F70() :
- instr_0F70();
- break;
-case 0x71:
- instr_0F71();
- break;
-case 0x72:
- instr_0F72();
- break;
-case 0x73:
- (*prefixes & PREFIX_66) ? instr_660F73() :
- instr_0F73();
- break;
-case 0x74:
- (*prefixes & PREFIX_66) ? instr_660F74() :
- instr_0F74();
- break;
-case 0x75:
- (*prefixes & PREFIX_66) ? instr_660F75() :
- instr_0F75();
- break;
-case 0x76:
- (*prefixes & PREFIX_66) ? instr_660F76() :
- instr_0F76();
- break;
-case 0x77:
- instr_0F77();
- break;
-case 0x78:
- instr_0F78();
- break;
-case 0x79:
- instr_0F79();
- break;
-case 0x7A:
- instr_0F7A();
- break;
-case 0x7B:
- instr_0F7B();
- break;
-case 0x7C:
- instr_0F7C();
- break;
-case 0x7D:
- instr_0F7D();
- break;
-case 0x7E:
- (*prefixes & PREFIX_66) ? instr_660F7E() :
- (*prefixes & PREFIX_F3) ? instr_F30F7E() :
- instr_0F7E();
- break;
-case 0x7F:
- (*prefixes & PREFIX_66) ? instr_660F7F() :
- (*prefixes & PREFIX_F3) ? instr_F30F7F() :
- instr_0F7F();
- break;
-case 0x80:
- instr16_0F80();
- break;
-case 0x81:
- instr16_0F81();
- break;
-case 0x82:
- instr16_0F82();
- break;
-case 0x83:
- instr16_0F83();
- break;
-case 0x84:
- instr16_0F84();
- break;
-case 0x85:
- instr16_0F85();
- break;
-case 0x86:
- instr16_0F86();
- break;
-case 0x87:
- instr16_0F87();
- break;
-case 0x88:
- instr16_0F88();
- break;
-case 0x89:
- instr16_0F89();
- break;
-case 0x8A:
- instr16_0F8A();
- break;
-case 0x8B:
- instr16_0F8B();
- break;
-case 0x8C:
- instr16_0F8C();
- break;
-case 0x8D:
- instr16_0F8D();
- break;
-case 0x8E:
- instr16_0F8E();
- break;
-case 0x8F:
- instr16_0F8F();
- break;
-case 0x90:
- instr_0F90();
- break;
-case 0x91:
- instr_0F91();
- break;
-case 0x92:
- instr_0F92();
- break;
-case 0x93:
- instr_0F93();
- break;
-case 0x94:
- instr_0F94();
- break;
-case 0x95:
- instr_0F95();
- break;
-case 0x96:
- instr_0F96();
- break;
-case 0x97:
- instr_0F97();
- break;
-case 0x98:
- instr_0F98();
- break;
-case 0x99:
- instr_0F99();
- break;
-case 0x9A:
- instr_0F9A();
- break;
-case 0x9B:
- instr_0F9B();
- break;
-case 0x9C:
- instr_0F9C();
- break;
-case 0x9D:
- instr_0F9D();
- break;
-case 0x9E:
- instr_0F9E();
- break;
-case 0x9F:
- instr_0F9F();
- break;
-case 0xA0:
- instr16_0FA0();
- break;
-case 0xA1:
- instr16_0FA1();
- break;
-case 0xA2:
- instr_0FA2();
- break;
-case 0xA3:
- instr16_0FA3();
- break;
-case 0xA4:
- instr16_0FA4();
- break;
-case 0xA5:
- instr16_0FA5();
- break;
-case 0xA6:
- instr_0FA6();
- break;
-case 0xA7:
- instr_0FA7();
- break;
-case 0xA8:
- instr16_0FA8();
- break;
-case 0xA9:
- instr16_0FA9();
- break;
-case 0xAA:
- instr_0FAA();
- break;
-case 0xAB:
- instr16_0FAB();
- break;
-case 0xAC:
- instr16_0FAC();
- break;
-case 0xAD:
- instr16_0FAD();
- break;
-case 0xAE:
- instr_0FAE();
- break;
-case 0xAF:
- instr16_0FAF();
- break;
-case 0xB0:
- instr_0FB0();
- break;
-case 0xB1:
- instr16_0FB1();
- break;
-case 0xB2:
- instr16_0FB2();
- break;
-case 0xB3:
- instr16_0FB3();
- break;
-case 0xB4:
- instr16_0FB4();
- break;
-case 0xB5:
- instr16_0FB5();
- break;
-case 0xB6:
- instr16_0FB6();
- break;
-case 0xB7:
- instr16_0FB7();
- break;
-case 0xB8:
- instr16_0FB8();
- break;
-case 0xB9:
- instr_0FB9();
- break;
-case 0xBA:
- instr16_0FBA();
- break;
-case 0xBB:
- instr16_0FBB();
- break;
-case 0xBC:
- instr16_0FBC();
- break;
-case 0xBD:
- instr16_0FBD();
- break;
-case 0xBE:
- instr16_0FBE();
- break;
-case 0xBF:
- instr16_0FBF();
- break;
-case 0xC0:
- instr_0FC0();
- break;
-case 0xC1:
- instr16_0FC1();
- break;
-case 0xC2:
- instr_0FC2();
- break;
-case 0xC3:
- instr_0FC3();
- break;
-case 0xC4:
- instr_0FC4();
- break;
-case 0xC5:
- (*prefixes & PREFIX_66) ? instr_660FC5() :
- instr_0FC5();
- break;
-case 0xC6:
- instr_0FC6();
- break;
-case 0xC7:
- instr_0FC7();
- break;
-case 0xC8:
- instr_0FC8();
- break;
-case 0xC9:
- instr_0FC9();
- break;
-case 0xCA:
- instr_0FCA();
- break;
-case 0xCB:
- instr_0FCB();
- break;
-case 0xCC:
- instr_0FCC();
- break;
-case 0xCD:
- instr_0FCD();
- break;
-case 0xCE:
- instr_0FCE();
- break;
-case 0xCF:
- instr_0FCF();
- break;
-case 0xD0:
- instr_0FD0();
- break;
-case 0xD1:
- instr_0FD1();
- break;
-case 0xD2:
- instr_0FD2();
- break;
-case 0xD3:
- (*prefixes & PREFIX_66) ? instr_660FD3() :
- instr_0FD3();
- break;
-case 0xD4:
- instr_0FD4();
- break;
-case 0xD5:
- (*prefixes & PREFIX_66) ? instr_660FD5() :
- instr_0FD5();
- break;
-case 0xD6:
- (*prefixes & PREFIX_66) ? instr_660FD6() :
- instr_0FD6();
- break;
-case 0xD7:
- (*prefixes & PREFIX_66) ? instr_660FD7() :
- instr_0FD7();
- break;
-case 0xD8:
- instr_0FD8();
- break;
-case 0xD9:
- instr_0FD9();
- break;
-case 0xDA:
- (*prefixes & PREFIX_66) ? instr_660FDA() :
- instr_0FDA();
- break;
-case 0xDB:
- instr_0FDB();
- break;
-case 0xDC:
- (*prefixes & PREFIX_66) ? instr_660FDC() :
- instr_0FDC();
- break;
-case 0xDD:
- (*prefixes & PREFIX_66) ? instr_660FDD() :
- instr_0FDD();
- break;
-case 0xDE:
- (*prefixes & PREFIX_66) ? instr_660FDE() :
- instr_0FDE();
- break;
-case 0xDF:
- instr_0FDF();
- break;
-case 0xE0:
- instr_0FE0();
- break;
-case 0xE1:
- instr_0FE1();
- break;
-case 0xE2:
- instr_0FE2();
- break;
-case 0xE3:
- instr_0FE3();
- break;
-case 0xE4:
- (*prefixes & PREFIX_66) ? instr_660FE4() :
- instr_0FE4();
- break;
-case 0xE5:
- instr_0FE5();
- break;
-case 0xE6:
- instr_0FE6();
- break;
-case 0xE7:
- (*prefixes & PREFIX_66) ? instr_660FE7() :
- instr_0FE7();
- break;
-case 0xE8:
- instr_0FE8();
- break;
-case 0xE9:
- instr_0FE9();
- break;
-case 0xEA:
- instr_0FEA();
- break;
-case 0xEB:
- (*prefixes & PREFIX_66) ? instr_660FEB() :
- instr_0FEB();
- break;
-case 0xEC:
- instr_0FEC();
- break;
-case 0xED:
- instr_0FED();
- break;
-case 0xEE:
- instr_0FEE();
- break;
-case 0xEF:
- (*prefixes & PREFIX_66) ? instr_660FEF() :
- instr_0FEF();
- break;
-case 0xF0:
- instr_0FF0();
- break;
-case 0xF1:
- instr_0FF1();
- break;
-case 0xF2:
- instr_0FF2();
- break;
-case 0xF3:
- instr_0FF3();
- break;
-case 0xF4:
- instr_0FF4();
- break;
-case 0xF5:
- instr_0FF5();
- break;
-case 0xF6:
- instr_0FF6();
- break;
-case 0xF7:
- instr_0FF7();
- break;
-case 0xF8:
- instr_0FF8();
- break;
-case 0xF9:
- instr_0FF9();
- break;
-case 0xFA:
- (*prefixes & PREFIX_66) ? instr_660FFA() :
- instr_0FFA();
- break;
-case 0xFB:
- instr_0FFB();
- break;
-case 0xFC:
- instr_0FFC();
- break;
-case 0xFD:
- instr_0FFD();
- break;
-case 0xFE:
- instr_0FFE();
- break;
-case 0xFF:
- instr_0FFF();
- break;
-default: assert(false);
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
}
+ break;
+ case 0x01:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x02:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F02_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F02_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x03:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F03_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F03_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x04:
+ {
+ instr_0F04();
+ }
+ break;
+ case 0x05:
+ {
+ instr_0F05();
+ }
+ break;
+ case 0x06:
+ {
+ instr_0F06();
+ }
+ break;
+ case 0x07:
+ {
+ instr_0F07();
+ }
+ break;
+ case 0x08:
+ {
+ instr_0F08();
+ }
+ break;
+ case 0x09:
+ {
+ instr_0F09();
+ }
+ break;
+ case 0x0A:
+ {
+ instr_0F0A();
+ }
+ break;
+ case 0x0B:
+ {
+ instr_0F0B();
+ }
+ break;
+ case 0x0C:
+ {
+ instr_0F0C();
+ }
+ break;
+ case 0x0D:
+ {
+ instr_0F0D();
+ }
+ break;
+ case 0x0E:
+ {
+ instr_0F0E();
+ }
+ break;
+ case 0x0F:
+ {
+ instr_0F0F();
+ }
+ break;
+ case 0x10:
+ {
+ instr_0F10();
+ }
+ break;
+ case 0x11:
+ {
+ instr_0F11();
+ }
+ break;
+ case 0x12:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20F12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F20F12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x13:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F13_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F13_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F13_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F13_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x14:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F14_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F14_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F14_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F14_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x15:
+ {
+ instr_0F15();
+ }
+ break;
+ case 0x16:
+ {
+ instr_0F16();
+ }
+ break;
+ case 0x17:
+ {
+ instr_0F17();
+ }
+ break;
+ case 0x18:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F18_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F18_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x19:
+ {
+ instr_0F19();
+ }
+ break;
+ case 0x1A:
+ {
+ instr_0F1A();
+ }
+ break;
+ case 0x1B:
+ {
+ instr_0F1B();
+ }
+ break;
+ case 0x1C:
+ {
+ instr_0F1C();
+ }
+ break;
+ case 0x1D:
+ {
+ instr_0F1D();
+ }
+ break;
+ case 0x1E:
+ {
+ instr_0F1E();
+ }
+ break;
+ case 0x1F:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F1F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F1F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x20:
+ {
+ int32_t modrm_byte = read_imm8();
+ instr_0F20(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ break;
+ case 0x21:
+ {
+ int32_t modrm_byte = read_imm8();
+ instr_0F21(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ break;
+ case 0x22:
+ {
+ int32_t modrm_byte = read_imm8();
+ instr_0F22(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ break;
+ case 0x23:
+ {
+ int32_t modrm_byte = read_imm8();
+ instr_0F23(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ break;
+ case 0x24:
+ {
+ instr_0F24();
+ }
+ break;
+ case 0x25:
+ {
+ instr_0F25();
+ }
+ break;
+ case 0x26:
+ {
+ instr_0F26();
+ }
+ break;
+ case 0x27:
+ {
+ instr_0F27();
+ }
+ break;
+ case 0x28:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F28_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F28_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F28_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F28_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x29:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F29_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F29_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F29_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F29_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x2A:
+ {
+ instr_0F2A();
+ }
+ break;
+ case 0x2B:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F2B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F2B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F2B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F2B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x2C:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F2C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F2C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20F2C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F20F2C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F2C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F2C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F2C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F2C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x2D:
+ {
+ instr_0F2D();
+ }
+ break;
+ case 0x2E:
+ {
+ instr_0F2E();
+ }
+ break;
+ case 0x2F:
+ {
+ instr_0F2F();
+ }
+ break;
+ case 0x30:
+ {
+ instr_0F30();
+ }
+ break;
+ case 0x31:
+ {
+ instr_0F31();
+ }
+ break;
+ case 0x32:
+ {
+ instr_0F32();
+ }
+ break;
+ case 0x33:
+ {
+ instr_0F33();
+ }
+ break;
+ case 0x34:
+ {
+ instr_0F34();
+ }
+ break;
+ case 0x35:
+ {
+ instr_0F35();
+ }
+ break;
+ case 0x36:
+ {
+ instr_0F36();
+ }
+ break;
+ case 0x37:
+ {
+ instr_0F37();
+ }
+ break;
+ case 0x38:
+ {
+ instr_0F38();
+ }
+ break;
+ case 0x39:
+ {
+ instr_0F39();
+ }
+ break;
+ case 0x3A:
+ {
+ instr_0F3A();
+ }
+ break;
+ case 0x3B:
+ {
+ instr_0F3B();
+ }
+ break;
+ case 0x3C:
+ {
+ instr_0F3C();
+ }
+ break;
+ case 0x3D:
+ {
+ instr_0F3D();
+ }
+ break;
+ case 0x3E:
+ {
+ instr_0F3E();
+ }
+ break;
+ case 0x3F:
+ {
+ instr_0F3F();
+ }
+ break;
+ case 0x40:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F40_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F40_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x41:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F41_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F41_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x42:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F42_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F42_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x43:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F43_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F43_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x44:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F44_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F44_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x45:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F45_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F45_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x46:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F46_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F46_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x47:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F47_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F47_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x48:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F48_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F48_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x49:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F49_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F49_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4A:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F4A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F4A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4B:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F4B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F4B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4C:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F4C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F4C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4D:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F4D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F4D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4E:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F4E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F4E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4F:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0F4F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0F4F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x50:
+ {
+ instr_0F50();
+ }
+ break;
+ case 0x51:
+ {
+ instr_0F51();
+ }
+ break;
+ case 0x52:
+ {
+ instr_0F52();
+ }
+ break;
+ case 0x53:
+ {
+ instr_0F53();
+ }
+ break;
+ case 0x54:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F54_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F54_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F54_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F54_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x55:
+ {
+ instr_0F55();
+ }
+ break;
+ case 0x56:
+ {
+ instr_0F56();
+ }
+ break;
+ case 0x57:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F57_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F57_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F57_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F57_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x58:
+ {
+ instr_0F58();
+ }
+ break;
+ case 0x59:
+ {
+ instr_0F59();
+ }
+ break;
+ case 0x5A:
+ {
+ instr_0F5A();
+ }
+ break;
+ case 0x5B:
+ {
+ instr_0F5B();
+ }
+ break;
+ case 0x5C:
+ {
+ instr_0F5C();
+ }
+ break;
+ case 0x5D:
+ {
+ instr_0F5D();
+ }
+ break;
+ case 0x5E:
+ {
+ instr_0F5E();
+ }
+ break;
+ case 0x5F:
+ {
+ instr_0F5F();
+ }
+ break;
+ case 0x60:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F60_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F60_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F60_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F60_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x61:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F61_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F61_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F61_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F61_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x62:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F62_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F62_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F62_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F62_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x63:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F63_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F63_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F63_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F63_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x64:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F64_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F64_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F64_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F64_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x65:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F65_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F65_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F65_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F65_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x66:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F66_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F66_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F66_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F66_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x67:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F67_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F67_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F67_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F67_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x68:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F68_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F68_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F68_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F68_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x69:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F69_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F69_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F69_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F69_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6A:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6B:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6C:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6D:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6E:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6F:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F6F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F6F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x70:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F70_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_660F70_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20F70_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_F20F70_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F70_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_F30F70_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F70_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_0F70_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 0x71:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 2:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F71_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F71_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F71_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F71_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 4:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F71_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F71_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F71_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F71_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 6:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F71_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F71_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F71_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F71_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x72:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 2:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F72_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F72_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F72_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F72_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 4:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F72_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F72_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F72_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F72_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 6:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F72_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F72_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F72_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F72_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x73:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 2:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F73_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F73_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F73_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F73_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 3:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F73_3_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F73_3_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F73_3_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F73_3_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 6:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F73_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F73_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F73_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F73_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 7:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F73_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F73_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F73_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F73_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x74:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F74_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F74_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F74_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F74_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x75:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F75_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F75_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F75_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F75_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x76:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F76_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F76_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F76_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F76_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x77:
+ {
+ instr_0F77();
+ }
+ break;
+ case 0x78:
+ {
+ instr_0F78();
+ }
+ break;
+ case 0x79:
+ {
+ instr_0F79();
+ }
+ break;
+ case 0x7A:
+ {
+ instr_0F7A();
+ }
+ break;
+ case 0x7B:
+ {
+ instr_0F7B();
+ }
+ break;
+ case 0x7C:
+ {
+ instr_0F7C();
+ }
+ break;
+ case 0x7D:
+ {
+ instr_0F7D();
+ }
+ break;
+ case 0x7E:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F7E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F7E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F7E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F7E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F7E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F7E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x7F:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F7F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F7F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F7F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F7F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F7F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F7F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x80:
+ {
+ instr16_0F80(read_imm16());
+ }
+ break;
+ case 0x81:
+ {
+ instr16_0F81(read_imm16());
+ }
+ break;
+ case 0x82:
+ {
+ instr16_0F82(read_imm16());
+ }
+ break;
+ case 0x83:
+ {
+ instr16_0F83(read_imm16());
+ }
+ break;
+ case 0x84:
+ {
+ instr16_0F84(read_imm16());
+ }
+ break;
+ case 0x85:
+ {
+ instr16_0F85(read_imm16());
+ }
+ break;
+ case 0x86:
+ {
+ instr16_0F86(read_imm16());
+ }
+ break;
+ case 0x87:
+ {
+ instr16_0F87(read_imm16());
+ }
+ break;
+ case 0x88:
+ {
+ instr16_0F88(read_imm16());
+ }
+ break;
+ case 0x89:
+ {
+ instr16_0F89(read_imm16());
+ }
+ break;
+ case 0x8A:
+ {
+ instr16_0F8A(read_imm16());
+ }
+ break;
+ case 0x8B:
+ {
+ instr16_0F8B(read_imm16());
+ }
+ break;
+ case 0x8C:
+ {
+ instr16_0F8C(read_imm16());
+ }
+ break;
+ case 0x8D:
+ {
+ instr16_0F8D(read_imm16());
+ }
+ break;
+ case 0x8E:
+ {
+ instr16_0F8E(read_imm16());
+ }
+ break;
+ case 0x8F:
+ {
+ instr16_0F8F(read_imm16());
+ }
+ break;
+ case 0x90:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F90_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F90_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x91:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F91_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F91_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x92:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F92_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F92_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x93:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F93_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F93_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x94:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F94_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F94_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x95:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F95_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F95_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x96:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F96_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F96_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x97:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F97_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F97_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x98:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F98_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F98_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x99:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F99_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F99_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9A:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9B:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9C:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9D:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9E:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9F:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xA0:
+ {
+ instr16_0FA0();
+ }
+ break;
+ case 0xA1:
+ {
+ instr16_0FA1();
+ }
+ break;
+ case 0xA2:
+ {
+ instr_0FA2();
+ }
+ break;
+ case 0xA3:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FA3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FA3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xA4:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FA4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr16_0FA4_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ break;
+ case 0xA5:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FA5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FA5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xA6:
+ {
+ instr_0FA6();
+ }
+ break;
+ case 0xA7:
+ {
+ instr_0FA7();
+ }
+ break;
+ case 0xA8:
+ {
+ instr16_0FA8();
+ }
+ break;
+ case 0xA9:
+ {
+ instr16_0FA9();
+ }
+ break;
+ case 0xAA:
+ {
+ instr_0FAA();
+ }
+ break;
+ case 0xAB:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FAB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FAB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xAC:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FAC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr16_0FAC_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ break;
+ case 0xAD:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FAD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FAD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xAE:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xAF:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FAF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FAF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB0:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FB0_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FB0_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB1:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FB1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FB1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB2:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FB2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FB2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB3:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FB3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FB3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB4:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FB4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FB4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB5:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FB5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FB5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB6:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FB6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FB6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB7:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FB7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FB7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB8:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_F30FB8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_F30FB8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FB8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FB8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xB9:
+ {
+ instr_0FB9();
+ }
+ break;
+ case 0xBA:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FBA_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_0FBA_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FBA_5_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_0FBA_5_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FBA_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_0FBA_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FBA_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr16_0FBA_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xBB:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FBB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FBB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xBC:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FBC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FBC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xBD:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FBD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FBD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xBE:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FBE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FBE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xBF:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FBF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FBF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC0:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC0_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FC0_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC1:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr16_0FC1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr16_0FC1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC2:
+ {
+ instr_0FC2();
+ }
+ break;
+ case 0xC3:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FC3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC4:
+ {
+ instr_0FC4();
+ }
+ break;
+ case 0xC5:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FC5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_660FC5_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_0FC5_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 0xC6:
+ {
+ instr_0FC6();
+ }
+ break;
+ case 0xC7:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC7_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FC7_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC7_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FC7_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xC8:
+ {
+ instr_0FC8();
+ }
+ break;
+ case 0xC9:
+ {
+ instr_0FC9();
+ }
+ break;
+ case 0xCA:
+ {
+ instr_0FCA();
+ }
+ break;
+ case 0xCB:
+ {
+ instr_0FCB();
+ }
+ break;
+ case 0xCC:
+ {
+ instr_0FCC();
+ }
+ break;
+ case 0xCD:
+ {
+ instr_0FCD();
+ }
+ break;
+ case 0xCE:
+ {
+ instr_0FCE();
+ }
+ break;
+ case 0xCF:
+ {
+ instr_0FCF();
+ }
+ break;
+ case 0xD0:
+ {
+ instr_0FD0();
+ }
+ break;
+ case 0xD1:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD2:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD3:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD4:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD5:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD6:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20FD6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F20FD6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30FD6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30FD6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD7:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD8:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD9:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDA:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDB:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDC:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDD:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDE:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDF:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE0:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE0_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE0_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE0_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE0_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE1:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE2:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE3:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE4:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE5:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE6:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20FE6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F20FE6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30FE6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30FE6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE7:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE8:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE9:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEA:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEB:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEC:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xED:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FED_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FED_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FED_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FED_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEE:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEF:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF0:
+ {
+ instr_0FF0();
+ }
+ break;
+ case 0xF1:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF2:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF3:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF4:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF5:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF6:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF7:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF8:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF9:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFA:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFB:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFC:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFD:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFE:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFF:
+ {
+ instr_0FFF();
+ }
+ break;
+ default:
+ assert(false);
+}
}
static void run_instruction0f_32(int32_t opcode)
{
// XXX: This table is generated. Don't modify
- switch(opcode)
+switch(opcode)
+{
+ case 0x00:
{
-case 0x00:
- instr_0F00();
- break;
-case 0x01:
- instr_0F01();
- break;
-case 0x02:
- instr32_0F02();
- break;
-case 0x03:
- instr32_0F03();
- break;
-case 0x04:
- instr_0F04();
- break;
-case 0x05:
- instr_0F05();
- break;
-case 0x06:
- instr_0F06();
- break;
-case 0x07:
- instr_0F07();
- break;
-case 0x08:
- instr_0F08();
- break;
-case 0x09:
- instr_0F09();
- break;
-case 0x0A:
- instr_0F0A();
- break;
-case 0x0B:
- instr_0F0B();
- break;
-case 0x0C:
- instr_0F0C();
- break;
-case 0x0D:
- instr_0F0D();
- break;
-case 0x0E:
- instr_0F0E();
- break;
-case 0x0F:
- instr_0F0F();
- break;
-case 0x10:
- instr_0F10();
- break;
-case 0x11:
- instr_0F11();
- break;
-case 0x12:
- (*prefixes & PREFIX_66) ? instr_660F12() :
- instr_0F12();
- break;
-case 0x13:
- (*prefixes & PREFIX_66) ? instr_660F13() :
- instr_0F13();
- break;
-case 0x14:
- (*prefixes & PREFIX_66) ? instr_660F14() :
- instr_0F14();
- break;
-case 0x15:
- instr_0F15();
- break;
-case 0x16:
- instr_0F16();
- break;
-case 0x17:
- instr_0F17();
- break;
-case 0x18:
- instr_0F18();
- break;
-case 0x19:
- instr_0F19();
- break;
-case 0x1A:
- instr_0F1A();
- break;
-case 0x1B:
- instr_0F1B();
- break;
-case 0x1C:
- instr_0F1C();
- break;
-case 0x1D:
- instr_0F1D();
- break;
-case 0x1E:
- instr_0F1E();
- break;
-case 0x1F:
- instr_0F1F();
- break;
-case 0x20:
- instr_0F20();
- break;
-case 0x21:
- instr_0F21();
- break;
-case 0x22:
- instr_0F22();
- break;
-case 0x23:
- instr_0F23();
- break;
-case 0x24:
- instr_0F24();
- break;
-case 0x25:
- instr_0F25();
- break;
-case 0x26:
- instr_0F26();
- break;
-case 0x27:
- instr_0F27();
- break;
-case 0x28:
- (*prefixes & PREFIX_66) ? instr_660F28() :
- instr_0F28();
- break;
-case 0x29:
- (*prefixes & PREFIX_66) ? instr_660F29() :
- instr_0F29();
- break;
-case 0x2A:
- instr_0F2A();
- break;
-case 0x2B:
- (*prefixes & PREFIX_66) ? instr_660F2B() :
- instr_0F2B();
- break;
-case 0x2C:
- (*prefixes & PREFIX_F2) ? instr_F20F2C() :
- instr_0F2C();
- break;
-case 0x2D:
- instr_0F2D();
- break;
-case 0x2E:
- instr_0F2E();
- break;
-case 0x2F:
- instr_0F2F();
- break;
-case 0x30:
- instr_0F30();
- break;
-case 0x31:
- instr_0F31();
- break;
-case 0x32:
- instr_0F32();
- break;
-case 0x33:
- instr_0F33();
- break;
-case 0x34:
- instr_0F34();
- break;
-case 0x35:
- instr_0F35();
- break;
-case 0x36:
- instr_0F36();
- break;
-case 0x37:
- instr_0F37();
- break;
-case 0x38:
- instr_0F38();
- break;
-case 0x39:
- instr_0F39();
- break;
-case 0x3A:
- instr_0F3A();
- break;
-case 0x3B:
- instr_0F3B();
- break;
-case 0x3C:
- instr_0F3C();
- break;
-case 0x3D:
- instr_0F3D();
- break;
-case 0x3E:
- instr_0F3E();
- break;
-case 0x3F:
- instr_0F3F();
- break;
-case 0x40:
- instr32_0F40();
- break;
-case 0x41:
- instr32_0F41();
- break;
-case 0x42:
- instr32_0F42();
- break;
-case 0x43:
- instr32_0F43();
- break;
-case 0x44:
- instr32_0F44();
- break;
-case 0x45:
- instr32_0F45();
- break;
-case 0x46:
- instr32_0F46();
- break;
-case 0x47:
- instr32_0F47();
- break;
-case 0x48:
- instr32_0F48();
- break;
-case 0x49:
- instr32_0F49();
- break;
-case 0x4A:
- instr32_0F4A();
- break;
-case 0x4B:
- instr32_0F4B();
- break;
-case 0x4C:
- instr32_0F4C();
- break;
-case 0x4D:
- instr32_0F4D();
- break;
-case 0x4E:
- instr32_0F4E();
- break;
-case 0x4F:
- instr32_0F4F();
- break;
-case 0x50:
- instr_0F50();
- break;
-case 0x51:
- instr_0F51();
- break;
-case 0x52:
- instr_0F52();
- break;
-case 0x53:
- instr_0F53();
- break;
-case 0x54:
- (*prefixes & PREFIX_66) ? instr_660F54() :
- instr_0F54();
- break;
-case 0x55:
- instr_0F55();
- break;
-case 0x56:
- instr_0F56();
- break;
-case 0x57:
- (*prefixes & PREFIX_66) ? instr_660F57() :
- instr_0F57();
- break;
-case 0x58:
- instr_0F58();
- break;
-case 0x59:
- instr_0F59();
- break;
-case 0x5A:
- instr_0F5A();
- break;
-case 0x5B:
- instr_0F5B();
- break;
-case 0x5C:
- instr_0F5C();
- break;
-case 0x5D:
- instr_0F5D();
- break;
-case 0x5E:
- instr_0F5E();
- break;
-case 0x5F:
- instr_0F5F();
- break;
-case 0x60:
- (*prefixes & PREFIX_66) ? instr_660F60() :
- instr_0F60();
- break;
-case 0x61:
- (*prefixes & PREFIX_66) ? instr_660F61() :
- instr_0F61();
- break;
-case 0x62:
- instr_0F62();
- break;
-case 0x63:
- instr_0F63();
- break;
-case 0x64:
- instr_0F64();
- break;
-case 0x65:
- instr_0F65();
- break;
-case 0x66:
- instr_0F66();
- break;
-case 0x67:
- (*prefixes & PREFIX_66) ? instr_660F67() :
- instr_0F67();
- break;
-case 0x68:
- (*prefixes & PREFIX_66) ? instr_660F68() :
- instr_0F68();
- break;
-case 0x69:
- instr_0F69();
- break;
-case 0x6A:
- instr_0F6A();
- break;
-case 0x6B:
- instr_0F6B();
- break;
-case 0x6C:
- instr_0F6C();
- break;
-case 0x6D:
- instr_0F6D();
- break;
-case 0x6E:
- (*prefixes & PREFIX_66) ? instr_660F6E() :
- instr_0F6E();
- break;
-case 0x6F:
- (*prefixes & PREFIX_66) ? instr_660F6F() :
- (*prefixes & PREFIX_F3) ? instr_F30F6F() :
- instr_0F6F();
- break;
-case 0x70:
- (*prefixes & PREFIX_66) ? instr_660F70() :
- (*prefixes & PREFIX_F2) ? instr_F20F70() :
- (*prefixes & PREFIX_F3) ? instr_F30F70() :
- instr_0F70();
- break;
-case 0x71:
- instr_0F71();
- break;
-case 0x72:
- instr_0F72();
- break;
-case 0x73:
- (*prefixes & PREFIX_66) ? instr_660F73() :
- instr_0F73();
- break;
-case 0x74:
- (*prefixes & PREFIX_66) ? instr_660F74() :
- instr_0F74();
- break;
-case 0x75:
- (*prefixes & PREFIX_66) ? instr_660F75() :
- instr_0F75();
- break;
-case 0x76:
- (*prefixes & PREFIX_66) ? instr_660F76() :
- instr_0F76();
- break;
-case 0x77:
- instr_0F77();
- break;
-case 0x78:
- instr_0F78();
- break;
-case 0x79:
- instr_0F79();
- break;
-case 0x7A:
- instr_0F7A();
- break;
-case 0x7B:
- instr_0F7B();
- break;
-case 0x7C:
- instr_0F7C();
- break;
-case 0x7D:
- instr_0F7D();
- break;
-case 0x7E:
- (*prefixes & PREFIX_66) ? instr_660F7E() :
- (*prefixes & PREFIX_F3) ? instr_F30F7E() :
- instr_0F7E();
- break;
-case 0x7F:
- (*prefixes & PREFIX_66) ? instr_660F7F() :
- (*prefixes & PREFIX_F3) ? instr_F30F7F() :
- instr_0F7F();
- break;
-case 0x80:
- instr32_0F80();
- break;
-case 0x81:
- instr32_0F81();
- break;
-case 0x82:
- instr32_0F82();
- break;
-case 0x83:
- instr32_0F83();
- break;
-case 0x84:
- instr32_0F84();
- break;
-case 0x85:
- instr32_0F85();
- break;
-case 0x86:
- instr32_0F86();
- break;
-case 0x87:
- instr32_0F87();
- break;
-case 0x88:
- instr32_0F88();
- break;
-case 0x89:
- instr32_0F89();
- break;
-case 0x8A:
- instr32_0F8A();
- break;
-case 0x8B:
- instr32_0F8B();
- break;
-case 0x8C:
- instr32_0F8C();
- break;
-case 0x8D:
- instr32_0F8D();
- break;
-case 0x8E:
- instr32_0F8E();
- break;
-case 0x8F:
- instr32_0F8F();
- break;
-case 0x90:
- instr_0F90();
- break;
-case 0x91:
- instr_0F91();
- break;
-case 0x92:
- instr_0F92();
- break;
-case 0x93:
- instr_0F93();
- break;
-case 0x94:
- instr_0F94();
- break;
-case 0x95:
- instr_0F95();
- break;
-case 0x96:
- instr_0F96();
- break;
-case 0x97:
- instr_0F97();
- break;
-case 0x98:
- instr_0F98();
- break;
-case 0x99:
- instr_0F99();
- break;
-case 0x9A:
- instr_0F9A();
- break;
-case 0x9B:
- instr_0F9B();
- break;
-case 0x9C:
- instr_0F9C();
- break;
-case 0x9D:
- instr_0F9D();
- break;
-case 0x9E:
- instr_0F9E();
- break;
-case 0x9F:
- instr_0F9F();
- break;
-case 0xA0:
- instr32_0FA0();
- break;
-case 0xA1:
- instr32_0FA1();
- break;
-case 0xA2:
- instr_0FA2();
- break;
-case 0xA3:
- instr32_0FA3();
- break;
-case 0xA4:
- instr32_0FA4();
- break;
-case 0xA5:
- instr32_0FA5();
- break;
-case 0xA6:
- instr_0FA6();
- break;
-case 0xA7:
- instr_0FA7();
- break;
-case 0xA8:
- instr32_0FA8();
- break;
-case 0xA9:
- instr32_0FA9();
- break;
-case 0xAA:
- instr_0FAA();
- break;
-case 0xAB:
- instr32_0FAB();
- break;
-case 0xAC:
- instr32_0FAC();
- break;
-case 0xAD:
- instr32_0FAD();
- break;
-case 0xAE:
- instr_0FAE();
- break;
-case 0xAF:
- instr32_0FAF();
- break;
-case 0xB0:
- instr_0FB0();
- break;
-case 0xB1:
- instr32_0FB1();
- break;
-case 0xB2:
- instr32_0FB2();
- break;
-case 0xB3:
- instr32_0FB3();
- break;
-case 0xB4:
- instr32_0FB4();
- break;
-case 0xB5:
- instr32_0FB5();
- break;
-case 0xB6:
- instr32_0FB6();
- break;
-case 0xB7:
- instr32_0FB7();
- break;
-case 0xB8:
- instr32_0FB8();
- break;
-case 0xB9:
- instr_0FB9();
- break;
-case 0xBA:
- instr32_0FBA();
- break;
-case 0xBB:
- instr32_0FBB();
- break;
-case 0xBC:
- instr32_0FBC();
- break;
-case 0xBD:
- instr32_0FBD();
- break;
-case 0xBE:
- instr32_0FBE();
- break;
-case 0xBF:
- instr32_0FBF();
- break;
-case 0xC0:
- instr_0FC0();
- break;
-case 0xC1:
- instr32_0FC1();
- break;
-case 0xC2:
- instr_0FC2();
- break;
-case 0xC3:
- instr_0FC3();
- break;
-case 0xC4:
- instr_0FC4();
- break;
-case 0xC5:
- (*prefixes & PREFIX_66) ? instr_660FC5() :
- instr_0FC5();
- break;
-case 0xC6:
- instr_0FC6();
- break;
-case 0xC7:
- instr_0FC7();
- break;
-case 0xC8:
- instr_0FC8();
- break;
-case 0xC9:
- instr_0FC9();
- break;
-case 0xCA:
- instr_0FCA();
- break;
-case 0xCB:
- instr_0FCB();
- break;
-case 0xCC:
- instr_0FCC();
- break;
-case 0xCD:
- instr_0FCD();
- break;
-case 0xCE:
- instr_0FCE();
- break;
-case 0xCF:
- instr_0FCF();
- break;
-case 0xD0:
- instr_0FD0();
- break;
-case 0xD1:
- instr_0FD1();
- break;
-case 0xD2:
- instr_0FD2();
- break;
-case 0xD3:
- (*prefixes & PREFIX_66) ? instr_660FD3() :
- instr_0FD3();
- break;
-case 0xD4:
- instr_0FD4();
- break;
-case 0xD5:
- (*prefixes & PREFIX_66) ? instr_660FD5() :
- instr_0FD5();
- break;
-case 0xD6:
- (*prefixes & PREFIX_66) ? instr_660FD6() :
- instr_0FD6();
- break;
-case 0xD7:
- (*prefixes & PREFIX_66) ? instr_660FD7() :
- instr_0FD7();
- break;
-case 0xD8:
- instr_0FD8();
- break;
-case 0xD9:
- instr_0FD9();
- break;
-case 0xDA:
- (*prefixes & PREFIX_66) ? instr_660FDA() :
- instr_0FDA();
- break;
-case 0xDB:
- instr_0FDB();
- break;
-case 0xDC:
- (*prefixes & PREFIX_66) ? instr_660FDC() :
- instr_0FDC();
- break;
-case 0xDD:
- (*prefixes & PREFIX_66) ? instr_660FDD() :
- instr_0FDD();
- break;
-case 0xDE:
- (*prefixes & PREFIX_66) ? instr_660FDE() :
- instr_0FDE();
- break;
-case 0xDF:
- instr_0FDF();
- break;
-case 0xE0:
- instr_0FE0();
- break;
-case 0xE1:
- instr_0FE1();
- break;
-case 0xE2:
- instr_0FE2();
- break;
-case 0xE3:
- instr_0FE3();
- break;
-case 0xE4:
- (*prefixes & PREFIX_66) ? instr_660FE4() :
- instr_0FE4();
- break;
-case 0xE5:
- instr_0FE5();
- break;
-case 0xE6:
- instr_0FE6();
- break;
-case 0xE7:
- (*prefixes & PREFIX_66) ? instr_660FE7() :
- instr_0FE7();
- break;
-case 0xE8:
- instr_0FE8();
- break;
-case 0xE9:
- instr_0FE9();
- break;
-case 0xEA:
- instr_0FEA();
- break;
-case 0xEB:
- (*prefixes & PREFIX_66) ? instr_660FEB() :
- instr_0FEB();
- break;
-case 0xEC:
- instr_0FEC();
- break;
-case 0xED:
- instr_0FED();
- break;
-case 0xEE:
- instr_0FEE();
- break;
-case 0xEF:
- (*prefixes & PREFIX_66) ? instr_660FEF() :
- instr_0FEF();
- break;
-case 0xF0:
- instr_0FF0();
- break;
-case 0xF1:
- instr_0FF1();
- break;
-case 0xF2:
- instr_0FF2();
- break;
-case 0xF3:
- instr_0FF3();
- break;
-case 0xF4:
- instr_0FF4();
- break;
-case 0xF5:
- instr_0FF5();
- break;
-case 0xF6:
- instr_0FF6();
- break;
-case 0xF7:
- instr_0FF7();
- break;
-case 0xF8:
- instr_0FF8();
- break;
-case 0xF9:
- instr_0FF9();
- break;
-case 0xFA:
- (*prefixes & PREFIX_66) ? instr_660FFA() :
- instr_0FFA();
- break;
-case 0xFB:
- instr_0FFB();
- break;
-case 0xFC:
- instr_0FFC();
- break;
-case 0xFD:
- instr_0FFD();
- break;
-case 0xFE:
- instr_0FFE();
- break;
-case 0xFF:
- instr_0FFF();
- break;
-default: assert(false);
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F00_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F00_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
}
+ break;
+ case 0x01:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F01_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0F01_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x02:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F02_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F02_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x03:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F03_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F03_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x04:
+ {
+ instr_0F04();
+ }
+ break;
+ case 0x05:
+ {
+ instr_0F05();
+ }
+ break;
+ case 0x06:
+ {
+ instr_0F06();
+ }
+ break;
+ case 0x07:
+ {
+ instr_0F07();
+ }
+ break;
+ case 0x08:
+ {
+ instr_0F08();
+ }
+ break;
+ case 0x09:
+ {
+ instr_0F09();
+ }
+ break;
+ case 0x0A:
+ {
+ instr_0F0A();
+ }
+ break;
+ case 0x0B:
+ {
+ instr_0F0B();
+ }
+ break;
+ case 0x0C:
+ {
+ instr_0F0C();
+ }
+ break;
+ case 0x0D:
+ {
+ instr_0F0D();
+ }
+ break;
+ case 0x0E:
+ {
+ instr_0F0E();
+ }
+ break;
+ case 0x0F:
+ {
+ instr_0F0F();
+ }
+ break;
+ case 0x10:
+ {
+ instr_0F10();
+ }
+ break;
+ case 0x11:
+ {
+ instr_0F11();
+ }
+ break;
+ case 0x12:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20F12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F20F12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F12_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F12_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x13:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F13_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F13_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F13_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F13_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x14:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F14_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F14_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F14_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F14_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x15:
+ {
+ instr_0F15();
+ }
+ break;
+ case 0x16:
+ {
+ instr_0F16();
+ }
+ break;
+ case 0x17:
+ {
+ instr_0F17();
+ }
+ break;
+ case 0x18:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F18_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F18_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x19:
+ {
+ instr_0F19();
+ }
+ break;
+ case 0x1A:
+ {
+ instr_0F1A();
+ }
+ break;
+ case 0x1B:
+ {
+ instr_0F1B();
+ }
+ break;
+ case 0x1C:
+ {
+ instr_0F1C();
+ }
+ break;
+ case 0x1D:
+ {
+ instr_0F1D();
+ }
+ break;
+ case 0x1E:
+ {
+ instr_0F1E();
+ }
+ break;
+ case 0x1F:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F1F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F1F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x20:
+ {
+ int32_t modrm_byte = read_imm8();
+ instr_0F20(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ break;
+ case 0x21:
+ {
+ int32_t modrm_byte = read_imm8();
+ instr_0F21(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ break;
+ case 0x22:
+ {
+ int32_t modrm_byte = read_imm8();
+ instr_0F22(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ break;
+ case 0x23:
+ {
+ int32_t modrm_byte = read_imm8();
+ instr_0F23(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ break;
+ case 0x24:
+ {
+ instr_0F24();
+ }
+ break;
+ case 0x25:
+ {
+ instr_0F25();
+ }
+ break;
+ case 0x26:
+ {
+ instr_0F26();
+ }
+ break;
+ case 0x27:
+ {
+ instr_0F27();
+ }
+ break;
+ case 0x28:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F28_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F28_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F28_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F28_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x29:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F29_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F29_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F29_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F29_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x2A:
+ {
+ instr_0F2A();
+ }
+ break;
+ case 0x2B:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F2B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F2B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F2B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F2B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x2C:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F2C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F2C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20F2C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F20F2C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F2C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F2C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F2C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F2C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x2D:
+ {
+ instr_0F2D();
+ }
+ break;
+ case 0x2E:
+ {
+ instr_0F2E();
+ }
+ break;
+ case 0x2F:
+ {
+ instr_0F2F();
+ }
+ break;
+ case 0x30:
+ {
+ instr_0F30();
+ }
+ break;
+ case 0x31:
+ {
+ instr_0F31();
+ }
+ break;
+ case 0x32:
+ {
+ instr_0F32();
+ }
+ break;
+ case 0x33:
+ {
+ instr_0F33();
+ }
+ break;
+ case 0x34:
+ {
+ instr_0F34();
+ }
+ break;
+ case 0x35:
+ {
+ instr_0F35();
+ }
+ break;
+ case 0x36:
+ {
+ instr_0F36();
+ }
+ break;
+ case 0x37:
+ {
+ instr_0F37();
+ }
+ break;
+ case 0x38:
+ {
+ instr_0F38();
+ }
+ break;
+ case 0x39:
+ {
+ instr_0F39();
+ }
+ break;
+ case 0x3A:
+ {
+ instr_0F3A();
+ }
+ break;
+ case 0x3B:
+ {
+ instr_0F3B();
+ }
+ break;
+ case 0x3C:
+ {
+ instr_0F3C();
+ }
+ break;
+ case 0x3D:
+ {
+ instr_0F3D();
+ }
+ break;
+ case 0x3E:
+ {
+ instr_0F3E();
+ }
+ break;
+ case 0x3F:
+ {
+ instr_0F3F();
+ }
+ break;
+ case 0x40:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F40_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F40_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x41:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F41_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F41_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x42:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F42_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F42_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x43:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F43_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F43_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x44:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F44_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F44_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x45:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F45_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F45_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x46:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F46_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F46_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x47:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F47_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F47_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x48:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F48_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F48_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x49:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F49_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F49_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4A:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F4A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F4A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4B:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F4B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F4B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4C:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F4C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F4C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4D:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F4D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F4D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4E:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F4E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F4E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x4F:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0F4F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0F4F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x50:
+ {
+ instr_0F50();
+ }
+ break;
+ case 0x51:
+ {
+ instr_0F51();
+ }
+ break;
+ case 0x52:
+ {
+ instr_0F52();
+ }
+ break;
+ case 0x53:
+ {
+ instr_0F53();
+ }
+ break;
+ case 0x54:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F54_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F54_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F54_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F54_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x55:
+ {
+ instr_0F55();
+ }
+ break;
+ case 0x56:
+ {
+ instr_0F56();
+ }
+ break;
+ case 0x57:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F57_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F57_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F57_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F57_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x58:
+ {
+ instr_0F58();
+ }
+ break;
+ case 0x59:
+ {
+ instr_0F59();
+ }
+ break;
+ case 0x5A:
+ {
+ instr_0F5A();
+ }
+ break;
+ case 0x5B:
+ {
+ instr_0F5B();
+ }
+ break;
+ case 0x5C:
+ {
+ instr_0F5C();
+ }
+ break;
+ case 0x5D:
+ {
+ instr_0F5D();
+ }
+ break;
+ case 0x5E:
+ {
+ instr_0F5E();
+ }
+ break;
+ case 0x5F:
+ {
+ instr_0F5F();
+ }
+ break;
+ case 0x60:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F60_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F60_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F60_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F60_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x61:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F61_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F61_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F61_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F61_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x62:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F62_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F62_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F62_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F62_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x63:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F63_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F63_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F63_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F63_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x64:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F64_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F64_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F64_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F64_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x65:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F65_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F65_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F65_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F65_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x66:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F66_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F66_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F66_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F66_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x67:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F67_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F67_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F67_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F67_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x68:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F68_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F68_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F68_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F68_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x69:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F69_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F69_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F69_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F69_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6A:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6B:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6C:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6D:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6E:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x6F:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F6F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F6F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F6F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F6F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F6F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F6F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x70:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F70_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_660F70_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20F70_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_F20F70_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F70_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_F30F70_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F70_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_0F70_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 0x71:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 2:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F71_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F71_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F71_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F71_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 4:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F71_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F71_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F71_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F71_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 6:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F71_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F71_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F71_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F71_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x72:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 2:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F72_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F72_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F72_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F72_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 4:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F72_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F72_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F72_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F72_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 6:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F72_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F72_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F72_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F72_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x73:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 2:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F73_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F73_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F73_2_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F73_2_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 3:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F73_3_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F73_3_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F73_3_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F73_3_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 6:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F73_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F73_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F73_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F73_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 7:
+ {
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F73_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_660F73_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F73_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr_0F73_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0x74:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F74_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F74_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F74_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F74_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x75:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F75_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F75_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F75_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F75_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x76:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F76_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F76_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F76_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F76_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x77:
+ {
+ instr_0F77();
+ }
+ break;
+ case 0x78:
+ {
+ instr_0F78();
+ }
+ break;
+ case 0x79:
+ {
+ instr_0F79();
+ }
+ break;
+ case 0x7A:
+ {
+ instr_0F7A();
+ }
+ break;
+ case 0x7B:
+ {
+ instr_0F7B();
+ }
+ break;
+ case 0x7C:
+ {
+ instr_0F7C();
+ }
+ break;
+ case 0x7D:
+ {
+ instr_0F7D();
+ }
+ break;
+ case 0x7E:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F7E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F7E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F7E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F7E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F7E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F7E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x7F:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660F7F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660F7F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30F7F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30F7F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F7F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F7F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0x80:
+ {
+ instr32_0F80(read_imm32s());
+ }
+ break;
+ case 0x81:
+ {
+ instr32_0F81(read_imm32s());
+ }
+ break;
+ case 0x82:
+ {
+ instr32_0F82(read_imm32s());
+ }
+ break;
+ case 0x83:
+ {
+ instr32_0F83(read_imm32s());
+ }
+ break;
+ case 0x84:
+ {
+ instr32_0F84(read_imm32s());
+ }
+ break;
+ case 0x85:
+ {
+ instr32_0F85(read_imm32s());
+ }
+ break;
+ case 0x86:
+ {
+ instr32_0F86(read_imm32s());
+ }
+ break;
+ case 0x87:
+ {
+ instr32_0F87(read_imm32s());
+ }
+ break;
+ case 0x88:
+ {
+ instr32_0F88(read_imm32s());
+ }
+ break;
+ case 0x89:
+ {
+ instr32_0F89(read_imm32s());
+ }
+ break;
+ case 0x8A:
+ {
+ instr32_0F8A(read_imm32s());
+ }
+ break;
+ case 0x8B:
+ {
+ instr32_0F8B(read_imm32s());
+ }
+ break;
+ case 0x8C:
+ {
+ instr32_0F8C(read_imm32s());
+ }
+ break;
+ case 0x8D:
+ {
+ instr32_0F8D(read_imm32s());
+ }
+ break;
+ case 0x8E:
+ {
+ instr32_0F8E(read_imm32s());
+ }
+ break;
+ case 0x8F:
+ {
+ instr32_0F8F(read_imm32s());
+ }
+ break;
+ case 0x90:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F90_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F90_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x91:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F91_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F91_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x92:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F92_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F92_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x93:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F93_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F93_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x94:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F94_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F94_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x95:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F95_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F95_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x96:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F96_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F96_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x97:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F97_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F97_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x98:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F98_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F98_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x99:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F99_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F99_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9A:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9A_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9A_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9B:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9B_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9B_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9C:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9C_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9C_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9D:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9D_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9D_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9E:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9E_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9E_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0x9F:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0F9F_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0F9F_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xA0:
+ {
+ instr32_0FA0();
+ }
+ break;
+ case 0xA1:
+ {
+ instr32_0FA1();
+ }
+ break;
+ case 0xA2:
+ {
+ instr_0FA2();
+ }
+ break;
+ case 0xA3:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FA3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FA3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xA4:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FA4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr32_0FA4_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ break;
+ case 0xA5:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FA5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FA5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xA6:
+ {
+ instr_0FA6();
+ }
+ break;
+ case 0xA7:
+ {
+ instr_0FA7();
+ }
+ break;
+ case 0xA8:
+ {
+ instr32_0FA8();
+ }
+ break;
+ case 0xA9:
+ {
+ instr32_0FA9();
+ }
+ break;
+ case 0xAA:
+ {
+ instr_0FAA();
+ }
+ break;
+ case 0xAB:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FAB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FAB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xAC:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FAC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr32_0FAC_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ break;
+ case 0xAD:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FAD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FAD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xAE:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 0:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_0_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_0_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 2:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_2_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_2_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 3:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_3_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_3_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_4_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_4_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_5_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_5_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FAE_7_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FAE_7_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xAF:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FAF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FAF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB0:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FB0_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FB0_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB1:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FB1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FB1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB2:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FB2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FB2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB3:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FB3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FB3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB4:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FB4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FB4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB5:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FB5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FB5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB6:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FB6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FB6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB7:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FB7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FB7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xB8:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_F30FB8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_F30FB8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FB8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FB8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xB9:
+ {
+ instr_0FB9();
+ }
+ break;
+ case 0xBA:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 4:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FBA_4_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_0FBA_4_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 5:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FBA_5_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_0FBA_5_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FBA_6_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_0FBA_6_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ case 7:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FBA_7_mem(modrm_resolve(modrm_byte), read_imm8());
+ }
+ else
+ {
+ instr32_0FBA_7_reg(modrm_byte & 7, read_imm8());
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xBB:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FBB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FBB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xBC:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FBC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FBC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xBD:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FBD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FBD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xBE:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FBE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FBE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xBF:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FBF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FBF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC0:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC0_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FC0_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC1:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr32_0FC1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr32_0FC1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC2:
+ {
+ instr_0FC2();
+ }
+ break;
+ case 0xC3:
+ {
+ int32_t modrm_byte = read_imm8();
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FC3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ break;
+ case 0xC4:
+ {
+ instr_0FC4();
+ }
+ break;
+ case 0xC5:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FC5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_660FC5_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7, read_imm8());
+ }
+ else
+ {
+ instr_0FC5_reg(modrm_byte & 7, modrm_byte >> 3 & 7, read_imm8());
+ }
+ }
+ }
+ break;
+ case 0xC6:
+ {
+ instr_0FC6();
+ }
+ break;
+ case 0xC7:
+ {
+ int32_t modrm_byte = read_imm8();
+ switch(modrm_byte >> 3 & 7)
+ {
+ case 1:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC7_1_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FC7_1_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ case 6:
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FC7_6_mem(modrm_resolve(modrm_byte));
+ }
+ else
+ {
+ instr_0FC7_6_reg(modrm_byte & 7);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ trigger_ud();
+ }
+ }
+ break;
+ case 0xC8:
+ {
+ instr_0FC8();
+ }
+ break;
+ case 0xC9:
+ {
+ instr_0FC9();
+ }
+ break;
+ case 0xCA:
+ {
+ instr_0FCA();
+ }
+ break;
+ case 0xCB:
+ {
+ instr_0FCB();
+ }
+ break;
+ case 0xCC:
+ {
+ instr_0FCC();
+ }
+ break;
+ case 0xCD:
+ {
+ instr_0FCD();
+ }
+ break;
+ case 0xCE:
+ {
+ instr_0FCE();
+ }
+ break;
+ case 0xCF:
+ {
+ instr_0FCF();
+ }
+ break;
+ case 0xD0:
+ {
+ instr_0FD0();
+ }
+ break;
+ case 0xD1:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD2:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD3:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD4:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD5:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD6:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20FD6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F20FD6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30FD6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30FD6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD7:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD8:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xD9:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FD9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FD9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FD9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FD9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDA:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDB:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDC:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDD:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDE:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xDF:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FDF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FDF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FDF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FDF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE0:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE0_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE0_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE0_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE0_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE1:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE2:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE3:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE4:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE5:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE6:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F2)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F20FE6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F20FE6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else if(prefixes_ & PREFIX_F3)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_F30FE6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_F30FE6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE7:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE8:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xE9:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FE9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FE9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FE9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FE9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEA:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEB:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEC:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xED:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FED_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FED_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FED_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FED_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEE:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xEF:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FEF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FEF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FEF_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FEF_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF0:
+ {
+ instr_0FF0();
+ }
+ break;
+ case 0xF1:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF1_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF1_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF2:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF2_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF2_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF3:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF3_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF3_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF4:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF4_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF4_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF5:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF5_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF5_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF6:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF6_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF6_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF7:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF7_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF7_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF8:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF8_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF8_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xF9:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FF9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FF9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FF9_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FF9_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFA:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFA_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFA_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFB:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFB_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFB_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFC:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFC_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFC_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFD:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFD_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFD_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFE:
+ {
+ int32_t modrm_byte = read_imm8();
+ int32_t prefixes_ = *prefixes;
+ if(prefixes_ & PREFIX_66)
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_660FFE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_660FFE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ else
+ {
+ if(modrm_byte < 0xC0)
+ {
+ instr_0FFE_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7);
+ }
+ else
+ {
+ instr_0FFE_reg(modrm_byte & 7, modrm_byte >> 3 & 7);
+ }
+ }
+ }
+ break;
+ case 0xFF:
+ {
+ instr_0FFF();
+ }
+ break;
+ default:
+ assert(false);
}
+}
+
+#pragma clang diagnostic pop
diff --git a/src/native/log.c b/src/native/log.c
index 24a673bb..8fd91bc6 100644
--- a/src/native/log.c
+++ b/src/native/log.c
@@ -7,7 +7,10 @@
#include "const.h"
#include "global_pointers.h"
+void logop(int32_t, int32_t);
+
+void dbg_trace(void);
#define dbg_log(...) { if(DEBUG) { printf(__VA_ARGS__); } }
-#define dbg_assert(condition) { if(DEBUG) { assert(condition); } }
+#define dbg_assert(condition) { if(DEBUG) { if(!(condition)) dbg_log(#condition); assert(condition); } }
#define dbg_assert_message(condition, message) { if(DEBUG && !(condition)) { dbg_log(message); assert(false); } }
diff --git a/src/native/memory.c b/src/native/memory.c
index 353792ad..5b6674af 100644
--- a/src/native/memory.c
+++ b/src/native/memory.c
@@ -1,4 +1,8 @@
#include
+#include
+#include
+#include "const.h"
+#include "global_pointers.h"
bool in_mapped_range(uint32_t addr)
{
@@ -8,9 +12,56 @@ bool in_mapped_range(uint32_t addr)
int32_t mmap_read8(uint32_t);
int32_t mmap_read16(uint32_t);
int32_t mmap_read32(uint32_t);
-void mmap_write8(uint32_t, uint8_t);
-void mmap_write16(uint32_t, uint16_t);
-void mmap_write32(uint32_t, uint32_t);
+void mmap_write8(uint32_t, int32_t);
+void mmap_write16(uint32_t, int32_t);
+void mmap_write32(uint32_t, int32_t);
+
+/*
+ * There are 3 primary ways a cached basic block will be dirtied:
+ * 1. A write dirties basic block A independently (A is clean and
+ * write came from outside A)
+ * 2. A write from within basic block A dirties itself
+ * 3. A run_instruction during compilation dirties itself
+
+ * #3 won't happen with generate_instruction so we don't
+ * account for it
+ */
+void jit_dirty_cache(uint32_t start_addr, uint32_t end_addr)
+{
+#if ENABLE_JIT
+ assert(start_addr <= end_addr);
+ for(uint32_t i = start_addr; i < end_addr; i++)
+ {
+ uint32_t idx = i >> DIRTY_ARR_SHIFT;
+ // XXX: Overflow _can_ cause a stale cache (with
+ // group_status=0) to be mistakenly run, but the odds are low
+ // since it depends on a compiled block never being
+ // re-compiled or evicted for 2^32 times that
+ // another block in its group is dirtied
+ group_dirtiness[idx]++;
+
+ // We currently limit basic blocks to a length of
+ // MAX_BLOCK_LENGTH, which may still cause an overlap of 1
+ // page. The ongoing write may write to a block with a
+ // starting address lower than the start_addr of the write,
+ // i.e. in the previous page.
+ // XXX: Consider not generating blocks across boundaries
+
+ if(idx != 0)
+ {
+ group_dirtiness[idx - 1]++;
+ }
+ }
+#endif
+}
+
+void jit_empty_cache()
+{
+ for(uint32_t i = 0; i < CACHE_LEN; i++)
+ {
+ group_dirtiness[i]++;
+ }
+}
int32_t read8(uint32_t addr)
{
@@ -40,7 +91,7 @@ int32_t read16(uint32_t addr)
}
}
-uint16_t read_aligned16(uint32_t addr)
+int32_t read_aligned16(uint32_t addr)
{
dbg_assert(addr >= 0 && addr < 0x80000000);
if(USE_A20 && !*a20_enabled) addr &= A20_MASK16;
@@ -69,6 +120,20 @@ int32_t read32s(uint32_t addr)
}
}
+int64_t read64s(uint32_t addr)
+{
+ if(USE_A20 && *a20_enabled) addr &= A20_MASK;
+
+ if(in_mapped_range(addr))
+ {
+ return (int64_t)mmap_read32(addr) | (int64_t)mmap_read32(addr + 4) << 32;
+ }
+ else
+ {
+ return *(int64_t*)(mem8 + addr);
+ }
+}
+
int32_t read_aligned32(uint32_t addr)
{
if(USE_A20 && !*a20_enabled) addr &= A20_MASK32;
@@ -83,10 +148,12 @@ int32_t read_aligned32(uint32_t addr)
}
}
-void write8(uint32_t addr, uint8_t value)
+void write8(uint32_t addr, int32_t value)
{
if(USE_A20 && !*a20_enabled) addr &= A20_MASK;
+ jit_dirty_cache(addr, addr + 1);
+
if(in_mapped_range(addr))
{
mmap_write8(addr, value);
@@ -97,10 +164,12 @@ void write8(uint32_t addr, uint8_t value)
}
}
-void write16(uint32_t addr, uint16_t value)
+void write16(uint32_t addr, int32_t value)
{
if(USE_A20 && !*a20_enabled) addr &= A20_MASK;
+ jit_dirty_cache(addr, addr + 2);
+
if(in_mapped_range(addr))
{
mmap_write16(addr, value);
@@ -116,9 +185,12 @@ void write_aligned16(uint32_t addr, uint32_t value)
dbg_assert(addr >= 0 && addr < 0x80000000);
if(USE_A20 && !*a20_enabled) addr &= A20_MASK16;
- if(in_mapped_range(addr << 1))
+ uint32_t phys_addr = addr << 1;
+ jit_dirty_cache(phys_addr, phys_addr + 2);
+
+ if(in_mapped_range(phys_addr))
{
- mmap_write16(addr << 1, value);
+ mmap_write16(phys_addr, value);
}
else
{
@@ -130,6 +202,8 @@ void write32(uint32_t addr, int32_t value)
{
if(USE_A20 && !*a20_enabled) addr &= A20_MASK;
+ jit_dirty_cache(addr, addr + 4);
+
if(in_mapped_range(addr))
{
mmap_write32(addr, value);
@@ -144,9 +218,12 @@ void write_aligned32(int32_t addr, int32_t value)
{
if(USE_A20 && !*a20_enabled) addr &= A20_MASK32;
- if(in_mapped_range(addr << 2))
+ uint32_t phys_addr = addr << 2;
+ jit_dirty_cache(phys_addr, phys_addr + 4);
+
+ if(in_mapped_range(phys_addr))
{
- mmap_write32(addr << 2, value);
+ mmap_write32(phys_addr, value);
}
else
{
@@ -154,3 +231,17 @@ void write_aligned32(int32_t addr, int32_t value)
}
}
+void write64(uint32_t addr, int64_t value)
+{
+ if(USE_A20 && !*a20_enabled) addr &= A20_MASK;
+
+ if(in_mapped_range(addr))
+ {
+ mmap_write32(addr + 0, value & 0xFFFFFFFF);
+ mmap_write32(addr + 4, value >> 32);
+ }
+ else
+ {
+ *(int64_t*)(mem8 + addr) = value;
+ }
+}
diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c
index aa6f24b6..b9a93cea 100644
--- a/src/native/misc_instr.c
+++ b/src/native/misc_instr.c
@@ -15,6 +15,13 @@ void branch_not_taken();
void writable_or_pagefault(int32_t, int32_t);
+static void write_reg8(int32_t index, int32_t value);
+static int32_t read_reg16(int32_t index);
+static void write_reg16(int32_t index, int32_t value);
+static int32_t read_reg32(int32_t index);
+static void write_reg32(int32_t index, int32_t value);
+
+
int32_t getcf()
{
if(*flags_changed & 1)
@@ -106,9 +113,8 @@ void jmp_rel16(int32_t rel16)
branch_taken();
}
-void jmpcc8(bool condition)
+void jmpcc8(bool condition, int32_t imm8)
{
- int32_t imm8 = read_imm8s();
if(condition)
{
*instruction_pointer += imm8;
@@ -120,10 +126,8 @@ void jmpcc8(bool condition)
}
}
-void jmpcc16(bool condition)
+void jmpcc16(bool condition, int32_t imm16)
{
- int32_t imm16 = read_imm16();
-
if(condition)
{
jmp_rel16(imm16);
@@ -135,13 +139,11 @@ void jmpcc16(bool condition)
}
}
-void jmpcc32(bool condition)
+void jmpcc32(bool condition, int32_t imm32)
{
- int32_t op = read_imm32s();
-
if(condition)
{
- *instruction_pointer += op;
+ *instruction_pointer += imm32;
branch_taken();
}
else
@@ -150,21 +152,19 @@ void jmpcc32(bool condition)
}
}
-static void cmovcc16(bool condition)
+static void cmovcc16(bool condition, int32_t value, int32_t r)
{
- int32_t data = read_e16();
if(condition)
{
- write_g16(data);
+ write_reg16(r, value);
}
}
-static void cmovcc32(bool condition)
+static void cmovcc32(bool condition, int32_t value, int32_t r)
{
- int32_t data = read_e32s();
if(condition)
{
- write_g32(data);
+ write_reg32(r, value);
}
}
@@ -285,8 +285,12 @@ void pusha32()
push32(reg32s[EDI]);
}
-void setcc(bool condition) {
- set_e8(condition);
+void setcc_reg(bool condition, int32_t r) {
+ write_reg8(r, condition ? 1 : 0);
+}
+
+void setcc_mem(bool condition, int32_t addr) {
+ safe_write8(addr, condition ? 1 : 0);
}
int32_t fpu_load_status_word();
@@ -320,10 +324,10 @@ void fxsave(uint32_t addr)
// implementation dependent.
for(int32_t i = 0; i < 8; i++)
{
- safe_write32(addr + 160 + (i << 4) + 0, reg_xmm32s[i << 2 | 0]);
- safe_write32(addr + 160 + (i << 4) + 4, reg_xmm32s[i << 2 | 1]);
- safe_write32(addr + 160 + (i << 4) + 8, reg_xmm32s[i << 2 | 2]);
- safe_write32(addr + 160 + (i << 4) + 12, reg_xmm32s[i << 2 | 3]);
+ safe_write32(addr + 160 + (i << 4) + 0, reg_xmm[i].u32[0]);
+ safe_write32(addr + 160 + (i << 4) + 4, reg_xmm[i].u32[1]);
+ safe_write32(addr + 160 + (i << 4) + 8, reg_xmm[i].u32[2]);
+ safe_write32(addr + 160 + (i << 4) + 12, reg_xmm[i].u32[3]);
}
}
@@ -336,7 +340,7 @@ void fxrstor(uint32_t addr)
if(new_mxcsr & ~MXCSR_MASK)
{
- //dbg_log("Invalid mxcsr bits: " + h((new_mxcsr & ~MXCSR_MASK) >>> 0, 8));
+ dbg_log("#gp Invalid mxcsr bits");
trigger_gp(0);
}
@@ -358,10 +362,44 @@ void fxrstor(uint32_t addr)
for(int32_t i = 0; i < 8; i++)
{
- reg_xmm32s[i << 2 | 0] = safe_read32s(addr + 160 + (i << 4) + 0);
- reg_xmm32s[i << 2 | 1] = safe_read32s(addr + 160 + (i << 4) + 4);
- reg_xmm32s[i << 2 | 2] = safe_read32s(addr + 160 + (i << 4) + 8);
- reg_xmm32s[i << 2 | 3] = safe_read32s(addr + 160 + (i << 4) + 12);
+ reg_xmm[i].u32[0] = safe_read32s(addr + 160 + (i << 4) + 0);
+ reg_xmm[i].u32[1] = safe_read32s(addr + 160 + (i << 4) + 4);
+ reg_xmm[i].u32[2] = safe_read32s(addr + 160 + (i << 4) + 8);
+ reg_xmm[i].u32[3] = safe_read32s(addr + 160 + (i << 4) + 12);
}
}
+int32_t xchg8(int32_t data, int32_t r8)
+{
+ int32_t tmp = reg8[r8];
+ reg8[r8] = data;
+ return tmp;
+}
+
+int32_t xchg16(int32_t data, int32_t r16)
+{
+ int32_t tmp = reg16[r16];
+ reg16[r16] = data;
+ return tmp;
+}
+
+void xchg16r(int32_t r16)
+{
+ int32_t tmp = reg16[AX];
+ reg16[AX] = reg16[r16];
+ reg16[r16] = tmp;
+}
+
+int32_t xchg32(int32_t data, int32_t r32)
+{
+ int32_t tmp = reg32s[r32];
+ reg32s[r32] = data;
+ return tmp;
+}
+
+void xchg32r(int32_t r32)
+{
+ int32_t tmp = reg32s[EAX];
+ reg32s[EAX] = reg32s[r32];
+ reg32s[r32] = tmp;
+}
diff --git a/src/native/modrm.c b/src/native/modrm.c
index 2f5d6090..17272dc7 100644
--- a/src/native/modrm.c
+++ b/src/native/modrm.c
@@ -31,7 +31,9 @@ static int32_t resolve_sib(bool);
MODRM_ENTRY(0x40 | row, seg(((value) + read_imm8s() & 0xFFFF)))\
MODRM_ENTRY(0x80 | row, seg(((value) + read_imm16() & 0xFFFF)))\
+extern int32_t resolve_modrm16(int32_t modrm_byte);
+/*
static int32_t resolve_modrm16(int32_t modrm_byte)
{
switch(modrm_byte)
@@ -56,6 +58,7 @@ static int32_t resolve_modrm16(int32_t modrm_byte)
return 0;
}
+//*/
#undef MODRM_ENTRY16
@@ -64,6 +67,9 @@ static int32_t resolve_modrm16(int32_t modrm_byte)
MODRM_ENTRY(0x40 | row, seg((value) + read_imm8s()))\
MODRM_ENTRY(0x80 | row, seg((value) + read_imm32s()))\
+extern int32_t resolve_modrm32(int32_t modrm_byte);
+
+/*
static int32_t resolve_modrm32(int32_t modrm_byte)
{
switch(modrm_byte)
@@ -90,6 +96,7 @@ static int32_t resolve_modrm32(int32_t modrm_byte)
return 0;
}
+//*/
#undef MODRM_ENTRY32
#undef MODRM_ENTRY
diff --git a/src/native/profiler/profiler.c b/src/native/profiler/profiler.c
new file mode 100644
index 00000000..aceb1168
--- /dev/null
+++ b/src/native/profiler/profiler.c
@@ -0,0 +1,67 @@
+#include
+#include
+#include "profiler.h"
+
+#if ENABLE_PROFILER
+
+double profiler_init_time = 0;
+
+void profiler_init()
+{
+ profiler_init_time = get_time();
+ for(uint32_t i = 0; i < PROFILER_NAME_COUNT; i++)
+ {
+ struct profiler_data *entry = &profiler_arr[i];
+ entry->total = 0;
+ entry->current_start = 0;
+ entry->capturing = false;
+ }
+}
+
+void profiler_start(enum profile_name name)
+{
+ struct profiler_data *entry = &profiler_arr[name];
+ assert(!entry->capturing);
+
+ entry->current_start = get_time();
+ entry->capturing = true;
+}
+
+void profiler_end(enum profile_name name)
+{
+ struct profiler_data *entry = &profiler_arr[name];
+ if(entry->capturing)
+ {
+ entry->total += get_time() - entry->current_start;
+ entry->current_start = 0;
+ entry->capturing = false;
+ }
+}
+
+void profiler_print()
+{
+ double init_elapsed = get_time() - profiler_init_time;
+ printf("Elapsed: %d\n", (int32_t) init_elapsed);
+ for(uint32_t i = 0; i < PROFILER_NAME_COUNT; i++)
+ {
+ double cur_total = profiler_arr[i].total;
+ printf(
+ "\nIndex:\t%d"
+ "\nTotal:\t%d"
+ "\nPercentage:\t%d%%\n",
+ i,
+ (int32_t) cur_total,
+ (int32_t) (100 * cur_total / init_elapsed)
+ );
+ }
+}
+
+#else
+// Disable profiler
+
+void profiler_init() {}
+void profiler_start(enum profile_name name) {}
+void profiler_end(enum profile_name name) {}
+void profiler_print() {}
+
+#endif
diff --git a/src/native/profiler/profiler.h b/src/native/profiler/profiler.h
new file mode 100644
index 00000000..7132852c
--- /dev/null
+++ b/src/native/profiler/profiler.h
@@ -0,0 +1,29 @@
+#include
+#ifndef _PROFILER_H
+#define _PROFILER_H
+
+struct profiler_data {
+ double total;
+ double current_start;
+ bool capturing;
+} profiler_arr[4] = {{0, 0, false}};
+
+enum profile_name {
+ P_IDLE,
+ P_GEN_INSTR,
+ P_DO_MANY_CYCLES,
+ P_RUN_FROM_CACHE
+};
+
+#define PROFILER_NAME_COUNT 4
+
+
+void profiler_init();
+void profiler_start(enum profile_name name);
+void profiler_end(enum profile_name name);
+void profiler_print();
+
+// JS import
+double get_time();
+
+#endif
diff --git a/src/native/shared.h b/src/native/shared.h
new file mode 100644
index 00000000..41426dc7
--- /dev/null
+++ b/src/native/shared.h
@@ -0,0 +1,49 @@
+#ifndef _SHARED_H
+#define _SHARED_H
+
+#include
+#include "const.h"
+
+union reg128 {
+ uint8_t u8[16];
+ uint16_t u16[8];
+ uint32_t u32[4];
+ uint64_t u64[2];
+};
+typedef char assert_size_reg128[(sizeof(union reg128) == 16) * 2 - 1];
+
+union reg64 {
+ int8_t i8[8];
+ int16_t i16[4];
+ int32_t i32[2];
+ uint8_t u8[8];
+ uint16_t u16[4];
+ uint32_t u32[2];
+ uint64_t u64[1];
+ double f64[1];
+};
+typedef char assertion_size_reg64[(sizeof(union reg64) == 8) * 2 - 1];
+
+struct code_cache {
+ // Address of the start of the basic block
+ uint32_t start_addr;
+ // Address of the instruction immediately after the basic block ends
+ uint32_t end_addr;
+ int32_t opcode[100];
+ int32_t len;
+ // Cleanliness status of the entry's "group" (based on
+ // DIRTY_ARR_SHIFT). Value only has meaning in relation with the
+ // group_dirtiness value.
+ uint32_t group_status;
+} jit_cache_arr[CACHE_LEN] = {{0, 0, {0}, 0, 0}};
+
+// Flag indicating whether the instruction that just ran was a jump of some sort
+uint32_t jit_jump = 0;
+
+// Count of how many times prime_hash(address) has been called through a jump
+int32_t hot_code_addresses[HASH_PRIME] = {0};
+// An array indicating the current "initial group status" for entries that map
+// to the same group due to the shift
+uint32_t group_dirtiness[1 + (0xffffffff >> DIRTY_ARR_SHIFT)] = {0};
+
+#endif
diff --git a/src/native/string.c b/src/native/string.c
index 550c89ee..21b8ea86 100644
--- a/src/native/string.c
+++ b/src/native/string.c
@@ -1,3 +1,5 @@
+#include
+
#define MAX_COUNT_PER_CYCLE 0x1000
#define MIN(x, y) (x < y ? x : y)
@@ -29,7 +31,8 @@ void movsb_rep()
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -1 : 1;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -48,7 +51,7 @@ void movsb_rep()
cont = --count != 0;
}
while(cont && cycle_counter--);
- int32_t diff = size * (start_count - count) | 0;
+ int32_t diff = size * (start_count - count);
add_reg_asize(EDI, diff);
add_reg_asize(ESI, diff);
set_ecx_asize(count);
@@ -57,7 +60,6 @@ void movsb_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void movsb_no_rep()
@@ -90,7 +92,8 @@ void movsw_rep()
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -2 : 2;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -112,7 +115,7 @@ void movsw_rep()
cont = --count != 0;
}
while(cont && cycle_counter--);
- int32_t diff = size * (start_count - count) | 0;
+ int32_t diff = size * (start_count - count);
add_reg_asize(EDI, diff);
add_reg_asize(ESI, diff);
set_ecx_asize(count);
@@ -135,7 +138,6 @@ void movsw_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void movsw_no_rep()
@@ -168,7 +170,8 @@ void movsd_rep()
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -4 : 4;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -190,7 +193,7 @@ void movsd_rep()
cont = --count != 0;
}
while(cont && cycle_counter--);
- int32_t diff = size * (start_count - count) | 0;
+ int32_t diff = size * (start_count - count);
add_reg_asize(EDI, diff);
add_reg_asize(ESI, diff);
set_ecx_asize(count);
@@ -213,7 +216,6 @@ void movsd_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void movsd_no_rep()
@@ -247,7 +249,8 @@ void cmpsb_rep()
int32_t data_src, data_dest;
int32_t size = *flags & FLAG_DIRECTION ? -1 : 1;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -279,7 +282,6 @@ void cmpsb_rep()
}
cmp8(data_src, data_dest);
- diverged();
}
void cmpsb_no_rep()
@@ -317,7 +319,8 @@ void cmpsw_rep()
int32_t data_src, data_dest;
int32_t size = *flags & FLAG_DIRECTION ? -2 : 2;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -341,7 +344,7 @@ void cmpsw_rep()
cont = --count != 0 && (data_src == data_dest) == is_repz;
}
while(cont && cycle_counter--);
- int32_t diff = size * (start_count - count) | 0;
+ int32_t diff = size * (start_count - count);
add_reg_asize(EDI, diff);
add_reg_asize(ESI, diff);
set_ecx_asize(count);
@@ -367,7 +370,6 @@ void cmpsw_rep()
}
cmp16(data_src, data_dest);
- diverged();
}
void cmpsw_no_rep()
@@ -405,7 +407,8 @@ void cmpsd_rep()
int32_t data_src, data_dest;
int32_t size = *flags & FLAG_DIRECTION ? -4 : 4;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -429,7 +432,7 @@ void cmpsd_rep()
cont = --count != 0 && (data_src == data_dest) == is_repz;
}
while(cont && cycle_counter--);
- int32_t diff = size * (start_count - count) | 0;
+ int32_t diff = size * (start_count - count);
add_reg_asize(EDI, diff);
add_reg_asize(ESI, diff);
set_ecx_asize(count);
@@ -455,7 +458,6 @@ void cmpsd_rep()
}
cmp32(data_src, data_dest);
- diverged();
}
void cmpsd_no_rep()
@@ -492,7 +494,8 @@ void stosb_rep()
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -1 : 1;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -517,7 +520,6 @@ void stosb_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void stosb_no_rep()
@@ -549,7 +551,8 @@ void stosw_rep()
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -2 : 2;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -589,7 +592,6 @@ void stosw_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void stosw_no_rep()
@@ -621,7 +623,8 @@ void stosd_rep()
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -4 : 4;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -661,7 +664,6 @@ void stosd_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void stosd_no_rep()
@@ -691,7 +693,8 @@ void lodsb_rep()
{
int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI);
int32_t size = *flags & FLAG_DIRECTION ? -1 : 1;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -716,7 +719,6 @@ void lodsb_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void lodsb_no_rep()
@@ -746,7 +748,8 @@ void lodsw_rep()
int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI);
int32_t size = *flags & FLAG_DIRECTION ? -2 : 2;
- uint32_t count = ((uint32_t) get_reg_asize(ECX)) >> 0;
+ uint32_t count = ((uint32_t) get_reg_asize(ECX));
+ diverged();
if(count == 0) return;
bool cont = false;
uint32_t cycle_counter = MAX_COUNT_PER_CYCLE;
@@ -762,7 +765,6 @@ void lodsw_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void lodsw_no_rep()
@@ -793,7 +795,8 @@ void lodsd_rep()
int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI);
int32_t size = *flags & FLAG_DIRECTION ? -4 : 4;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t cycle_counter = MAX_COUNT_PER_CYCLE;
@@ -809,7 +812,6 @@ void lodsd_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void lodsd_no_rep()
@@ -841,7 +843,8 @@ void scasb_rep()
int32_t data_dest;
int32_t data_src = reg8[AL];
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -868,7 +871,6 @@ void scasb_rep()
*instruction_pointer = *previous_ip;
}
cmp8(data_src, data_dest);
- diverged();
}
void scasb_no_rep()
@@ -903,7 +905,8 @@ void scasw_rep()
int32_t data_dest;
int32_t data_src = reg16[AL];
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -945,7 +948,6 @@ void scasw_rep()
*instruction_pointer = *previous_ip;
}
cmp16(data_src, data_dest);
- diverged();
}
void scasw_no_rep()
@@ -980,7 +982,8 @@ void scasd_rep()
int32_t data_dest;
int32_t data_src = reg32s[EAX];
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -1022,7 +1025,6 @@ void scasd_rep()
*instruction_pointer = *previous_ip;
}
cmp32(data_src, data_dest);
- diverged();
}
void scasd_no_rep()
@@ -1059,7 +1061,8 @@ void insb_rep()
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -1 : 1;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -1084,7 +1087,6 @@ void insb_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void insb_no_rep()
@@ -1121,7 +1123,8 @@ void insw_rep()
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -2 : 2;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -1161,7 +1164,6 @@ void insw_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void insw_no_rep()
@@ -1198,7 +1200,8 @@ void insd_rep()
int32_t dest = get_seg(ES) + get_reg_asize(EDI);
int32_t size = *flags & FLAG_DIRECTION ? -4 : 4;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -1238,7 +1241,6 @@ void insd_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void insd_no_rep()
@@ -1275,7 +1277,8 @@ void outsb_rep()
int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI);
int32_t size = *flags & FLAG_DIRECTION ? -1 : 1;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -1300,7 +1303,6 @@ void outsb_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void outsb_no_rep()
@@ -1336,7 +1338,8 @@ void outsw_rep()
int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI);
int32_t size = *flags & FLAG_DIRECTION ? -2 : 2;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -1376,7 +1379,6 @@ void outsw_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void outsw_no_rep()
@@ -1412,7 +1414,8 @@ void outsd_rep()
int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI);
int32_t size = *flags & FLAG_DIRECTION ? -4 : 4;
- int32_t count = get_reg_asize(ECX) >> 0;
+ int32_t count = get_reg_asize(ECX);
+ diverged();
if(count == 0) return;
int32_t cont = false;
int32_t start_count = count;
@@ -1452,7 +1455,6 @@ void outsd_rep()
{
*instruction_pointer = *previous_ip;
}
- diverged();
}
void outsd_no_rep()
@@ -1479,4 +1481,3 @@ void outsd()
outsd_no_rep();
}
}
-
diff --git a/src/ps2.js b/src/ps2.js
index f3dad0d4..e00f54ef 100644
--- a/src/ps2.js
+++ b/src/ps2.js
@@ -1,5 +1,8 @@
"use strict";
+/** @const */
+let PS2_LOG_VERBOSE = false;
+
/**
* @constructor
* @param {CPU} cpu
@@ -270,7 +273,10 @@ PS2.prototype.send_mouse_packet = function(dx, dy)
this.mouse_buffer.push(delta_x);
this.mouse_buffer.push(delta_y);
- dbg_log("adding mouse packets: " + [info_byte, dx, dy], LOG_PS2);
+ if(PS2_LOG_VERBOSE)
+ {
+ dbg_log("adding mouse packets: " + [info_byte, dx, dy], LOG_PS2);
+ }
this.mouse_irq();
};
@@ -320,7 +326,11 @@ PS2.prototype.port60_read = function()
{
this.cpu.device_lower_irq(12);
this.last_port60_byte = this.mouse_buffer.shift();
- dbg_log("Port 60 read (mouse): " + h(this.last_port60_byte), LOG_PS2);
+
+ if(PS2_LOG_VERBOSE)
+ {
+ dbg_log("Port 60 read (mouse): " + h(this.last_port60_byte), LOG_PS2);
+ }
if(this.mouse_buffer.length >= 1)
{
diff --git a/tests/codegen.js b/tests/codegen.js
new file mode 100644
index 00000000..0c738845
--- /dev/null
+++ b/tests/codegen.js
@@ -0,0 +1,144 @@
+const fs = require('fs');
+const { TextDecoder } = require('util');
+
+//XXX: use a non-hacky method maybe
+const interfaceCode = fs.readFileSync(__dirname + '/../src/codegen.js', 'utf8');
+eval(interfaceCode);
+
+console.assert(typeof Codegen === "function");
+
+const codegenModuleBuffer = fs.readFileSync(__dirname + '/../build/codegen-test.wasm');
+
+const dec = new TextDecoder('utf-8');
+
+const vals = {
+ imm8: 1,
+ imm8s: 1,
+ imm16: 2,
+ imm32s: 3,
+ asize_32: false,
+ reg16: 0,
+ reg32s: 0,
+ instruction_pointer: 0,
+ previous_ip: 0,
+};
+
+load_wasm(codegenModuleBuffer, {
+ env: {
+ _read_imm8() { return vals.imm8; },
+ _read_imm8s() { return vals.imm8s; },
+ _read_imm16() { return vals.imm16; },
+ _read_imm32s() { return vals.imm32s; },
+ _is_asize_32() { return vals.asize_32; },
+
+ // static pointer imports
+ g$_reg16() { return vals.reg16; },
+ g$_reg32s() { return vals.reg32s; },
+ g$_instruction_pointer() { return vals.instruction_pointer; },
+ g$_previous_ip() { return vals.previous_ip; },
+ }
+ })
+ .then(function(wm) {
+ return new Codegen(wm);
+ })
+ .then(test);
+
+function test(gen)
+{
+ gen.reset();
+ gen.finish();
+
+ let buf = gen.get_module_code();
+
+ gen.reset();
+ gen.fn0('fn0');
+ gen.fn1('fn1', 0);
+ gen.fn2('fn2', 0, 1);
+ gen.increment_instruction_pointer(10);
+ gen.set_previous_eip();
+ gen.finish();
+
+ buf = gen.get_module_code();
+ fs.writeFileSync(__dirname + '/../build/myjit.wasm', buf);
+
+ const module = new WebAssembly.Module(buf);
+
+ const expected = [
+ ['fn0'],
+ ['fn1', 0],
+ ['fn2', 0, 1],
+ ];
+
+ const store = [];
+
+ const imports = {
+ e: {
+ fn0() { store.push(['fn0']); },
+ fn1(arg0) { store.push(['fn1', arg0]); },
+ fn2(arg0, arg1) { store.push(['fn2', arg0, arg1]); },
+ get_seg_prefix_ds() {},
+ get_seg_prefix_ss() {},
+ get_seg_prefix() {},
+ m: new WebAssembly.Memory({ initial: 256 * 1024 * 1024 / 64 / 1024 }),
+ },
+ };
+ const o = new WebAssembly.Instance(module, imports);
+ o.exports.f();
+ const view = new Uint32Array(imports.e.m.buffer);
+ console.assert(view[vals.instruction_pointer] === 10);
+ console.assert(view[vals.previous_ip] === 10);
+ if (JSON.stringify(store) === JSON.stringify(expected))
+ {
+ console.log('Test passed');
+ }
+ else
+ {
+ console.error('Test failed');
+ console.log('Expected:', expected);
+ console.log('Got:', store);
+ }
+}
+
+function load_wasm(buffer, imports, cb)
+{
+ if (!imports) {
+ imports = {};
+ }
+
+ // XXX: These should not be fixed in M
+ const STATIC_MEMORY_BASE = 256 - 32;
+ const WASM_MEMORY_SIZE = 256;
+
+ return WebAssembly.compile(buffer)
+ .then(module => {
+ if (!imports['env']) {
+ imports['env'] = {};
+ }
+ imports['env']['___assert_fail'] = (a, b, c, d) => {
+ console.error('Assertion Failed', a, b, c, d);
+ dbg_assert(false);
+ };
+ imports['env']['memoryBase'] = STATIC_MEMORY_BASE * 1024 * 1024;
+ imports['env']['tableBase'] = 0;
+ imports['env']['memory'] = new WebAssembly.Memory({ ['initial']: WASM_MEMORY_SIZE * 1024 * 1024 / 64 / 1024, });
+ imports['env']['table'] = new WebAssembly.Table({ ['initial']: 18, ['element']: 'anyfunc' });
+ return WebAssembly.instantiate(module, imports).then(instance => ({ instance, module }));
+ })
+ .then(({ instance, module }) => {
+ const ret = {
+ mem: imports['env']['memory'],
+ funcs: instance['exports'],
+ instance,
+ imports,
+ };
+ if (typeof cb === "function")
+ {
+ cb(ret);
+ }
+ else
+ {
+ return ret;
+ }
+ });
+}
+
diff --git a/tests/full/run.js b/tests/full/run.js
index e404228a..eba9a64d 100755
--- a/tests/full/run.js
+++ b/tests/full/run.js
@@ -283,6 +283,7 @@ function run_test(test, done)
bios: { url: bios },
vga_bios: { url: vga_bios },
autostart: true,
+ memory_size: 128 * 1024 * 1024,
};
if(test.cdrom)
@@ -295,7 +296,7 @@ function run_test(test, done)
}
if(test.hda)
{
- settings.hda = { url: test.hda };
+ settings.hda = { url: test.hda, async: true, };
}
if(test.expected_texts)
@@ -431,10 +432,19 @@ function run_test(test, done)
if(on_text.length)
{
let expected = on_text[0].text;
+
if(x < expected.length && bytearray_starts_with(line, expected))
{
var action = on_text.shift();
- emulator.keyboard_send_text(action.run);
+
+ if(action.after)
+ {
+ setTimeout(() => emulator.keyboard_send_text(action.run), action.after);
+ }
+ else
+ {
+ emulator.keyboard_send_text(action.run);
+ }
}
}
});
@@ -443,7 +453,7 @@ function run_test(test, done)
{
if(action.on_text)
{
- on_text.push({ text: string_to_bytearray(action.on_text), run: action.run, });
+ on_text.push({ text: string_to_bytearray(action.on_text), run: action.run, after: action.after, });
}
});
}
diff --git a/tests/jit-paging/Makefile b/tests/jit-paging/Makefile
new file mode 100644
index 00000000..b4a47c54
--- /dev/null
+++ b/tests/jit-paging/Makefile
@@ -0,0 +1,11 @@
+CC=gcc
+CC_I386=$(CC) -m32
+CFLAGS=-Wall -g -fno-strict-aliasing -fPIC -static
+LDFLAGS=
+
+
+test-jit: test-jit.c
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $( "~")
+ {
+ return;
+ }
+
+ if(chr === "\n")
+ {
+ var new_line = line;
+ console.error("Serial: %s", line);
+ line = "";
+ }
+ else
+ {
+ line += chr;
+ }
+
+ if(!ran_command && line.endsWith("~% "))
+ {
+ ran_command = true;
+ emulator.serial0_send("chmod +x /mnt/test-jit\n");
+ emulator.serial0_send("/mnt/test-jit > /mnt/result\n");
+ emulator.serial0_send("echo test fini''shed\n");
+ }
+
+ if(new_line && new_line.includes("test finished"))
+ {
+ console.error("Done. Reading result ...");
+
+ emulator.read_file("/result", function(err, data)
+ {
+ emulator.stop();
+ if(err) throw err;
+ let result = (new Buffer(data)).toString();
+ if(result !== 'test passed\n')
+ {
+ console.error('[!] Error. Result was:', result);
+ process.exit(1);
+ }
+ else
+ {
+ console.log('[+] Test passed');
+ }
+ });
+ }
+
+});
diff --git a/tests/jit-paging/test-jit.c b/tests/jit-paging/test-jit.c
new file mode 100644
index 00000000..1e98d9fa
--- /dev/null
+++ b/tests/jit-paging/test-jit.c
@@ -0,0 +1,84 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+int fib(int n)
+{
+ int first = 0, second = 1, next = 0, i = 0;
+ while(i <= n)
+ {
+ if(i < 2)
+ {
+ next = i;
+ }
+ else
+ {
+ next = first + second;
+ first = second;
+ second = next;
+ }
+ i++;
+ }
+ return next;
+}
+
+int pass_test()
+{
+ return 0x42;
+}
+
+void fatal(char *msg)
+{
+ fprintf(stderr, "*** FATAL ERROR: %s\n", (msg ? msg : "no message"));
+ fflush(stderr);
+ abort();
+}
+
+int main()
+{
+ static char filename[] = "/tmp/DoubleMapXXXXXX";
+ int fd = mkstemp(filename);
+ if(fd == -1)
+ {
+ fatal("mkstemp");
+ }
+ if(ftruncate(fd, PAGE_SIZE) == -1)
+ {
+ fatal("ftruncate");
+ }
+
+ char *const write_addr = mmap(0, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ char *const exec_addr = mmap(write_addr+PAGE_SIZE, PAGE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED, fd, 0);
+
+ if(write_addr == MAP_FAILED || exec_addr == MAP_FAILED)
+ {
+ fatal("mmap");
+ }
+
+ size_t size = PAGE_SIZE;
+ memcpy(write_addr, fib, size);
+
+ int (*fun_pointer)() = (void*)exec_addr;
+
+ // Give the JIT something to potentially cache
+ for(int i = 0; i < 15000; i++)
+ {
+ if(fun_pointer(20) != 6765)
+ {
+ fatal("fibonacci");
+ }
+ }
+
+ memcpy(write_addr, pass_test, size);
+ if(fun_pointer() == 0x42)
+ {
+ printf("test passed\n");
+ }
+
+ munmap(write_addr, size);
+ return 0;
+}
diff --git a/tests/nasm/Makefile b/tests/nasm/Makefile
index 87577c0b..adc00155 100644
--- a/tests/nasm/Makefile
+++ b/tests/nasm/Makefile
@@ -1,13 +1,14 @@
source_files := $(wildcard build/*.asm)
source_files += $(addprefix build/,$(wildcard *.asm))
+obj_files := $(patsubst %.asm,%.o,$(source_files))
host_executables := $(patsubst %.asm,%.bin,$(source_files))
v86_executables := $(patsubst %.asm,%.img,$(source_files))
host_fixtures := $(patsubst %.asm,%.fixture,$(source_files))
inc_files := $(addprefix build/,$(wildcard *.inc))
-all: $(source_files) $(host_executables) $(v86_executables) $(host_fixtures)
+all: $(source_files) $(obj_files) $(inc_files) $(host_executables) $(v86_executables) $(host_fixtures)
.PHONY: all
build/%.o: build/%.asm $(inc_files)
@@ -31,6 +32,7 @@ build/%.asm: %.asm
build/%.inc: %.inc
mkdir -p build; cp $< $@
+.PHONY: clean
clean:
rm -f *.o *.bin *.img *.fixture gen_*.asm # old location
rm -f build/*.o build/*.bin build/*.img build/*.fixture build/*.asm
diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js
index 3df06f53..a46833cb 100755
--- a/tests/nasm/create_tests.js
+++ b/tests/nasm/create_tests.js
@@ -1,988 +1,73 @@
#!/usr/bin/env node
"use strict";
-// http://ref.x86asm.net/coder32.html
-
// TODO
-// - lea (and all modrm/sib addressing modes)
-// - fix style (single quote, brace position)
// - multiple random tests
-// - 16 bit
-// - describe which registers are written and read
-// - string instructions (initialise ds, esi, es, edi)
const fs = require("fs");
+const encodings = require("../../gen/x86_table.js");
+const Prand = require("./prand.js");
-const zf = 1 << 6;
-const of = 1 << 11;
-const cf = 1 << 0;
-const af = 1 << 4;
-const pf = 1 << 2;
-const sf = 1 << 7;
+generate_tests();
-
-// os: the instruction behaves differently depending on the operand size
-// The following instructions are special and not properly described in this table
-// - C8 enter: Has an extra immediate byte after the described immediate
-// - EA jump / 9A callf: Have an extra immediate word after the described immediate
-
-const encodings = [
- { opcode: 0x06, os: 1, skip: 1, },
- { opcode: 0x07, os: 1, skip: 1, },
- { opcode: 0x0E, os: 1, skip: 1, },
- { opcode: 0x0F, os: 1, prefix: 1, },
- { opcode: 0x16, os: 1, skip: 1, },
- { opcode: 0x17, os: 1, skip: 1, },
- { opcode: 0x1E, os: 1, skip: 1, },
- { opcode: 0x1F, os: 1, skip: 1, },
- { opcode: 0x26, prefix: 1, },
- { opcode: 0x27, mask_flags: of, },
- { opcode: 0x2E, prefix: 1, },
- { opcode: 0x2F, mask_flags: of, },
- { opcode: 0x36, prefix: 1, },
- { opcode: 0x37, mask_flags: of | sf | pf | zf, },
- { opcode: 0x3E, prefix: 1, },
- { opcode: 0x3F, mask_flags: of | sf | pf | zf, },
-
- { opcode: 0x40, os: 1, },
- { opcode: 0x41, os: 1, },
- { opcode: 0x42, os: 1, },
- { opcode: 0x43, os: 1, },
- { opcode: 0x44, os: 1, },
- { opcode: 0x45, os: 1, },
- { opcode: 0x46, os: 1, },
- { opcode: 0x47, os: 1, },
-
- { opcode: 0x48, os: 1, },
- { opcode: 0x49, os: 1, },
- { opcode: 0x4A, os: 1, },
- { opcode: 0x4B, os: 1, },
- { opcode: 0x4C, os: 1, },
- { opcode: 0x4D, os: 1, },
- { opcode: 0x4E, os: 1, },
- { opcode: 0x4F, os: 1, },
-
- { opcode: 0x50, os: 1, },
- { opcode: 0x51, os: 1, },
- { opcode: 0x52, os: 1, },
- { opcode: 0x53, os: 1, },
- { opcode: 0x54, os: 1, },
- { opcode: 0x55, os: 1, },
- { opcode: 0x56, os: 1, },
- { opcode: 0x57, os: 1, },
-
- { opcode: 0x58, os: 1, },
- { opcode: 0x59, os: 1, },
- { opcode: 0x5A, os: 1, },
- { opcode: 0x5B, os: 1, },
- { opcode: 0x5C, os: 1, },
- { opcode: 0x5D, os: 1, },
- { opcode: 0x5E, os: 1, },
- { opcode: 0x5F, os: 1, },
-
- { opcode: 0x60, os: 1, },
- { opcode: 0x61, os: 1, },
- { opcode: 0x62, e: 1, g: 1, skip: 1, },
- { opcode: 0x63, e: 1, g: 1, },
- { opcode: 0x64, prefix: 1, },
- { opcode: 0x65, prefix: 1, },
- { opcode: 0x66, prefix: 1, },
- { opcode: 0x67, prefix: 1, },
-
- { opcode: 0x68, os: 1, imm1632: 1, },
- { opcode: 0x69, os: 1, e: 1, g: 1, imm: 1, mask_flags: af, }, // zf?
- { opcode: 0x6A, os: 1, imm8: 1, },
- { opcode: 0x6B, os: 1, e: 1, g: 1, imm8: 1, mask_flags: af, }, // zf?
-
- { opcode: 0x6C, skip: 1, },
- { opcode: 0x6D, os: 1, skip: 1, },
- { opcode: 0x6E, skip: 1, },
- { opcode: 0x6F, os: 1, skip: 1, },
-
- { opcode: 0x84, e: 1, g: 1, },
- { opcode: 0x85, os: 1, e: 1, g: 1, },
- { opcode: 0x86, e: 1, g: 1, },
- { opcode: 0x87, os: 1, e: 1, g: 1, },
- { opcode: 0x88, e: 1, g: 1, },
- { opcode: 0x89, os: 1, e: 1, g: 1, },
- { opcode: 0x8A, e: 1, g: 1, },
- { opcode: 0x8B, os: 1, e: 1, g: 1, },
-
- { opcode: 0x8C, os: 1, e: 1, g: 1, skip: 1, },
- { opcode: 0x8D, os: 1, e: 1, g: 1, only_mem: 1, }, // lea
- { opcode: 0x8E, e: 1, g: 1, skip: 1, },
- { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, },
-
- { opcode: 0x90, },
- { opcode: 0x91, os: 1, },
- { opcode: 0x92, os: 1, },
- { opcode: 0x93, os: 1, },
- { opcode: 0x94, os: 1, },
- { opcode: 0x95, os: 1, },
- { opcode: 0x96, os: 1, },
- { opcode: 0x97, os: 1, },
-
- { opcode: 0x98, os: 1, },
- { opcode: 0x99, os: 1, },
- { opcode: 0x9A, os: 1, imm1632: 1, skip: 1, },
- { opcode: 0x9B, skip: 1, },
- { opcode: 0x9C, os: 1, },
- { opcode: 0x9D, os: 1, skip: 1, }, // popf
- { opcode: 0x9E, },
- { opcode: 0x9F, },
-
- { opcode: 0xA0, immaddr: 1, },
- { opcode: 0xA1, os: 1, immaddr: 1, },
- { opcode: 0xA2, immaddr: 1, },
- { opcode: 0xA3, os: 1, immaddr: 1, },
-
- { opcode: 0xA4, },
- { opcode: 0xA5, os: 1, },
- { opcode: 0xA6, },
- { opcode: 0xA7, os: 1, },
-
- { opcode: 0xA8, imm: 1, },
- { opcode: 0xA9, os: 1, imm: 1, },
-
- { opcode: 0xAA, },
- { opcode: 0xAB, os: 1, },
- { opcode: 0xAC, },
- { opcode: 0xAD, os: 1, },
- { opcode: 0xAE, },
- { opcode: 0xAF, os: 1, },
-
- { opcode: 0xC2, os: 1, imm16: 1, skip: 1, },
- { opcode: 0xC3, os: 1, skip: 1, },
-
- { opcode: 0xC4, os: 1, e: 1, g: 1, skip: 1, },
- { opcode: 0xC5, os: 1, e: 1, g: 1, skip: 1, },
-
- { opcode: 0xC6, e: 1, fixed_g: 0, imm: 1, },
- { opcode: 0xC7, os: 1, e: 1, fixed_g: 0, imm: 1, },
-
- { opcode: 0xC8, os: 1, imm16: 1, }, // enter
- { opcode: 0xC9, os: 1, skip: 1, }, // leave: requires valid ebp
- { opcode: 0xCA, os: 1, imm16: 1, skip: 1, },
- { opcode: 0xCB, os: 1, skip: 1, },
- { opcode: 0xCC, skip: 1, },
- { opcode: 0xCD, skip: 1, },
- { opcode: 0xCE, skip: 1, },
- { opcode: 0xCF, os: 1, skip: 1, },
-
- { opcode: 0xD4, imm8: 1, }, // aam, may trigger #de
- { opcode: 0xD5, imm8: 1, mask_flags: of | cf | af, },
- { opcode: 0xD6, },
- { opcode: 0xD7, skip: 1, },
-
- { opcode: 0xD8, e: 1, skip: 1, },
- { opcode: 0xD9, e: 1, skip: 1, },
- { opcode: 0xDA, e: 1, skip: 1, },
- { opcode: 0xDB, e: 1, skip: 1, },
- { opcode: 0xDC, e: 1, skip: 1, },
- { opcode: 0xDD, e: 1, skip: 1, },
- { opcode: 0xDE, e: 1, skip: 1, },
- { opcode: 0xDF, e: 1, skip: 1, },
-
- { opcode: 0xE0, imm8: 1, skip: 1, },
- { opcode: 0xE1, imm8: 1, skip: 1, },
- { opcode: 0xE2, imm8: 1, skip: 1, },
- { opcode: 0xE3, imm8: 1, skip: 1, },
-
- { opcode: 0xE4, imm8: 1, skip: 1, },
- { opcode: 0xE5, os: 1, imm8: 1, skip: 1, },
- { opcode: 0xE6, imm8: 1, skip: 1, },
- { opcode: 0xE7, os: 1, imm8: 1, skip: 1, },
-
- { opcode: 0xE8, os: 1, imm1632: 1, skip: 1, },
- { opcode: 0xE9, os: 1, imm1632: 1, skip: 1, },
- { opcode: 0xEA, os: 1, imm1632: 1, skip: 1, },
- { opcode: 0xEB, imm: 1, skip: 1, },
-
- { opcode: 0xEC, skip: 1, },
- { opcode: 0xED, os: 1, skip: 1, },
- { opcode: 0xEE, skip: 1, },
- { opcode: 0xEF, os: 1, skip: 1, },
-
- { opcode: 0xF0, prefix: 1, },
- { opcode: 0xF1, skip: 1, },
- { opcode: 0xF2, prefix: 1, },
- { opcode: 0xF3, prefix: 1, },
- { opcode: 0xF4, skip: 1, },
- { opcode: 0xF5, },
-
- { opcode: 0xF6, fixed_g: 0, imm: 1, },
- { opcode: 0xF6, fixed_g: 1, imm: 1, },
- { opcode: 0xF6, fixed_g: 2, },
- { opcode: 0xF6, fixed_g: 3, },
- { opcode: 0xF6, fixed_g: 4, mask_flags: af | zf, },
- { opcode: 0xF6, fixed_g: 5, mask_flags: af | zf, },
- { opcode: 0xF6, fixed_g: 6, skip: 1, }, // zero divide
- { opcode: 0xF6, fixed_g: 7, skip: 1, },
-
- { opcode: 0xF7, os: 1, fixed_g: 0, imm: 1, },
- { opcode: 0xF7, os: 1, fixed_g: 1, imm: 1, },
- { opcode: 0xF7, os: 1, fixed_g: 2, },
- { opcode: 0xF7, os: 1, fixed_g: 3, },
- { opcode: 0xF7, os: 1, fixed_g: 4, mask_flags: zf | af, },
- { opcode: 0xF7, os: 1, fixed_g: 5, mask_flags: zf | af, },
- { opcode: 0xF7, os: 1, fixed_g: 6, skip: 1, }, // zero divide
- { opcode: 0xF7, os: 1, fixed_g: 7, skip: 1, },
-
- { opcode: 0xF8, },
- { opcode: 0xF9, },
- { opcode: 0xFA, skip: 1, },
- { opcode: 0xFB, skip: 1, },
- { opcode: 0xFC, },
- { opcode: 0xFD, },
-
- { opcode: 0xFE, e: 1, fixed_g: 0, },
- { opcode: 0xFE, e: 1, fixed_g: 1, },
- { opcode: 0xFF, os: 1, e: 1, fixed_g: 0, },
- { opcode: 0xFF, os: 1, e: 1, fixed_g: 1, },
- { opcode: 0xFF, os: 1, e: 1, fixed_g: 2, skip: 1, },
- { opcode: 0xFF, os: 1, e: 1, fixed_g: 3, skip: 1, },
- { opcode: 0xFF, os: 1, e: 1, fixed_g: 4, skip: 1, },
- { opcode: 0xFF, os: 1, e: 1, fixed_g: 5, skip: 1, },
- { opcode: 0xFF, os: 1, e: 1, fixed_g: 6, },
-
- { opcode: 0x0F00, e: 1, g: 1, skip: 1 },
- { opcode: 0x0F01, e: 1, g: 1, skip: 1 },
- { opcode: 0x0F02, os: 1, e: 1, g: 1, skip: 1 },
- { opcode: 0x0F03, os: 1, e: 1, g: 1, skip: 1 },
- { opcode: 0x0F04, skip: 1 },
- { opcode: 0x0F05, skip: 1 },
- { opcode: 0x0F06, skip: 1 },
- { opcode: 0x0F07, skip: 1 },
- { opcode: 0x0F08, skip: 1 },
- { opcode: 0x0F09, skip: 1 },
- { opcode: 0x0F09, skip: 1 },
- { opcode: 0x0F0A, skip: 1 },
- { opcode: 0x0F0B, skip: 1 },
- { opcode: 0x0F0C, skip: 1 },
- { opcode: 0x0F0D, skip: 1 },
- { opcode: 0x0F0E, skip: 1 },
- { opcode: 0x0F0F, skip: 1 },
-
- { opcode: 0x0F20, e: 1, g: 1, skip: 1 },
- { opcode: 0x0F21, e: 1, g: 1, skip: 1 },
- { opcode: 0x0F22, e: 1, g: 1, skip: 1 },
- { opcode: 0x0F23, e: 1, g: 1, skip: 1 },
-
- { opcode: 0x0F30, skip: 1 },
- { opcode: 0x0F31, skip: 1 },
- { opcode: 0x0F32, skip: 1 },
- { opcode: 0x0F33, skip: 1 },
- { opcode: 0x0F34, skip: 1 },
- { opcode: 0x0F35, skip: 1 },
-
- { opcode: 0x0F40, e: 1, g: 1, os: 1, },
- { opcode: 0x0F41, e: 1, g: 1, os: 1, },
- { opcode: 0x0F42, e: 1, g: 1, os: 1, },
- { opcode: 0x0F43, e: 1, g: 1, os: 1, },
- { opcode: 0x0F44, e: 1, g: 1, os: 1, },
- { opcode: 0x0F45, e: 1, g: 1, os: 1, },
- { opcode: 0x0F46, e: 1, g: 1, os: 1, },
- { opcode: 0x0F47, e: 1, g: 1, os: 1, },
- { opcode: 0x0F48, e: 1, g: 1, os: 1, },
- { opcode: 0x0F49, e: 1, g: 1, os: 1, },
- { opcode: 0x0F4A, e: 1, g: 1, os: 1, },
- { opcode: 0x0F4B, e: 1, g: 1, os: 1, },
- { opcode: 0x0F4C, e: 1, g: 1, os: 1, },
- { opcode: 0x0F4D, e: 1, g: 1, os: 1, },
- { opcode: 0x0F4E, e: 1, g: 1, os: 1, },
- { opcode: 0x0F4F, e: 1, g: 1, os: 1, },
-
- { opcode: 0x0F80, os: 1, skip: 1, },
- { opcode: 0x0F81, os: 1, skip: 1, },
- { opcode: 0x0F82, os: 1, skip: 1, },
- { opcode: 0x0F83, os: 1, skip: 1, },
- { opcode: 0x0F84, os: 1, skip: 1, },
- { opcode: 0x0F85, os: 1, skip: 1, },
- { opcode: 0x0F86, os: 1, skip: 1, },
- { opcode: 0x0F87, os: 1, skip: 1, },
- { opcode: 0x0F88, os: 1, skip: 1, },
- { opcode: 0x0F89, os: 1, skip: 1, },
- { opcode: 0x0F8A, os: 1, skip: 1, },
- { opcode: 0x0F8B, os: 1, skip: 1, },
- { opcode: 0x0F8C, os: 1, skip: 1, },
- { opcode: 0x0F8D, os: 1, skip: 1, },
- { opcode: 0x0F8E, os: 1, skip: 1, },
- { opcode: 0x0F8F, os: 1, skip: 1, },
-
- { opcode: 0x0F90, e: 1, g: 1, },
- { opcode: 0x0F91, e: 1, g: 1, },
- { opcode: 0x0F92, e: 1, g: 1, },
- { opcode: 0x0F93, e: 1, g: 1, },
- { opcode: 0x0F94, e: 1, g: 1, },
- { opcode: 0x0F95, e: 1, g: 1, },
- { opcode: 0x0F96, e: 1, g: 1, },
- { opcode: 0x0F97, e: 1, g: 1, },
- { opcode: 0x0F98, e: 1, g: 1, },
- { opcode: 0x0F99, e: 1, g: 1, },
- { opcode: 0x0F9A, e: 1, g: 1, },
- { opcode: 0x0F9B, e: 1, g: 1, },
- { opcode: 0x0F9C, e: 1, g: 1, },
- { opcode: 0x0F9D, e: 1, g: 1, },
- { opcode: 0x0F9E, e: 1, g: 1, },
- { opcode: 0x0F9F, e: 1, g: 1, },
-
- { opcode: 0x0FA0, os: 1, skip: 1, },
- { opcode: 0x0FA1, os: 1, skip: 1, },
- { opcode: 0x0FA2, skip: 1, },
-
- { opcode: 0x0FA8, os: 1, skip: 1, },
- { opcode: 0x0FA9, os: 1, skip: 1, },
-
- { opcode: 0x0FA3, os: 1, e: 1, g: 1, only_reg: 1, }, // bt (can also index memory, but not supported by test right now)
- { opcode: 0x0FAB, os: 1, e: 1, g: 1, only_reg: 1, },
- { opcode: 0x0FB3, os: 1, e: 1, g: 1, only_reg: 1, },
- { opcode: 0x0FBB, os: 1, e: 1, g: 1, only_reg: 1, },
-
- { opcode: 0x0FBA, os: 1, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, }, // bt
- { opcode: 0x0FBA, os: 1, e: 1, fixed_g: 5, imm8: 1, only_reg: 1, },
- { opcode: 0x0FBA, os: 1, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
- { opcode: 0x0FBA, os: 1, e: 1, fixed_g: 7, imm8: 1, only_reg: 1, },
-
- { opcode: 0x0FBC, os: 1, e: 1, g: 1, mask_flags: af, }, // bsf
- { opcode: 0x0FBD, os: 1, e: 1, g: 1, mask_flags: af, },
-
- // note: overflow flag only undefined if shift is > 1
- { opcode: 0x0FA4, os: 1, e: 1, g: 1, imm8: 1, mask_flags: af | of, }, // shld
- { opcode: 0x0FA5, os: 1, e: 1, g: 1, mask_flags: af | of, },
- { opcode: 0x0FAC, os: 1, e: 1, g: 1, imm8: 1, mask_flags: af | of, },
- { opcode: 0x0FAD, os: 1, e: 1, g: 1, mask_flags: af | of, },
-
- { opcode: 0x0FAE, e: 1, fixed_g: 0, only_mem: 1, skip: 1, }, // fxsave, ...
- { opcode: 0x0FAE, e: 1, fixed_g: 1, only_mem: 1, skip: 1, },
- { opcode: 0x0FAE, e: 1, fixed_g: 2, only_mem: 1, skip: 1, },
- { opcode: 0x0FAE, e: 1, fixed_g: 3, only_mem: 1, skip: 1, },
-
- { opcode: 0x0FAE, e: 1, fixed_g: 5, only_reg: 1, }, // mfence, ...
- { opcode: 0x0FAE, e: 1, fixed_g: 6, only_reg: 1, },
- { opcode: 0x0FAE, e: 1, fixed_g: 7, only_reg: 1, },
-
- { opcode: 0x0FAF, os: 1, e: 1, g: 1, mask_flags: af | zf }, // imul
-
- { opcode: 0x0FB0, e: 1, g: 1 }, // cmxchg
- { opcode: 0x0FB1, os: 1, e: 1, g: 1 },
- { opcode: 0x0FC7, e: 1, fixed_g: 1, only_mem: 1, }, // cmpxchg8b (memory)
-
- { opcode: 0x0FB2, os: 1, e: 1, g: 1, skip: 1, }, // lss, lfs, lgs
- { opcode: 0x0FB4, os: 1, e: 1, g: 1, skip: 1, },
- { opcode: 0x0FB5, os: 1, e: 1, g: 1, skip: 1, },
-
- { opcode: 0x0FB6, os: 1, e: 1, g: 1, }, // movzx
- { opcode: 0x0FB7, os: 1, e: 1, g: 1, },
-
- { opcode: 0xF30FB8, os: 1, e: 1, g: 1 }, // popcnt
-
- { opcode: 0x0FBE, os: 1, e: 1, g: 1, }, // movzx
- { opcode: 0x0FBF, os: 1, e: 1, g: 1, },
-
- { opcode: 0x0FC0, e: 1, g: 1, }, // xadd
- { opcode: 0x0FC1, os: 1, e: 1, g: 1, },
-
- { opcode: 0x0FC8, }, // bswap
- { opcode: 0x0FC9, },
- { opcode: 0x0FCA, },
- { opcode: 0x0FCB, },
- { opcode: 0x0FCC, },
- { opcode: 0x0FCD, },
- { opcode: 0x0FCE, },
- { opcode: 0x0FCF, },
-
-
- // mmx, sse
- // - Commented out are not implemented
- // - Missing are sse3+, and floating point
-
- { opcode: 0x660F12, only_mem: 1, e: 1, g: 1 },
- { opcode: 0x660F13, only_mem: 1, e: 1, g: 1 },
- { opcode: 0x660F14, e: 1, g: 1 },
-
- { opcode: 0x0F28, e: 1, g: 1 },
- { opcode: 0x660F28, e: 1, g: 1 },
- { opcode: 0x0F29, only_mem: 1, e: 1, g: 1 }, // XXX: Remove only_mem once supported by v86
- { opcode: 0x660F29, only_mem: 1, e: 1, g: 1 }, // XXX: Remove only_mem once supported by v86
- { opcode: 0x0F2B, only_mem: 1, e: 1, g: 1 },
- { opcode: 0x660F2B, only_mem: 1, e: 1, g: 1 },
-
- // emscripten bug causes this ported instruction to throw "integer result unpresentable"
- // https://github.com/kripken/emscripten/issues/5433
- { opcode: 0xF20F2C, e: 1, g: 1, skip: 1 },
-
- { opcode: 0x0F54, e: 1, g: 1 },
- { opcode: 0x660F54, e: 1, g: 1 },
- { opcode: 0x0F57, e: 1, g: 1 },
- { opcode: 0x660F57, e: 1, g: 1 },
-
- { opcode: 0x660F60, e: 1, g: 1 },
- { opcode: 0x0F60, e: 1, g: 1 },
- { opcode: 0x660F61, e: 1, g: 1 },
- { opcode: 0x0F61, e: 1, g: 1 },
- //{ opcode: 0x660F62, e: 1, g: 1 },
- { opcode: 0x0F62, e: 1, g: 1 },
- //{ opcode: 0x660F63, e: 1, g: 1 },
- { opcode: 0x0F63, e: 1, g: 1 },
- //{ opcode: 0x660F64, e: 1, g: 1 },
- { opcode: 0x0F64, e: 1, g: 1 },
- //{ opcode: 0x660F65, e: 1, g: 1 },
- { opcode: 0x0F65, e: 1, g: 1 },
- //{ opcode: 0x660F66, e: 1, g: 1 },
- { opcode: 0x0F66, e: 1, g: 1 },
- { opcode: 0x660F67, e: 1, g: 1 },
- { opcode: 0x0F67, e: 1, g: 1 },
- { opcode: 0x660F68, e: 1, g: 1 },
- { opcode: 0x0F68, e: 1, g: 1 },
- //{ opcode: 0x660F69, e: 1, g: 1 },
- { opcode: 0x0F69, e: 1, g: 1 },
- //{ opcode: 0x660F6A, e: 1, g: 1 },
- { opcode: 0x0F6A, e: 1, g: 1 },
- //{ opcode: 0x660F6B, e: 1, g: 1 },
- { opcode: 0x0F6B, e: 1, g: 1 },
- //{ opcode: 0x660F6C, e: 1, g: 1 },
- //{ opcode: 0x660F6D, e: 1, g: 1 },
- //{ opcode: 0xF30F6E, e: 1, g: 1 },
- { opcode: 0x660F6E, e: 1, g: 1 },
- { opcode: 0x0F6E, e: 1, g: 1 },
- { opcode: 0xF30F6F, e: 1, g: 1 },
- { opcode: 0x660F6F, e: 1, g: 1 },
- { opcode: 0x0F6F, e: 1, g: 1 },
-
- { opcode: 0x660F70, e: 1, g: 1, imm8: 1, },
- { opcode: 0xF20F70, e: 1, g: 1, imm8: 1, },
- { opcode: 0xF30F70, e: 1, g: 1, imm8: 1, },
- { opcode: 0x0F70, e: 1, g: 1, imm8: 1, },
-
- { opcode: 0x0F71, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
- //{ opcode: 0x660F71, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
- { opcode: 0x0F71, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, },
- //{ opcode: 0x660F71, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, },
- { opcode: 0x0F71, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
- //{ opcode: 0x660F71, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
-
- { opcode: 0x0F72, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
- //{ opcode: 0x660F72, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
- { opcode: 0x0F72, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, },
- //{ opcode: 0x660F72, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, },
- { opcode: 0x0F72, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
- //{ opcode: 0x660F72, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
-
- { opcode: 0x0F73, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
- { opcode: 0x660F73, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, },
- //{ opcode: 0x660F73, e: 1, fixed_g: 3, imm8: 1, only_reg: 1, },
- { opcode: 0x0F73, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
- //{ opcode: 0x660F73, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, },
- //{ opcode: 0x660F73, e: 1, fixed_g: 7, imm8: 1, only_reg: 1, },
-
- { opcode: 0x0F74, e: 1, g: 1, },
- { opcode: 0x660F74, e: 1, g: 1, },
- { opcode: 0x0F75, e: 1, g: 1, },
- { opcode: 0x660F75, e: 1, g: 1, },
- { opcode: 0x0F76, e: 1, g: 1, },
- { opcode: 0x660F76, e: 1, g: 1, },
- { opcode: 0x0F77 },
-
- { opcode: 0x0F7E, e: 1, g: 1 },
- { opcode: 0x660F7E, e: 1, g: 1 },
- { opcode: 0xF30F7E, e: 1, g: 1 },
- { opcode: 0x0F7F, e: 1, g: 1 },
- { opcode: 0x660F7F, only_mem: 1, e: 1, g: 1 }, // XXX: Remove only_mem once supported by v86
- { opcode: 0xF30F7F, only_mem: 1, e: 1, g: 1 }, // XXX: Remove only_mem once supported by v86
-
- { opcode: 0x0FC3, e: 1, g: 1, only_mem: 1, },
- { opcode: 0x660FC5, e: 1, g: 1, only_reg: 1, imm8: 1, },
-
- { opcode: 0x0FD1, e: 1, g: 1 },
- //{ opcode: 0x660FD1, e: 1, g: 1 },
- { opcode: 0x0FD2, e: 1, g: 1 },
- //{ opcode: 0x660FD2, e: 1, g: 1 },
- { opcode: 0x0FD3, e: 1, g: 1 },
- { opcode: 0x660FD3, e: 1, g: 1 },
- { opcode: 0x0FD3, e: 1, g: 1 },
- //{ opcode: 0x660FD3, e: 1, g: 1 },
- //{ opcode: 0x0FD4, e: 1, g: 1 },
- //{ opcode: 0x660FD4, e: 1, g: 1 },
- { opcode: 0x0FD5, e: 1, g: 1 },
- { opcode: 0x660FD5, e: 1, g: 1 },
-
- { opcode: 0x660FD6, only_mem: 1, e: 1, g: 1 }, // XXX: Remove only_mem once supported by v86
- //{ opcode: 0xF20FD6, e: 1, g: 1 },
- //{ opcode: 0xF30FD6, e: 1, g: 1 },
-
- //{ opcode: 0x0FD7, e: 1, g: 1, only_reg: 1, },
- { opcode: 0x660FD7, e: 1, g: 1, only_reg: 1, },
- { opcode: 0x0FD8, e: 1, g: 1 },
- //{ opcode: 0x660FD8, e: 1, g: 1 },
- { opcode: 0x0FD9, e: 1, g: 1 },
- //{ opcode: 0x660FD9, e: 1, g: 1 },
- //{ opcode: 0x0FDA, e: 1, g: 1 },
- { opcode: 0x660FDA, e: 1, g: 1 },
- { opcode: 0x0FDB, e: 1, g: 1 },
- //{ opcode: 0x660FDB, e: 1, g: 1 },
- { opcode: 0x0FDC, e: 1, g: 1 },
- { opcode: 0x660FDC, e: 1, g: 1 },
- { opcode: 0x0FDD, e: 1, g: 1 },
- { opcode: 0x660FDD, e: 1, g: 1 },
- //{ opcode: 0x0FDE, e: 1, g: 1 },
- { opcode: 0x660FDE, e: 1, g: 1 },
- { opcode: 0x0FDF, e: 1, g: 1 },
- //{ opcode: 0x660FDF, e: 1, g: 1 },
-
- //{ opcode: 0x0FE0, e: 1, g: 1 },
- //{ opcode: 0x660FE0, e: 1, g: 1 },
- { opcode: 0x0FE1, e: 1, g: 1 },
- //{ opcode: 0x660FE1, e: 1, g: 1 },
- { opcode: 0x0FE2, e: 1, g: 1 },
- //{ opcode: 0x660FE2, e: 1, g: 1 },
- //{ opcode: 0x0FE3, e: 1, g: 1 },
- //{ opcode: 0x660FE3, e: 1, g: 1 },
- //{ opcode: 0x0FE4, e: 1, g: 1 },
- { opcode: 0x660FE4, e: 1, g: 1 },
- { opcode: 0x0FE5, e: 1, g: 1 },
- //{ opcode: 0x660FE5, e: 1, g: 1 },
-
- //{ opcode: 0x660FE6, e: 1, g: 1 },
- //{ opcode: 0xF20FE6, e: 1, g: 1 },
- //{ opcode: 0xF30FE6, e: 1, g: 1 },
- //{ opcode: 0x0FE7, e: 1, g: 1, only_mem: 1, },
- { opcode: 0x660FE7, e: 1, g: 1, only_mem: 1, },
-
- { opcode: 0x0FE8, e: 1, g: 1 },
- //{ opcode: 0x660FE8, e: 1, g: 1 },
- { opcode: 0x0FE9, e: 1, g: 1 },
- //{ opcode: 0x660FE9, e: 1, g: 1 },
- //{ opcode: 0x0FEA, e: 1, g: 1 },
- //{ opcode: 0x660FEA, e: 1, g: 1 },
- { opcode: 0x0FEB, e: 1, g: 1 },
- { opcode: 0x660FEB, e: 1, g: 1 },
- { opcode: 0x0FEC, e: 1, g: 1 },
- //{ opcode: 0x660FEC, e: 1, g: 1 },
- { opcode: 0x0FED, e: 1, g: 1 },
- //{ opcode: 0x660FED, e: 1, g: 1 },
- //{ opcode: 0x0FEE, e: 1, g: 1 },
- //{ opcode: 0x660FEE, e: 1, g: 1 },
- { opcode: 0x0FEF, e: 1, g: 1 },
- { opcode: 0x660FEF, e: 1, g: 1 },
-
- { opcode: 0x0FF1, e: 1, g: 1 },
- //{ opcode: 0x660FF1, e: 1, g: 1 },
- { opcode: 0x0FF2, e: 1, g: 1 },
- //{ opcode: 0x660FF2, e: 1, g: 1 },
- { opcode: 0x0FF3, e: 1, g: 1 },
- //{ opcode: 0x660FF3, e: 1, g: 1 },
- //{ opcode: 0x0FF4, e: 1, g: 1 },
- //{ opcode: 0x660FF4, e: 1, g: 1 },
- { opcode: 0x0FF5, e: 1, g: 1 },
- //{ opcode: 0x660FF5, e: 1, g: 1 },
- //{ opcode: 0x0FF6, e: 1, g: 1 },
- //{ opcode: 0x660FF6, e: 1, g: 1 },
- //{ opcode: 0x0FF7, e: 1, g: 1 },
- //{ opcode: 0x660FF7, e: 1, g: 1 },
- { opcode: 0x0FF8, e: 1, g: 1 },
- //{ opcode: 0x660FF8, e: 1, g: 1 },
- { opcode: 0x0FF9, e: 1, g: 1 },
- //{ opcode: 0x660FF9, e: 1, g: 1 },
- { opcode: 0x0FFA, e: 1, g: 1 },
- { opcode: 0x660FFA, e: 1, g: 1 },
- //{ opcode: 0x0FFB, e: 1, g: 1 },
- //{ opcode: 0x660FFB, e: 1, g: 1 },
- { opcode: 0x0FFC, e: 1, g: 1 },
- //{ opcode: 0x660FFC, e: 1, g: 1 },
- { opcode: 0x0FFD, e: 1, g: 1 },
- //{ opcode: 0x660FFD, e: 1, g: 1 },
- { opcode: 0x0FFE, e: 1, g: 1 },
- //{ opcode: 0x660FFE, e: 1, g: 1 },
-];
-
-for(var i = 0; i < 8; i++)
+function generate_tests()
{
- encodings.push.apply(encodings, [
- { opcode: 0x00 | i << 3, e: 1, g: 1, },
- { opcode: 0x01 | i << 3, os: 1, e: 1, g: 1, },
- { opcode: 0x02 | i << 3, e: 1, g: 1, },
- { opcode: 0x03 | i << 3, os: 1, e: 1, g: 1, },
- { opcode: 0x04 | i << 3, eax: 1, imm: 1, },
- { opcode: 0x05 | i << 3, os: 1, eax: 1, imm: 1, },
+ const build_folder = __dirname + "/build/";
- { opcode: 0x70 | i, imm8: 1, skip: 1, },
- { opcode: 0x78 | i, imm8: 1, skip: 1, },
-
- { opcode: 0x80, e: 1, fixed_g: i, imm: 1, },
- { opcode: 0x81, os: 1, e: 1, fixed_g: i, imm: 1, },
- { opcode: 0x82, e: 1, fixed_g: i, imm: 1, },
- { opcode: 0x83, os: 1, e: 1, fixed_g: i, imm8: 1, },
-
- { opcode: 0xB0 | i, imm8: 1, },
- { opcode: 0xB8 | i, os: 1, imm1632: 1, },
-
- // note: overflow flag only undefined if shift is > 1
- // note: the adjust flag is undefined for shifts > 0 and unaffected by rotates
- { opcode: 0xC0, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, },
- { opcode: 0xC1, os: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, },
- { opcode: 0xD0, e: 1, fixed_g: i, mask_flags: af, },
- { opcode: 0xD1, os: 1, e: 1, fixed_g: i, mask_flags: af, },
- { opcode: 0xD2, e: 1, fixed_g: i, mask_flags: of | af, },
- { opcode: 0xD3, os: 1, e: 1, fixed_g: i, mask_flags: of | af, },
- ]);
-}
-
-encodings.sort((e1, e2) => {
- let o1 = (e1.opcode & 0xFF00) === 0x0F00 ? e1.opcode & 0xFFFF : e1.opcode & 0xFF;
- let o2 = (e2.opcode & 0xFF00) === 0x0F00 ? e2.opcode & 0xFFFF : e2.opcode & 0xFF;
- return o1 - o2 || e1.fixed_g - e2.fixed_g;
-});
-
-function repeat(s, n)
-{
- let out = "";
- for(let i = 0; i < n; i++) out += s;
- return out;
-}
-
-function indent(lines, how_much)
-{
- return lines.map(line => repeat(" ", how_much) + line);
-}
-
-function hex_byte(n)
-{
- let s = n.toString(16).toUpperCase();
- if(s.length === 1) s = "0" + s;
- return s;
-}
-
-function print_syntax_tree(statements)
-{
- let code = [];
-
- for(let statement of statements)
+ try
{
- if(typeof statement === "string")
+ fs.mkdirSync(build_folder);
+ }
+ catch(e)
+ {
+ if(e.code !== "EEXIST")
{
- code.push(statement);
- }
- else if(statement.type === "switch")
- {
- console.assert(statement.condition);
- code.push(`switch(${statement.condition})`);
- code.push(`{`);
- code.push.apply(code, indent(print_syntax_tree(statement.body), 4));
- code.push(`}`);
- }
- else if(statement.type === "case")
- {
- for(let case_ of statement.cases)
- {
- code.push(`case ${case_}:`);
- }
-
- code.push(`{`);
- code.push.apply(code, indent(print_syntax_tree(statement.body), 4));
- code.push(`}`);
- code.push(`break;`);
- }
- else if(statement.type === "default-case")
- {
- console.assert(statement.body);
-
- code.push(`default:`);
- code.push.apply(code, indent(statement.body, 4));
- }
- else
- {
- console.assert(false, "Unexpected type: " + statement.type);
+ throw e;
}
}
- return code;
-}
-
-function gen_read_imm_call(op, size_variant)
-{
- let size = (op.os || op.opcode % 2 === 1) ? size_variant : 8;
-
- if(op.imm || op.imm8 || op.imm16 || op.imm1632 || op.immaddr)
+ for(const op of encodings)
{
- if(op.imm8 || (op.imm && size === 8))
- {
- return "read_imm8()";
- }
- else
- {
- if(op.immaddr)
- {
- // immaddr: depends on address size
- return "read_moffs()";
- }
- else
- {
- console.assert(op.imm1632 || op.imm16 || (op.imm && (size === 16 || size === 32)));
+ const configurations = [
+ { mem: 0, size: 16, },
+ { mem: 0, size: 32, },
+ { mem: 1, size: 16, },
+ { mem: 1, size: 32, },
+ ];
- if(size === 16 || op.imm16)
+ let i = 0;
+
+ for(const config of configurations)
+ {
+ for(const code of create_nasm(op, config))
+ {
+ const filename = "gen_" + format_opcode(op.opcode) + "_" + (op.fixed_g || 0) + "_" + i + ".asm";
+ const dirname = build_folder + filename;
+
+ let old_code = undefined;
+
+ try
{
- return "read_imm16()";
+ old_code = fs.readFileSync(dirname, { encoding: "ascii" });
+ }
+ catch(e)
+ {
+ }
+
+ if(old_code !== code)
+ {
+ console.log("Creating %s", filename);
+ fs.writeFileSync(dirname, code);
}
else
{
- return "read_imm32s()";
+ console.log("Unchanged: %s", filename);
}
+
+ i++;
}
}
}
- else
- {
- return undefined;
- }
-}
-
-function gen_instruction_body(encoding, size)
-{
- let suffix = encoding[0].os ? `${size}` : "";
-
- let opcode = encoding[0].opcode & 0xFF;
- let opcode_hex = hex_byte(opcode);
-
- if(encoding[0].fixed_g === undefined && encoding[0].e)
- {
- let prefix_call = [];
-
- if(opcode === 0x8D)
- {
- // special case: requires call before modrm_resolve
- prefix_call = [`if(modrm_byte < 0xC0) { instr${suffix}_${opcode_hex}_mem_pre(); };`];
- }
-
- return [].concat(
- `int32_t modrm_byte = read_imm8();`,
- prefix_call,
- `modrm_byte < 0xC0 ?`,
- ` instr${suffix}_${opcode_hex}_mem(modrm_resolve(modrm_byte), modrm_byte >> 3 & 7) :`,
- ` instr${suffix}_${opcode_hex}_reg(modrm_byte & 7, modrm_byte >> 3 & 7);`
- );
- }
- else if(encoding[0].fixed_g !== undefined)
- {
- let cases = encoding.slice().sort((e1, e2) => e1.fixed_g - e2.fixed_g);
-
- for(let case_ of cases)
- {
- console.assert(typeof case_.fixed_g === "number");
- }
-
- return [
- "int32_t modrm_byte = read_imm8();",
- {
- type: "switch",
- condition: "modrm_byte >> 3 & 7",
- body: cases.map(case_ => {
- let prefix_call = [];
-
- if(opcode === 0x8F)
- {
- // special case: requires call before modrm_resolve
- prefix_call = [`if(modrm_byte < 0xC0) { instr${suffix}_${opcode_hex}_${case_.fixed_g}_mem_pre(); };`];
- }
-
- return {
- type: "case",
- cases: [case_.fixed_g],
- body: prefix_call.concat([
- `modrm_byte < 0xC0 ?`,
- ` instr${suffix}_${opcode_hex}_${case_.fixed_g}_mem(modrm_resolve(modrm_byte)) :`,
- ` instr${suffix}_${opcode_hex}_${case_.fixed_g}_reg(modrm_byte & 7);`,
- ]),
- };
- }).concat([
- {
- type: "default-case",
- body: ["assert(false);"],
- }
- ]),
- }
- ];
- }
- else
- {
- if(opcode === 0x9A || opcode === 0xEA) // special case: 2 immediate operands
- {
- var imm_read = gen_read_imm_call(encoding[0], size);
- console.assert(imm_read);
- return [`instr${suffix}_${opcode_hex}(${imm_read}, read_imm16());`];
- }
- else if(opcode === 0xC8) // special case: 2 immediate operands
- {
- var imm_read = gen_read_imm_call(encoding[0], size);
- console.assert(imm_read);
- return [`instr${suffix}_${opcode_hex}(${imm_read}, read_imm8());`];
- }
- else
- {
- return [`instr${suffix}_${opcode_hex}();`];
- }
- }
-}
-
-function gen_table()
-{
- let by_opcode = Object.create(null);
- let by_opcode0f = Object.create(null);
-
- for(let o of encodings)
- {
- let opcode = o.opcode;
-
- if(opcode >= 0x100)
- {
- if((opcode & 0xFF00) === 0x0F00)
- {
- opcode &= 0xFF;
- by_opcode0f[opcode] = by_opcode0f[opcode] || [];
- by_opcode0f[opcode].push(o);
- }
- }
- else
- {
- by_opcode[opcode] = by_opcode[opcode] || [];
- by_opcode[opcode].push(o);
- }
- }
-
- let t = [];
- for(let opcode = 0; opcode < 0x100; opcode++)
- {
- let encoding = by_opcode[opcode];
- console.assert(encoding && encoding.length);
-
- let opcode_hex = hex_byte(opcode);
-
- if(encoding[0].os)
- {
- t.push({
- type: "case",
- cases: [`0x${opcode_hex}`],
- body: gen_instruction_body(encoding, 16),
- });
- t.push({
- type: "case",
- cases: [`0x${opcode_hex}|0x100`],
- body: gen_instruction_body(encoding, 32),
- });
- }
- else
- {
- t.push({
- type: "case",
- cases: [`0x${opcode_hex}`, `0x${opcode_hex}|0x100`],
- body: gen_instruction_body(encoding, undefined),
- });
- }
- }
- t.push({
- type: "default-case",
- body: ["assert(false);"],
- });
- fs.writeFileSync("/tmp/table", print_syntax_tree(t).join("\n"));
-
- let t0f_16 = ``;
- let t0f_32 = ``;
- for(let opcode = 0; opcode < 0x100; opcode++)
- {
- let encoding = by_opcode0f[opcode];
-
- if(!encoding)
- {
- encoding = [
- {},
- ];
- }
-
- console.assert(encoding && encoding.length);
-
- let opcode_hex = opcode.toString(16).toUpperCase();
- if(opcode_hex.length === 1) opcode_hex = "0" + opcode_hex;
-
- if(encoding[0].os)
- {
- t0f_16 += `case 0x${opcode_hex}:\n`;
- t0f_16 += ` instr16_0F${opcode_hex}();\n`;
- t0f_16 += ` break;\n`;
-
- t0f_32 += `case 0x${opcode_hex}:\n`;
- t0f_32 += ` instr32_0F${opcode_hex}();\n`;
- t0f_32 += ` break;\n`;
- }
- else
- {
- t0f_16 += `case 0x${opcode_hex}:\n`;
- t0f_16 += ` instr_0F${opcode_hex}();\n`;
- t0f_16 += ` break;\n`;
-
- t0f_32 += `case 0x${opcode_hex}:\n`;
- t0f_32 += ` instr_0F${opcode_hex}();\n`;
- t0f_32 += ` break;\n`;
- }
- }
- t0f_16 += `default: assert(false);\n`;
- t0f_32 += `default: assert(false);\n`;
- fs.writeFileSync("/tmp/table0f_16", t0f_16);
- fs.writeFileSync("/tmp/table0f_32", t0f_32);
-}
-gen_table();
-
-try
-{
- fs.mkdirSync(__dirname + "/build/");
-}
-catch(e)
-{
- if(e.code !== 'EEXIST')
- {
- throw e;
- }
-}
-
-for(const op of encodings)
-{
- const configurations = [
- { mem: 0, size: 16, },
- { mem: 0, size: 32, },
- { mem: 1, size: 16, },
- { mem: 1, size: 32, },
- ];
-
- let i = 0;
-
- for(const config of configurations)
- {
- for(const code of create_nasm(op, config))
- {
- const filename = "gen_" + format_opcode(op.opcode) + "_" + (op.fixed_g || 0) + "_" + i + ".asm";
- const dirname = __dirname + "/build/" + filename;
-
- let old_code = undefined;
-
- try
- {
- old_code = fs.readFileSync(dirname, { encoding: "ascii" });
- }
- catch(e)
- {
- }
-
- if(old_code !== code)
- {
- console.log("Creating %s", filename);
- fs.writeFileSync(dirname, code);
- }
- else
- {
- console.log("Unchanged: %s", filename);
- }
-
- i++;
- }
- }
}
function format_opcode(n)
@@ -991,20 +76,78 @@ function format_opcode(n)
return (x.length === 1 || x.length === 3) ? "0" + x : x;
}
-function random_int32()
+function create_nasm_modrm_combinations_16()
{
- return Math.random() * 0x100000000 | 0;
+ let result = [];
+
+ for(let modrm = 0; modrm < 0xC0; modrm++)
+ {
+ let mod = modrm >> 6;
+ let rm = modrm & 7;
+
+ let has_imm8 = mod === 1;
+ let has_imm16 = mod === 2 || rm === 6 && mod === 0;
+
+ console.assert(!has_imm8 || !has_imm16);
+
+ let line = ["db " + modrm];
+ if(has_imm8) line.push("db 9ah");
+ if(has_imm16) line.push("dw 9a1fh");
+ result.push(line);
+ }
+
+ return result;
}
-function is_string_instruction(op)
+function create_nasm_modrm_combinations_32()
{
- return (op.opcode >= 0x6C && op.opcode <= 0x6F)
- || (op.opcode >= 0xA4 && op.opcode <= 0xA7)
- || (op.opcode >= 0xAA && op.opcode <= 0xAF);
+ let result = [];
+
+ let sample_sib_bytes = [0x05, 0x65, 0xAD, 0xCD, 0x20, 0xFF];
+ let exhaustive_sib_bytes = [];
+ for(let sib = 0; sib < 0x100; sib++) exhaustive_sib_bytes.push(sib);
+
+ for(let modrm = 0; modrm < 0xC0; modrm++)
+ {
+ let mod = modrm >> 6;
+ let reg = modrm >> 3 & 7;
+ let rm = modrm & 7;
+
+ let has_imm8 = mod === 1;
+ let has_imm32 = mod === 2 || rm === 5 && mod === 0;
+ let has_sib = rm === 4;
+
+ console.assert(!has_imm8 || !has_imm32);
+
+ if(has_sib)
+ {
+ // avoid generating an excessive number of tests
+ let sib_bytes = reg === 0 ? exhaustive_sib_bytes : sample_sib_bytes;
+
+ for(let sib of sib_bytes)
+ {
+ let line = ["db " + modrm, "db " + sib];
+ if(has_imm8) line.push("db 9ah");
+ if(has_imm32 || mod === 0 && (sib & 7) === 5) line.push("dd 9a1fbcdeh");
+ result.push(line);
+ }
+ }
+ else
+ {
+ let line = ["db " + modrm];
+ if(has_imm8) line.push("db 9ah");
+ if(has_imm32) line.push("dd 9a1fbcdeh");
+ result.push(line);
+ }
+ }
+
+ return result;
}
+
function create_nasm(op, config)
{
+ const op_rand = new Prand(op.opcode);
if(op.prefix || op.skip)
{
return [];
@@ -1034,14 +177,14 @@ function create_nasm(op, config)
}
}
- var size = (op.os || op.opcode % 2 === 1) ? config.size : 8;
- var is_modrm = op.e || op.g || op.fixed_g !== undefined;
+ const size = (op.os || op.opcode % 2 === 1) ? config.size : 8;
+ const is_modrm = op.e || op.fixed_g !== undefined;
- var codes = [];
+ const codes = [];
for(let reg of ["eax", "ecx", "edx", "ebx", "ebp", "esi", "edi"])
{
- let rand = random_int32();
+ let rand = op_rand.next();
codes.push("mov " + reg + ", " + rand);
}
@@ -1050,8 +193,8 @@ function create_nasm(op, config)
codes.push("sub esp, 8");
for(let i = 0; i < 8; i++)
{
- codes.push("mov dword [esp], " + random_int32());
- codes.push("mov dword [esp + 4], " + random_int32());
+ codes.push("mov dword [esp], " + op_rand.next());
+ codes.push("mov dword [esp + 4], " + op_rand.next());
codes.push("movq mm" + i + ", [esp]");
}
codes.push("add esp, 8");
@@ -1062,10 +205,10 @@ function create_nasm(op, config)
codes.push("sub esp, 16");
for(let i = 0; i < 8; i++)
{
- codes.push("mov dword [esp], " + random_int32());
- codes.push("mov dword [esp + 4], " + random_int32());
- codes.push("mov dword [esp + 8], " + random_int32());
- codes.push("mov dword [esp + 12], " + random_int32());
+ codes.push("mov dword [esp], " + op_rand.next());
+ codes.push("mov dword [esp + 4], " + op_rand.next());
+ codes.push("mov dword [esp + 8], " + op_rand.next());
+ codes.push("mov dword [esp + 12], " + op_rand.next());
codes.push("movdqu xmm" + i + ", [esp]");
}
codes.push("add esp, 16");
@@ -1076,11 +219,11 @@ function create_nasm(op, config)
for(let i = 0; i < 8; i++)
{
codes.push("sub esp, 4");
- codes.push("mov dword [esp], " + random_int32());
+ codes.push("mov dword [esp], " + op_rand.next());
}
}
- codes.push("push dword " + (random_int32() & ~(1 << 8 | 1 << 9)));
+ codes.push("push dword " + (op_rand.next() & ~(1 << 8 | 1 << 9)));
codes.push("popf");
if(true)
@@ -1099,7 +242,7 @@ function create_nasm(op, config)
}
}
- if(is_string_instruction(op))
+ if(op.is_string)
{
codes.push("mov ecx, 3");
codes.push("mov edi, (120000h-16)");
@@ -1113,50 +256,64 @@ function create_nasm(op, config)
}
let opcode = op.opcode;
- console.assert(opcode < 0x1000000);
- if(opcode >= 0x10000)
+
+ if(opcode === 0x8D)
{
- let c = opcode >> 16;
- console.assert(c === 0x66 || c === 0xF3 || c === 0xF2);
- codes.push("db " + c);
- opcode &= ~0xFF0000;
+ // special case: lea: generate 16-bit addressing and all modrm combinations
+ console.assert(is_modrm);
+
+ codes.push([].concat(
+ create_nasm_modrm_combinations_16().map(lines => ["db 67h", "db 8dh"].concat(lines).join("\n")),
+ create_nasm_modrm_combinations_32().map(lines => ["db 8dh"].concat(lines).join("\n"))
+ ));
}
- if(opcode >= 0x100)
+ else
{
- let c = opcode >> 8;
- console.assert(c === 0x0F, "Expected 0f prefix, got " + c.toString(16));
- codes.push("db " + c);
- opcode &= ~0xFF00;
- }
- codes.push("db " + opcode);
-
- if(is_modrm)
- {
- let g = 7; // edi / di / bh
-
- if(op.fixed_g !== undefined)
+ console.assert(opcode < 0x1000000);
+ if(opcode >= 0x10000)
{
- g = op.fixed_g;
+ let c = opcode >> 16;
+ console.assert(c === 0x66 || c === 0xF3 || c === 0xF2);
+ codes.push("db " + c);
+ opcode &= ~0xFF0000;
}
-
- let e;
- let sib;
-
- if(config.mem)
+ if(opcode >= 0x100)
{
- e = 0x04; // [esp]
- sib = 0x24;
- }
- else // op.only_mem
- {
- e = 0xc2; // edx
- sib = "";
+ let c = opcode >> 8;
+ console.assert(c === 0x0F, "Expected 0f prefix, got " + c.toString(16));
+ codes.push("db " + c);
+ opcode &= ~0xFF00;
}
+ codes.push("db " + opcode);
- codes.push("db " + (e | g << 3));
- if(e < 0xC0)
+ if(is_modrm)
{
- codes.push("db " + sib);
+ let g = 7; // edi / di / bh
+
+ if(op.fixed_g !== undefined)
+ {
+ g = op.fixed_g;
+ }
+
+ let e;
+ let sib;
+
+ if(config.mem)
+ {
+ e = 0x04; // [esp]
+ sib = 0x24;
+ }
+ else // op.only_mem
+ {
+ e = 0xc2; // edx
+ sib = "";
+ }
+
+ codes.push("db " + (e | g << 3));
+ if(e < 0xC0)
+ {
+ codes.push("db " + sib);
+ }
}
}
@@ -1165,10 +322,9 @@ function create_nasm(op, config)
codes.push("dw 8h");
codes.push("db 0h");
}
- else
- if(op.imm || op.imm8 || op.imm16 || op.imm1632 || op.immaddr)
+ else if(op.imm8 || op.imm8s || op.imm16 || op.imm1632 || op.imm32 || op.immaddr)
{
- if(op.imm8 || (op.imm && size === 8))
+ if(op.imm8 || op.imm8s)
{
codes.push("db 12h");
}
@@ -1182,14 +338,15 @@ function create_nasm(op, config)
}
else
{
- console.assert(op.imm1632 || op.imm16 || (op.imm && (size === 16 || size === 32)));
+ console.assert(op.imm1632 || op.imm16 || op.imm32);
- if(size === 16 || op.imm16)
+ if(op.imm1632 && size === 16 || op.imm16)
{
codes.push("dw 34cdh");
}
else
{
+ console.assert(op.imm1632 && size === 32 || op.imm32);
codes.push("dd 1234abcdh");
}
}
@@ -1217,7 +374,7 @@ function create_nasm(op, config)
function all_combinations(xs)
{
- var result = [xs];
+ let result = [xs];
for(let i = 0; i < xs.length; i++)
{
diff --git a/tests/nasm/gdbauto b/tests/nasm/gdbauto
index 352bcb3b..ba31fd08 100644
--- a/tests/nasm/gdbauto
+++ b/tests/nasm/gdbauto
@@ -1,5 +1,7 @@
# Invocation: gdb -x gdbauto xyz.bin
+set $STACK_TOP=0x120000
+
break loop
run
@@ -67,22 +69,22 @@ printf " %d,\n", $xmm7.v4_int32[2]
printf " %d,\n", $xmm7.v4_int32[3]
printf " \n"
-printf " %d,\n", *(int*)(0x120000-64)
-printf " %d,\n", *(int*)(0x120000-60)
-printf " %d,\n", *(int*)(0x120000-56)
-printf " %d,\n", *(int*)(0x120000-52)
-printf " %d,\n", *(int*)(0x120000-48)
-printf " %d,\n", *(int*)(0x120000-44)
-printf " %d,\n", *(int*)(0x120000-40)
-printf " %d,\n", *(int*)(0x120000-36)
-printf " %d,\n", *(int*)(0x120000-32)
-printf " %d,\n", *(int*)(0x120000-28)
-printf " %d,\n", *(int*)(0x120000-24)
-printf " %d,\n", *(int*)(0x120000-20)
-printf " %d,\n", *(int*)(0x120000-16)
-printf " %d,\n", *(int*)(0x120000-12)
-printf " %d,\n", *(int*)(0x120000-8)
-printf " %d,\n", *(int*)(0x120000-4)
+printf " %d,\n", *(int*)($STACK_TOP-64)
+printf " %d,\n", *(int*)($STACK_TOP-60)
+printf " %d,\n", *(int*)($STACK_TOP-56)
+printf " %d,\n", *(int*)($STACK_TOP-52)
+printf " %d,\n", *(int*)($STACK_TOP-48)
+printf " %d,\n", *(int*)($STACK_TOP-44)
+printf " %d,\n", *(int*)($STACK_TOP-40)
+printf " %d,\n", *(int*)($STACK_TOP-36)
+printf " %d,\n", *(int*)($STACK_TOP-32)
+printf " %d,\n", *(int*)($STACK_TOP-28)
+printf " %d,\n", *(int*)($STACK_TOP-24)
+printf " %d,\n", *(int*)($STACK_TOP-20)
+printf " %d,\n", *(int*)($STACK_TOP-16)
+printf " %d,\n", *(int*)($STACK_TOP-12)
+printf " %d,\n", *(int*)($STACK_TOP-8)
+printf " %d,\n", *(int*)($STACK_TOP-4)
printf " \n"
printf " %d\n", $eflags
diff --git a/tests/nasm/header.inc b/tests/nasm/header.inc
index afedb1cc..6d05733a 100644
--- a/tests/nasm/header.inc
+++ b/tests/nasm/header.inc
@@ -10,7 +10,7 @@ align 4
dd CHECKSUM
section .bss
- resb 128*1024
+ resb 128*1024 ; 0x20000
stack_top:
diff --git a/tests/nasm/prand.js b/tests/nasm/prand.js
new file mode 100644
index 00000000..952d522b
--- /dev/null
+++ b/tests/nasm/prand.js
@@ -0,0 +1,21 @@
+"use strict";
+const assert = require("assert");
+
+/**
+ * Creates a pseudo-random value generator. The seed must be an integer.
+ */
+function Random(seed) {
+ assert.equal(typeof seed, "number");
+ this._seed = seed % 2147483647;
+ if (this._seed <= 0) this._seed += 2147483646;
+}
+
+/**
+ * Returns a 32-bit pseudo-random value.
+ */
+Random.prototype.next = function () {
+ this._seed = (this._seed * 16807) & 0xffffffff;
+ return (this._seed - 1) | 0;
+};
+
+module.exports = Random;
diff --git a/tests/nasm/run.js b/tests/nasm/run.js
index 40c853e5..4dda9f1e 100755
--- a/tests/nasm/run.js
+++ b/tests/nasm/run.js
@@ -2,8 +2,8 @@
'use strict';
// Mapping between signals and x86 exceptions:
-// "Program received signal SIGILL, Illegal instruction." -> #UD
-// "Program received signal SIGFPE, Arithmetic exception." -> #GP
+// "Program received signal SIGILL, Illegal instruction." -> #UD (6)
+// "Program received signal SIGFPE, Arithmetic exception." -> #DE (0)
// to be determined -> #GP
// to be determined -> #NM
// to be determined -> #TS
@@ -26,7 +26,7 @@ const TERMINATE_MSG = 'DONE';
const MASK_ARITH = 1 | 1 << 2 | 1 << 4 | 1 << 6 | 1 << 7 | 1 << 11;
try {
- var V86 = require('../../build/libv86.js').V86Starter;
+ var V86 = require('../../build/libv86-debug.js').V86Starter;
}
catch(e) {
console.error('Failed to import build/libv86.js. Run ' +
@@ -61,9 +61,10 @@ function h(n, len)
return "0x" + pad0(str.toUpperCase(), len || 1);
}
-if (cluster.isMaster) {
-
- function extract_json(name, fixture_text) {
+if(cluster.isMaster)
+{
+ function extract_json(name, fixture_text)
+ {
if(fixture_text.includes("SIGFPE, Arithmetic exception"))
{
return { exception: "DE", };
@@ -150,7 +151,8 @@ if (cluster.isMaster) {
let failed_tests = [];
let finished_workers = 0;
- for (let i = 0; i < nr_of_cpus; i++) {
+ for(let i = 0; i < nr_of_cpus; i++)
+ {
let worker = cluster.fork();
worker.on('message', function(message) {
@@ -188,10 +190,16 @@ if (cluster.isMaster) {
console.error('\n[-] %s:', test_failure.img_name);
- test_failure.failures.forEach(function(individual_failure) {
- console.error("\n\t" + individual_failure.name);
- console.error("\tActual: 0x" + (individual_failure.actual >>> 0).toString(16));
- console.error("\tExpected: 0x" + (individual_failure.expected >>> 0).toString(16));
+ test_failure.failures.forEach(function(failure) {
+ function format_value(v) {
+ if(typeof v === "number")
+ return "0x" + (v >>> 0).toString(16);
+ else
+ return String(v);
+ }
+ console.error("\n\t" + failure.name);
+ console.error("\tActual: " + format_value(failure.actual));
+ console.error("\tExpected: " + format_value(failure.expected));
});
});
process.exit(1);
@@ -207,6 +215,7 @@ else {
return;
}
+ waiting_for_test = false;
current_test = test;
console.info('Testing', test.img_name);
@@ -222,10 +231,12 @@ else {
let loaded = false;
let current_test = undefined;
let first_test = undefined;
+ let waiting_for_test = false;
let emulator = new V86({
autostart: false,
memory_size: 2 * 1024 * 1024,
+ log_level: 0,
});
emulator.add_listener("emulator-loaded", function()
@@ -238,7 +249,51 @@ else {
}
});
+ emulator.cpu_exception_hook = function(n)
+ {
+ if(waiting_for_test)
+ {
+ return true;
+ }
+
+ waiting_for_test = true;
+ emulator.stop();
+
+ const exceptions = {
+ 0: "DE",
+ 6: "UD",
+ };
+
+ const exception = exceptions[n];
+
+ if(exception === undefined)
+ {
+ console.error("Unexpected CPU exception: " + n);
+ process.exit(1);
+ }
+
+ if(current_test.fixture.exception !== exception)
+ {
+ process.send({
+ failures: [{
+ name: "Exception",
+ actual: exception,
+ expected: current_test.fixture.exception || "(none)",
+ }],
+ img_name: current_test.img_name,
+ });
+ }
+ else
+ {
+ process.send(DONE_MSG);
+ }
+
+ return true;
+ };
+
emulator.bus.register('cpu-event-halt', function() {
+ console.assert(!waiting_for_test);
+ waiting_for_test = true;
emulator.stop();
var cpu = emulator.v86.cpu;
diff --git a/tests/qemu/Makefile b/tests/qemu/Makefile
index b4cef7d7..8997288b 100644
--- a/tests/qemu/Makefile
+++ b/tests/qemu/Makefile
@@ -2,7 +2,7 @@
CC=gcc
CC_I386=$(CC) -m32
QEMU_INCLUDES += -I../..
-CFLAGS=-Wall -O2 -g -fno-strict-aliasing -static -mmmx -mno-sse
+CFLAGS=-Wall -O2 -g -fno-strict-aliasing -static -mmmx -msse
LDFLAGS=
diff --git a/tests/qemu/compiler.h b/tests/qemu/compiler.h
index 2f7998b6..340e5fdc 100644
--- a/tests/qemu/compiler.h
+++ b/tests/qemu/compiler.h
@@ -1,9 +1,15 @@
-/* public domain */
+/* compiler.h: macros to abstract away compiler specifics
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
#ifndef COMPILER_H
#define COMPILER_H
-#include "config-host.h"
+#if defined __clang_analyzer__ || defined __COVERITY__
+#define QEMU_STATIC_ANALYSIS 1
+#endif
/*----------------------------------------------------------------------------
| The macro QEMU_GNUC_PREREQ tests for minimum version of the GNU C compiler.
@@ -18,10 +24,14 @@
#define QEMU_NORETURN __attribute__ ((__noreturn__))
-#if QEMU_GNUC_PREREQ(3, 4)
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+
+#define QEMU_SENTINEL __attribute__((sentinel))
+
+#if QEMU_GNUC_PREREQ(4, 3)
+#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
#else
-#define QEMU_WARN_UNUSED_RESULT
+#define QEMU_ARTIFICIAL
#endif
#if defined(_WIN32)
@@ -30,19 +40,66 @@
# define QEMU_PACKED __attribute__((packed))
#endif
-#define cat(x,y) x ## y
-#define cat2(x,y) cat(x,y)
-#define QEMU_BUILD_BUG_ON(x) \
- typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1];
+#define QEMU_ALIGNED(X) __attribute__((aligned(X)))
+
+#ifndef glue
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+#endif
+
+#ifndef likely
+#if __GNUC__ < 3
+#define __builtin_expect(x, n) (x)
+#endif
+
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof(((type *) 0)->member) *__mptr = (ptr); \
+ (type *) ((char *) __mptr - offsetof(type, member));})
+#endif
+
+/* Convert from a base type to a parent type, with compile time checking. */
+#ifdef __GNUC__
+#define DO_UPCAST(type, field, dev) ( __extension__ ( { \
+ char __attribute__((unused)) offset_must_be_zero[ \
+ -offsetof(type, field)]; \
+ container_of(dev, type, field);}))
+#else
+#define DO_UPCAST(type, field, dev) container_of(dev, type, field)
+#endif
+
+#define typeof_field(type, field) typeof(((type *)0)->field)
+#define type_check(t1,t2) ((t1*)0 - (t2*)0)
+
+#define QEMU_BUILD_BUG_ON_STRUCT(x) \
+ struct { \
+ int:(x) ? -1 : 1; \
+ }
+
+#if defined(CONFIG_STATIC_ASSERT)
+#define QEMU_BUILD_BUG_ON(x) _Static_assert(!(x), "not expecting: " #x)
+#elif defined(__COUNTER__)
+#define QEMU_BUILD_BUG_ON(x) typedef QEMU_BUILD_BUG_ON_STRUCT(x) \
+ glue(qemu_build_bug_on__, __COUNTER__) __attribute__((unused))
+#else
+#define QEMU_BUILD_BUG_ON(x)
+#endif
+
+#define QEMU_BUILD_BUG_ON_ZERO(x) (sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - \
+ sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)))
#if defined __GNUC__
# if !QEMU_GNUC_PREREQ(4, 4)
/* gcc versions before 4.4.x don't support gnu_printf, so use printf. */
-# define GCC_ATTR __attribute__((__unused__, format(printf, 1, 2)))
# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
# else
/* Use gnu_printf when supported (qemu uses standard format strings). */
-# define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2)))
# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
# if defined(_WIN32)
/* Map __printf__ to __gnu_printf__ because we want standard format strings
@@ -51,7 +108,6 @@
# endif
# endif
#else
-#define GCC_ATTR /**/
#define GCC_FMT_ATTR(n, m)
#endif
diff --git a/tests/qemu/run.js b/tests/qemu/run.js
index ac0c4ec4..4793c26e 100755
--- a/tests/qemu/run.js
+++ b/tests/qemu/run.js
@@ -56,7 +56,11 @@ emulator.add_listener("serial0-output-char", function(chr)
emulator.read_file("/result", function(err, data)
{
- if(err) throw err;
+ if(err)
+ {
+ console.error("Reading test result failed: " + err);
+ process.exit(1);
+ }
console.error("Got result, writing to stdout");
process.stdout.write(new Buffer(data));
emulator.stop();
diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c
index ef5a1d20..d1e0bacf 100644
--- a/tests/qemu/test-i386.c
+++ b/tests/qemu/test-i386.c
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
#if !defined(__x86_64__)
//#define TEST_VM86
@@ -65,6 +66,7 @@
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
+#define UNUSED(s) (void)(s)
#define CC_C 0x0001
#define CC_P 0x0004
@@ -211,7 +213,7 @@ static inline long i2l(long v)
#define TEST_LEA16(STR)\
{\
asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
- : "=wq" (res)\
+ : "=r" (res)\
: "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
printf("lea %s = %08lx\n", STR, res);\
}
@@ -338,21 +340,21 @@ void test_lea(void)
TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)");
#else
/* limited 16 bit addressing test */
- //TEST_LEA16("0x4000");
- //TEST_LEA16("(%%bx)");
- //TEST_LEA16("(%%si)");
- //TEST_LEA16("(%%di)");
- //TEST_LEA16("0x40(%%bx)");
- //TEST_LEA16("0x40(%%si)");
- //TEST_LEA16("0x40(%%di)");
- //TEST_LEA16("0x4000(%%bx)");
- //TEST_LEA16("0x4000(%%si)");
- //TEST_LEA16("(%%bx,%%si)");
- //TEST_LEA16("(%%bx,%%di)");
- //TEST_LEA16("0x40(%%bx,%%si)");
- //TEST_LEA16("0x40(%%bx,%%di)");
- //TEST_LEA16("0x4000(%%bx,%%si)");
- //TEST_LEA16("0x4000(%%bx,%%di)");
+ TEST_LEA16("0x4000");
+ TEST_LEA16("(%%bx)");
+ TEST_LEA16("(%%si)");
+ TEST_LEA16("(%%di)");
+ TEST_LEA16("0x40(%%bx)");
+ TEST_LEA16("0x40(%%si)");
+ TEST_LEA16("0x40(%%di)");
+ TEST_LEA16("0x4000(%%bx)");
+ TEST_LEA16("0x4000(%%si)");
+ TEST_LEA16("(%%bx,%%si)");
+ TEST_LEA16("(%%bx,%%di)");
+ TEST_LEA16("0x40(%%bx,%%si)");
+ TEST_LEA16("0x40(%%bx,%%di)");
+ TEST_LEA16("0x4000(%%bx,%%si)");
+ TEST_LEA16("0x4000(%%bx,%%di)");
#endif
}
@@ -1072,7 +1074,7 @@ void test_fbcd(double a)
void test_fenv(void)
{
- struct QEMU_PACKED {
+ struct __attribute__((__packed__)) {
uint16_t fpuc;
uint16_t dummy1;
uint16_t fpus;
@@ -1082,7 +1084,7 @@ void test_fenv(void)
uint32_t ignored[4];
long double fpregs[8];
} float_env32;
- struct QEMU_PACKED {
+ struct __attribute__((__packed__)) {
uint16_t fpuc;
uint16_t fpus;
uint16_t fptag;
@@ -1267,17 +1269,14 @@ void test_bcd(void)
#define TEST_CMPXCHG(op, size, opconst, eax)\
{\
long op0, op1, op2;\
- long eflags;\
op0 = i2l(0x12345678);\
op1 = i2l(0xfbca7654);\
op2 = i2l(eax);\
- asm(#op " %" size "0, %" size "1\n" \
- "pushf\n" \
- "pop %2\n" \
- : "=q" (op0), opconst (op1), "=g" (eflags) \
+ asm(#op " %" size "0, %" size "1" \
+ : "=q" (op0), opconst (op1) \
: "0" (op0), "a" (op2));\
- printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX " CC=%02lx\n",\
- #op, op2, op0, op1, eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
+ printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\
+ #op, op2, op0, op1);\
}
void test_xchg(void)
@@ -1432,7 +1431,7 @@ void test_segs(void)
struct {
uint32_t offset;
uint16_t seg;
- } QEMU_PACKED segoff;
+ } __attribute__((__packed__)) segoff;
ldt.entry_number = 1;
ldt.base_addr = (unsigned long)&seg_data1;
@@ -1877,7 +1876,7 @@ int tab[2];
void sig_handler(int sig, siginfo_t *info, void *puc)
{
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
printf("si_signo=%d si_errno=%d si_code=%d",
info->si_signo, info->si_errno, info->si_code);
@@ -1988,7 +1987,7 @@ void test_exceptions(void)
printf("lock nop exception:\n");
if (setjmp(jmp_env) == 0) {
/* now execute an invalid instruction */
- asm volatile(".byte 0xf0, 0x90"); /* lock nop */
+ asm volatile(".byte 0xf0, 0x90");
}
#endif
@@ -2076,7 +2075,7 @@ void test_exceptions(void)
/* specific precise single step test */
void sig_trap_handler(int sig, siginfo_t *info, void *puc)
{
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]);
}
@@ -2958,10 +2957,210 @@ void test_conv(void)
#endif
}
+
+void fatal(char *msg)
+{
+ fprintf(stderr, "*** FATAL ERROR: %s\n", (msg ? msg : "no message"));
+ fflush(stderr);
+ abort();
+}
+
+void byte_read(uint8_t* buffer, uint16_t offset, size_t num_bytes)
+{
+ printf("%-12s: offset=%x value=", "byte_r", offset);
+ size_t i = num_bytes;
+ while(i > 0)
+ {
+ i--;
+ printf("%02" PRIx8, buffer[offset + i]);
+ }
+ printf("\n");
+}
+
+uint64_t seq_counter = 0x8070605040302010;
+uint64_t get_seq64()
+{
+ seq_counter += 0x0101010101010101;
+ return seq_counter;
+}
+
+void byte_write_seq(uint8_t* target, uint16_t offset, size_t num_bytes)
+{
+ printf("%-12s: offset=%x value=", "byte_w", offset);
+ size_t i = num_bytes;
+ while(i > 0)
+ {
+ i--;
+ uint8_t byte = get_seq64();
+ target[offset + i] = byte;
+ printf("%02" PRIx8, byte);
+ }
+ printf("\n");
+}
+
+#define GENERATE_CHUNK_READ(INSTR, BITS, CONSTR) \
+ void chunk_read ## BITS(uint8_t* addr, uint16_t offset) \
+ { \
+ uint ## BITS ## _t chunk = 0; \
+ asm volatile(INSTR " %1, %0" : \
+ "=" CONSTR (chunk) : \
+ "m" (*(addr + offset)), "0" (chunk)); \
+ printf("%-12s: offset=%x value=%" PRIx ## BITS "\n", \
+ "chunk" #BITS "_r", \
+ offset, \
+ chunk); \
+ }
+
+#define GENERATE_CHUNK_WRITE(INSTR, BITS, CONSTR) \
+ void chunk_write ## BITS(uint8_t* addr, uint16_t offset) \
+ { \
+ uint ## BITS ## _t chunk = get_seq64(); \
+ asm volatile(INSTR " %0, %1" : \
+ "=" CONSTR (chunk) : \
+ "m" (*(addr + offset)), "0" (chunk)); \
+ printf("%-12s: offset=%x value=%" PRIx ## BITS "\n", \
+ "chunk" #BITS "_w", \
+ offset, \
+ chunk); \
+ }
+
+#define GENERATE_CHUNK_FNS(INSTR, BITS, CONSTR) \
+ GENERATE_CHUNK_READ(INSTR, BITS, CONSTR) \
+ GENERATE_CHUNK_WRITE(INSTR, BITS, CONSTR)
+
+#define TEST_CHUNK_READ(BITS, ADDR, OFFSET) \
+ byte_write_seq(ADDR, OFFSET, (BITS) >> 3); \
+ chunk_read ## BITS(ADDR, OFFSET);
+
+#define TEST_CHUNK_WRITE(BITS, ADDR, OFFSET) \
+ chunk_write ## BITS(ADDR, OFFSET); \
+ byte_read(ADDR, OFFSET, (BITS) >> 3);
+
+#define TEST_CHUNK_READ_WRITE(BITS, ADDR, OFFSET) \
+ byte_write_seq(ADDR, OFFSET, (BITS) >> 3); \
+ chunk_read_write ## BITS(ADDR, OFFSET); \
+ byte_read(ADDR, OFFSET, (BITS) >> 3); \
+
+// Based on BITS, we calculate the offset where cross-page reads/writes would begin
+#define TEST_CROSS_PAGE(BITS, ADDR) \
+ for(size_t offset = (PAGE_SIZE + 1 - (BITS >> 3)); \
+ offset < PAGE_SIZE; offset++) \
+ { \
+ TEST_CHUNK_READ(BITS, ADDR, offset); \
+ TEST_CHUNK_WRITE(BITS, ADDR, offset); \
+ TEST_CHUNK_READ_WRITE(BITS, ADDR, offset); \
+ }
+
+GENERATE_CHUNK_FNS("movw", 16, "r");
+GENERATE_CHUNK_FNS("mov", 32, "r");
+
+#ifdef TEST_SSE
+GENERATE_CHUNK_FNS("movq", 64, "y");
+
+void chunk_read_write16(uint8_t* addr, uint16_t offset)
+{
+ uint16_t chunk = get_seq64();
+ asm volatile("addw %0, %1" :
+ "=r" (chunk) :
+ "m" (*(addr + offset)), "0" (chunk));
+ printf("%-12s: offset=%x value=%" PRIx16 "\n",
+ "chunk16_rw",
+ offset,
+ chunk);
+}
+
+void chunk_read_write32(uint8_t* addr, uint16_t offset)
+{
+ uint32_t chunk = get_seq64();
+ asm volatile("add %0, %1" :
+ "=r" (chunk) :
+ "m" (*(addr + offset)), "0" (chunk));
+ printf("%-12s: offset=%x value=%" PRIx32 "\n",
+ "chunk32_rw",
+ offset,
+ chunk);
+}
+
+// No 64 or 128-bit read-write x86 instructions support a memory address as the destination
+void chunk_read_write64(uint8_t* addr, uint16_t offset)
+{
+ UNUSED(addr);
+ UNUSED(offset);
+}
+
+void chunk_read_write128(uint8_t* addr, uint16_t offset)
+{
+ UNUSED(addr);
+ UNUSED(offset);
+}
+
+void chunk_read128(uint8_t* addr, uint16_t offset)
+{
+ XMMReg chunk;
+ chunk.q[0] = chunk.q[1] = 0.0;
+ asm volatile("movdqu %1, %0" :
+ "=x" (chunk.dq) :
+ "m" (*(addr + offset)), "0" (chunk.dq)
+ );
+ printf("%-12s: offset=%x value=" FMT64X FMT64X "\n",
+ "chunk128_r",
+ offset,
+ chunk.q[1],
+ chunk.q[0]);
+}
+
+void chunk_write128(uint8_t* addr, uint16_t offset)
+{
+ XMMReg chunk;
+ chunk.q[0] = get_seq64();
+ chunk.q[1] = get_seq64();
+ asm volatile("movdqu %0, %1" :
+ "=x" (chunk.dq) :
+ "m" (*(addr + offset)), "0" (chunk.dq)
+ );
+ printf("%-12s: offset=%x value=" FMT64X FMT64X "\n",
+ "chunk128_w",
+ offset,
+ chunk.q[1],
+ chunk.q[0]);
+}
+#endif
+
+void test_page_boundaries()
+{
+ // mmap 2 consecutive pages
+ uint8_t *const page0 = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ // throwaway mmap to reduce likelhood of page0 and page1 mapping to consecutive physical frames
+ uint8_t *const throwaway = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ uint8_t *const page1 = mmap(page0 + PAGE_SIZE, PAGE_SIZE,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+
+ if(page0 == MAP_FAILED || throwaway == MAP_FAILED || page1 == MAP_FAILED)
+ {
+ fatal("mmap");
+ }
+
+ // Trigger page-faults causing virtual pages to be allocated to physical frames
+ page0[0] = 0x42;
+ throwaway[0] = 0x42;
+ page1[0] = 0x42;
+
+ TEST_CROSS_PAGE(16, page0);
+ TEST_CROSS_PAGE(32, page0);
+#ifdef TEST_SSE
+ TEST_CROSS_PAGE(64, page0);
+ TEST_CROSS_PAGE(128, page0);
+#endif
+
+ munmap(page0, PAGE_SIZE);
+ munmap(page1, PAGE_SIZE);
+}
+
extern void *__start_initcall;
extern void *__stop_initcall;
-
int main(int argc, char **argv)
{
void **ptr;
@@ -2993,7 +3192,9 @@ int main(int argc, char **argv)
test_vm86();
#endif
#if !defined(__x86_64__)
+ test_exceptions();
test_self_modifying_code();
+ //test_single_step();
#endif
test_enter();
test_conv();
@@ -3001,7 +3202,6 @@ int main(int argc, char **argv)
test_sse();
//test_fxsave();
#endif
- test_exceptions();
- //test_single_step();
+ test_page_boundaries();
return 0;
}
diff --git a/v86.css b/v86.css
index e841239c..305d62f0 100644
--- a/v86.css
+++ b/v86.css
@@ -57,9 +57,13 @@ a {
width: 0;
height: 0;
resize: none;
- border: 0;
- padding: 0;
position: absolute;
+ opacity: 0;
+ left: -9999em;
+ top: 0;
+ z-index: -10;
+ white-space: nowrap;
+ overflow: hidden;
}
h4 {
margin: 0px 0px 20px 0px;